=================== QGen Code Generator =================== Using ``qgenc`` =============== Code generation is performed using the ``qgenc`` executable which can be invoked in three methods: .. image:: img/qgen_toolset.png 1. From the Simulink GUI Code generation can be launched directly from within a Simulink model in the MATLAB GUI. This method is the easiest and most straightforward, however it is less flexible than the other methods in terms of the configuration options it provides. 2. From the MATLAB Command Line Code generation can be launched by calling the ``qgen_build`` function in the MATLAB Command Line. This method allows configuring the code generation through arguments passed to ``qgen_build``. 3. From the System Command Line Code generation can be launched by running the ``qgenc`` executable from the system command line. This method requires a preliminary execution of the ``qgen_export_xmi`` MATLAB function to extract relevant information from the Simulink model and serialize it in multiple XMI files, one per model and one for the base workspace, as explained in :ref:`exporting-model`. Once the files are generated, ``qgenc`` no longer requires the MATLAB/Simulink environment which makes this method better suited for nightly and regression testing. Prerequisites ============= Before performing code generation with QGen, it is necessary to ensure that the model is consistent and simulation can be run in Simulink with no errors. Generating Code from the Simulink GUI ===================================== QGen can be invoked from the Simulink user interface. This requires QGen to be correctly setup in MATLAB following the instructions in :ref:`qgen-setup-in-matlab`. A QGen menu item is available in the menu bar of any Simulink model. .. image:: img/gui_bar.png Clicking on ``Verify and Generate`` gives an option to generate code for the current model or the active subsystem, and then shows the following menu. Clicking on the gear icon allows to select the code generation options of QGen. Code generation options will be explained in :ref:`from-matlab-command-line` and :ref:`from-command-line`. .. image:: img/gui_menu.png .. note:: This code generation method only proposes a few code generation options. More code generation options are available with the other invocation methods in :ref:`from-matlab-command-line` and :ref:`from-command-line`. It is also possible to right-click on a subsystem and execute QGen on a specific subsystem only. .. image:: img/gui_contextual.png .. _from-matlab-command-line: Generating Code from the MATLAB Command Line ============================================ QGen can be invoked from the MATLAB command line using the ``qgen_build`` function. This requires QGen to be correctly setup in MATLAB following the instructions in :ref:`qgen-setup-in-matlab`. .. ``qgen_build`` encapsulates all the steps of QGen code generation in a single .. entry point that is still .. .. Execution from within MATLAB has the following advantages: .. .. * Encapsulating the exporting phase into XMI files and the code generation .. step into one command .. * Providing a GUI detailing available export and code generation options The ``qgen_build`` function performs the following main steps: 1. Load the given model in Simulink 2. Export the model information using the ``qgen_export_xmi`` function in a manner similar to :ref:`exporting-model`. 3. Invoke the ``qgenc`` executable. As a result of step 1, Simulink itself is launched. Do not worry if you see the Simulink model being loaded upon the invocation of ``qgen_build``. Models with Externally Defined Constants ---------------------------------------- QGen supports models that use parameter values defined outside the model itself. Such values are defined in variables declared either in the MATLAB workspace, or in a separate ``.m`` file. When using a separate ``.m`` file, only variable definitions are supported but **not statements** such as ``if`` and ``for`` constructs. Quick Examples -------------- Here are some quick examples on how to invoke the ``qgen_build`` function. Given an arbitrary model ``mymodel.mdl``, the following invocation generates Ada code in the directory ``generated_code/`` for the model ``mymodel.mdl``. The ``--clean`` argument instructs QGen to delete all contents of the output directory ``generated_code/`` before generating code. .. code-block:: text >> qgen_build ('./mymodel.mdl', 'ada', '-o', './generated_code', '--clean') Let us take the example in the directory ``speedometer``, located in the ``$QGEN_INSTALL/share/qgen/examples/`` directory. This example requires some global variables which are defined in a separate file. The following exports XMI files into the ``qgen_xmi_dir`` directory and then generates Ada code in the folder ``./generated_code`` for ``speedometer.mdl`` and, by using the ``speedometer_def.m`` MATLAB file, defines global variables used by the model. .. code-block:: text >> speedometer_def >> qgen_build ('./speedometer.mdl', 'ada', '-o, qgen_xmi_dir', '-o', ... './generated_code', '--clean') .. image:: img/qgen_build.png In the following invocation the default output directory ``speedometer.xmi_generated/`` will be used since the ``-o`` argument was not specified. The ``--incremental`` argument instructs QGen to keep the current content of the output directory, and to only regenerate for the models that changed this the last generation in that directory. .. code-block:: text >> qgen_build ('./speedometer.mdl', 'ada', '--incremental') When running from within MATLAB, it is possible to use the ``-v`` switch in the exporter_options to get the complete output of loading and analyzing the Simulink model. This is particularly useful to detect the use of call backs in models, blocks or port which may disrupt the use of QGen. If global variables used by the model are defined in several m-files, it is possible to include them all as follows: .. code-block:: text >> qgen_build ('./my_model.mdl', 'ada', '-v', '--incremental') The command above loads my_model_param.m and my_model_def.m into MATLAB workspace, export the contents of the workspace to file my_model_base_ws.m and executes ``qgenc`` with command line ``qgenc my_model.xmi --pre-process-xmi -l ada --incremental`` ``qgen_build`` Arguments ------------------------ The ``qgen_build`` script has three required inputs and a number of optional parameters: .. code-block:: text qgen_build (, , [, ]); * ``mdl_path`` Name of the mdl or slx file optionally with path (absolute or relative). * ``lang`` Name of the language. Accepted values are ``ada`` and ``c``. The exporter options switches should be provided as a single string each value being separated by a comma. If no exporter_options nor qgen_options are specified exporter_options ``-o _qgen_xmi`` is used by default. All exporter options are documented in :ref:`qgen_export_xmi_args`. Options are all string values. Each option is either a single boolean switch or a switch followed by a value. Options can be passed in an arbitrary order. .. note:: Several options correspond to identical or similar options of the ``qgenc`` executable. As a result, more details on options will be provided in :ref:`from-command-line`. .. note:: Options can be passed either as function arguments, or as a cell array of length 1 where the value of the first element is also a cell array containing the list of options. The allowed qgen_options are described below. ``qgen_build`` accepts the following boolean switches (no value): * ``--wmisra`` Treat violations to MISRA Simulink as warnings. * ``--no-misra`` Accept violations to MISRA Simulink. * ``--global-io`` Generate main subsystem's IO as global variables. * ``--gen-entrypoint`` Generate an entry module for the top-level model with ``init`` and ``comp`` functions. This module declares all necessary states variables and provides a simple interface to call from hand-written code. See :ref:`gen-code-interface`. * ``--eggshell`` Generate root subsystems in "eggshell" models as root models. "Eggshell" models are Simulink models with no interface (Inport or Outport blocks), consisting only of subsystems (with interface or not). * ``--po-wrapper`` Generate a protected object wrapper (for SPARK/Ada only) to ensure mutual exclusion when changing input signals to execute a computation step. * ``--consts-as-vars`` Always generate system parameters as variables without this switch constants are created. * ``--wrap-io`` Wrap IO of top-level subsystem to structure. * ``--noreuse-flattening`` Flatten code for subsystems not marked as Reusable function. * ``--full-flattening, --ff`` Flatten code for the entire model. * ``--ref-flattening, --rf`` Flatten code for each model. * ``--unroll-threshold`` Expand expressions as loops when more elements than the threshold. * ``--coverage-check`` Detect patterns where model coverage may not imply code coverage. They include: * Conditions within if statements that are predefined by conditions that are part of enclosing if statements, leading to uncoverable code. * Complex conditions in truth tables. If these conditions contain a combination of elementary conditions then coverage of the generated code is not guaranteed because model coverage does not check the elementary conditions. * ``--export-ws, -w`` Export workspace contents to an m-file, ignore MATLAB file passed in the function input. * ``-v`` Print verbose output when exporting the model. * ``--prettyprint`` Wrap all lines to 80 characters. * ``--clean, -c`` Instructs QGen to delete all the content of the output directory before starting the code generation. * ``--incremental, -i`` Instructs QGen to leave the content of the output directory as is. Generated files will overwrite existing files with the same name, but other existing files will remain untouched. If the input file is an XMI file generated from Simulink, this option performs an incremental code generation that only regenerates the sources that originate from models that changed since the last code generation. * ``--debug`` Run in debug mode. Switch-value pairs shall be passed as two arguments. First is the key and the second is value. It is assumed that values never start with ``'-'`` to distinguish them from other switches * ``--trace`` Generate a mappings.json file in the output directory to allow debugging at model level using GNAT Studio. * ``--subsys`` Generate code for the subsystem whose fully qualified name is PATH. For example ``--subsys MyModel/MySubsystem/AnotherSubsystem``. .. note:: * The selected block must be a Simulink subsystem. The option is not supported for Stateflow charts. However, the selected subsystem can contain Stateflow charts. * The selected Simulink subsystem can have a dedicated trigger or enable port (i.e. contain a Trigger or Enable block at the root level). * The selected Simulink subsystem must not have function call signals entering or leaving the subsystem's boundary through other ports (i.e. input or output ports). * ``--arith-conf`` Specify a file containing the configuration for arithmetic operations. See :ref:`arith-conf`. * ``--block-conf`` Specify a file containing the configuration for block libraries. See :ref:`block-conf`. * ``--blocks-signatures`` Generate a file named qgen__blocks_signatures.txt to use as a basis for block configuration. :ref:`block-conf`. * ``--output, -o`` Specify the code generation target directory. By default the files are placed in ``_generated``. * ``--steps, -s`` Specify compilation steps (one or more characters from the following list): * ``p`` preprocessor * ``s`` sequencer * ``g`` code model generation * ``j`` remove goto statements (no jump) * ``o`` code model simplification * ``x`` code model expansion * ``c`` code model postprocessing * ``d`` printing to target language * ``e`` export the result of previous step to XMI The --steps switch determines the transformations that shall be executed by QGenc. The order of switches above corresponds to the order of transformations executed by the tool (except for 'e'). This order is hard-coded and can not be modified by the --steps switch. Fully optional steps are 'j' and 'o' which can be left out at any time and 'e' which has a specific usage explained below. The other steps can be omitted only in a workflow where either it is desired to stop code generation at certain point or an external tool takes care of omitted intermediate transformations. Step 'e' is useful in conjunction with another step only -- it dumps the model produced by the step preceding it in the list. For example, to execute the preprocessor and then dump the resulting model to xmi without generating code, use ``--steps pe``. It is possible to use the 'e' key multiple times, for example to dump to xmi at every step, use: ``--steps pesegeoed``. Executing ``qgenc`` without the --steps switch is equivalent to ``--steps psgoxcd`` (preprocessor, sequencing, code model generation, code model simplification, code model expansion, code model postprocessing and printing). It is possible to use both --debug and --steps switches simultaneously. In that case, --steps should be either 'psgxcd' or any combination of those steps with 'e' (e.g. 'psegxcede'). Using the --debug switch with the 'o' step is not allowed. .. _from-command-line: Generating Code from the System Command Line ============================================ ``qgenc`` is the core executable that performs code generation. It runs completely outside the MATLAB/Simulink environment but requires representation of the model in a set of XMI files generated from the model within MATLAB/Simulink. .. _exporting-model: Exporting the model information ------------------------------- A set of XMI files is produced from within Simulink by executing the ``qgen_export_xmi`` function which is available in MATLAB after setting up QGen in MATLAB as per the instructions in :ref:`qgen-setup-in-matlab`. One file is generated for the base workspace, called QGen_Base_Workspace.xmi and one file will be generated per model referenced (including the root). .. image:: img/export_phase.png During generation of the files warning and errors will be displayed, they are not necessarily blocking QGen from executing properly. .. note:: The export phase will by default only re-export models that changed since the last export in the given output directory. This means that the first export can be long but if the model is architectured with multiple model references and only some are modified then subsequent incremental exports will be faster. .. _qgen_export_xmi_args: ``qgen_export_xmi`` Arguments ------------------------------------ The function has one mandatory argument, the name of the Simulink model, and several optional arguments to tune its behaviour: .. code-block:: text qgen_export_xmi ( [, ]) * ``mdl_path`` Name of the mdl or slx file optionally with an absolute or relative path. file extensions ``.mdl`` and ``.slx`` are added automatically when no extension is found. Options are all string values. Each option is either a single boolean switch or a switch followed by a value. Options can be passed in an arbitrary order. .. note:: Options can be passed either as function arguments, or as a cell array of length 1 where the value of the first element is also a cell array containing the list of options. The accepted boolean switches are: * ``--force, -f`` Re-export the entire model discarding previously generated XMI files in the output directory. * ``--fast-export, -fe`` Only look at the model version to determine whether a model has to be re-exported or not. Export will be faster but this can cause faulty code generation when non-modified model have datatypes that depend on other modified models. * ``--no-simulink-sequencing, -ns`` Disable the use of Simulink Debugger to retrieve the block sequencing, see more detail on the next option below. This option will provide a faster export process at the risk of a deviation between the generated code and the Simulink sequencing. * ``--force-simulink-sequencing, -fs`` Force the use of Simulink Debugger to retrieve block sequencing, this will open each referenced model in Simulink and actively focus it. Without those options QGen uses the Debugger by default on subsystems that contain DataStores or Function-Call Susbsystem that can cause complex sequencing patterns. The default option is the best compromise between a fast export and accurate sequencing data. * ``--no-workspace-export, -nw`` Do not export the workspace. * ``--export-unsupported, -eu`` Force the export of blocks not supported by QGen. This option should not be used when code generation is intended. It is provided for translation of XMI to other languages and for advanced compatibility checking. Switch-value pairs shall be passed as two arguments. First is the key and the second is value. It is assumed that the value does not start with ``'-'`` to distinguish it from other switches. * ``-o, --output`` Specify the output directory where generated XMI files are stored. By default files are place in _qgen_xmi. ``qgen_export_xmi`` Examples ----------------------------------- Example 1: Exporting the XMI files of ``test.mdl`` with default parameters .. code-block:: text qgen_export_xmi ('test') Example 2: Exporting the XMI files of ``test2.mdl`` in the ``XMI_test2`` folder without exporting the workspace. .. code-block:: text qgen_export_xmi ('./test2.mdl', '-o', 'XMI_test2', '-nw') ``qgenc`` Arguments ------------------- ``qgenc`` is invoked on the system command line as follows: .. code-block:: text qgenc FILE [switches] ``FILE`` is an .xmi file exported within MATLAB compliant with the *Geneauto* metamodel as available in ``share/qgen/plugins/geneauto/geneauto.ecore``. The following command lists all command line arguments supported by ``qgenc``: .. code-block:: text qgenc --help Mandatory Arguments ^^^^^^^^^^^^^^^^^^^ For code generation, there are three mandatory arguments: .. code-block:: text qgenc FILE [switches] --language ada|c --pre-process-xmi * ``FILE`` is the root model file exported in xmi format. * ``--language, -l VALUE`` ``VALUE`` can be either ``ada`` or ``c``. If the ``--language`` switch is not provided, the tool will not produce any code. * ``--pre-process-xmi`` Mandatory argument to treat the root XMI file as one generated from MATLAB/Simulink :ref:`exporting-model`. QGenc accepts other XMI files as input that are a result of previous executions and do not require this argument. Input and Output Data ^^^^^^^^^^^^^^^^^^^^^ * ``--output, -o DIR`` Specifies an output directory for the generated code. If this argument is not specified, code is generated in ``_generated`` by default. If the output directory is not empty, then one of the switches ``--clean`` or ``--incremental`` must be provided. * ``--clean, -c`` Instructs QGen to delete all the content of the output directory before starting the code generation. * ``--incremental, -i`` Instructs QGen to leave the content of the output directory as is. Generated files will overwrite existing files with the same name, but other existing files will remain untouched. When passing an .mdl or a .slx file, the following additional switches are available: * ``--trace`` Generate a mappings.json file in the output directory to allow debugging at model level using GNAT Studio. MISRA Constraints Options ^^^^^^^^^^^^^^^^^^^^^^^^^ QGen automatically checks that the input model conforms to selected MISRA Simulink constraints. QGenc should not be used as a MISRA checker tool. The checks are limited to constructs which directly influence the code generation policy. For full check one should use a dedicated MISRA checker. The following flags control the implemented MISRA checks: * ``--no-misra`` Disable checks for MISRA Simulink constraints. * ``--wmisra`` Treat violations of MISRA Simulink as warnings. Code Generation Options ^^^^^^^^^^^^^^^^^^^^^^^ * ``--all-variants`` Generate code for all Model Reference Variants and an If statement choosing which Variant to execute using the Variant Condition from Simulink. * ``--arith-conf`` Specifies a file with transformations for arithmetic functions. See :ref:`arith-conf`. * ``--consts-as-vars`` Generates all constants defined in .m files as variables. * ``--debug`` Generate non-optimized code * ``--gen-entrypoint`` Generate an entry module for the top-level model with ``init`` and ``comp`` functions. This module declares all necessary states variables and provides a simple interface to call from hand-written code. See :ref:`gen-code-interface`. * ``--from-simulink`` Indicates that ``qgenc`` was executed from the MATLAB command line. This instructs QGen to produce block references in error messages as Simulink hyperlinks. * ``--full-flattening, --ff`` Specifies to flatten all non-virtual subsystems. * ``--ref-flattening, --rf`` Flatten code for each model. * ``--global-io`` Generates the function parameters of the main module as global variables in a separate module. * ``--no-jump`` Removes goto statements. * ``--prettyprint NUM, -pp NUM`` Format lines to be at most NUM characters long. * ``--remove-assertions`` Remove code for assertion blocks and their inputs. * ``--noreuse-flattening`` Use Simulink Function Packaging for subsystem code generation. * ``--steps, -s VALUES`` Specifies the code generation steps, which are: * ``p`` preprocessor * ``s`` sequencing * ``g`` code model generation * ``o`` code model optimization * ``x`` code model expansion * ``j`` removal of goto statements * ``c`` code model postprocessing * ``d`` printing * ``e`` export to xmi For example, to execute the preprocessor and then dump the resulting model to xmi without generating code, use ``--steps pe``. It is possible to use the same code generation step multiple times, for example to dump to xmi at every step, use: ``--steps pesegeoed``. Executing ``qgenc`` without this switch is equivalent to ``--steps psgxcd`` (preprocessor, sequencing, code model generation, code model expansion, code model postprocessing and printing). * ``--subsys PATH`` Generate code for the subsystem whose fully qualified name is ``PATH``. For example ``--subsys MyModel/MySubsystem/AnotherSubsystem``. .. note:: * The selected block must be a Simulink subsystem. The option is not supported for Stateflow charts. However, the selected subsystem can contain Stateflow charts. * The selected Simulink subsystem can have a dedicated trigger or enable port (i.e. contain a Trigger or Enable block at the root level). * The selected Simulink subsystem must not have function call signals entering or leaving the subsystem's boundary through other ports (i.e. input or output ports). * ``--wrap-io`` Encapsulate formal parameters in Ada record types or C structs. * ``--unroll-threshold`` Expand expressions as loops when more elements than the threshold. * ``--eggshell`` Generate root subsystems in "eggshell" models as root models. "Eggshell" models are Simulink models with no interface (Inport or Outport blocks), consisting only of subsystems (with interface or not). ``qgenc`` Examples ------------------ To incrementally generate C code for ``myModel.mdl`` export into ``myModel_qgen_xmi`` folder inside ``myFolder`` and using full flattening: .. code-block:: text qgenc myModel/qgen_xmi/myModel.xmi --pre-process-xmi --incremental --language c --output myFolder --full-flattening .. note:: The XMI file ``myModel.xmi`` is generated by running the following in MATLAB prior to invoking ``qgenc``: .. code-block:: text qgen_export_xmi('./myModel.mdl') For more information on the generation of XMI files see :ref:`exporting-model`. To do the same, but dump the xmi after the import: .. code-block:: text qgenc myModel.xmi --incremental --pre-process-xmi --language c --output myFolder --steps epsgd --full-flattening To just run the importer and dump the xmi .. code-block:: text qgenc myModel.xmi --pre-process-xmi --output myFolder --steps e Errors and Warnings =================== When investigating errors and warnings issued by the QGen toolset, first make sure that the model is consistent and that simulation can be run in Simulink. Often errors issued by QGen are due to inconsistencies in the model that should be fixed within Simulink before invoking QGen tools. The detailed list of errors and warnings issued by the QGen tools is given in :ref:`error-list`. .. _gen-code-interface: Calling the generated code ========================== To call the code generated from hand-written code you should use the ``--gen-entrypoint`` switch to generate a module called ``qgen_entry_[modelname]``. This module contains two exported functions ``init`` and ``comp`` (prefixed by the model name in C) that you should call in that order. The ``init`` function corresponds to the Simulink initialization phase and initializes the values for static variables across all the code, including the code coming from all referenced models. The ``comp`` function corresponds to the execution of one Simulink iteration step and is typically called inside a loop. There are several ways how data can be passed to and from the ``comp`` when executing it: * By default an input argument is generated for each input port and output argument for each output port in ``comp`` function. .. code-block:: c extern void qgen_entry_CodeOrder_init (void); extern void qgen_entry_CodeOrder_comp (GAREAL const In1, GAREAL const In2, GAREAL* const Out1, GAREAL* const Out2); .. code-block:: ada package qgen_entry_CodeOrder is procedure init; procedure comp (In1 : Long_Float; In2 : Long_Float; Out1 : out Long_Float; Out2 : out Long_Float); end qgen_entry_CodeOrder; * the ``--wrap-io`` switch tells qgen to encapsulate parameters corresponding to input and output ports into a datastructure. The list of IO parameters of the ``comp`` function is replaced with a single input-output argument. .. code-block:: c typedef struct { GAREAL In1; GAREAL In2; } qgen_entry_CodeOrder_comp_Input; typedef struct { GAREAL Out1; GAREAL Out2; } qgen_entry_CodeOrder_comp_Output; extern void qgen_entry_CodeOrder_init (void); extern void qgen_entry_CodeOrder_comp (qgen_entry_CodeOrder_comp_Input const* const Input, qgen_entry_CodeOrder_comp_Output* const Output); .. code-block:: ada package qgen_type_wrap_io_qgen_entry_CodeOrder is type qgen_entry_CodeOrder_comp_Input is record In1 : Long_Float; In2 : Long_Float; end record; type qgen_entry_CodeOrder_comp_Output is record Out1 : Long_Float; Out2 : Long_Float; end record; end qgen_type_wrap_io_qgen_entry_CodeOrder; package qgen_entry_CodeOrder is procedure init; procedure comp (Input : qgen_entry_CodeOrder_comp_Input; Output : out qgen_entry_CodeOrder_comp_Output); end qgen_entry_CodeOrder; * when calling qgen with ``--global-io`` switch the parameters are replaced with global variables. Input values are expected to be written to these variables before calling the ``comp`` function and the output values are written to global variables corresponding to output ports. Each of the generated IO variables can be replaced with a variable imported from an external module. See :ref:`import-var` for a detailed description of this scenario. .. code-block:: c CodeOrder_State CodeOrder_memory; GAREAL qgen_entry_CodeOrder_comp_In1; GAREAL qgen_entry_CodeOrder_comp_In2; GAREAL qgen_entry_CodeOrder_comp_Out1; GAREAL qgen_entry_CodeOrder_comp_Out2; extern void qgen_entry_CodeOrder_init (void); extern void qgen_entry_CodeOrder_comp (void); .. code-block:: ada package qgen_entry_CodeOrder_io is CodeOrder_memory : CodeOrder_State; qgen_entry_CodeOrder_comp_In1 : Long_Float; qgen_entry_CodeOrder_comp_In2 : Long_Float; qgen_entry_CodeOrder_comp_Out1 : Long_Float; qgen_entry_CodeOrder_comp_Out2 : Long_Float; end qgen_entry_CodeOrder_io; package qgen_entry_CodeOrder is procedure init; procedure comp; end qgen_entry_CodeOrder; * the ``--po-wrapper`` switch works in conjunction with the ``--global-io`` and instructs QGen to put the global IO variables within the private part of an Ada protected object. This switch has no effect when generating code for C. Access to the input/output values is granted through protected procedures as setters for the different input signals, and protected functions as getters for the output signals. The input signals are set asynchronously by the setter procedures, and then the ``comp`` procedure uses the latest values for the input signals to compute the new output signals, that can be asynchronously read by the getter functions. .. code-block:: ada package qgen_entry_CodeOrder is procedure init; procedure comp (Out1 : out Long_Float; Out2 : out Long_Float); protected po is procedure comp (Out1 : out Long_Float; Out2 : out Long_Float); procedure set_In1 (In1 : Long_Float); procedure set_In2 (In2 : Long_Float); function get_Out1 return Long_Float; function get_Out2 return Long_Float; private qgen_entry_CodeOrder_comp_In1 : Long_Float; qgen_entry_CodeOrder_comp_In2 : Long_Float; qgen_entry_CodeOrder_comp_Out1 : Long_Float; qgen_entry_CodeOrder_comp_Out2 : Long_Float; end po; end qgen_entry_CodeOrder; User-specific Headers ======================= It is possible to add user-specific headers by modifying the files ``header.ada_header`` and ``header.c_header`` in the directory ``share/qgen/library`` of your QGen installation. .. Bus Signals .. ====================== .. include:: qgenc-buses.inc .. _custom-data-types: Custom Data Types ================= QGen supports custom type definitions based on ``Simulink.Aliastype``, ``Simulink.Bus`` and ``Simulink.IntEnumType`` object definitions. For signals, parameters, variables etc. in the Simulink / Stateflow model that have been defined to be of such custom types QGen shall use the corresponding type. By default, QGen shall generate respective type definitions. However, it is also possible to bind those Simulink objects with external type definitions in the target language (Ada or C). Then QGen shall use the respective external definitions in the generated code. Generally, this facilitates the integration of generated and external application code. See :ref:`external-types` for more. .. note:: The custom type definitions must be loaded into the MATLAB workspace before running QGen (before the XMI export phase). The typing information required for code generation will then be automatically extracted into the XMI files, as needed. .. note:: Structured parameters don't require explicit type definitions and can also be given in a parameter file. See :ref:`eml-params-accepted-constructs`. General Constraints for Custom Data Types ----------------------------------------- Array and Structure Types ^^^^^^^^^^^^^^^^^^^^^^^^^ Simulink doesn't support defining custom array (vector, matrix, etc.) types. Array types are usually defined implicitly as needed based on the base type and size of elements in the model. However, custom arrays with fixed size can be defined within buses (records/structures) as bus elements. Structures containing arrays and arrays containing structures are supported with a limitation that * when a structure is included in an array, it must have only scalar members and * when a structure member is an array, the elements of this array must not be structures. Enumerated Types ^^^^^^^^^^^^^^^^ Enumerated types are supported. The integer values that are associated with enumeration literals don't have to be ordered or consecutive. However, when the chosen target language is Ada they must be distinct within the given enumerated type. This is a requirement in the Ada language. Such type definitions should be refined and the models updated accordingly. C code generation does not have this constraint. Duplicate values will map to the same value also in the corresponding C code. QGen Attributes --------------- For using custom data types with QGen some attributes must be specified in the Description field of the respective Simulink data objects. The Description can also contain other text. Only the keyword patterns indicated below will be processed by QGen. .. note:: In older versions of Simulink the Description field is not available for ``BusElement`` objects (it is available for ``Bus`` objects only). This limitation does not affect Simulink versions 8.5 (R2015a) and above. For earlier versions the support of the Description field for ``BusElement`` objects should be checked. If it is not available, then the usage of custom types with QGen is more limited. .. list-table:: Description of the supported QGen attributes :header-rows: 1 * - Attribute - Description * - QGen.AdaSpecFile - (mandatory for Ada generation) The name of the external file containing custom type definitions * - QGen.RangeName - (mandatory when the range does not start from 1) The name of the range type used for the array indices of a custom array type (represented as a bus) * - QGen.ValueRange - (optional) The allowed range of values for a numeric type * - QGen.TypeName - (optional) If specified, the name to be used for the type Example: .. code-block:: matlab % Alias to a standard numeric type in Simulink MyReal = Simulink.AliasType; MyReal.BaseType = 'double'; MyReal.Description = ... ['This field contains description about this data type ', ... 'as well as QGen-specific attributes. ', ... 'The latter must be separated from the rest of text by whitespace. ', ... 'Hence, there is a space character after this sentence. ', ... 'QGen.AdaSpecFile:mytypes.ads QGen.ValueRange:[0.0, 1000.0] ', ... ' More text follows after whitespace.']; Value Range Checks -------------------- For aliases of numeric data types one can optionally specify also the expected numeric range of the data with the ``QGen.ValueRange`` attribute. For Ada code QGen will generate a cast that enforces the values to be in this range and will raise a run-time exception, if this is not the case. For C code such casts are not generated. However, this information can also be used by the QGen Model Verifier that performs static analysis of the model and can reveal certain design issues also statically. Example: .. code-block:: matlab % Alias to a standard numeric type in Simulink MyReal = Simulink.AliasType; MyReal.BaseType = 'double'; MyReal.Description = 'QGen.ValueRange:[0.0, 1000.0]'; .. _external-types: Custom Data Types Based on External Definitions ----------------------------------------------- QGen can use custom externally defined data types in the generated code instead of generating default type definitions. The functionality is slightly different when generating Ada or C code. The external type definitions are assumed to be in the same programming language as the code generation target language. In both cases the external data types must also be defined in Simulink using ``Simulink.Aliastype``, ``Simulink.Bus`` or ``Simulink.IntEnumType`` objects. For signals, parameters, variables etc. in the Simulink / Stateflow model that have been defined to be of such custom types QGen shall use the corresponding target language types as well. For elements defined using Simulink predefined types QGen shall generate default type definitions. QGen also generates the respective ``with`` and ``use`` clauses (Ada) and ``#include`` statements (C) for the external type definitions. It is the user's task to ensure that the external files are accessible at compile time. External Data Types for Ada Code Generation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The names of the Ada types and reference to the external spec (.ads) file containing the definitions for the target Ada code should be indicated in the ``Description`` field of Simulink data objects as shown below using the ``QGen.AdaSpecFile`` attribute. Definition from external spec files may use standard Ada naming convention for packages with a hyphen as package delimiter, such as: ``mytypes.ads``, ``mytypes-subpackage.ads``, ``mytypes-subpackage-basictypes.ads``. Generated files will then include them as: .. code-block:: ada with mytypes; use mytypes; with mytypes.subpackage; use mytypes.subpackage; with mytypes.subpackage.basictypes; use mytypes.subpackage.basictypes; Simulink doesn't support defining custom array types. However, for the custom array types used within buses (records/structures) one can optionally also provide the name of the range type used for the array indices with the QGen attribute ``QGen.RangeName``. Providing the range type is mandatory, when the range does not start from 1. Examples ```````` This MATLAB script demonstrates how to set up custom Ada types for using with Simulink and Stateflow. This example assumes that the external type definitions are in the file ``mytypes.ads``. The content of the latter is provided further below. .. This source code examples are from gms/tests/himoco/models/stateflow/features/CustomTypes/CTSF3Ada/ CustomTypesExample.mdl and CustomTypesExample_def.m We do not want to include them automatically from the testsuite to avoid direct dependencies. .. In the default pdf output the listing is not broken correctly across pages. Raw latex commands are used instead below. The new page after is sometimes necessary to avoid breaking the listing too much and interspersing with other elements. .. only:: html or singlehtml .. literalinclude:: listings/mytypes_ada_def.m :language: matlab :caption: MATLAB code for defining external Ada-based custom data types .. only:: latex or latexpdf .. raw:: latex \lstinputlisting[language=matlab, caption={MATLAB code for defining external Ada-based custom data types}] {../../listings/mytypes_ada_def.m} %\newpage The file ``mytypes.ads`` has the following contents. .. only:: html or singlehtml .. literalinclude:: listings/mytypes.ads :language: ada :lines: 25- :caption: Ada type definitions to be used in the target code. .. only:: latex or latexpdf .. raw:: latex \lstinputlisting[language=ada, caption={Ada type definitions to be used in the target code.}, firstline=25] {../../listings/mytypes.ads} %\newpage External Data Types for C Code Generation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Reference to the external header (.h) file containing the type definitions for the target C code should be indicated in the ``HeaderFile`` field of Simulink data objects as shown below. Configuring the Custom Code Section for Simulation `````````````````````````````````````````````````` .. note:: If the model contains also Stateflow charts, then before simulating you must also configure Simulink to read the data from this header file. For this you should open the Configuration Parameters dialog box Simulation Target pane and enter the custom header file and directory as needed. See also the corresponding figure. **Tip:** The data in these fields is only used by Simulink and Stateflow. QGen does not read them. Also, one should separately make sure that the file is available also when compiling and linking the generated code. .. figure:: img/CustomTypesExample_SL-C_config.png Configuring Simulink to use a custom C header file for simulation. .. only:: latex or latexpdf .. raw:: latex % Put page break to avoid mixing with listings in pdf. \newpage Examples ```````` The MATLAB script below demonstrates how to set up custom C types for using with Simulink and Stateflow. This example assumes that the external type definitions are in the file ``mytypes.h``. The content of the latter is provided further below. .. This source code examples are from gms/tests/himoco/models/stateflow/features/CustomTypes/CTSF3C/ CustomTypesExample.mdl and CustomTypesExample_def.m We do not want to include them automatically from the testsuite to avoid direct dependencies. .. In the default pdf output the listing is not broken correctly across pages. Raw latex commands are used instead below. The new page after is sometimes necessary to avoid breaking the listing too much and interspersing with other elements. .. only:: html or singlehtml .. literalinclude:: listings/mytypes_c_def.m :language: matlab :caption: MATLAB code for defining external C-based custom data types. .. only:: latex or latexpdf .. raw:: latex \lstinputlisting[language=matlab, caption={MATLAB code for defining external C-based custom data types.}] {../../listings/mytypes_c_def.m} %\newpage The file ``mytypes.h`` has the following contents. .. In the default pdf output the listing is not broken correctly across pages. Raw latex commands are used instead below. The new page after is sometimes necessary to avoid breaking the listing too much and interspersing with other elements. .. only:: html or singlehtml .. literalinclude:: listings/mytypes.h :language: c :lines: 27- :caption: C type definitions to be used in the target code. .. only:: latex or latexpdf .. raw:: latex \lstinputlisting[language=c, caption={C type definitions to be used in the target code.}, firstline=27] {../../listings/mytypes.h} %\newpage .. include:: qgenc-naming-convention.inc .. _arith-conf: Customizing Arithmetic Functions ================================ Thanks to the ``--arith-conf`` switch, it is possible to customize the call for arithmetic functions on both scalar and matrices. The switch take in input a textual file containing the specification of the transformation in the following format: .. code-block:: text TRANS ::= ARITY : SATURATION : SIGNATURE : MODULE where the arity of the arithmetic operation expressed as: .. code-block:: text ARITY ::= TYPE([]([])?)? = TYPE([]([])?)? OPERATOR TYPE([]([])?)? TYPE ::= double|single|int32|int16|int8|uint32|uint16|uint8|boolean OPERATOR ::= +|-|*|/|# where the ``#`` operator is the element-wise multiplication for matrices. SATURATION is a boolean value 'true' or 'false', where 'true' indicates that the custom call replaces a saturated operator. SIGNATURE is the signature of the function to be called, using the special MATLAB variables uN, yN and the size function. Finally, MODULE is the name of the .h/.ads file where the external functions are located. For example, the following text: .. code-block:: text double = double+double : false : double y1 = my_add(double u1, double u2) : my_lib.h means that, whenever the '+' operator between double is found, it should be replaced by a call to function ``my_add`` declared in file ``my_lib.h``. In this case, ``u1`` represents the first operand, while ``u2`` represents the second. With the transformation above, the code: .. code-block:: text double a, b, c; c = a + b; is transformed into: .. code-block:: text #include "my_lib.h" ... double a, b, c; c = my_add (a, b); When it comes to matrices, it is typical to call a void function, for example: .. code-block:: text double[][] = double[][]+double[][] : false : my_element_wise_sum (double u1[][], double u2[][], int32 size(u2, 1), int32 size(u2, 2)) : my_lib.h In this case, the matrix multiplication is replaced by a call to the my_matrix_element_wise function. Since the function signature does not contain a return value, an implicit parameters is added ad the end of the call. With the transformation above, the code: .. code-block:: text double[][] a, b, c; ... for (i = 0; i < size_1; i++){ for (j = 0; j < size_2; j++){ c[i][j] = a[i][j] + b[i][j]; } } is transformed into: .. code-block:: text #include "my_lib.h" ... double[][] a, b, c; my_element_wise_sum (a, b, size_1, size_2, c); Since C does not have a proper syntax to pass two dimensional arrays as arguments, matrices are passed as serialized row-major vectors: .. code-block:: text void my_element_wise_sum (double a[], double b[], int size_1, int size_2, double c[]) { int i, j; for (i = 0; i < size_1; ++i) { for (j = 0; j < size_2; ++j) c[i * size_2 + j] = ...; /* instead of c[i][j] */ } } An example of a configuration file is available in ``share/qgen/examples/customization/arith``. .. _block-conf: Customizing Block Implementations ================================= With the ``--block-conf`` switch, it is possible to replace the implementation of supported blocks with functions calls. The switch takes as parameter a textual file containing the specifications for block replacement: .. code-block:: text TRANS ::= BLOCK_TYPE : ARITY : (PARAMETER_FILTERS)? : (INIT_SIGNATURE)? : (COMPUTE_SIGNATURE)? : (UPDATE_SIGNATURE)? : MODULE Where the arity of the block is expressed as: .. code-block:: text ARITY ::= TYPE([]([])?)?(,TYPE([]([])?)?)* <- TYPE([]([])?)?(,TYPE([]([])?)?)* TYPE ::= double|single|int32|int16|int8|uint32|uint16|uint8|boolean Where the types on the left of '<-' represent the types of the output ports of the block and the types on the right are the input ports of the block. PARAMETER_FILTERS is a list of parameter names associated to a value: .. code-block:: text PARAMETER_FILTERS ::= (PARAM_NAME => VALUE (# PARAM_NAME => VALUE)*)? INIT_SIGNATURE is the signature of the function to call for the initialization step of the block. COMPUTE_SIGNATURE is the signature of the function called at the computation steps of the block. UPDATE_SIGNATURE is the signature of the function called after each computation steps to update internal data. The three signatures use the MATLAB special variables uN, yN and the size function. The feature also provides special variables mN to designate persistent memory variables and allows references to block parameters by using the parameter's name. Finally, MODULE is the name of the .h/.ads file where the external functions are located. For example, the following line: .. code-block:: text Gain : double <- double : : : double y1 = gain_comp(double u1) : : libgain.h tells that all Gain blocks whose input and output are of type double should be replaced by a call to function gain_comp declared in file libgain.h. No init update function are needed here since there is no persistent memory at stake. Another example with parameter filtering: .. code-block:: text Abs : double<-double : SaturateOnIntegerOverflow => off : \ : double y1 = abs_comp(double u1) : : libabs.h This tells to replace only Abs blocks whose parameter SaturateOnIntegerOverflow is off by a call to abs_comp. As is pattern matching, you can define a "default" case for block of the same type and arity but didn't match the parameter filters: .. code-block:: text Abs : double<-double : : : double y1 = abs_sat_comp(double u1) : : libabs.h This line in combination with the one above will make QGen replace Abs blocks using saturation. Here's another example with using memory variables an parameter references: .. code-block:: text UnitDelay : double[]<-double[] : \ : ud_init (double InitialValue[], uint32 size(InitialValue,1), \ double m1[size(InitialValue,1)], uint32 size(m1,1)) \ : ud_comp (double y1[], uint32 size(y1,1), double m1[], \ uint32 size(m1,1)) \ : ud_up (double u1[], uint32 size(u1,1), double m1[], \ uint32 size(m1,1)) \ : libunitd.h This line provides the three function signatures to replace UnitDelay blocks: - ud_init: This function is called for initialization, "double m1[size(InitialValue,1)]" will at the same time define a new memory persistent variable and specify that the created variable shall be passed to the function. The lengths of the arrays can also be provided as arguments to the function with the size() function (often needed when interfacing with C code). .. note:: When variables mN are of type array, the size of each dimension **must** be provided in the INIT_SIGNATURE. The numbering of mN variables shall start from one and the variables should appear in INIT_SIGNATURE in increasing order according to their numbering (no index shall be omitted). - ud_comp: For computation, the unit delay needs to set its output y1 with its memory variable m1. Since the variable is already allocated, there is no need to provide its size. However, as in the above case, the function might still need to have the lengths of arrays as arguments. - ud_up: Finally, the update function updates the m1 variable with the input of the unit delay block. An example of configuration file is available in share/qgen/examples/customization/blocks. Generating code with the ``--blocks-signatures`` on a given model switch will generate a file called "qgen__blocks_signatures.txt. This file will contain the signatures of all blocks present in the model. These signatures can be used as a basis to create custom configuration files.