Code Generation with Redundant Data Storage
All C code examples have been generated for the PC target with Implementation Experiment code generator. |
If the code generation option Use Redundant Data Storage is activated, and code is generated for the Implementation Experiment or for Object Based Controller Implementation, the following happens:
Each element marked as redundant is stored in a second place, the complement representation.
The implementation data type of the complement is set via the <result type> in the complement service. If no <result type> is given, the implementation data type is an unsigned integer type of the same bit size as the original element, especially for originals with a signed implementation data type.
Example
The exported send message msg and the local variable cont are marked as redundant.

They are implemented as follows:

The complement service is defined as follows:
complement|s16|s16=complement_%t1%(%i1%)
In the generated *.h file, the elements are defined as follows (the complements are set in bold):
/*----Local variables object structure -----------------------------*/
struct MODULE_BLOCK_DIAGRAM_IMPL_Obj {
sint16_Obj *cont;
sint16_Obj *_ASCET_copy_cont;
};
/*----Imported/Exported variables object structure -----------------*/
typedef struct {
sint16_Obj *msg;
sint16_Obj *_ASCET_copy_msg;
} MODULE_BLOCK_DIAGRAM_IMPL_Class;
Each assignment to an element marked as redundant is replaced by an assignment to a temporary variable, followed by an assignment to the original representation.
The complementary value (calculated via a complement service) of the temporary variable is assigned to the element's complement representation.
Example
The local variable cont_local is marked as redundant and implemented as sint16. An assignment is specified:

The following code is generated for the assignment. The assignment to the temporary variable is limited to the sint16 value range.
sint16 _t1sint16;
_t1sint16 = (MODULE_IMPLinstance->contPar->val <= 32766) ? (MODULE_IMPLinstance->contPar->val + 1) : 32767;
MODULE_IMPLinstance->cont_local->val = _t1sint16;
MODULE_IMPLinstance->_ASCET_copy_cont_local->val = complementService(_t1sint16);
The temporary variable is omitted for very simple assignments, e.g., the direct assignment of a parameter or a constant.
Example
The local variable cont_local is marked as redundant and implemented as sint16. A direct assignment is specified:

The following code is generated for the assignment:
MODULE_IMPLinstance->cont->val = MODULE_IMPLinstance->contPar->val;
MODULE_IMPLinstance->_ASCET_copy_cont->val = complementService(MODULE_IMPLinstance->contPar->val);
Each verify operation for a scalar element x is replaced by (complement(x) == xcopy), where x is the original and xcopy the complement. The complement function is the complement service for the type of x.
Example
The local variable cont is marked as redundant and implemented as sint16. A simple verify operation is specified:
/ log_scalar = cont.verify();
The following code is generated for the operation:
MODULE_IMPLinstance->log_scalar->val =
(complementService(MODULE_IMPLinstance->cont->val) == MODULE_IMPLinstance->_ASCET_copy_cont->val);
Each verify operation for an array or matrix marked as redundant is replaced by a for loop construction, which verifies all elements of the array/matrix in the same way as scalars.
Examples:
array /
matrix
The array variable array is marked as redundant and implemented as uint32. A simple verify operation is specified:
/ log_array = array.verify();
The following code is generated for the operation:
uint8 _t1uint8;
uint8 _t2uint8;
_t1uint8 = true;
if (_t1uint8)
{
for(_t2uint8 = 0U;_t2uint8 < 4U;_t2uint8++)
{
{
_t1uint8 = _t1uint8 &&
(complementService(Vec_uint32_getAtProtected (MODULE_IMPLinstance->array,
_t2uint8, "variable <MODULE_IMPLinstance->array> in component <Module::Impl>"))
==
Vec_uint32_getAtProtected (MODULE_IMPLinstance->_ASCET_copy_array, _t2uint8,
"variable <MODULE_IMPLinstance->_ASCET_copy_array> in component
<Module::Impl>"));
}
}
}
MODULE_IMPLinstance->log_array->val = _t1uint8;
The matrix variable matrix is marked as redundant and implemented as sint16. A simple verify operation is specified:
/ log_matrix = matrix.verify();
The following code is generated for the operation:
uint8 _t1uint8;
uint8 _t2uint8;
uint8 _t3uint8;
_t1uint8 = true;
if (_t1uint8)
{
for(_t2uint8 = 0U;_t2uint8 < 3U;_t2uint8++)
{
{
for(_t3uint8 = 0U;_t3uint8 < 3U;_t3uint8++)
{
{
_t1uint8 = _t1uint8 &&
(complementService(Mat_sint16_getAtProtected (MODULE_IMPLinstance->matrix,
_t2uint8, _t3uint8,
"variable <MODULE_IMPLinstance->matrix> in component <Module::Impl>"))
==
Mat_uint16_getAtProtected (MODULE_IMPLinstance->_ASCET_copy_matrix,
_t2uint8, _t3uint8,
"variable <MODULE_IMPLinstance->_ASCET_copy_matrix> in component <Module::Impl>"));
}
}
}
}
}
MODULE_BLOCK_DIAGRAM_1_IMPLinstance->log_matrix->val = _t1uint8;
If code is generated for an ASCET‑SE target, the following happens in addition to the list above:
- All pointers that are dereferenced within the code generated for a verify operation have to be checked before dereferencing. The check is done by taking care that the pointer is one of the instances known to ASCET.
If the code generation option Use Redundant Data Storage is not activated, or if code is generated for the Physical or Quantized Physical experiment, the following happens:
See also
Redundant Data Storage
Memory Classes for Redundant Data Storage
Complement Service for Redundant Data Storage
Block Diagram Editor – Using the Verify Operator
ESDL Editor – Verify Operation
Project Editor – Code Generation Options
Temporary Variables