Main Content

Generate Shared Utility Code

When to Generate Shared Utility Code

Blocks in a model can require common functionality to implement their algorithms. Consider modularizing this functionality into standalone support or helper functions. This approach can be more efficient than inlining the code for the functionality for each block instance. To decide about using a library or a shared utility, consider:

  • Packaging functions that can have multiple callers into a library when the functions are defined statically. That is, before you use the code generator to produce code for your model, the function source code exists in a file.

  • Packaging functions that can have multiple callers as shared utilities (produced during code generation) when the functions cannot be defined statically. For example, several model- and block-specific properties specify which functions are used and their behavior. Also, these properties determine type definitions (for example, typedef) in shared utility header files. The number of possible combinations of properties that determine unique behavior make it impractical to define statically the possible function files before code generation.

Configure Naming of Generated Functions

Configure a default naming rule for generated shared utility functions by using one of these methods.

ConfigurationAction
A new model or an existing model for which you have mapped default customization settings by using the Code Mappings Editor – C or code mappings programming interfaceIn the Embedded Coder Dictionary, define a function customization template that specifies a custom function naming rule. Then, in the Code Mappings editor or by using the code mappings programming interface, map the Shared utility function category to that template. For more information, see Configure Default C Code Generation for Categories of Data Elements and Functions.
A model created in a release earlier than R2018a and that has not been configured with the Code Mappings Editor – C or code mappings programming interfaceSet the model configuration parameter Shared utilities identifier format (CustomSymbolsStrUtil) to a custom function naming rule. For more information, see Identifier Format Control.

Once you use the Code Mappings Editor – C or code mappings programming interface to configure a model, setting model configuration parameter Shared utilities identifier format does not impact code generation. This setting is not applicable for models configured with these specifications.

System Target FileProgramming Language
ert.tlcC++
autosar.tlcC
autosar_adaptive.tlcC++

The naming rule for shared utility functions must include the conditional checksum token $C. To customize the length of the checksum that the code generator produces, use parameter Shared checksum length (SharedChecksumLength). Increasing the length of the checksum reduces the probability of clashes.

This example shows the customization of shared utility function names for C code generation.

  1. Open the example model ConfigurationInterface.

    openExample('ConfigurationInterface')

  2. Open the Embedded Coder app.

  3. Set model configuration parameter Shared code placement to Shared location.

  4. Open the Embedded Coder Dictionary. On the C Code tab, select Code Interface > Embedded Coder Dictionary.

  5. Select Function Customization Template and click Create to add a new function customization template.

  6. For the function customization template, specify these configurations:

    • Name: exSharedUtility

    • Function Naming Rule: mymodel_$N$C

      You can customize this format by using a string. You must include token $C.

  7. Open the Code Mappings editor. On the C Code tab, select Code Interface > Default Code Mappings.

  8. On the Function Defaults tab, for the Shared Utility category, configure Function Customization Template as exSharedUtility.

  9. Generate code and a code generation report.

  10. In the left navigation pane of the report, review the list of generated files for shared utilities under Shared files.

Control Placement of Shared Utility Code

Control placement of shared utility code with the model configuration parameter Shared code placement. The default option value is Auto. For this setting, the code generator places required code for fixed-point and other utilities in the model.c file, the model.cpp file, or a separate file in the build folder (for example, vdp_grt_rtw) if a model does not contain existing shared utility code or one of these blocks:

  • Model blocks

  • Simulink Function blocks

  • Function Caller blocks

  • Calls to Simulink Functions from Stateflow or MATLAB Function blocks

  • Stateflow graphical functions when you select parameter Export Chart Level Functions

If a model contains one or more of the preceding blocks, the code generator creates and uses a shared utilities folder within slprj. The naming convention for shared utility folders is slprj/target/_sharedutils. target is sim for simulations with Model blocks or the name of the system target file for code generation.

slprj/sim/_sharedutils      % folder used with simulation
slprj/grt/_sharedutils      % folder used with grt.tlc STF
slprj/ert/_sharedutils      % folder used with ert.tlc STF
slprj/mytarget/_sharedutils % folder used with mytarget.tlc STF

To force a model build to use the slprj folder for shared utility generation, even when the current model does not contain existing shared utility code or one of the preceding blocks, set parameter Shared code placement to Shared location. The code generator places utilities under the slprj folder rather than in the normal build folder. This setting is useful when you are manually combining code from several models, because it prevents symbol collisions between the models.

Control Placement of rtwtypes.h for Shared Utility Code

When the configuration parameter Data type replacement is set to Use coder typedefs, the generated rtwtypes.h header file provides fundamental type definitions, #define statements, and enumerations. For more information, see rtwtypes.h.

Control placement of rtwtypes.h file by selecting whether the build process uses the shared utilities folder. If the model build uses a shared utilities folder, the build process places rtwtypes.h in slprj/target/_sharedutils. Otherwise, the software places rtwtypes.h in model_target_rtw.

Adding a model to a model hierarchy or changing an existing model in the hierarchy can result in updates to the shared rtwtypes.h file during code generation. If updates occur, recompile and, depending on your development process, reverify previously generated code. To minimize updates to the rtwtypes.h file, make these model configuration parameter changes:

  • Select model configuration parameter Support: complex numbers even if the model does not currently use complex data types. Selecting this parameter protects against a future requirement to add support for complex data types when integrating code.

  • Clear parameter Support non-inlined S-functions. If you use noninlined S-functions in the model, this option generates an error.

Avoid Duplicate Header Files for Exported Data

Exported header files appear in the shared utility folder when:

  • You control the file placement of declarations for signals, parameters, and states by defining and applying storage classes.

  • The code generator places utility code in a shared location.

For example, you can specify a header file for data by using:

  • A storage class that you define in the Embedded Coder Dictionary and map to categories of model data in the Code Mappings Editor – C.

  • The Code Generation tab in a Signal Properties dialog box.

  • The HeaderFile property of a data object. Data objects are objects of the classes Simulink.Signal and Simulink.Parameter.

If you want the declaration to appear in the file model.h, it is a best practice to leave the header file name unspecified. By default, the code generator places data declarations in model.h.

If you specify model.h as the header file name, and if the code generator places utility code in a shared location, you cannot generate code from the model. The code generator cannot create the file model.h in both the model build folder and the shared utility folder.

Reduce Shared Utility Code Generation with Incremental Builds

You can specify that the model build generates C source files in a shared utilities folder. See Control Placement of Shared Utility Code. These files include C source files that contain function definitions and header files that contain macro definitions. For this discussion, the term functions means functions and macros.

Blocks within the same model and blocks in different models can use a shared function when you use model reference or when you build multiple standalone models from the same start build folder. The code generator produces the code for a given function only once for the block that first triggers code generation. As the product determines the requirement to generate function code for subsequent blocks, it performs a file existence check. If the file exists, the model build does not regenerate the function. The shared utility code mechanism requires that a given function and file name represent the same functional behavior regardless of which block or model generates the function. To satisfy this requirement:

  • Model properties that determine function behavior contribute to the shared utility checksum or determine the function and file name.

  • Block properties that determine the function behavior also determine the function and file name.

During compilation, makefile rules for the shared utilities folder select compilation of only new C files and incrementally archive the object file into the shared utility library, rtwshared.lib, or rtwshared.a. Incremental compilation also occurs.

Manage the Shared Utility Code Checksum

When you set the model configuration parameter Shared code placement to Shared location or when the model contains Model blocks, the code generator places shared code in the shared utilities folder. The build process generates a shared utilities checksum of the code generation configuration for the shared code.

During subsequent code generation, if the checksum file slprj/target/_sharedutils/checksummap.mat exists relative to the current folder, the code generator reads that file. The code generator verifies that the current model that you are building has configuration properties that match the checksum of properties from the shared utility model. If mismatches occur between the properties defined in checksummap.mat and the current model properties, you see an error. Use the error message to manage the checksum (for example, diagnose and resolve the configuration issues with the current model).

View the Shared Utility Checksum Hash Table

It is helpful to view the property values that contribute to the checksum. This example uses the LctStartTermActions model. To load the checksum.mat file into MATLAB® and view the targetInfoStruct that defines the checksum-related properties:

  1. Open the LctStartTermActions model. In the Command Window, type:

    openExample('LctStartTermActions')
  2. Build the model, which is set up to produce shared utilities.

    1. On the Apps tab, under Code Generation, click Simulink Coder.

    2. On the C Code tab, in the Generate Code section, click the Build button.

  3. Move to the _sharedutils folder created by the build process.

    cd slprj\grt\_sharedutils
  4. Load the checksummap.mat file into MATLAB.

    load checksummap
  5. Display the contents of hashTbl.targetInfoStruct and examine the checksum-related property values.

    hashTbl.targetInfoStruct

For this example, the Command Window displays hashTbl.targetInfoStruct for the shared utilities that you generated from the model:

ans = 

  struct with fields:

                         ShiftRightIntArith: 'on'
                     ProdShiftRightIntArith: 'on'
                                  Endianess: 'LittleEndian'
                              ProdEndianess: 'LittleEndian'
                                wordlengths: '8,16,32,32,64,32,64,64,64,64'
                            Prodwordlengths: '8,16,32,32,64,32,64,64,64,64'
                             TargetWordSize: '64'
                               ProdWordSize: '64'
                         TargetHWDeviceType: 'Custom Processor->Custom Processor'
                           ProdHWDeviceType: 'Custom Processor->Custom Processor'
                        TargetIntDivRoundTo: 'Zero'
                          ProdIntDivRoundTo: 'Zero'
          UseDivisionForNetSlopeComputation: 'on'
                          PurelyIntegerCode: 'off'
                          PortableWordSizes: 'off'
                     SupportNonInlinedSFcns: ''
                        RTWReplacementTypes: ''
                                  MaxIdInt8: 'MAX_int8_T'
                                  MinIdInt8: 'MIN_int8_T'
                                 MaxIdUint8: 'MAX_uint8_T'
                                 MaxIdInt16: 'MAX_int16_T'
                                 MinIdInt16: 'MIN_int16_T'
                                MaxIdUint16: 'MAX_uint16_T'
                                 MaxIdInt32: 'MAX_int32_T'
                                 MinIdInt32: 'MIN_int32_T'
                                MaxIdUint32: 'MAX_uint32_T'
                                 MaxIdInt64: 'MAX_int64_T'
                                 MinIdInt64: 'MIN_int64_T'
                                MaxIdUint64: 'MAX_uint64_T'
                              BooleanTrueId: 'true'
                             BooleanFalseId: 'false'
           TypeLimitIdReplacementHeaderFile: ''
                       SharedCodeRepository: ''
                                 TargetLang: 'C'
                              TargetLangStd: 'C89/C90 (ANSI)'
                      InstructionSetExtions: 'None'
                   PreserveExternInFcnDecls: 'on'
                    ImplementImageWithCVMat: 'off'
                    EnableSignedRightShifts: 'on'
                     EnableSignedLeftShifts: 'on'
                                    TflName: 'None'
                                TflCheckSum: [4.0787e+09 3.7630e+09 … ] (1×4 double)
                     UtilMemSecPreStatement: ''
                    UtilMemSecPostStatement: ''
                          UtilMemSecComment: ''
                       CodeCoverageChecksum: [3.6498e+09 78774415 … ] (1×4 double)
                 TargetLargestAtomicInteger: 'Char'
                   TargetLargestAtomicFloat: 'None'
                   ProdLargestAtomicInteger: 'Char'
                     ProdLargestAtomicFloat: 'None'
                               LongLongMode: 'on'
                           ProdLongLongMode: 'on'
                        DataTypeReplacement: 'CoderTypedefs'
    ExistingSharedCodeUsingClassicNonFinite: 0
                          HeaderGuardPrefix: ''
                              HardwareBoard: 'None'
                             toolchainOrTMF: 'Microsoft Visual C++ 2022 v17.0 | nmake (64-bit Windows)'

Relate the Shared Utility Checksum to Configuration Parameters

Examine the targetInfoStruct hash table from the shared utility model. Some key-value pairs relate directly to a model property. Other pairs relate to groups of properties.

The following table describes the key-value pairs.

Key NamesModel Properties
ShiftRightIntArithTargetShiftRightIntArith
ProdShiftRightIntArithProdShiftRightIntArith
EndianessTargetEndianess
ProdEndianessProdEndianess
wordlengthsTargetBitPerChar, TargetBitPerShort, TargetBitPerInt, TargetBitPerLong, TargetBitPerLongLong, TargetBitPerFloat, TargetBitPerDouble,TargetWordSize, TargetBitPerPointer, TargetBitPerSizeT, TargetBitPerPtrDiffT
ProdwordlengthsProdBitPerChar, ProdBitPerShort, ProdBitPerInt, ProdBitPerLong, ProdBitPerLongLong, ProdBitPerFloat, ProdBitPerDouble,ProdWordSize, ProdBitPerPointer, ProdBitPerSizeT, ProdBitPerPtrDiffT
TargetWordSizeTargetWordSize
ProdWordSizeProdWordSize
TargetHWDeviceTypeTargetHWDeviceType
ProdHWDeviceTypeProdHWDeviceType
TargetIntDivRoundToTargetIntDivRoundTo
ProdIntDivRoundToProdIntDivRoundTo
UseDivisionForNetSlopeComputationUseDivisionForNetSlopeComputation
PurelyIntegerCodePurelyIntegerCode
PortableWordSizesPortableWordSizes
SupportNonInlinedSFcnsSupportNonInlinedSFcns
RTWReplacementTypesEnableUserReplacementTypes, ReplacementTypes
MaxIdInt8MaxIdInt8
MinIdInt8MinIdInt8
MaxIdUint8MaxIdUint8
MaxIdInt16MaxIdInt16
MinIdInt16MinIdInt16
MaxIdUint16MaxIdUint16
MaxIdInt32MaxIdInt32
MinIdInt32MinIdInt32
MaxIdUint32MaxIdUint32
MaxIdInt64MaxIdInt64
MinIdInt64MinIdInt64
MaxIdUint64MaxIdUint64
BooleanTrueIdBooleanTrueId
BooleanFalseIdBooleanFalseId
TypeLimitIdReplacementHeaderFileTypeLimitIdReplacementHeaderFile
SharedCodeRepositoryReserved (internal use only)
TargetLangTargetLang
TargetLangStdTargetLangStandard
InstructionSetExtions InstructionSetExtensions
PreserveExternInFcnDeclsPreserveExternInFcnDecls
ImplementImageWithCVMatImplementImageWithCVMat
EnableSignedRightShiftsEnableSignedRightShifts
EnableSignedLeftShiftsEnableSignedLeftShifts
TflNameCodeReplacementLibrary
TflCheckSumReserved (internal use only)
UtilMemSecPreStatementMemSecFuncSharedUtil, MemSecPackage
UtilMemSecPostStatementMemSecFuncSharedUtil, MemSecPackage
UtilMemSecCommentMemSecFuncSharedUtil, MemSecPackage
CodeCoverageChecksumReserved (internal use only)
TargetLargestAtomicIntegerTargetLargestAtomicInteger
TargetLargestAtomicFloatTargetLargestAtomicFloat
ProdLargestAtomicIntegerProdLargestAtomicInteger
ProdLargestAtomicFloatProdLargestAtomicFloat
LongLongModeTargetLongLongMode
ProdLongLongModeProdLongLongMode
DataTypeReplacementDataTypeReplacement
ExistingSharedCodeUsingClassicNonFiniteReserved (internal use only)
HeaderGuardPrefixHeaderGuardPrefix
HardwareBoardHardwareBoard
toolchainOrTMF

Name of:

  • Toolchain if build process uses either a toolchain (Toolchain) or a template makefile that is associated with a toolchain.

  • Template makefile if build process uses template makefile (TemplateMakefile).

Generating Shared Utility Code for MATLAB Functions

The code generator does not produce shared utility code for either the main function or the subfunctions that you define inside a MATLAB Function block or a Stateflow® block.

If the block uses a MATLAB function that you define in a separate file, the code generator produces shared utility code for this function by default. However, if this function satisfies any of these conditions, the code generator marks the function as unshared and does not produce shared utility code:

  • Uses a persistent or global variable.

  • Calls a Simulink® function.

  • Is used in a block that has a function call output.

  • Refers to an input, output, or local variable of a Stateflow Chart (Stateflow).

  • Uses a bus or enumeration whose DataScope property is set to 'Auto' and HeaderFile property is empty.

  • Uses variable-size data.

  • Calls a custom C/C++ function using coder.ceval.

  • Calls another MATLAB function that the code generator already marked as unshared for any of the reasons listed here. This rule applies transitively. For example, suppose that foo1 calls foo2, which in turn calls foo3. Even if only the function foo3 uses a global or persistent variable, the code generator marks all three functions as unshared.

Related Topics