Chapter 16 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 14.2.1.
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.
16.1 Quick Start
-
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.
- To subject an S-Function to white-box analysis, do the following:
-
Right-click on the S-Function in the main Reactis panel
and select Assign RSM File
- Accept the default file name
- Click Yes to create a new .rsm file
- Add the C source files that implement the S-Function using the dialog.
- Custom code will be processed automatically when the Reactis for C Plugin
is enabled. No .rsm file is necessary.
- 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.
- 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.
- 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 section 16.2 for more details.
16.2 Configuring Reactis for C
16.2.1 Global Settings
Figure 16.1: The Global Settings dialog with Reactis for C selected. |
Figure 16.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.
16.2.2 Model-Specific Settings
16.2.2.1 Error Checking Pane
Figure 16.2: The Error Checking pane of the Reactis Info File Editor with
the C code settings shown. |
Figure 16.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 Section 16.10. - 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
Section 16.10.
- 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
Section 16.10.
- 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.
- 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 Section 16.11.1.
- 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 settings 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.
- 11. 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.
16.2.2.2 Coverage Metrics Pane
Figure 16.3: C-Specific coverage metrics. |
Figure 16.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 Section 16.5.
16.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.
Figure 16.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 16.4 is interpreted
and used as follows:
- 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.
- 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.
- 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).
- Type. This indicates the type of C code used in the model. These types
are described in Section 16.3 and 16.4.
- S-Function Name. This gives the name of the S-Function used, where
applicable. (As discussed in section 16.3
and 16.4, S-Function Libraries, custom code, and custom C
code libraries do not have associated S-Function names).
- RSM File. This is the Reactis Make file (.rsm) that describes the
necessary C files, includes, libraries, search paths and defines (as described
in Section 16.3).
- 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 16.4, 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.
16.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 16.5, Figure 16.7,
and Figure 16.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.
Figure 16.5: The (a) Source Files and (b) Include Search Path
panes of the .rsm file editor. |
16.3.1 Source Files
Figure 16.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 16.5(a) are used as follows:
-
This button is used to add one or more source files to the LUC (see Section 16.3.1.1).
- This button converts all currently selected source files to relative
path format.
- This button converts all currently selected source files to absolute
path format.
- This button removes all currently selected source files from the LUC.
- These buttons let you reorder items in the list.
- This button opens the help dialog.
- This button generates stub source code for missing functions and variables.
- This button builds the LUC.
- This button closes the .rsm file editor and saves any pending modifications.
- This button closes the .rsm file editor without saving any pending modifications.
16.3.1.1 Adding Source Files
Figure 16.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 16.6. The labeled items in
Figure 16.6 are used as follows:
-
This button opens the Select All Source Files in Folder dialog.
- The directory containing the source files is entered here.
- This button opens a browser dialog which is used to select the directory
containing the source files (item 2).
- When checked, only those source files which match one of the file selection patterns (item 5)
will be selected.
- 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.
- When checked, subfolders will be searched for matching files.
- When checked, subfolders which match one of the directory exclusion patterns (item 8) will not be
searched.
- 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.
16.3.2 Include Search Path
Figure 16.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 16.5(b) are used as follows:
-
This button is used to add one or more directories to the LUC.
- This button converts all currently selected directories to relative
path format.
- This button converts all currently selected directories to absolute
path format.
- This button removes all currently selected directories from the LUC.
- 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.
- This button opens the help dialog.
- This button generates stub source code for missing functions and variables.
- This button builds the LUC.
- This button closes the .rsm file editor and saves any pending modifications.
- This button closes the .rsm file editor without saving any pending modifications.
Figure 16.7: The (a) Libraries and (b) Defines
panes of the .rsm file editor. |
16.3.3 Libraries
Figure 16.7(a) shows the Libraries
pane of the .rsm file editor,
which lists the libraries used by the LUC.
The labeled items in Figure 16.7(a) are used as follows:
-
This button is used to add one or more libraries to the LUC.
- 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.
- This button converts all currently selected libraries to relative
path format.
- This button converts all currently selected libraries to absolute
path format.
- This button removes all currently selected libraries from the LUC.
- This button opens the help dialog.
- This button generates stub source code for missing functions and variables.
- This button builds the LUC.
- This button closes the .rsm file editor and saves any pending modifications.
- This button closes the .rsm file editor without saving any pending modifications.
16.3.4 Defines
Figure 16.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 16.7(b) are used as follows:
-
This button is used to add one or more macro definitions to the LUC.
- This button opens a editor from which the currently selected macro
definition can be changed.
- This button removes all currently selected macro definitions from the LUC.
- This button opens the help dialog.
- This button generates stub source code for missing functions and variables.
- This button builds the LUC.
- This button closes the .rsm file editor and saves any pending modifications.
- This button closes the .rsm file editor without saving any pending modifications.
Figure 16.8: The General pane of the .rsm file editor. |
16.3.5 General
Figure 16.8 shows the General
pane of the .rsm file editor,
which contains a few general settings for the LUC.
The labeled items in Figure 16.8 are used as follows:
-
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.
- This button makes the LUC a dynamic library.
- 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.
- If (3) is selected, the prefix used for dynamic library pointers will
appear here and can be edited if desired.
- 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.
- This button opens the help dialog.
- This button generates stub source code for missing functions and variables.
- This button builds the LUC.
- This button closes the .rsm file editor and saves any pending modifications.
- This button closes the .rsm file editor without saving any pending modifications.
16.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.
16.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 Section 14.2.1.
16.4 Custom C Code
Figure 16.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 16.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.
Figure 16.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 16.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 16.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 section 16.3. 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.
Figure 16.11: Creating an .rsm file for a library
used by custom code. |
16.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.
16.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 16.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 Chapter 6.
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.
16.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 16.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
16.13) may be displayed by right clicking on the
decision and selecting View Coverage Details. For a description
of this dialog, please see Chapter 6.
Lines containing unexercised targets are distinguished by a
red bar which
is drawn just to the right of the line number of that line.
Figure 16.12: Coverage highlighting in C code. |
Figure 16.13: View the MC/DC-related coverage details
associated with a decision by right-clicking on the decision and
selecting View Coverage Details. |
16.6 C Code in the Main Reactis Window
As shown in Figure 16.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.
Figure 16.14: Assigning .rsm files to S-Functions. |
Figure 16.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.
Figure 16.15: Clicking on a C filename in the
hierarchy panel displays the C file in the main panel. |
16.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:
-
Reverse Step Out Of. -
Step backwards to just before the currently executing function was called.
-
Reverse Step Over. -
When paused after a function call, clicking this button steps back to
just before the function was called.
-
Reverse Step Into. -
Step backwards one statement. If a function call just returned, step back to the
last statement of the function.
-
Step Into. -
Executes until either the current line of source code
completes or a function is called.
-
Step Over. -
Executes until the current line of source code completes,
including all function calls performed during its execution.
-
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 (
) 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 16.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 Section 16.5.1.
Figure 16.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 16.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).
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.
Table 16.1: Sizes and alignments of the common C types, in bytes. |
16.8 C Code and Reactis Tester
When the Reactis for C Plugin is enabled, Tester automatically tries to exercise the
coverage targets (described in Section 16.5) 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.
16.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.
16.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 Section 16.2.
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:
-
Any integer constant with a U or u suffix is unsigned.
- Any decimal constant without a U or u suffix is signed.
- 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:
-
If one type is larger than the other, then the larger type is chosen.
- 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).
16.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:
-
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.
- 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.
16.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.
16.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.
16.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.
16.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 Section 14.2.1.
- 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
16.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