Code Generation
As a separately licensed feature, PLECS can generate C code from a simulation model to facilitate real-time simulations. Code generation is subject to certain limitations, which are described in the first section of this chapter. The next two sections describe how the code generation capabilities are used within PLECS Standalone and the PLECS Blockset, respectively.
Code Generation for Physical Systems
As described earlier in this manual, PLECS models physical systems using piecewise linear state-space equations that can be described using multiple sets of state-space matrices. For details see Physical Model Equations.
During normal simulations, PLECS calculates new sets of state-space matrices on the fly as the individual switching components change their states. This is not possible in the generated C code because the algorithms for calculating the matrices are proprietary and because the calculation would simply be too time consuming under real-time constraints.
When generating code for a physical model, PLECS therefore embeds the
matrices for all combinations of switch states that it expects to encounter during the
execution of a simulation run. In general this means that for a system with switch
elements
sets of state-space matrices are calculated and embedded into the
generated C code. The actual number can be reduced by eliminating impossible
combinations. For instance, the Triple Switch blocks internally consists of 3 switch
elements but it still only accounts for 3 instead of
combinations because
one and only one switch will conduct at any time. Even so, systems with
many switches will lead to large source and executable files and long compile
times.
Limiting the Code Size
You can reduce the size of the generated code and the required compile time
by specifying the combinations for which code should be generated. The
combinations are specified separately for the electrical and mechanical domain. You
must specify the combinations of switch states for a domain explicitly if
PLECS finds that there are over 1024 () possible combinations in this
domain.
The combinations are provided as a struct variable with two fields, electrical and mechanical. The field values must be matrices where the individual columns represent the switch elements of the physical model and each row represents one combination of switch states (zero for an open switch and non-zero for a closed switch). The column order of the matrices can be determined from the command line by querying the model parameter StateSpaceOrder (see Extraction of State-Space Matrices). An empty matrix defaults to all possible combination. For backward compatibility reasons, if instead of a struct only a matrix is provided, it is assumed to apply to the electrical domain.
If at run-time a combination is encountered for which no code has been generated, the execution is aborted with an error message.
Maximum Number of Switches
The number of switch elements is limited to 32 per physical domain. This is due to the fact that the switch states of a physical domain are stored internally in a single unsigned integer variable. Note that some components, such as the Triple Switch, internally consist of more than one switch element.
Naturally Commutated Devices
Switched physical models are difficult to handle in real-time simulations if the natural switching instants can occur between two time steps. This is the case for naturally commutated components where switching events are triggered by internal quantities of the physical model. Examples of such components are the diode (which turns on when the voltage becomes positive and turns off then the current becomes negative) or the mechanical friction components (which start slipping when the torque resp. force exceeds a certain level and become stuck when the speed becomes zero).
During normal simulations, PLECS handles such non-sampled switching events using an interpolation scheme (see Interpolation of Non-Sampled Switching Events). This is not practical under real-time constraints because the computation time required for the interpolation is several times larger than that of an ordinary simulation step. By default, PLECS will therefore not generate code for models that contain naturally commutated devices.
You can override the default behavior and generate code for naturally commutated devices with a parameter setting as described in the following sections for PLECS Standalone and the PLECS Blockset. Non-sampled switching events will then be handled at the following simulation step. Note that this can reduce the accuracy or even lead to inconsistent conditions or state discontinuities in the model after switching.
As an example, consider the turn-off of a diode connected in series with an inductor. In general the zero-crossing of the inductor current will not occur exactly at a simulation step; it will be either positive or negative. If it is negative, the diode will turn off. Unless there is another path for the inductor current, the inductor state will become inconsistent and the program execution is aborted.
You can override this type of error and instruct PLECS to enforce consistent conditions. In the above example the inductor current would simple be reset to zero after the diode turn-off so as to obtain a consistent circuit state. Note, however, that this happens at the cost of a discontinuity of the inductor current which is not physically possible.
Unsupported Components
PLECS currently does not support code generation for the following components:
- Variable Inductor
- Variable Resistor with Variable Series Inductor
- Variable Resistor with Constant Series Inductor
- Variable Capacitor
- Variable Resistor with Variable Parallel Capacitor
- Variable Resistor with Constant Parallel Capacitor
- Brushless DC Machine
- Switched Reluctance Machine
Additionally, PLECS currently cannot generate code for components with a discrete sample time such as Zero Order Hold, Delay or Discrete Transfer Function.
Code Generation with PLECS Standalone
PLECS Standalone produces C code in an embedded format, generating entry point functions that must be called from a main application. The following functions are generated:
- void model_initialize(double time)
- This function should be called once at the beginning of a simulation to initialize the internal data structures and the start value of the global clock for components that depend on the absolute time.
- void model_step()
- This function should be called at every simulation step to advance the model by one step.
- void model_terminate()
- This function should be called at the end of a simulation to release resources that were acquired at the beginning of or during a simulation.
where the prefix model is replaced by a model-specific string.
The generated header and implementation files are placed in a folder model_codegen next to the model file.
Generating Code for a Model
To generate code for a complete model, choose Simulation parameters... from the Simulation menu and select the Code Generation page. This page only appears if you have a license for the PLECS Standalone Coder.
The two options Allow natural commutation and Suppress state inconsistencies configure the code generation for naturally commutated devices as described above (see Naturally Commutated Devices).
To generate code, click on the button Generate Code. Note that you need to choose the fixed-step Discrete solver on the Solver page. It is not possible to generate code for a model that uses a variable-step solver.
Code generation can also be initiated via the XML-RPC interface using the command
plecs.codegen('model')
plecs.codegen('model', 'outputDir')
If outputDir is provided, the generated files will be placed in this folder instead of the default folder.
Generating Code for a Subsystem
To enable code generation for an individual subsystem in a model, select the subsystem, then choose Subsystem settings... from the Edit menu or the context menu. In the Subsystem Settings dialog check the option Enable code generation. This option is only shown if you have a license for the PLECS Standalone Coder. Checking this option implicitly also checks the option Treat as atomic unit and unchecks the option Minimize occurrence of algebraic loops. For more information on these options see Virtual and Atomic Subsystems.
Note It is not possible to generate code for subsystems that have physical terminals.
Checking the option Enable code generation also enables the Code Generation page. This page allows you to configure the generated code. The parameter Discretization step size specifies the sample time used to discretize the model equations for the physical components in the subsystem. The two options Allow natural commutation and Suppress state inconsistencies configure the code generation for naturally commutated devices as described above (see Naturally Commutated Devices). The Input order and Output order fields allow you to specify the order, in which the input and output signals appear in the generated code. The parameter Base name allows you to specify a custom prefix used to name the interface functions of the generated code. By default, the base name is derived from the subsystem name.
To generate code, click on the button Generate Code. Code generation can also be initiated via the XML-RPC interface using the command
plecs.codegen('subsystemPath')
plecs.codegen('subsystemPath', 'outputDir')
If outputDir is provided, the generated files will be placed in this folder instead of the default folder.
Simulating a Subsystem in CodeGen Mode
Checking the option Enable code generation also enables the Simulation Mode parameter on the General page. When this parameter is set to Normal, which is the default, the subsystem is simulated like a normal subsystem. When the parameter is set to CodeGen, the generated code is compiled and linked to PLECS to be executed instead of the subsystem during a simulation.
In connection with the "Traces" feature of the scopes (see Adding Traces), this allows you to easily verify the fidelity of the generated code against a normal simulation.
Code Generation Options
The following table lists the parameters that can be used to customize the code generation process of PLECS Standalone.
Parameter | Description |
CodeGenTopologies | A struct specifying the combinations of switch states in each physical domain, for which code should be generated (see Limiting the Code Size). The default is [] meaning that PLECS will generate code for all possible combinations. |
CodeGenAllowNaturalCommutation | Specifies whether code should be generated for models containing naturally commutated devices (such as diodes or friction blocks). Possible values are on and off. The default is off. |
CodeGenSuppressStateInconsistencies | Specifies whether persistent state inconsistencies should be suppressed (on) or lead to a run-time error (off). The default is off. |
Code Generation with the PLECS Blockset
The PLECS Blockset fully integrates with Simulink Coder (formerly Real-Time Workshop) to generate C code for your simulation model. Whenever you start the build process from within Simulink, PLECS automatically generates the code for a circuit block and inserts it at the appropriate places into the code generated by Simulink Coder.
Note Scopes which are placed in PLECS schematics are not updated during a simulation using code generation. To view the simulation results all scopes must be placed in the Simulink model.
Code Generation Targets
PLECS can generate code for two different targets: the Rapid Simulation target (or RSim target) and the Real-Time target. These two targets are described in detail in the following two sections. The table below highlights the differences between the targets.
RSim Target | Real-Time Target | |
Purpose | Rapid, non-real-time simulations. | Real-time simulations. |
Technique | A compressed description of the circuit schematic is embedded in the code and interpreted at run time. | Signal and state-space equations are inlined as ANSI C code. |
Limitations | none | Limited support for naturally commutated devices and non-linear components. |
Inlining | Parameters may be declared tunable, so that they are evaluated at run time. | All parameters are inlined, i.e. evaluated at compile time and embedded into the generated code. |
Deployment | Requires distribution of the PLECS RSim module. | Generated code does not have external dependencies. |
Licensing | Requires a PLECS license at run time. | Requires a PLECS Blockset Coder license at build time. |
Real-Time Target
The Real-Time Target is selected by default when you generate code using any of the real-time targets of Simulink Coder. Code generation for the Real-Time target requires a separate license for the PLECS Coder for PLECS Blockset.
For a detailed description of the code generation process for physical systems and its current limitations see Code Generation for Physical Systems.
Rapid Simulation Target
The RSim target is selected by default when you run a simulation using Simulink's Rapid Accelerator mode or when you generate an executable using the RSim target or the S-Function target of Simulink Coder. The resulting code links against the RSim module of PLECS, a shared library which part of the standard installation.
Deploying Rapid Simulation Executables
To deploy the generated executable you need to copy the appropriate shared library file onto the target computer. The following table lists the library files for the supported platforms.
Parameter | Description |
Windows 32-bit | plecs/bin/win32/plecsrsim.dll |
Windows 64-bit | plecs/bin/win64/plecsrsim.dll |
Mac Intel 32-bit | plecs/bin/maci/libplecsrsim.dylib |
Mac Intel 64-bit | plecs/bin/maci64/libplecsrsim.dylib |
Linux 32-bit | plecs/bin/glnx86/libplecsrsim.so |
Linux 64-bit | plecs/bin/glnxa64/libplecsrsim.so |
Licensing Protocols for the PLECS RSim Module
The RSim module checks out a PLECS license for the duration of execution. It uses the environment variable PLEXIM_LICENSE_FILE to locate the license file. If the module is unable to check out a PLECS license, it issues an error message and stops the simulation.
Note The PLECS RSim module does not link against MATLAB. Therefore, it cannot accept license files that use MATLAB-based host IDs.
Tunable Circuit Parameters in Rapid Simulations
By default, PLECS evaluates the parameters of all circuit components at compile time and inlines them into the circuit description. However, for certain applications - such as rapid simulations on different parameter sets or parameterized S-Functions - it is desirable that the parameters be evaluated at simulation start instead. This can be achieved by declaring the circuit parameters tunable.
To declare circuit parameters tunable,
- Mask the PLECS Circuit block and define all parameters that you wish to keep tunable as mask variables. Mask variables can either be mask parameters (that appear in the parameter dialog) or variables defined in the mask initialization commands. For more information see Customizing the Circuit Block.
- On the Advanced pane of the PLECS simulation parameters, uncheck the option Inline circuit parameters for RSim target.
- Include the variable names in the list of tunable model parameters. Please see the Simulink Coder User's Guide for details.
Limitations on Tunable Circuit Parameters If you declare circuit parameters tunable, the RSim module uses its own parser to evaluate parameter expressions at simulation start; it currently cannot handle mask initialization commands. You will receive runtime errors if your circuit contains masked subsystems using mask initialization commands, or if a parameter expression contains a MATLAB function call.
Other limitations apply due to the way the Simulink Coder handles tunable parameters:
- Circuit parameters must be double-precision, 2-dimensional, non-sparse arrays.
- The first four characters of the parameter names must be unique.
Code Generation Options
The following table lists the parameters that can be used to customize the code generation process.
Parameter | Description |
RTWTarget | Specifies the code generation target. Possible values are auto, RSim and RealTime. The default is auto meaning that PLECS selects the target depending on the Simulink Coder target. |
RTWTopologies | A struct specifying the combinations of switch states in each physical domain, for which code should be generated for the Real-Time target (see Limiting the Code Size). The default is [] meaning that PLECS will generate code for all possible combinations. |
RTWAllowNaturalCommutation | Specifies for the Real-Time target whether code should be generated for circuits containing naturally commutated switches (such as diodes). Possible values are on and off. The default is off. |
RTWSuppressStateInconsistencies | Specifies for the Real-Time target whether persistent state inconsistencies should be suppressed (on) or lead to a run-time error (off). The default is off. |
RSimInlineCircuitParams | Specifies for the RSim target whether parameters should be evaluated at compile time and inlined into the code (on) or evaluated at run time (off). The default is on. |
With the exception of RSimInlineCircuitParams these parameters can currently only be set via the command line interface. For example, the command below enables the code-generation for a circuit with naturally commutated devices:
plecs('set', circuit, 'RTWAllowNaturalCommutation', 'on');
where circuit is the full Simulink path of the circuit block.