17. Reactis for C Plugin#

In Simulink there exist several options for calling existing C code from a model:

  • S-Function blocks

  • Calling custom code via C Caller blocks

  • Calling custom code from C action language Stateflow charts

  • Adding C code via C Function blocks

For S-Functions, a .mex file is created within Simulink by combining the user’s C code with some wrapper functions required by Simulink and compiling the resulting code using the “mex” compiler. This process can be made simpler by using a S-Function Builder block. The result is a .mexw32 or .mexw64 file which can then be inserted into the model via a S-Function block. The base Reactis product supports such S-Function blocks as long as they adhere to the restrictions defined in the S-Functions section.

To call C code from a Stateflow chart or via a Simulink C Caller block, the C code must be attached to the model in the Simulation Target tab of the model’s Configuration Parameters dialog within Simulink. Any function defined within such code (hereafter called “custom code”) can be called either from within a Stateflow chart or a C Caller block in Simulink. Reactis supports calling custom code by either of the two means.

C Function blocks are currently not supported in Reactis.

While the base Reactis product supports S-Functions and custom code, they are treated as black boxes. Models containing such C code can be processed, but the C source code is inaccessible. Hence, there is no way to perform basic debugging operations such as single-stepping, viewing variable values, setting breakpoints, or browsing the source code during simulation. Furthermore, targets cannot be created within the C source code when generating tests. The Reactis for C Plugin integrates seamlessly with Reactis to offer white-box testing and validation of the C-code portions of models (S-Functions and custom code). Together, Reactis and Reactis for C Plugin automate the generation of test data from, and validation of models constructed with Simulink, Stateflow, and C code.

A separate license is required to use the Reactis for C Plugin. If your organization does not yet own such a license, please contact sales@reactive-systems.com to inquire about purchase options or to obtain a demo license for the product. The Reactis for C Plugin requires base Reactis to run.

17.1. Quick Start#

  1. In the main Reactis window, select File > Global Settings… and then display the Reactis for C tab. Make sure the Enable white-box analysis of C code check-box is selected.

  2. To subject an S-Function to white-box analysis, do the following:

    1. Right-click on the S-Function in the main Reactis panel and select Assign RSM File

    2. Accept the default file name

    3. Click Yes to create a new .rsm file

    4. Add the C source files that implement the S-Function using the dialog.

  3. Custom code will be processed automatically when the Reactis for C Plugin is enabled. No .rsm file is necessary.

  4. Navigate to an S-Function in the hierarchy panel to display the C code for the S-Function. Custom code will be listed at the bottom of the hierarchy panel in the C Libraries section in a subsection called Custom Code.

  5. The C code can be observed from Simulator and targets within the C code will be used by Tester to generate test suites that aim to maximize coverage of the C code.

  6. Selecting Edit > C Code will bring up the C code tab in the Info File Editor. This dialog displays the locations of all C components in the model. From here .rsm files can be added, edited or removed by right-clicking. See the Configuring Reactis for C section for more details.

17.2. Configuring Reactis for C#

17.2.1. Global Settings#

_images/rfcSettingsA.png

Fig. 17.1 The Global Settings dialog with Reactis for C selected.#

Figure 17.1 shows the Reactis for C Plugin tab of the Reactis Global Settings dialog that lets you configure some aspects of the Reactis for C Plugin. The purpose of each dialog element is as follows:

1. Enable white-box analysis of C code.

Enable or disable the Reactis for C Plugin.

2. Display line numbers.

Toggle the display of line numbers in the main Reactis panel when displaying C source files. The Background Color button allows you to select the background color of screen region where the line numbers are displayed.

3. Display line grid.

Toggle the highlighting of every other line a different color. The Background Color button allows you to select which color is used.

4. Highlight comments.

Toggle the highlighting of comments within C source code. The Text Color button allows you to select the color of comment text.

5. Highlight inactive code.

Toggle the highlighting of code which has been disabled by preprocessor directives such as #ifdef. The Text Color button allows you to select the color of inactive code text.

6. Source File Editor.

This allows you to specify an external editor that can be launched from Reactis to edit C source files.

17.2.2. Model-Specific Settings#

17.2.2.1. Error Checking Pane#

_images/rsifeErrChkCPlugin.png

Fig. 17.2 The Error Checking pane of the Reactis Info File Editor with the C code settings shown.#

Figure 17.2 shows the model-specific settings for C code. The effect of each of these settings is explained below.

1. On signed integer overflow.

This item determines the behavior of the C-Plugin when overflow occurs during a signed integer computation. The effect of integer overflows outside of the C-Plugin are not affected. There are three possible settings:

Wrap over.

Emulate typical C runtime behavior and accept the hardware-produced result.

Produce warning.

Emulate typical C runtime behavior and accept the hardware-produced result, but also generate a warning.

Produce error.

Stop execution and generate an error message.

Integer overflows are discussed in more detail in the Integer Overflows section.

2. On unsigned integer overflow.

This item determines the behavior of the C-Plugin when overflow occurs during a signed integer computation. The effect of integer overflows outside of the C-Plugin are not affected. There are three possible settings:

Wrap over.

Emulate typical C runtime behavior and accept the hardware-produced result.

Produce warning.

Emulate typical C runtime behavior and accept the hardware-produced result, but also generate a warning.

Produce error.

Stop execution and generate an error message.

Note that C specifies that unsigned integer calculations should wrap around when a result is too large to fit, and many programs are designed with this behavior in mind.

3. On overflow during conversion from unsigned to signed integer.

This item determines the behavior of the C-Plugin when an overflow occurs while converting an unsigned integer to a signed integer. There are four possible settings:

Wrap over.

Emulate typical C runtime behavior and accept the hardware-produced result.

Produce warning.

Emulate typical C runtime behavior and accept the hardware-produced result, but also generate a warning.

Produce error.

Stop execution and generate an error message.

Inherit from “On signed integer overflow.”

Behave according to the setting of On signed integer overflow.

Integer conversions are discussed in more detail in the Integer Overflows section.

4. On overflow during conversion from floating-point to integer.

This item determines the behavior of the C-Plugin when an overflow occurs while converting a floating-point value to integer. There are four possible settings:

Wrap over.

Emulate typical C runtime behavior and accept the hardware-produced result.

Produce warning.

Emulate typical C runtime behavior and accept the hardware-produced result, but also generate a warning.

Produce error.

Stop execution and generate an error message.

Inherit from “On signed integer overflow.”

Behave according to the setting of On signed integer overflow (the previous setting).

Integer conversions are discussed in more detail in the Integer Overflows section.

5. When detecting Inf or NaN values.

This setting determines what action is taken when one of the values NaN, +inf, or -inf is produced by an expression whose input values do not include NaN, +inf, or -inf. Possible settings are:

No action.

Ignore NaN and infinite values and allow execution to continue.

Produce warning.

Generate a warning message and allow execution to continue.

Produce error.

Stop execution and generate an error message.

Inherit from “When detecting Inf or NaN values.”

Behave according to the setting of When detecting Inf or NaN values in the Simulink and Stateflow section of this pane.

6. When detecting subnormal floating-point values.

This setting determines what action is taken when a subnormal floating-point value is produced by an expression whose input values are not subnormal. Possible settings are:

No action.

Ignore subnormal values and allow execution to continue.

Produce warning.

Generate a warning message and allow execution to continue.

Produce error.

Stop execution and generate an error message.

Flush to zero.

Replace the subnormal value with zero and continue simulation or test-generation.

7. On invalid pointer creation.

This item determines what happens when a pointer expression yields an invalid address. There are three possible settings:

No action.

Ignore the invalid pointer. An error will occur if the pointer is used to access memory (which might never happen).

Produce warning.

Generate a warning message and allow execution to continue.

Produce error.

Stop execution and generate an error message.

Details on the use of this option are provided in the Invalid Pointer Creation section.

8. When an empty struct/union type is created.

This settings determines what happens when a struct or union type is defined which does not have any members. There are three possible settings:

No action.

Ignore the empty structure type. Errors may occur if variables of the empty type are used at runtime.

Produce warning.

Generate a warning message and allow execution to continue.

Produce error.

Stop execution and generate an error message.

9. When an undefined function is called.

This settings determines what happens when a function which has been declared but not defined is called. There are two possible settings:

Return zero.

Act as if the function has no side-effects and returns a value of zero. This allows unit testing to be done without generating stub code for missing functions.

Produce error.

Stop execution and generate an error message.

10. When an extern variable is undefined.

This setting determines what happens when an extern variable is declared but never defined. There are three possible settings:

Initialize to zero.

Define the variable with an initial value of zero.

Initialize to zero and produce warning.

Define the variable with an initial value of zero, but also generate a warning.

Produce error.

Stop execution and generate an error message.

  1. Infinite loop timeout (seconds.) : Maximum time for an S-function or C custom code to complete. If the computation exceeds this limit, Reactis assumes there is an infinite loop and the simulation is then terminated and an error message printed. A value of zero disables the timeout.

17.2.2.2. Coverage Metrics Pane#

_images/rsifeCMetrics.png

Fig. 17.3 C-Specific coverage metrics.#

Figure 17.3 shows the C-specific coverage metrics settings within the Coverage Metrics pane of the Info File Editor. There are four settings:

1. C Statements

Enables or disables tracking of the C Statement coverage metric.

2. C Functions

Enables or disables tracking of the C Function coverage metric.

3. C Function Calls

Enables or disables tracking of the C Function Call coverage metric.

4. Decision metric

This setting determines which expressions in a C program are counted as decisions for tracking decision, condition, MC/DC, and MCC coverage. There are three options:

Expressions which control if/while/for statements.

Expressions which control if/while/for statements or the ? operator.

All non-trivial Boolean statements except static initializers.

All of the above metrics are explained in the C Code Coverage Metrics section.

17.2.2.3. C Code Pane#

Reactis for C settings are also available in the C Code pane. The pane also displays a list of locations in the current model that reference C code (S-Functions and custom code) and gives you the ability to configure associated .rsm files.

_images/rfcCCodetab.png

Fig. 17.4 Viewing list of C Code components in a model using the C Code pane of the Info File Editor.#

Each of the window items labeled in Figure 17.4 is interpreted and used as follows:

  1. S-Function source code coverage tracking. This menu item configures the setting for tracking coverage within the C code in S-Functions. This setting may be overridden for an individual S-Function within the .rsm file for the S-Function. The supported settings are:

    Off.

    Turn off coverage tracking within S-Functions.

    Cumulative.

    When there are multiple instances of the same S-Function in a model, track coverage cumulatively for all instances.

    Separate.

    When there are multiple instances of the same S-Function in a model, track coverage separately for the instances.

  2. Create and use cache files for C code. In order to analyze C code, the Reactis for C Plugin must convert the source file into a Reactis object file (.rso file). Enabling this feature causes .rso files to be stored on disk (in the folder where the C code resides). Subsequently, a C source file will only be recompiled if the C source file is modified, or if a new version of Reactis is installed.

  3. Promote ’float’ values to ’double’ to reduce round-off error. When checked, single-precision floating-point values will always be converted to double-precision prior to any calculation, which reduces round-off error in some cases. For strict C99 compliance, this should be disabled (not checked).

  4. Type. This indicates the type of C code used in the model. These types are described in the S-Function C Code section and the Custom C Code section.

  5. S-Function Name. This gives the name of the S-Function used, where applicable. (As discussed in the S-Function C Code section and the Custom C Code section, S-Function Libraries, custom code, and custom C code libraries do not have associated S-Function names).

  6. RSM File. This is the Reactis Make file (.rsm) that describes the necessary C files, includes, libraries, search paths and defines (as described in the S-Function C Code section).

  7. Location. This is the path location of the C code instance. If the type is custom code, it can be accessed from any Stateflow chart or Simulink C Caller block in the model, so here it is labeled ’global’.

By right-clicking on a row of this dialog, you can bring up a menu to add, edit, or remove .rsm files. These functions are the same ones presented when you right-click on an .rsm file in the model hierarchy panel.

Double-clicking on any line with a named S-Function will cause the Reactis main window to jump to that location in the model hierarchy, and briefly highlight that system. Double-clicking on a line whose location is ’global’ will only highlight the C code library in the hierarchy panel.

Clicking on each column heading will sort the rows alphabetically according to that column. In the example, some S-Function name and .rsm file columns have “n/a” (not applicable) in various locations. As explained in the Custom C Code section, custom code does not have an associated S-Function, nor is an .rsm file required. Libraries in custom code or S-Functions require an .rsm file, but do not have separate S-Functions.

17.3. S-Function C Code#

Simulink does not require you to specify the C source files that implement an S-Function; instead only a name is given. For white-box testing, the Reactis for C Plugin requires the C source files that implement an S-Function as well as the source files for any libraries referenced by the S-Function. Since the .slx file does not include this information, the Reactis for C Plugin has a mechanism for listing the C source files which comprise an S-Function. This mechanism is described in the rest of this section.

The collection of C source files that implement an S-Function is specified using a Reactis Make File (.rsm file), which is created and modified by the editor shown in Figure 17.5, Figure 17.7, and Figure 17.8. An .rsm file is created to specify how the Reactis for C Plugin should compile the S-Function. Additionally, a separate .rsm file is constructed for each library referenced by the S-Function. The .rsm files for the S-Function and any libraries referenced by the S-Function are defined in the same way. In the following discussion we denote the library compiled from an .rsm file as the library under construction (LUC). The .rsm file editor consists of 5 panes, each of which is described in the following subsections.

_images/rsmEditor1.png

Fig. 17.5 The (a) Source Files and (b) Include Search Path panes of the .rsm file editor.#

17.3.1. Source Files#

Figure 17.5(a) shows the Source Files pane of the .rsm file editor, which lists the C source files which implement the LUC. The labeled items in Figure 17.5(a) are used as follows:

  1. This button is used to add one or more source files to the LUC (see the Adding Source Files section).

  2. This button converts all currently selected source files to relative path format.

  3. This button converts all currently selected source files to absolute path format.

  4. This button removes all currently selected source files from the LUC.

  5. These buttons let you reorder items in the list.

  6. This button opens the help dialog.

  7. This button generates stub source code for missing functions and variables.

  8. This button builds the LUC.

  9. This button closes the .rsm file editor and saves any pending modifications.

  10. This button closes the .rsm file editor without saving any pending modifications.

17.3.1.1. Adding Source Files#

_images/batchAddSourceFiles.png

Fig. 17.6 Adding a batch of source files in the .rsm file editor.#

When adding source files to an .rsm file, you may choose to either (1) enter the name of a file directly, (2) locate the file by browsing the filesystem, or (3) use the batch add facility, as shown in Figure 17.6. The labeled items in Figure 17.6 are used as follows:

  1. This button opens the Select All Source Files in Folder dialog.

  2. The directory containing the source files is entered here.

  3. This button opens a browser dialog which is used to select the directory containing the source files (item 2).

  4. When checked, only those source files which match one of the file selection patterns (item 5) will be selected.

  5. File selection patterns are entered here. Within a pattern, asterisk (*) matches any (possibly empty) sequence of characters and semicolon (;) separates patterns. A filename is a match if it matches any of the listed patterns. For example, the pattern sequence a*.c;b*.c will select any filename which starts with a or b and has extension .c.

  6. When checked, subfolders will be searched for matching files.

  7. When checked, subfolders which match one of the directory exclusion patterns (item 8) will not be searched.

  8. Directory exclusion patterns are entered here. Within a pattern, asterisk (*) matches any (possibly empty) sequence of characters and semicolon (;) separates patterns. A directory is excluded if it matches any of the listed patterns. For example, the pattern sequence .*;slprj will exclude any directory which starts with a period or is named slprj.

17.3.2. Include Search Path#

Figure 17.5(b) shows the Include Search Path pane of the .rsm file editor, which lists the directories to be searched when processing a #include directive. The labeled items in Figure 17.5(b) are used as follows:

  1. This button is used to add one or more directories to the LUC.

  2. This button converts all currently selected directories to relative path format.

  3. This button converts all currently selected directories to absolute path format.

  4. This button removes all currently selected directories from the LUC.

  5. These buttons are used to move the currently selected directories up or down in the list. The list is searched from top to bottom when processing a #include directive.

  6. This button opens the help dialog.

  7. This button generates stub source code for missing functions and variables.

  8. This button builds the LUC.

  9. This button closes the .rsm file editor and saves any pending modifications.

  10. This button closes the .rsm file editor without saving any pending modifications.

_images/rsmEditor2.png

Fig. 17.7 The (a) Libraries and (b) Defines panes of the .rsm file editor.#

17.3.3. Libraries#

Figure 17.7(a) shows the Libraries pane of the .rsm file editor, which lists the libraries used by the LUC. The labeled items in Figure 17.7(a) are used as follows:

  1. This button is used to add one or more libraries to the LUC.

  2. This button opens the currently selected library in a new instance of the .rsm file editor. The current editor instance is suspended until the new instance of the editor is closed.

  3. This button converts all currently selected libraries to relative path format.

  4. This button converts all currently selected libraries to absolute path format.

  5. This button removes all currently selected libraries from the LUC.

  6. This button opens the help dialog.

  7. This button generates stub source code for missing functions and variables.

  8. This button builds the LUC.

  9. This button closes the .rsm file editor and saves any pending modifications.

  10. This button closes the .rsm file editor without saving any pending modifications.

17.3.4. Defines#

Figure 17.7(b) shows the Defines pane of the .rsm file editor, which lists the macro definitions which are to be defined at the start of compilation of the LUC. Macros are defined using expressions of the form:

  • name=value, in which case instances of the identifier name will be replaced by value during preprocessing, or

  • name, in which case name will be replaced by the literal 1 during preprocessing.

There is no mechanism provided to define macros which accept arguments or use macro operators such as stringification or token catenation. This is similar to the way the -D option works on most C compilers.

The labeled items in Figure 17.7b) are used as follows:

  1. This button is used to add one or more macro definitions to the LUC.

  2. This button opens a editor from which the currently selected macro definition can be changed.

  3. This button removes all currently selected macro definitions from the LUC.

  4. This button opens the help dialog.

  5. This button generates stub source code for missing functions and variables.

  6. This button builds the LUC.

  7. This button closes the .rsm file editor and saves any pending modifications.

  8. This button closes the .rsm file editor without saving any pending modifications.

_images/rsmEditor3.png

Fig. 17.8 The General pane of the .rsm file editor.#

17.3.5. General#

Figure 17.8 shows the General pane of the .rsm file editor, which contains a few general settings for the LUC. The labeled items in Figure 17.8 are used as follows:

  1. This button makes the LUC a static library. Static library is the default and recommended setting for libraries. This setting can only be changed when the library is first created.

  2. This button makes the LUC a dynamic library.

  3. If (2) is selected, this checkbox makes the pointers used to implement dynamic linking visible, and may be useful in cases where code has been written that directly accesses the pointers to library objects.

  4. If (3) is selected, the prefix used for dynamic library pointers will appear here and can be edited if desired.

  5. This pulldown menu determines the coverage tracking for the library. The possible choices are:

    Inherited.

    Inherit the setting from the S-Function source code coverage tracking setting in the C Code pane of the Reactis Info File Editor. Note that the Inherited option is only available for S-Function .rsm files.

    Off.

    Turn off coverage tracking within the LUC.

    Cumulative.

    When there are multiple instances of the LUC in a model, track coverage cumulatively for all instances.

    Separate.

    When there are multiple instances of the LUC in a model, track coverage separately for the instances. Note that the Separate option is only available for S-Function .rsm files.

  6. This button opens the help dialog.

  7. This button generates stub source code for missing functions and variables.

  8. This button builds the LUC.

  9. This button closes the .rsm file editor and saves any pending modifications.

  10. This button closes the .rsm file editor without saving any pending modifications.

17.3.6. Pathnames#

The path to each source file or library can be either relative or absolute. The location of a source file whose path is relative is determined by appending the relative path to the directory containing the .rsm file. For example, if the .rsm file C:\models\cruise\cruise.rsm references the source file ..\csrc\ramp.c, the absolute path to ramp.c will be C:\models\csrc\ramp.c. For convenience, the .rsm file editor provides buttons for converting paths from relative to absolute form, and vice-versa. To use one of these buttons, first select a source file or library by clicking on it, and then click on either the Relative or Absolute button to the right of the window containing the source file name or library name.

17.3.7. S-Function Requirements#

All source code (for both an S-Function and any referenced libraries) must be available. In addition, all code must satisfy the requirements listed in the S-Functions section.

17.4. Custom C Code#

_images/rfcModelWithCustomCCode.png

Fig. 17.9 A model containing Custom C Code before an .rsm file has been specified for ctest10_code_lib.lib.#

The Reactis for C Plugin will automatically determine the custom C Code files being called from Stateflow charts or Simulink C Caller blocks. This is possible because Simulink requires you to specify the C source files in the Simulation Target dialog [1] and stores the names of the files in the .slx file for a model. The Reactis for C Plugin automatically processes any custom code files. User input is only required in cases where custom code links to external libraries.

When a model is opened, the custom code files will be listed at the bottom of the Reactis hierarchy panel in the C Libraries section, subsection Custom Code. This is illustrated in Figure 17.9. In this case, C source file ctest10_code.c and library ctest10_code_lib.lib were added to the model in Simulink’s Simulation Target options dialog. The C source file and library are shown by Reactis in the tree of model components. Note the error icon next to ctest10_code_lib.lib. This icon indicates that user input is required to tell the Reactis for C Plugin what sources belong to the library.

_images/rfcMoreInfoMessage.png

Fig. 17.10 The Reactis for C Plugin requesting information about the source code used to compile a custom code library.#

After selecting ctest10_code_lib.lib, the message shown in Figure 17.10 is displayed. This message indicates that it will be necessary to create an .rsm file because the .slx file does not list the sources used to build ctest10_code_lib.lib. To specify the sources, right-click on the library model name in the hierarchy panel (in this case ctest10_code_lib.lib) and select Assign RSM File. A dialog window similar to the one in Figure 17.11 will appear. The process of creating the .rsm file is nearly the same as the process for creating S-Function .rsm files discussed in the S-Function C Code section. The only two differences are (1) that the editor window does not contain a library section, and (2) there is no coverage selection dialog. No coverage selection dialog is presented because coverage data in custom code called from Stateflow charts or Simulink C Caller blocks is always collected cumulatively.

_images/rfcLibMakefileEditor.png

Fig. 17.11 Creating an .rsm file for a library used by custom code.#

17.4.1. Custom C Code Requirements#

The Reactis for C Plugin supports analysis of custom code for which all C source code is available. The source files need not necessarily reside in the same directory as the model. Reactis will automatically search the directories in the Reactis path if a custom code source file or library is not found in the model directory. This behavior emulates the behavior of MATLAB. Regardless of what directory a library is found in, the .rsm file editor will start in the model directory when assigning the .rsm file associated with the library. If the .rsm file does not yet exist, the file system tree displayed as part of the open dialog window can be used to select a directory other than the model directory in which to create the .rsm file. For example, it could be desirable to create the .rsm file for a library which shared between models in the directory containing the source files used to build the library.

17.5. C Code Coverage Metrics#

Reactis uses a number of different coverage metrics to measure how thoroughly a test or set of tests exercises a model. In general, coverage metrics record how many of a given class of coverage targets (model features such as Stateflow states, C program statements, etc.) have been executed at least once. Coverage metrics may be visualized using Simulator and are central to test generation and model validation using Tester and Validator.

Chapter 6 describes the coverage metrics that are tracked within the Simulink and Stateflow portions of models. Those metrics include some which are specific to Simulink, some which appear only in Stateflow, and others which are generic and can appear in either Simulink or Stateflow. Three of the generic metrics are also tracked in the C code portions of models by the Reactis for C Plugin. These are decision coverage, condition coverage, and modified condition / decision coverage (MC/DC).

Decision coverage tracks whether each decision in a program has evaluated to both true and false. The program elements that Reactis for C identifies as decisions can be configured via the Decision metric setting in the C Code tab of the Info File Editor (item 4 in Figure 17.3) . There are three possible Decision metric settings:

Expressions which control if/while/for statements.

Only expressions which appear within the parentheses following the if, while, or for keywords are decisions. Boolean expressions appearing in other contexts, such as the expression x < 100 in the assignment statement b = x < 100, are not decisions.

Expressions which control if/while/for statements or the ? operator.

In addition to expressions which appear within the parentheses following the if, while, or for keywords, the first argument of the C ? operator is also a decision. For example, in a program which contains the statement x = y<0? -y : y, y < 0 is a decision.

All non-trivial Boolean expressions except static initializers.

Under this criterion, any Boolean expression which does not appear in a static initializer and also is not a simple assignment of one Boolean variable to another, is a decision. For example, if a function f contains the assignment b = x < 100 (where b is a local variable of f), then x < 100 is a decision.

Note that the argument of a switch statement is not a decision.

Condition coverage tracks whether each condition in a program has evaluated to both true and false.

For the definition of MC/DC coverage, please see the Reactis Coverage Metrics chapter.

In addition to the generic coverage metrics discussed above, the Reactis for C Plugin also tracks three C-specific coverage metrics. These are:

C Statements.

This metric has one target for each statement in a C program. A target is covered when the corresponding statement has been executed at least once.

C Functions.

This metric has one target for each function in a C program. A target is covered when the corresponding function has been executed at least once.

C Function Calls.

This metric has one target for each function call expression in a C program. A target is covered when the corresponding function call expression has been executed at least once.

17.5.1. Visualizing Coverage in C Code#

When Coverage > Show Details in Simulator is selected, unexercised coverage targets in C code are reported visually as shown in Figure 17.12. Any unexecuted C statement is rendered in red. If a function has not been called, its name is rendered in red. If a function call expression has not been executed, the name of the function within the call expression is rendered in red.

If a decision has not evaluated to true it has a thin red overline. If a decision has not evaluated to false it has a thin red underline. If a condition has not evaluated to true it has a thick red overline. If a condition has not evaluated to false it has a thick red underline. If a decision has not met the MC/DC or MCC criteria, then the text of the decision is displayed in red. MC/DC and MCC coverage details associated with a decision (Figure 17.13) may be displayed by right clicking on the decision and selecting View Coverage Details. For a description of this dialog, please see the Reactis Coverage Metrics chapter.

Lines containing unexercised targets are distinguished by a red bar which is drawn just to the right of the line number of that line.

_images/rfcCvgHighlight.png

Fig. 17.12 Coverage highlighting in C code.#

_images/rfcCvgDetails.png

Fig. 17.13 View the MC/DC-related coverage details associated with a decision by right-clicking on the decision and selecting View Coverage Details.#

17.6. C Code in the Main Reactis Window#

As shown in Figure 17.14, an .rsm file may be assigned, edited, or removed by right-clicking on the S-Function in the main panel when Simulator is disabled. After an .rsm file is assigned, the C source files for an S-Function are listed in the hierarchy panel and RSM appears in the upper right corner of the S-Function in the main panel.

_images/rfcMainWinSfun.png

Fig. 17.14 Assigning .rsm files to S-Functions.#

Figure 17.15 shows that a C file may be displayed in the main panel by clicking on the filename in the hierarchy panel. Line numbers and the grid may be turned on or off from the Reactis for C tab of the Global Settings dialog.

_images/rfcMainWinCDisplayed.png

Fig. 17.15 Clicking on a C filename in the hierarchy panel displays the C file in the main panel.#

17.7. C Code and Reactis Simulator#

When the Reactis for C Plugin is enabled, Simulator seamlessly steps into custom code and S-Functions that have .rsm files assigned. The Simulator controls in the tool bar work in the same way within C code as they do for the Simulink and Stateflow portions of models. Five additional buttons are available to step through C source code. The behavior of those five and the Step Into button (also available when stepping through Simulink / Stateflow) is described below:

stepOutRBtn Reverse Step Out Of.

Step backwards to just before the currently executing function was called.

stepOverRBtn Reverse Step Over.

When paused after a function call, clicking this button steps back to just before the function was called.

miniStepRBtn Reverse Step Into.

Step backwards one statement. If a function call just returned, step back to the last statement of the function.

miniStepBtn Step Into.

Executes until either the current line of source code completes or a function is called.

stepOverBtn Step Over.

Executes until the current line of source code completes, including all function calls performed during its execution.

stepOutBtn Step Out Of.

Executes until the current function completes.

Other buttons continue to operate the same as when not using the Reactis for C Plugin. For example, the step button (stepBtn) reads all harness inputs of the model and then executes the blocks (possibly including C code), updating the harness outputs of the model with the results of executing the step.

As shown in Figure 17.16, a breakpoint may be toggled on lines within a C file which contain an executable C statement by double-clicking just to the right of the line number, or by right-clicking to the right of the line number and selecting Toggle Breakpoint. When trying to set a breakpoint in C code on a line that does not contain an executable statement, Reactis remaps the breakpoint to a different line according to the following rules:

  • If the attempted breakpoint line is within a multi-line executable statement, the breakpoint is placed at the first line of multi-line statement.

  • If the attempted breakpoint line is on a line with no executable statement (e.g. a comment or a variable declaration), then the breakpoint is placed on the first subsequent line that contains an executable statement.

Note that the following are not executable statements:

  • type declarations,

  • function prototypes,

  • static variable declarations with or without an initializer,

  • declarations of uninitialized local variables,

  • preprocessor commands, and

  • lines which are empty or only contain comments.

When execution reaches a line containing a breakpoint, execution will he paused before the line is executed. While paused, hovering over many identifiers in the source code will cause information about the identifier to be displayed. The information displayed depends on the type of the identifier:

  • If the identifier is an instance of a macro, the expansion of the macro will be displayed.

  • If the identifier is a variable, information about the type and value of the variable will be displayed. In addition, pertinent source code locations, such as the location where the variable was last modified, will be displayed.

  • If the identifier is a function, the function type, the argument types and values, the location where the function is defined and the current call stack will be displayed.

  • If the identifier is a user-defined type, the type details will be displayed.

  • If the identifier is a pointer, the value pointed to is displayed.

For a description of how Simulator visually presents coverage information please see the Visualizing Coverage in C Code section.

_images/rfcBreakpoint.png

Fig. 17.16 Debugging C code in Simulator.#

The sizes and alignments of the common built-in C types under the Reactis for C Plugin are listed in Table 17.1. These match the behavior of GCC (GNU C Compiler) and most other x86 C compilers. Integers are stored using a little endian byte order (the least-significant byte is stored first).

Table 17.1 Sizes and alignments of the common C types, in bytes.#

Type

sizeof

alignof

char, bool, void

1

1

short int

2

2

int, long int, float

4

4

long long int, double, long double*

8

8

*long double is not currently supported - it is mapped to type double

17.8. C Code and Reactis Tester#

When the Reactis for C Plugin is enabled, Tester automatically tries to exercise the coverage targets (described in the C Code Coverage Metrics section) in custom code and S-Functions that have .rsm files assigned. The launch dialog includes a check-box to enable or disable C statement coverage.

17.9. C Code and Reactis Validator#

Reactis Validator can check requirements on top-level S-Function inputs and outputs. To do so, Validator objectives are inserted within the subsystem which contains the S-Function. The Reactis for C Plugin does not currently support the insertion of Validator objectives within the C code.

17.10. Integer Overflows#

The C-Plugin supports detection and flagging of overflows during operations on integer values. This feature can be turned on or off by changing the value of the On integer overflow configuration parameter, as discussed in the Configuring Reactis for C section.

When On integer overflow is set to Wrap Over, the C-Plugin emulates the behavior of typical hardware, in which the most significant bits of a value which is too large are dropped until the value is small enough to be represented. The result of an unsigned wrapped-over overflow is typically equal to the large result modulo 2n, where n is the width (in bits) of the container type.

When signed values overflow, the sign bit may change, producing results much smaller or larger than if no overflow occurred. For example, in most 32-bit environments, adding the maximum signed int value (0x7fffffff) to itself produces the wrapped-over result −2.

When On integer overflow is set to Error, the C-Plugin will stop execution and display an error dialog window whenever an integer computation overflows. When a signed integer addition, subtraction, multiplication or left shift operation is performed, the result is considered to have overflowed when it is too large or too small to be represented.

Note that according to the C language specification, no overflow occurs during unsigned computations. Instead, the result is computed by wrapping over the large value, using the modulo approach mentioned in the previous paragraph. This has the effect of truncating (in binary) the larger value. For example, assigning the value 0x1234u to an unsigned char variable is the same as assigning the value 0x34.

When a value of one integer type is converted to a value of a different integer type, an overflow can only occur when the destination type is signed. This means that the statements

int x = -1;
unsigned int y = x;

will not produce an overflow. Instead, y will receive the value 0xffffffff. However, if a third statement is added:

int x = -1;
unsigned int y = x;
x = y;

then an overflow will occur, because the value of y (0xffffffff) is larger than the maximum positive value that can be represented by x (0x7fffffff). To avoid such errors while catching arithmetic overflows, set On integer conversion overflow to Wrap over. Alternatively, the following macro can be used to convert an unsigned int to an int without causing an overflow:

#define UINT_TO_INT(x) \
        (((x) <= INT_MAX)? (int)(x) : \
                          (((int)((x)^INT_MIN))+INT_MIN))

The values INT_MAX and INT_MIN are defined in the system header file limits.h.

The C-Plugin uses C99 rules for determining the signedness of expressions, which affects when overflows may occur. For integer constants, the type of the constant is determined by radix of the constant and the presence of a U or u suffix, as determined by the following rules:

  1. Any integer constant with a U or u suffix is unsigned.

  2. Any decimal constant without a U or u suffix is signed.

  3. Any non-decimal constant X without a U or u suffix will be assigned the first type that can represent X from the following list: int, unsigned int, long long int, unsigned long long int. This means that 0xffffffff will be assigned type unsigned int and 4294967295 will be assigned type long long int even though the two values are equivalent. In the latter case, if the literal is changed to 4294967295U, it will be assigned type unsigned int.

The C99 rules for evaluating integer expressions state that values of any type smaller than int, including unsigned types, are first converted to type int before any subsequent evaluations are performed. This forces values of type unsigned short and unsigned char to become signed, so that, for example, adding two variables of type unsigned short will produce a signed int result.

When two integer values are combined in a binary expression, the width and signedness of the result are determined by two rules:

  1. If one type is larger than the other, then the larger type is chosen.

  2. If both types have the same size, then the result is unsigned if either type is unsigned.

Operator arguments are converted to the result type before the expression is evaluated. This means that the expression ((int)-1) > ((unsigned int)1) will evaluate to 0 (false).

17.11. Memory Errors#

Whenever a pointer is used to access memory, the Reactis for C Plugin performs a safety check to ensure that pointer is valid. There are two steps in the validity check:

  1. Spatial validity. A pointer is not allowed to access memory outside of the bounds of the data object it originally pointed to (henceforth called the referent). For example, a pointer to an array can only be used to access memory within the bounds of the array. If a pointer is dereferenced and it points outside the bounds of its referent, then a spatial memory error occurs.

  2. Temporal validity. The referent of a pointer must not have been deallocated prior to an access attempt. Pointers to heap objects are no longer temporally valid once the referent has been deallocated by a call to free(). Pointers to local variables of a function are no longer valid once the function has returned. Data stored in static memory, such as variables declared outside of a function scope are never deallocated and are hence always temporally valid. Attempts to access a temporally invalid referent result in a temporal memory error.

Note that it is possible that a program which appears to function correctly actually contains a memory error. For example, a function that sums an array may have an error in the iteration termination condition which causes the function to read 1 element past the end of the array. If the element which follows the end of the array happens to always be zero, this error may have never been detected. At some point in the future, a change to the program may cause the invalid memory access to return a non-zero value. Even worse, there may be rare runtime conditions under which the memory access returns a non-zero value, causing intermittent program malfunctions which are difficult to reproduce and diagnose. Hence it is best to detect and fix such errors even though they may not seem to be presently causing a problem.

17.11.1. Invalid Pointer Creation#

The Reactis for C Plugin can produce an error or warning whenever a pointer expression produces an invalid pointer. This can help determine the source of a memory error. However, there are cases where invalid pointers are produced which are never dereferenced, such as the following program fragment:

int A[10], B[10], i, *a = A, *b = B;
while (i < 10) {
  *(a++) = *(b++);
}

During the last iteration of the above loop, the pointers a and b are both assigned invalid pointer values. This is not a problem because the invalid pointer values are never used. For such programs, the On invalid pointer creation setting should be set to No action or Produce warning.

17.12. Other Runtime Errors#

In addition to memory errors and overflows, the Reactis for C Plugin also detects the errors listed below. The C standard states that the results of these operations are undefined.

  • Divide by zero. An attempt to compute the quotient or remainder of a fraction in which the divisor is zero.

  • Invalid shift. An attempt to shift a value by an amount which is either (a) greater than or equal to the width of the value, or (b) a negative amount.

17.13. Stub File Generation#

The .rsm file editor includes a stub file generator, which produces a source file that contains definitions of missing functions and variables. The stub generator is launched by clicking on the Stub button. Note that the generated stub file initially does not contain any type definitions and will not compile until all required type definitions have been added to the file, which is typically done by adding #include statements to the stub file with a text editor.

17.14. Unsupported C Features#

The Reactis for C Plugin supports a very large subset of the C99 standard. The following features, however, are not currently supported:

  • Variable-length arrays (e.g., int f(int n) { char s[n]; }).

  • ANSI Trigraphs.

  • Universal character codes (a \u or \U escape which can be followed by a UCS-2 or UCS-4 hex code).

  • Signals.

  • Types _Complex and _Imaginary.

  • Type long double.

  • Wide character types.

  • File I/O during simulation.

  • Designated initializers (e.g., struct { int x; int y; } s = { .y = 5 };).

  • Non-constant static initializers (e.g., static int A[1] = { f(x); };).

The following restrictions apply to white-box analysis of S-Functions:

  • All general restrictions for S-Function support as mentioned in the S-Functions section.

  • MATLAB external interface functions dealing with sparse matrices (mxCreateSparse, mxCreateSparseLogicalMatrix, mxGetIr, mxGetJc, mxSetIr and mxSetJc) are not supported.

  • MATLAB external interface functions dealing with imaginary data (mxGetImagData, mxGetPi, mxSetImagData, mxSetPi) are not supported.

In custom code, pointers to functions are not currently supported.

The following runtime library functions are currently unimplemented:

complex.h

cabsf cargf cimagf crealf cabs carg cimag creal cabsl cargl cimagl creall cacosf cacoshf casinf casinhf catanf catanhf ccosf ccoshf cexpf clogf conjf cpowf cprojf csinf csinhf csqrtf ctanf ctanhf cacos cacosh casin casinh catan catanh ccos ccosh cexp clog conj cpow cproj csin csinh csqrt ctan ctanh cacosl cacoshl casinl casinhl catanl catanhl ccosl ccoshl cexpl clogl conjl cpowl cprojl csinl csinhl csqrtl ctanl ctanhl

dlfcn.h

dlopen dlsym dlclose dlerror

fcntl.h

creat fcntl open close read write lseek unlink

math.h

asinh asinhf asinhl acosh acoshf acoshl atanh tanhf atanhl erf erff erfl erfc erfcf erfcl fam fmaf faml hypot hypotf hypotl lgamma lgammaf lgammal tgamma tgammaf tgammal expm1 expm1f exp1ml ilogb ilogbf ilogbl log1p log1pf log1pl rint rintf rintl

setjmp.h

sigsetjmp siglongjmp

signal.h

raise

stdio.h

freopen fseek ftell rewind fgetpos fsetpos ungetc fscanf scanf vfprintf vfscanf vscanf vsscanf fread fwrite feof ferror clearerr rename remove tmpfile tmpname

stdlib.h

atexit system execl execlp execle execv execvp execve bsearch qsort

unistd.h

access alarm brk chdir chroot chown close confstr crypt ctermid cuserid dup dup2 encrypt fchown fchdir fdatasync fork fpathconf fsync ftruncate getcwd getdtablesize getegid geteuid getgid getgroups gethostid getlogin getlogin_r getpagesize getpass getpgid getpgrp getpid getppid getsid getuid getwd isatty lchown link lockf lseek nice pathconf pause pipe pread pthread_atfork pwrite read readlink rmdir sbrk setgid setpgid setpgrp setregid setreuid setsid setuid sleep swab symlink sync sysconf tcgetpgrp tcsetpgrp truncate ttyname ttyname_r ualarm unlink usleep vfork write

utime.h

utime

wchar.h

wcscat wcsncat wcscmp wcsncmp wcscpy wcsncpy wcslen wcschr wcsrchr wcsspn wcscspn wcspbrk wcstok wcsstr wcscoll wcsxfrm wmemchr wmemcmp wmemcpy wmemmove wmemset fwide fgetwc getwc getwchar ungetwc fgetws fwscanf wscanf swscanf fputwc putwc putwchar fputws fwprintf wprintf swprintf vfwprintf vswprintf vwprintf vfwscanf vswscanf vwscanf

wctype.h

mbrlen btowc mbrtowc wctob wcrtomb mbsinit iswalnum iswalpha iswcntrl iswdigit iswxdigit iswgraph iswpunct iswprint iswlower iswupper iswspace towlower towupper wctype iswctype wctrans towctrans

17.15. Supported C Library Functions#

The following C library functions are currently provided by the Reactis for C Plugin.

assert.h

assert

ctype.h

isalnum isalpha isascii iscntrl iscsym iscsymf isdigit isxdigit isprint isgraph ispunct islower isupper isspace isblank toint tolower toupper

errno.h

strerror

fenv.h

fegetround fesetround

math.h

acos sqrt sin cos tan asin acos atan atan2 exp exp2 pow ln log log2 log10 sinh cosh tanh acosf sqrtf sinf cosf tanf asinf acosf atanf atan2f expf exp2f powf lnf logf log2f log10f sinhf coshf tanhf acosl sqrtl sinl cosl tanl asinl acosl atanl atan2l expl exp2l powl lnl logl log2l log10l sinhl coshl tanhl

memory.h

bcopy memccpy

setjmp.h

longjmp setjmp

stdarg.h

va_start va_arg va_copy va_end

stddef.h

offsetof

stdlib.h

malloc calloc realloc free abs labs llabs div ldiv lldiv atof atoi atol atoll strtof strtod strtold strtol strtoll strtoul strtoull exit _Exit abort getenv bsearch qsotr mblen mbtowc mbstowcs wcstombs rand srand

string.h

memchr memcmp memcpy memmove memset strlen strchr strcpy strncpy strcat strncat strcmp strncmp strspn strcspn strpbrk strtok strcoll strxfrm strdup strndup

tgmath.h

sin cos tan sinh cosh tanh asin acos atan exp exp2 sqrt cbrt ln log log2 erf erfc lgamma tgamma expm1 ilogb log1p fabs ceil floor nearbyint rint lrint round lround trunc atan2 pow copysign fdim hypot fmin fmax fmod remainder nextafter nexttoward frexp ldexp modf scalbn scalbnln remquo