CIF code generator

The CIF code generator can be used to generate implementation code for various languages/platforms. The generated code is complete, and can be used as is, without any CIF related library or runtime.

The remainder of this page explains general information about the tool, that applies to all target languages/platforms. Specific information is available for each of the target languages/platforms, on separate pages:

The generated code adheres to the execution scheme defined by the CIF controller properties checker.

Starting the generator

The generator can be started in the following ways:

  • In Eclipse, right click a .cif file in the Project Explorer tab or Package Explorer tab and choose CIF implementation tools  Generate code for CIF specification…​.

  • In Eclipse, right click an open text editor for a .cif file and choose CIF implementation tools  Generate code for CIF specification…​.

  • Use the cifcodegen tool in a ToolDef script. See the scripting documentation and tools overview page for details.

  • Use the cifcodegen command line tool.

Options

Besides the general application options, this application has the following options that apply to all target languages/platforms:

  • Input file: The absolute or relative local file system path to the input CIF specification.

  • Output directory: The absolute or relative local file system path to the output directory. This is the directory to which the generated code files will be written. If the directory does not yet exist, it is automatically created. By default, the current directory is used.

  • Target language: Specifies the target language/platform for which to generate code. By default, Simulink code is generated. The following languages/platforms are supported:

    Target language/platform Command line value

    C89

    c89

    C99

    c99

    Java

    java

    JavaScript

    javascript

    HTML

    html

    Simulink

    simulink

    The first column indicates the target language/platform, and is linked to a page with more information for that specific language/platform. The second column indicates the command line value to use for the option, to select that target language/platform.

  • Code prefix: The code prefix, used to prefix file names, identifiers in the code, etc. If no prefix is given, the prefix is derived from the input filename, by removing the .cif file extension, if present. This is also the default. The prefix must be a valid CIF identifier, i.e. consist of only letters (a to z, A to Z), numbers (0 to 9), and underscores (_), and not start with a number.

Supported specifications

The CIF code generator supports a subset of CIF specifications. The following restrictions apply:

  • Specifications without automata are not supported.

  • Only events that are declared as controllable or uncontrollable are supported. All other events are not supported, including the tau event when used explicitly or as an edge without events.

  • Initialization predicates in components are not supported, except if it can be determined statically that they are trivially true.

  • State invariants (in components as well as locations) are not supported, except if it can be determined statically that they are trivially true.

  • Discrete variables with multiple initial values (including any) are not supported.

  • External user-defined functions are not supported.

  • Urgent locations are not supported.

  • Initialization predicates in locations that can not be statically evaluated are not supported.

  • Automata that do not have exactly one initial location are not supported.

  • Urgent edges are not supported.

  • Data types other than bool, int (with or without range), real, string, enumerations, tuples, and arrays, are not supported. This applies to the data types of variables, parameters of functions, return types of functions, etc.

  • Sampling of distributions is not supported.

  • The use of the conjunction and disjunction binary operators on anything other than boolean values is not supported.

  • The use of the equality and inequality binary operators on anything other than boolean, integer, real, string, or enumeration values is not supported.

  • The use of the addition binary operators on anything other than numeric or string values is not supported.

  • The use of the subtraction binary operators on anything other than numeric values is not supported.

  • The use of the element test and subset binary operators is not supported.

  • Projection on anything other than tuples, arrays, and strings is not supported. This applies to expressions as well as addressables (the left hand sides of assignments). For arrays, both 0-based indices (counting from the left) as well as negative indices (counting from the right) are supported.

  • Slicing is not supported.

  • Function calls on anything other than standard library functions and internal user-defined functions is not supported.

  • The del, pop, acosh, asinh, atanh, cosh, sinh, and tanh standard library functions are not supported.

  • The empty standard library function on anything other than arrays is not supported.

  • The size standard library function on anything other than strings and arrays is not supported.

  • The distribution standard library functions are not supported.

  • Lists (except for arrays), sets, and dictionaries are not supported.

  • The use of functions as values is not supported. That is, functions may only be used in function calls, and may for instance not be stored in variables, or passed to other functions.

  • Print declarations with pre/source state text and post/target state filtering (when) are not supported.

  • Print declarations with post/target state text and pre/source state filtering (when) are not supported.

  • CIF/SVG declarations are supported only for HTML code generation. SVG input mappings with update are not supported. If the specification connects to an SVG image, but no CIF/SVG input or output mappings apply to that image, a warning is printed. For the other target languages, a warning is printed if any CIF/SVG declarations are encountered, and these declarations are then ignored.

The restrictions on types and expressions do not apply to their use in values of documentation annotation arguments.

Specific target languages may add additional restrictions. Check their specific information for the details.

Preprocessing

The following CIF to CIF transformations are applied as preprocessing (in the given order), to increase the subset of CIF specifications that can be transformed:

After these preprocessing steps, the generator checks whether the specification is supported. It then applies the following additional CIF to CIF transformations:

Generated code

This section explains the basics behind the generated code, as they apply to all target languages. The specific pages that explain the code generated for specific target languages provide further details.

For all languages, the generated code adheres to the execution scheme defined by the CIF controller properties checker. Note however that CIF specifications with SVG input mappings that map to events should be avoided if full compliance is desired, and SVG input mappings with updates to input variables should be used instead.

Code overview

Code that executes edges of a CIF model is called event loop code. The generated code for a CIF specification has multiple event loops. If the target supports SVG input mappings, the first event loop is for the interactive SVG input events. For all targets, what follows is an event loop for the edges with uncontrollable events, and one for the edges with controllable events. The event loops are not the only code that is executed. Before the loops, the values of the input variables are obtained from the environment, the initial state is initialized (for the first execution only), and the values of the continuous variables are updated to account for the amount of time that has passed (for all but the first execution). Then the event loops are executed. Finally, output values may be supplied to the environment.

For further details, see the execution scheme defined by the CIF controller properties checker.

Repeated execution

During the execution of the code, variable time from the CIF model is not updated. Execution of the code takes time. After the code is executed, potentially more time passes. Then, the code can be executed again. The time (in seconds) between the first execution and the current execution is the total time that has passed since execution started, and this becomes the new value of variable time.

How often the code is executed, and whether this is done with a fixed cycle time (periodic task scheduling) or with a variable cycle times (non-periodic tasks) can be influenced by the end user. The details differ per target language, and can be found on their respective pages.

Event loops

The CIF model is first linearized to eliminate parallel composition. The result is self loop edges with guards and updates. The main part of the generated code essentially consists of update code that is conditionally executed. This code is part of the event loops, that execute edges for the various events. Each event loop repeatedly executes its enabled edges, until no more edges are enabled. Once no more edges are enabled, an event loop terminates. The order in which the code is generated for the different edges (in the event loops), is done in such a way that it matches the execution scheme defined by the CIF controller properties checker.

Termination

If in the CIF model always at least one event is enabled, the generated code will run forever, and will never terminate. Time will not pass. Code generation should be avoided for such models. It is the responsibility of the modeler to ensure this is taken into account. A bounded response check can be done to ensure the CIF specification does not have infinite sequences of enabled events.

Predictability of execution time

If during an iteration of an event loop none of its edges is enabled, the loop terminates. If at least one of its edges is enabled, the event loop is executed again.

This approach generally does not result in predictable execution times of the program body. That is, if a certain edge keeps being enabled, its loop is executed over and over again. In that case, the execution time of the body may exceed the fixed cycle time, and the controller is no longer guaranteed to work correctly.

Even if a loop is only executed a finite number of times, the execution time of the body may exceed the fixed cycle time. One may consider monitoring the execution times to detect such issues. All implementations provide a way to obtain execution time statistics. The details differ per target language, and can be found on their respective pages.

Optional execution feedback

Several implementations provide additional information during simulation, such as which events have been executed, timing information, and what new print output has been generated. Such information can generally be enabled and disabled in the implementations. The details differ per target language, and can be found on their respective pages.

Correct handling of I/O

The generated code cannot guarantee its correct behavior if the inputs from the external I/O change more rapidly than the generated code is executed. That is, if an input changes during a single execution of the code, the change is not noticed until the next execution. If an input changes during an execution and changes back during that same execution, the change is not noticed at all. Therefore, executing the code often enough per second, is essential. In other words, choosing an appropriate cycle time is essential for the correct functioning of the generated code.

Accuracy over time

The generated C89, C99, Java, JavaScript and HTML code maintains the running time in seconds. Due to the finite representation of numeric values, this results in numeric overflow after execution for a long time. Running the code continuously for longer than 100 years should be avoided.

The continuous variables from the CIF specification in the generated code are updated each execution using the Euler method for integration. That is, each execution the time that has elapsed since the previous execution is multiplied by the derivative of the continuous variable in the state of the previous execution. This value is added to the value of the continuous variable. Essentially, a linear approximation of the derivative is used, calculated using the state of the previous execution.

The Euler method can be numerically unstable, it can suffer from rounding errors due to the use finite binary representations of real values, and has some other issues as well. The effects are likely to be limited if linear continuous variable (continuous variables with constant derivatives) are used. Especially clocks (derivative +1 or -1) generally don’t suffer too much from these issues. However, even clocks may suffer from loss of accuracy over time. As such, clocks should not be used to measure over long periods of time. Instead they should be reset, rendering the past loss of accuracy irrelevant for any future measurements.

Enumerations

One of the preprocessing transformations merges all enumerations into a single enumeration. This is done in such a way that the behavior of the original CIF model is left intact. However, it is up to the implementer that connects the inputs from the environment to the generated code, to ensure that only valid enumeration literals are assigned to the input variables of the generated code.

Annotations

All annotations in the specification are ignored, except for documentation annotations:

  • The documentation of algebraic parameters, algebraic variables, constants, discrete variables, enumeration literals, events, function parameters, function variables, functions, input variables, locations of automata with at least two locations, and specifications is included in the generated code.

  • The documentation of continuous variables is also included in the generated code, except when generating Simulink code.

  • The documentation of automata, automaton definitions, automaton instantiations, edges, enumerations, groups, group definitions, group instantiations, invariants, locations of automata with only one location, and type declarations is ignored.