Main Content

Configure Signal Data for C Code Generation

Signal data consists of variables that store intermediate results in global memory as generated algorithmic code computes values of block output signals from block input signals, excluding signals that connect to root Inport and Outport blocks. Signal data is not signal lines in a model diagram. For example, in these cases, a signal line has no data representation in generated code:

  • Feeds a function-call port

  • Exits a message block, such as the Send block

  • Crosses subsystem boundaries with no computation blocks in between

When you configure a model for code generation, you choose the block input and output signals to make accessible in the generated code. For example, configure signal data to:

  • Make the data accessible for interaction and monitoring while the generated code executes.

  • Minimize the amount of data that is stored in memory.

  • Control where the code generator places signal data in memory.

  • Promote signal data to the model interface so that other components and systems can access that data.

  • Improve readability and traceability of the generated code.

The code generator checks for signal line configuration consistency. For example, the code generator verifies that the configuration of a signal line feeding into a subsystem matches the configuration of the signal line that exits the corresponding subsystem inport.

For code generation, examples show how to configure block signals for the model ConfigurationInterface. You can configure code mappings by using the Code Mappings Editor – C or code mappings programming interface (coder.mapping.api.CodeMapping).

Choose Code Configuration Options for Signals

Based on your code generation requirements, decide which block signals to represent in the generated code and how to represent the signal data. By default, signals in a model appear in generated code as fields of a global data structure named model_B. If you do not configure customizations, the code generator determines whether to eliminate or change the representation of signals in generated code for optimization purposes. If you configure customizations, decide:

  • Which signals to make accessible in the generated code

    You must add signals that you want to make accessible in the generated code to the model code mappings.

  • Whether to set up a default configuration

    If you need to gain access to a significant number (for example, more than 10) of signals , it is more efficient to configure the signals with default settings and then override those settings for special cases. If you need to gain access to a few signals that have unique source, naming, or placement requirements, consider configuring the signals individually.

  • How to declare and handle signal data in the generated code

    • As separate global variables

    • To read input data from global variables defined in external code

    • As calls to access functions. Requires Embedded Coder®

    For more information about these options, see Control Data and Function Interface in Generated Code.

Other considerations include whether to:

For a list of interface requirements that are relevant to signals with corresponding storage classes and storage class properties, see Choose Storage Class and Storage Class Properties for Data Stores.

Signal requirements for example model ConfigurationInterface are:

  • Configure signals that feed into and exit from the Switch block for code generation. Retain that signal data for monitoring while the generated code executes.

  • Represent signals as separate global variables.

  • Apply prefix dout_ to names of variables that represent signals.

Set the default representation of signals in the generated code as global variables that have the static type qualifier. Then, you configure the output signals of the two lookup table blocks to use the default storage class and unique code identifiers that include the required prefix dout_.

Add Signals to Model Code Mappings

Before you can configure a signal for code generation, add the signal to the model code mappings. Add the output signals for the two lookup table blocks to the model code mappings.

  1. Open example model ConfigurationInterface. Save a copy of the model to a writable location.

    Simulink model to use for learning how to configure signals for code generation.

  2. Open the Embedded Coder app.

  3. In the C Code tab, select Code Interface > Individual Element Code Mappings.

  4. In the Code Mappings editor, click the Signals/States tab. No signals are listed.

  5. Add signals to the code mappings. For the output signal of lookup table blocks Table1 and Table2:

    1. In the model, select the signal.

    2. Pause on the ellipsis that appears above or below the signal line to open the action bar. Click the Add Signal button.

      Action bar that appears over signal line when you pause on ellipsis.

    In the Code Mappings editor, the Signals node expands and lists the two signals that you added.

    Code Mappings editor with Signals/States tab selected and Signals tree node expanded, listing signals Table1:1 and Table2:1.

Configure Default Code Generation Settings for Signals

A default code generation setting for signals can reduce the effort of preparing a model for code generation, especially if a model has a significant number of signals that you want to monitor while the generated code executes. Choose configuration settings once, and the code generator applies those settings to signals across the model. Simulink® stores the default configuration as part of the model.

Consider configuring default code generation settings for model signals if your model uses multiple signals that do not have unique requirements or uses a shared Embedded Coder Dictionary.

This example shows how to use the Code Mappings Editor – C to set the default storage class for signals in the model ConfigurationInterface to FileScope. With that storage class setting, the code generator represents signal data in the generated code as global variables that have the static type qualifier.

  1. If you have not already done so, add signals to the model code mappings as described in Add Signals to Model Code Mappings.

  2. In the C Code tab, select Code Interface > Default Code Mappings.

  3. In the Code Mappings editor, on the Data Defaults tab, under Signals, select category Signals, states, and internal data. Set the default storage class to FileScope.

    Code Mappings editor with Data Defaults tab selected, Signals tree node expanded, and storage class for Signals, states, and internal data set to FileScope.

  4. Save the model.

Configure Code Generation Settings for Individual Signals

You can configure individual signals for code generation. For example, if a model has two signals that have unique code generation requirements, configure the signals individually. Or, if you configure default settings for signals, you can override those settings for specific signals.

If your model meets at least one of these criteria, consider configuring code generation settings for signals individually:

  • Uses multiple signals that have unique source, naming, or placement requirements.

  • Uses a few signals.

  • Has a default configuration for signals and you need to override the configuration for some specific signals.

This example shows how to use the Code Mappings editor to apply your default storage class setting to the output signals of lookup table blocks Table1 and Table2 in model ConfigurationInterface. The example also shows how configure code identifiers for those output signals. You can specify code generation identifiers, for example for integration, without modifying the model design.

  1. If you have not already done so, complete the steps in Configure Default Code Generation Settings for Signals.

  2. In the Code Mappings editor, click the Signals/States tab. Expand Signals. The editor lists the names or block port identifiers of signals that you added to the code mappings. If a signal resolves to a signal object, a resolve-to-signal-object icon appears to the right of the element name or port identifier. The storage class for each signal is set to Auto, which means that the code generator might eliminate or change the representation of relevant code for optimization purposes. If optimizations are not possible, the code generator applies the model default configuration. For this example, the model default configuration specifies storage class FileScope.

    • To avoid optimizations and force the code generator to use the default configuration, set the storage class to Model default.

    • To override the default configuration, specify the storage class that meets the code generation requirements for that signal.

  3. In the Code Mappings editor, select the output signals for blocks Table1 and Table2. Set the storage class to Model default: FileScope.

  4. Configure the code identifier for the output signals for the two lookup table blocks with names that include the prefix dout_. In the Code Mappings editor, select signal Table1:1. Click the Icon to configure additional code mapping properties icon and set the Identifier property to dout_Table1. For signal Table2:1, set Identifier to dout_Table2.

    Code Mappings editor with Signals/States tab selected, Signals tree node expanded, and storage class for signals Table1:1 and Table2:1 set to Model default: FileScope. Mapping Inspector shows Identifer property for signal Table1:1 set to dout_Table1.

  5. Save the model.

  6. Generate and view the code. For example, in ConfigurationInterface.c, find the data definitions for the lookup table data.

    static MYTYPE dout_Table1;
    static MYTYPE dout_Table2;
    

    Find where lookup table data is used in the step entry-point function.

    .
    .
    .
      dout_Table1 = look1_binlc(input2, ((const MYTYPE *)&(mp_Table1.BP[0])), ((
        const MYTYPE *)&(mp_Table1.Table[0])), 10U);
    
      if (mode) {
        output = (real_T)mp_K1 * dout_Table1;
      } else {
        output = dstate_X;
      }
    
      dout_Table2 = look2_binlc(input3, input4, ((const MYTYPE *)&(mp_Table2.BP1[0])),
        ((const MYTYPE *)&(mp_Table2.BP2[0])), ((const MYTYPE *)&(mp_Table2.Table[0])),
        ((const uint32_T *)&(rtwdemo_configi_Table2_maxIndex[0])), 3U);
    	
      dstate_X = dout_Table2;
    }
    

Remove Signals from Model Code Mappings

  1. In the C Code tab, select Code Interface > Individual Element Code Mappings.

  2. In the Code Mappings editor, click the Signals/States tab.

  3. For each signal that you want to remove:

    1. In the model, select the signal.

    2. Pause on the ellipsis that appears above or below the signal line to open the action bar. Click the Remove Signal button.

Configure Code Generation Settings for Signals Programmatically

To automate configuration of signals for code generation, use the programming interface for code mappings. For example, when creating custom block libraries or part of an application test environment, use the programming interface to automate data configuration.

This example shows how to use the programming interface to configure signals for model ConfigurationInterface. Set the default representation of signals in the generated code as global variables that have the static type qualifier. Then, configure the output signals of the two lookup table blocks to use the default storage class and unique code identifiers that include the required prefix dout_.

  1. Open the example model.

    openExample("ConfigurationInterface")
    
  2. Create object cm by calling function coder.mapping.api.get. The object stores the code generation configuration for data and functions for model ConfigurationInterface.

    cm = coder.mapping.api.get("ConfigurationInterface");
    
  3. Configure default settings for signals by calling function setDataDefault. For the arguments, specify these values:

    • The object returned by coder.mapping.api.get

    • InternalData for the default category

    • Property name StorageClass with property value FileScope

    setDataDefault(cm,"InternalData","StorageClass","FileScope");
    
  4. Verify your default configuration for signals. Issue a call to getDataDefault that specifies the object returned by coder.mapping.api.get and category InternalData. Specify the third argument as property StorageClass.

    getDataDefault(cm,"InternalData","StorageClass")
    
    ans =
    
        'FileScope'
    
  5. Get handles to the output ports for lookup table blocks Table1 and Table2. You use the port handles to add the signal data to the model code mappings.

    lut1D_ports = get_param("ConfigurationInterface/Table1","PortHandles");
    lut2D_ports = get_param("ConfigurationInterface/Table2","PortHandles");
    
    lut1D_outPort = lut1D_ports.Outport;
    lut2D_outPort = lut2D_ports.Outport;
    
  6. Add the output signals of the lookup table blocks to the model code mappings.

    addSignal(cm,[lut1D_outPort,lut2D_outPort]);
    
  7. Apply the default configuration for signals to the output signal of the lookup table blocks.

    By default, Simulink sets the storage class for individual signals to Auto. The code generator:

    • Determines whether to eliminate the data from the generated code for optimization purposes.

    • If retaining the data, determines how to efficiently represent the data in the generated code, taking into account default configuration settings.

    To control the configuration for a signal, call function setSignal.

    For each signal, issue a call to setSignal that specifies:

    • Object returned by coder.mapping.api.get

    • Port handle for the signal, lut1D_outport or lut2D_outport.

    • Default storage class previously set for signals by using property StorageClass and property value Model default.

    • Property Identifier and property value dout_Table1 or dout_Table2

    setSignal(cm,lut1D_outPort,"StorageClass","Model default","Identifier","dout_Table1");
    setSignal(cm,lut2D_outPort,"StorageClass","Model default","Identifier","dout_Table2");
    
  8. Verify your configuration settings by calling function getsignal. Specify the object returned by coder.mapping.api.get, the port handle for the signal (lut1D_outport or lut2D_outport), and property StorageClass or Identifier.

    getSignal(cm,lut1D_outPort,"StorageClass")
    
    ans =
    
        'Model default'
    
    getSignal(cm,lut1D_outPort,"Identifier")
    
    ans =
    
        'dout_Table1'
    
    getSignal(cm,lut2D_outPort,"StorageClass")
    
    ans =
    
        'Model default'
    
    getSignal(cm,lut2D_outPort,"Identifier")
    
    ans =
    
        'dout_Table2'
    
  9. Save the model.

  10. Generate and view the code. For example, in ConfigurationInterface.c, find the data definitions for the lookup table data.

    static MYTYPE dout_Table1;
    static MYTYPE dout_Table2;
    

    Find where lookup table data is used in the step entry-point function.

    .
    .
    .
      dout_Table1 = look1_binlc(input2, ((const MYTYPE *)&(mp_Table1.BP[0])), ((
        const MYTYPE *)&(mp_Table1.Table[0])), 10U);
    
      if (mode) {
        output = (real_T)mp_K1 * dout_Table1;
      } else {
        output = dstate_X;
      }
    
      dout_Table2 = look2_binlc(input3, input4, ((const MYTYPE *)&(mp_Table2.BP1[0])),
        ((const MYTYPE *)&(mp_Table2.BP2[0])), ((const MYTYPE *)&(mp_Table2.Table[0])),
        ((const uint32_T *)&(rtwdemo_configi_Table2_maxIndex[0])), 3U);
    	
      dstate_X = dout_Table2;
    }
    

Choose Storage Class and Storage Class Properties for Signals

Depending on your code generation requirements, choose from these storage classes to configure code generation for block signals. The list of storage classes is defined in the coder dictionary.

Tip

In the default mappings, signals are configured in the section Signals, states, and internal data.

RequirementsStorage Class for Default MappingsStorage Class for Individual Mappings
Enable optimizations, potentially generating more efficient code. Auto
For data elements that cannot be optimized, represent data as a field of a standard data structure.Default 
Prevent optimizations from eliminating storage for a data element and use the default storage class for the data element category. Model Default
When using a shared coder dictionary, select the dictionary default for data elements that you do not want the code generator to optimize.Dictionary Default 
Generate a structure that stores Boolean, fixed-point, or integer data in named bitfields. Bitfield (Individual mapping only)
Generate a global variable definition and declaration that have the volatile type qualifier.Volatile (See Const, Volatile, and ConstVolatile)Volatile (See Const, Volatile, and ConstVolatile)
Generate a global variable definition and declaration.ExportedGlobalExportedGlobal
Generate a global variable definition and declaration to a specified file.ExportToFileExportToFile
Generate a global variable definition and declaration that have the static type qualifier.FileScopeFileScope
Generate code that interacts with data by calling your custom accessor functions.GetSetGetSet
Generate code that reads from and writes to a global variable or global variable pointer defined by your external code.ImportedExtern, ImportedExternPointerImportedExtern, ImportedExternPointer
Generate code that reads from and writes to a global variable defined by your external header file.ImportFromFileImportFromFile
Generate variables that are local to functions.LocalizableLocalizable
Generate a global structure that has a name, which you can specify. Struct
Generate a global variable that enables buffer reuse. Reusable
Generate variables for single-instance data and generate structures for multi-instance data.MultiInstanceMultiInstance

The list of available storage classes might include other project-specific storage classes defined in an Embedded Coder Dictionary. If you have special requirements that are not met by the listed storage classes and you have Embedded Coder software, you can define a storage class. See Define Service Interfaces, Storage Classes, Memory Sections, and Function Templates for Software Architecture.

For an individual signal, use the Identifier storage class property to configure a name for the variable representing the signal in the generated code. If you leave the Identifier property blank, the code generator uses the signal label. If the signal label is empty, the code generator uses the name of the block that outputs the signal.

With Embedded Coder, depending on the storage class that you choose, you can also configure these properties.

PropertyDescriptionRelevant Storage Classes
DefinitionFileSource definition file that contains definitions for global data, which is read by the signal and external codeExportToFile and Volatile
GetFunctionSignal appears in the generated code as a call to a specified get functionGetSet
HeaderFileSource header file that contains declarations for global data, which is read by the signal and external codeExportToFile, GetSet, ImportFromFile, and Volatile
Memory Section (default signal configuration only)Memory section that contains data read by the signalDefault
OwnerCode generator places the definition for signals in the code generated for one of multiple models in a model hierarchy that share definitions. You must select the model configuration parameter Use owner from data object for data definition placement. See Control Placement of Global Data Definitions and Declarations in Generated Files.ExportToFile and Volatile
PreserveDimensionsCode generator preserves dimensions of signal data that is represented in generated code as a multidimensional array. You must set model configuration parameter Array layout to Row-major. See Preserve Dimensions of Multidimensional Arrays in Generated Code.ExportToFile, FileScope, GetSet, ImportFromFile, Localizable and Volatile
SetFunctionSignal appears in the generated code as a call to a specified set function.GetSet
StructNameName for structure in the generated code for signal.BitField and Struct

See Also

|

Related Topics