Main Content

Control Placement of Global Data Definitions and Declarations in Generated Files

The generated code can create standard, global structure variables whose fields represent the signal, state, and parameter data in a model. With storage classes, you can configure data to appear in the code as separate global variables or custom global structures. For information about the standard data structures, see How Generated Code Stores Internal Signal, State, and Parameter Data and How Generated Code Exchanges Data with an Environment. For information about storage classes, see Choose Storage Class for Controlling Data Representation in Generated Code.

You can control the file placement of the variable definitions and declarations. Use the information in the table.

GoalDetails and Techniques
Generate a variable that external code can use

Apply a storage class with exported data scope, such as ExportToFile. The generated code declares the variable in a file that your code can include (#include).

To generate an extern declaration in model.h, consider using the storage class ExportedGlobal.

Alternatively, to place the declaration in a file whose name you can specify, choose one of these techniques:

  • To aggregate multiple variable declarations into one or more specific header files by default, apply a storage class such as ExportToFile to a category of data by using the Code Mappings editor. As you add blocks and signals to the model, new data items are declared in the files that you specify.

  • To explicitly specify the placement for an individual data item, directly apply a storage class such as ExportToFile and specify a header file name by using the Header file property.

See Exchange Data Between External Calling Code and Generated Code.

Generate code that uses a variable defined by external code

Apply a storage class with imported data scope, such as ImportFromFile, to a data element in a model that represents the variable. Then, the generated code does not define the variable, but instead includes (#include) an external header file whose name you can specify. The generated algorithm (for example, the model step function) reads and writes to the variable.

Alternatively, if you do not have an external declaration header file or do not want the generated code to include a header file, apply the storage class ImportedExtern. Then, the generated code declares the variable in model_private.h.

See Exchange Data Between External Calling Code and Generated Code.

  • Reduce the size of a generated file by creating multiple smaller files

  • Organize data into different files to make generated code easier to understand

Depending on the setting of Configuration Parameters > File packaging format, generated files such as model.c and model_data.c can contain many definitions of global variables. Corresponding header files can contain many declarations.

  • To make model.c smaller, consider setting File packaging format to Modular or Compact (with separate data file). Then, the generated code defines the standard structures that represent tunable and constant parameter data in model_data.c instead of model.c.

  • To place different categories of data (for example, external parameters, block states, and internal signals) in specific files by default, use the Code Mappings editor. For each category of data, use a storage class such as ExportToFile and specify the property Header file. See Configure Default Code Generation for Data.

  • For precise control over the file placement of data, apply storage classes such as ExportToFile to individual data items. Use the properties of the storage class, such as Definition file and Header file, to specify file placement for each data item. For an example, see Definition and Declaration of Signal Data.

Combine multiple files into a single file

  • Consider setting the model configuration parameter File packaging format to Compact. Then, the code generator does not create the model_data.c file. Instead, the definitions of the standard structures that store tunable and constant parameter data appear in model.c.

  • When you apply a storage class such as ExportToFile to data elements, leave the properties Definition file and Header file blank, the default value. Also, set the model configuration parameter Data definition to Data defined in source file. Then, the data definitions appear in model.c with the definitions of other global data.

Separate data definitions from function definitions

By default, the generated file that defines the entry-point functions for a model or subsystem also defines the data for that model or subsystem. When you frequently make changes to data, especially initial values for tunable parameters, the changing source code files can impede verification and make change management more difficult. To separate the data from the functions:

  • Consider setting the model configuration parameter File packaging format to a value that results in the generation of the separate data file model_data.c. Then, the definitions of the standard structures that store tunable and constant parameter data appear in this file instead of in model.c.

  • Apply storage classes such as ExportToFile to data elements by using the Code Mappings editor. Use the properties of the storage class, such as Definition file and Header file, to specify file placement. For more information, see Configure Default Code Generation for Data and Organize Parameter Data into a Structure by Using Struct Storage Class.

Isolate data definitions in separate files for component-based, team-oriented model development

See Organize Data to Support Component-Based, Team-Oriented Model Development.

Aggregate definitions of variant control parameters (#define macros) into a single header file

As described in Compile Code Conditionally for Variations of Component Represented Using Variant Block, a variant control parameter is a parameter object such as Simulink.Parameter. You apply a storage class that makes the object appear in the generated code as a macro. To control the file placement, choose one of these techniques:

  • For each variant control parameter that uses the storage class Define, set the Header file property to the same value. To configure these objects in a list that you can search, sort, and filter, you can use the Model Data Editor Parameters tab. For an example, see Organize Variant Control Macros in Same Header File.

  • Create one or more storage classes that represent variant control parameters. In the Custom Storage Class Designer, you can set Header file to a value that applies to all of the variant control parameters that use the storage class. With this technique, you do not need to manually specify a header file for each variant control parameter. For more information, see Create Storage Classes by Using the Custom Storage Class Designer.

Organize Data to Support Component-Based, Team-Oriented Model Development

Depending on your model configuration, data definitions can appear aggregated in large generated files. In a system of components (subsystems or referenced models), you can separate and organize the data definitions into manageable, meaningful files based on the component hierarchy.

GoalTechnique

Establish ownership of global data by placing the data definitions with the code generated for specific components

When you divide a system into components by using referenced models and atomic subsystems, by default, global data is typically defined by the code generated for the top component in the hierarchy. Global data includes parameters, signals, and states to which you apply storage classes (see C Data Code Interface Configuration for Model Interface Elements).

Instead, you can place global data definitions with other components in the hierarchy. For an example involving referenced models, see Establish Data Ownership in a Model Hierarchy.

  • To place a data definition with the code generated for a referenced model, use a built-in storage class such as ExportToFile, or a storage class that you create in a package, and set the Owner property to the name of the referenced model.

    To use Owner in a model, you must select the model configuration parameter Use owner from data object for data definition placement. The default setting for this parameter, cleared, means the code generator ignores the setting that you specify for Owner.

    If only one referenced model uses a parameter object, consider storing the object in the model workspace of that model. Then, the code generated for that model defines the data. You do not need to specify an owner (Owner) for the object.

  • In an atomic subsystem, use a storage class such as ExportToFile and explicitly specify the name of the definition file by using the Definition file property. However, you cannot place the definition file with the source files that belong to the subsystem. Instead, the definition file that you specify appears in the folder generated for the model.

For an atomic subsystem, place the standard data structures for the subsystem with the subsystem code

By default, the standard data structures for an atomic subsystem appear as substructures of the data structures for the entire model.

To generate separate data structures for a subsystem, select the Function with separate data parameter in the subsystem block. Then, the subsystem data appear in separate structure variables that the subsystem code defines. See Generate Modular Function Code for Nonvirtual Subsystems.

Specify Default Placement

When you create data in a model by adding blocks and signal lines, by default, the data definitions appear in model.c. To specify a different default placement, use these tools and parameters:

  • The model configuration parameter File packaging format. The setting that you choose determines whether the code generator places the standard structures that store tunable and constant parameter data in model_data.c instead of model.c. See File packaging format.

  • The Code Mappings editor. For each category of model data, you can specify a default storage class, which controls file placement. For example, apply the storage class ExportToFile to a data category and, in the Property Inspector, use the DefinitionFile, HeaderFile, and Owner properties to control file placement.

  • The model configuration parameters Data definition and Data declaration. These configuration parameters specify the default file placement for data items that you apply storage classes to.

    • These configuration parameters do not affect data items that you apply these storage classes to:

      • ExportedGlobal

      • ImportedExtern

      • ImportedExternPointer

      • BitField

      • FileScope

      • Localizable

      • Struct

      • CompilerFlag

      In the Embedded Coder® Dictionary, the Header File value for unsupported storage classes is empty. You cannot specify default file placement for unsupported storage classes.

    • If you apply a storage class that explicitly specifies definition and declaration files for a data element, those specifications override the Data definition and Data declaration configuration parameters.

    For more information, see Data definition and Data declaration.

  • The subsystem block parameter Function with separate data. When you select this parameter, the standard structures that store the subsystem data, such as the DWork structure, appear as separate structure variables. By default, the variable definitions appear in the source file that defines the subsystem execution function. See Generate Modular Function Code for Nonvirtual Subsystems.

Override Default Placement for Individual Data Items

For an individual data item, to override the default file placement, use the Code Mappings editor to apply a storage class directly. For example, to make a data item appear in the generated code as a global variable, apply the storage class ExportToFile. Then, use the Definition file and Header file properties to control file placement. To apply storage classes directly, see Organize Parameter Data into a Structure by Using Struct Storage Class.

Prevent Name Clashes by Configuring Data Item as static

To apply the C keyword static to a global variable, which can help you avoid name clashes by limiting the scope of the variable name to the file that defines the variable, choose one of these techniques:

  • Apply the built-in storage class FileScope. For more information, see Choose Storage Class for Controlling Data Representation in Generated Code.

  • If FileScope does not satisfy your requirements, create your own storage class by using the Custom Storage Class Designer. In the Designer, set Data scope to File or Auto.

    • With File, the data element appears in the code as a static global variable.

    • With Auto, the code generator first attempts to represent the data element with a local variable in a function. If this attempt fails, the code generator uses a static global variable.

    For an example that shows how to create your own storage class by using the Designer, see Create and Apply Storage Class Defined in User-Defined Package.

You cannot apply static to the standard data structures such as the DWork structure.

To access static data, you can configure the generated code to include an interface such as an a2l (ASAP2) file. For more information, see Export ASAP2 File for Data Measurement and Calibration. To place the data in a specific memory location by including pragmas or other decorations in the generated code, create your own memory section and storage class. See Control Data and Function Placement in Memory by Inserting Pragmas.

Code Generation Impact of Storage Location for Parameter Objects

You can create a parameter object (such as Simulink.Parameter) in the base workspace, a model workspace, or a data dictionary. However, when you apply a storage class to the object, the location of the object can impact the file placement of the corresponding data definition in the generated code. See Code Generation Impact of Storage Location for Parameter Objects.

Specify Default #include Syntax for Data Header Files

To control the file placement of a data item, such as a signal line or block state, in the generated code, you can apply a storage class to the data item (see Organize Parameter Data into a Structure by Using Struct Storage Class). You then use the Header file property to specify the generated or external header file that contains the declaration of the data.

To reduce maintenance effort and data entry, when you specify Header file, you can omit delimiters (" or <>) and use only the file name. You can then control the default delimiters that the generated code uses for the corresponding #include directives. To use angle brackets by default, set Configuration Parameters > Code Generation > Code Placement > #include file delimiters to #include <header.h>.

Related Topics