[Previous] [Next] [Contents] [Index]


    The Cmicro Code Generator

The Cmicro Code Generator translates your SDL system into a C program that you can compile together with the Cmicro Library and the Cmicro Tester target library. The Cmicro Library and the Cmicro Tester target library is not available as a pre-linked library but is delivered as source to enable scaling of the kernel. The scaling is dependent upon the SDL system characteristics. This chapter is a reference manual for the Cmicro Code Generator.

Table of Contents 

Introduction

Application Area for the Cmicro Code Generator

The application area for the Cmicro Code Generator is:

In this part of the chapter, the general behavior of the Cmicro Code Generator, as seen from the users point of view, is discussed.

Highly Optimized Code for Target

The generated code in combination with the Cmicro Library is highly optimized, which is unavoidable for microcontrollers and real-time applications. Some optimizations have been possible only by introducing restrictions in the use of SDL. Other optimizations have been possible by generating more compact code. For the restrictions in the use of SDL please see SDL Restrictions. Details regarding the output of the Cmicro code generation can be found in Output of Code Generation.

Target Debug

With the generated code it is possible to debug the application on the target using the Cmicro Library and the Cmicro Tester target library. The parts of the Cmicro code generation which are used for the Cmicro Tester are also highly optimized. Please see The Cmicro Tester.

Overview of the Cmicro Code Generator

The SDT Analyzer, which can be invoked from the Organizer, contains an SDL parser, an SDL semantic checker, and -- among other code generators -- the Cmicro Code Generator.

Many options can be chosen from the user which affect the analysis of the SDL system. Furthermore, a lot of error checks are performed automatically before code generation starts. This makes it possible to improve written SDL specifications before any run-time testing must be done.

The options that the user may choose for analysis and the error checks that are performed by the analyzer are described in The SDT Analyzer.

At some places the Cmicro Code Generator can be used in exactly the same way as the SDT C Code Generator (Cbasic/Cadvanced) can be used. At some other places the use of this C Code Generator, or what this C Code Generator produce, is different.

The Cmicro Code Generator generally can process the same input as the SDT C Code Generator can. The differences are explained within this chapter.

The differences in the output of the both code generators are described within the subsection Output of Code Generation.

The overall differences of the both code generators are described in the section Differences between Cmicro and Cadvanced.

The following subsections describe how the Cmicro Code Generator might be used.

Generated Files

The C files, which are generated by the Cmicro Code Generator, can only be used in connection with the Cmicro Library and the Cmicro Tester. It is not possible to validate and simulate the SDL system with the C code generated by the Cmicro Code Generator as this code is only suitable for target applications. To simulate and validate the SDL system within SDT, the user has to choose the Cbasic Code Generator. In order to view the process of generating C applications see the Organizer's Make dialog in The Organizer.

The SDT Analyzer, which contains the Cmicro Code Generator can also be started as a stand-alone tool. For more information about this possibility please see The SDT Analyzer.

There are several steps that must be carried out before the generated C files can be compiled and linked together with the Cmicro Library. The user should follow the procedures that are documented in the section Targeting with the Cmicro Package.

In the following subsections the different files that are generated are explained.

Generated Configuration File

The first file that is generated from the Cmicro Code Generator is called sdl_cfg.h. It is used to scale the Cmicro Kernel depending on what characteristics the SDL system has. This is called automatic scaling and automatic dimensioning facility.

The file contains a header, process ID declarations, and then a #define or a /*NOT define ... */ for each of the flags that the Cmicro Code Generator can generate automatically.


Example 421 : The Header of an sdl_cfg.h      

The XMK_CFG_TIME macro is used internally when compiling and executing with the Cmicro Tester takes place. With this macro, a rough consistency check for the generated files is done. The <GenerationTime> of the different files that are generated is compared in the Library, by the BodyBuilder and by the Cmicro Tester. If there is an inconsistency, compilation errors will occur.

The process ID declarations are generated as #define values in C, like:

where the first process in the system is the value of 0 assigned, the second process gets the value 1, and so on. Due to the implementation of SDL'92 object orientation in the Cmicro Code Generator, there is also an automatic prefix generated. Using this prefix in the user's environment functions, it is possible to distinguish between several processes with the same name. Please refer to Generation of Identifiers for more information.

The rest of the file sdl_cfg.h is about the automatic scaling and automatic dimensioning of the SDL system. It may look for example like:


Example 422 : The Tail of an sdl_cfg.h      

For a first rough understanding of the meaning of the different flags: The SDL system from above contains <N> process types (using SDL'88 terminology), all the processes are declared in the form (0,1) or (1,1). There are <X> timers declared (in this case, <X> must be 0, because XMK_USED_TIMER is undefined, and the system uses an amount of <Z> signals. The system does not use any create or stop (XMK_USED_DYNAMIC_CREATE and XMK_USED_DYNAMIC_STOP are undefined). In this way all the other flags have special meaning.

For explanations about the different flags the user should refer to Automatic Scaling Included in Cmicro.

Generated C File

Assumed, that the user selected "No separation" in the Organizer's Make Dialog, and no partitioning is used, then the Cmicro Code Generator will generate one C file per SDL system. This file contains all the characteristics of the SDL system including all the declarations that the SDL system itself needs. For an explanation of this file see Output of Code Generation.

Generated Environment Header File

There is one file generated from the Cmicro Code Generator that contains all the definitions and declarations that are necessary to implement the environment functions xInEnv and xOutEnv.

The file is generated only if the option Generate environment header file of the Organizer's Make dialog is switched on.

The file is called <systemname>.ifc and it contains a header, the type definitions used on system level (newtypes, syntypes, synonyms), the signal IDs and the structure type definitions for the parameters of the signals.


Example 423 : The Header of an <systemname>.ifc file      

The XMK_IFC_TIME macro is used internally when compiling and executing with the Cmicro Tester takes place. With this macro, a rough consistency check for the generated files is done. The <GenerationTime> of the different files that are generated is compared in the Library, by the BodyBuilder and by the Cmicro Tester. If there is an inconsistency, compilation errors will occur.

Followed by the header the section about sorts follows. The sorts are generated according to the documentation in The Cadvanced/Cbasic Code Generator.

Next, the definitions for signals follows, which consists of:

For easy interpretation: For an SDL signal without parameters, going from the environment to SDL, like:

the following is generated into the .ifc file:

For an SDL signal with parameters, going from SDL to the environment, like

the following is generated into the .ifc file:

At least the signal ID (here: SOut) and the name of the structure (here: yPDef_SOut) must be used in the xOutEnv C function in this case.

The code generation of structure types and signal IDs is (except the C comment about IN or OUT) independent from the direction the signal goes.

In order to give some additional help for making C identifiers unique, the Cmicro Code Generator generates, in the section declaring sorts:


Example 424 : A Newtype Declaration      

If the user defines the flag XPREFIX_NAMES_IN_IFC, the prefix pTYPE_ is used for all the names of the sorts that are generated into the .ifc file, which will help to distinguish a sort name from a signal name for example.

Caution! 

As there are defines generated that contain no prefixes, there might be compiler warnings like "Illegal redefinition of macro". Such redefinitions should never be ignored because fatal errors during run-time may occur. The user should introduce a prefix for signals or sorts with different meaning on SDL level, in order to map these names to unambiguous identifiers in C.

More explanation about the environment header file is given in The Cmicro Library.

Generated Make File

The Cmicro Code Generator generates a file that contains production rules for the C program. This file can be used together with "make" facility only. The make facility that the user wants to use must be conform to the UNIX make. The file is called <systemname>.m and the use of it is described in The Cmicro Library.

Generated Symbol File

The generated symbol file is used to store symbolic information about the SDL system. The file has meaning for the host part of the Cmicro Tester only and is called <systemname>.sym. It is used for Cmicro Tester purposes only and is described within The Host Symbol Table.

Generated Kernel Group File

The generated kernel group file contains information about process names. This file is especially used in integrations, when OO is used and processes are instantiated. Using the information from this file, it is possible to distinguish between several process instantiations with the same name.

Implementation

In this section the implementation details are discussed. These details are meaningful for understanding how a generated Cmicro application does work.

Time

For host simulation, with the predefined kernels, a time unit represents one second. In target applications, time is to be implemented by the user (see subsection Defining the SDL System Time Functions in mk_stim.c).

Real Time

If real time is used, then there will be a connection between the clock in the executing program and the wall clock. For applications the user must provide the connection with the wall clock, normally the hardware timer.

Note: 

The C standard function time used as the real time clock returns the time in seconds. The implementation of the clock can be changed by re-implementing the function xmk_NOW in mk_stim.c.

Scheduling

The Cmicro Kernel does not use a process ready queue. It processes the signals in the order of their appearance. To do this, there is a signal queue which stores the signals sent to any process (either internally or externally). There are different ways to influence the scheduling when using the Cmicro Code Generator:

Assigning Priorities to Processes -- Preemptive Scheduling

It is possible to assign priorities to process types (using SDL'88 terminology). The processes' priorities are assigned when designing the SDL system. They are assigned using the #PRIO directive.

There are some things to be kept in mind when using process priorities:

The Cmicro Kernel handles process priorities by collecting all signals sent to processes of the same priority in a separate queue. Thus, there is a queue for each priority level.

While the SDL system is running the kernel checks for signals in the queues with decreasing priority. This check takes place whenever an SDL output appears or a process performs an SDL nextstate operation. Because of the kernel checking for signals whenever an output takes place, it is possible to have preemptive scheduling.

Assume, there are two process types lowprio and highprio. Let process type lowprio have the priority one and process type highprio have the priority zero.

If an instance of process type lowprio performs an output to process type highprio, there appears a signal in a queue of a higher priority level (zero is the highest priority level available, process lowprio has priority one) which leads to the kernel immediately working on the signal sent to the process highprio. The transition of process lowprio will not end until process highprio has finished its transition invoked by the signal.

This way of scheduling is implemented using recursion.

Note: 

Process priorities are available only when using a compiler which can handle recursion.

There is basically no restriction on the number of priority levels, but the target and compiler used will of course limit the depth of recursion.

As a general recommendation process priorities should not be assigned one per process type, but the process types should be grouped according to their purposes and these groups should then be assigned a priority level.

Assigning Priorities to Signals

The signals in the queue(s) are normally ordered according to their appearance (FIFO-strategy). By assigning priorities to signals this ordering is user definable. The directive #PRIO is used to assign a priority to signals.

Priority increases with decreasing numbers, but there is no restriction to use consecutive numbering.

Whenever a signal is sent, it is inserted into the signal queue(s) according to its priority.

Assume, there is a process performing two signal outputs, first_sig and second_sig. Using the standard FIFO-strategy signal first_sig would be worked on before signal second_sig. But with signal priorities and signal first_sig assigned priority fifty and signal second_sig assigned priority twenty, signal second_sig would be in front of signal first_sig in the queue and thus would be worked on before signal first_sig.

For more details please refer to Assigning Priorities -- Directive #PRIO.

Combinations of Signal/Process Priority

Every combination of signal and process priorities may be used. In this way it is possible to adapt the scheduling to the users' needs.

Note: 

Without process priorities a transition once started will have to be finished before the next transition can be dealt with. This is valid regardless of the time it will need to finish a transition.

Synonyms

General

The Cmicro Code Generator only allows SDL synonyms to be implemented as C macros. To be translated to a macro the expression defining the value of the synonym must be:

Synonyms that cannot be calculated at analyze time are not supported by the Cmicro Code Generator. That is to say synonyms that would normally be implemented as variables in the generated code are not supported by the Cmicro Code Generator.

External Synonyms

External synonyms can be used to parameterize an SDL system and thereby also a generated program. The values that should be used for the external synonyms can be included as macro definitions into the generated code, for instance by including another header file.

Using a Macro Definition

To use a macro definition in C to specify the value of an external synonym, the user should perform the following steps:

  1. Write the actual macro definitions on a file.


  2. Example 425 : Macro Definition      

    #define synonym1 value1
    #define synonym2 value2
    


    The synonym names are the SDL names (without any prefixes).
  3. Introduce the following #CODE directive at the system level among the SDL definitions of synonyms, sorts, and signals, for example, but before any use of the synonyms.


  4. Example 426 : #CODE Directive      

    /*#CODE
    #TYPE
    #include "filename"
    */
    

If this structure is used, the value of an external synonym can be changed merely by changing the corresponding macro definition and re-compiling the system.

Note: 

When an application is created, the macro definitions should be used for all external synonyms, as the function for reading synonym values stored on file is not available. (See below.)

Reading Values at Program Start up

This method of reading external synonyms is not supported for applications and is therefore not supported by the Cmicro Code Generator.

Procedure Calls and Operator Calls

In SDL-92, value returning procedures and operator calls are introduced. This means, that an SDL procedure can be called within an expression. As the Cmicro Code Generator cannot handle procedures with states, it is not necessary to map such calls to a different scheme.


Example 427 : Procedure Call      

Note: 

The value returning procedure calls are transformed to C functions which return values.

Operators which are defined using operator diagrams, are as in the models in the SDL recommendation, treated exactly as value returning procedures.

Generation of PAD function

The code generation for the PAD function is different compared with Cadvanced, in the way that code that is common in process types is copied into the PAD function for instantiated processes. This is implemented in contrast to Cadvanced, where for each process type definition there is a C function generated once, that is called by the instantiated PAD function, for common code. This makes a difference when system partitioning and/or file separation is used.

Any

`Any' should not be used in applications using the Cmicro Code Generator, because it leads to an error message. Random is not implemented in the Cmicro Package.

Calculation of Receiver in Outputs

The Cmicro Code Generator is a code generator using the semantics of SDL-92 with some restrictions. The behavior for output is according to the rules described in the following:

Abstract Data Types

In this section the specialities and exceptions about abstract data types for Cmicro are discussed only. A complete documentation about the abstract data types is given in The Cadvanced/Cbasic Code Generator.

General C Definitions

All the macros and external definitions for functions can be found in the files sctpred.h and sctpredg.h, except for the PId sort which is handled in the file ml_typ.h.

The C functions for the handling of predefined sorts are defined in the file sctpred.c.

On UNIX these files can be found in $sdtdir/cmicro/kernel.

In Windows these files can be found in the Telelogic Tau installation under %SDTDIR%\cmicro\kernel.

Exceptions for SDL Predefined Types

A general exception existing for all the predefined types is that the user must configure which predefined types are to be compiled into the target C program. This is necessary to hold the target C program as small as possible. The configuration is to be performed with the help of the BodyBuilder, which is explained in The Cmicro Library.

Caution! 

Problems will occur during compilation when the configuration is not according to what the SDL system needs. The user should refer to the explanations about manual scaling in The Cmicro Library.

External Synonyms

External synonyms are to be defined by the user in the following way.

For a synonym like

the Cmicro Code Generator expects to see xternal as a #define value that is to be defined by the user. This can be done for example in the following way:

This also means, that if xternal is not defined from the user, it will lead to compilation errors.

Charstring

Charstrings can be used either in the usual way as they are when using Cadvanced, or they can be used in a restricted way. The decision is up to the user and is a question of configuration. The user should be aware that some of the predefined sorts from ASN.1 are based on the implementation of SDL charstrings. This is discussed in subsection Support of SDL Constructs.

Time/Duration

The predefined data types Time and Duration are implemented in a more or less restrictive way. It is possible to specify a real value for Time and Duration on SDL level, like 23.45. The Cmicro Library uses only the integer part in front of the dot, 23 in this example. The mapping of SDL time units to time units in a target application is -- in any case -- up to the user.

UnionC

The #UNIONC directive is not recommended when using the Cmicro Code Generator because there is no support for checking the validity of the component selection. Both the #UNION directive and the CHOICE concept are a better alternative.

Predefined Generators Array, String, Powerset, Bag, Ref

These generators are implemented in Cmicro, but the user should be aware that the use of any of them requires that dynamic memory allocation is used in the target system. Generally, Cmicro tries to prevent the use of dynamic memory allocation whenever possible. The reasons for this are explained in The Cmicro Library.

ctypes.sdl

This package can be used together with Cmicro with the following restriction.

There are two operators that are excluded when Cmicro C code is compiled. The operators are "CStar2CString" and "CharStar".

The reason for this is that with Cmicro it is possible to define an array of char in C instead of the predefined solution of Cadvanced (to use dynamic memory allocation). This is discussed in subsection Support of SDL Constructs.

idltypes.sdl

This package cannot be used with Cmicro.

access.pr

This ADT cannot be used together with Cmicro because it refers to Cadvanced code.

byte.pr

This ADT can be used together with Cmicro in the same way as described for Cadvanced.

file.pr

This ADT is not useful for typical Cmicro applications (embedded systems usually do not provide a hard disk in Cmicro applications) and for that reason never has been tested. The ADT may however work with Cmicro.

idltypes.pr

This ADT cannot be used together with Cmicro.

idnode.pr

This ADT cannot be used together with Cmicro because it refers to Cadvanced code.

list1/list2.pr

This ADT can be used together with Cmicro.

long_int.pr

This ADT can be used together with Cmicro.

pidlist.pr

This ADT cannot be used together with Cmicro, generally.

Instead of pidlist.pr, the user may include the cm_pidlist.pr file. The use of this ADT is however restricted, because Cmicro implements a different scheduling algorithm. This means, that systems that are successfully simulated first, may contain problems when a Cmicro target application is build and executed.

It is therefore recommended not to use neither pidlist.pr nor cm_pidlist.pr, in order to achieve the best possible SDL conformity.

pointer.pr

This ADT can be used together with Cmicro but the user should be aware of it's own restrictions. For more explanations please see Pointer Types.

random.pr

This ADT can be used together with Cmicro.

unsigned.pr

This ADT can be used together with Cmicro.

unsigned_long.pr

This ADT can be used together with Cmicro.

Default Values

Default values are in principle generated in the same way as with the Cadvanced Code Generator. It is however possible to configure the default value setting, which is explained in The Cmicro Library. The right configuration is essential to prevent illegal behavior.

Exceptions for Implementations of Operators

Read and Write Functions

The Cmicro Code Generator does not provide read and write functions. The reason is, that the Cmicro Code Generator mainly is used to build target applications, and not simulations. This is also a consequence of optimizing the target program. If the user uses the Q (question) operator, the Cmicro Code Generator ignores this.

Error Situations in Operators

In the C function used to implement operators (and literals), it is possible to define error situations and handle them as ordinary SDL run-time errors. The C library function ErrorHandler, with the following prototype

can be used for this purpose. xmk_OPT_INT is defined in ml_typ.h, normally as an ordinary C int. errnum may be one of the free values of error numbers. Please inspect ml_err.h in order to get a list of reserved values.


Example 428 : Error Handler in Operator      

This is a simplified version of the test in the function for the operator First in the sort Charstring. Here the error situation is when we try to access the first character in a charstring of length 0. In this case the C function ErrorHandler is called and a default value is returned (NULL). By including the call to ErrorHandler between #ifdef XMK_USE_ERR_CHECK - #endif the function is only called to report the error, if error checks are turned on. The one parameter to the C function ErrorHandler should identify the error. The number must be given by the user.


Another possibility to route error messages to the host system is to use the C function xmk_PrintString of the Cmicro Tester, defined as:


Example 429 : Error Handler in Operator      

Access to Predefined Sorts based on Charstring

As already mentioned in earlier subsections, the user should be aware that some of the ASN.1 predefined sorts are based on the implementation of SDL charstrings. The user should also refer to subsection Support of SDL Constructs.

To avoid problems one should be aware that Charstring is implemented as char * in C and take the consequences thereof. There are a number of help functions (that implement the operators for the Charstring sort) supplied in the run-time library that might be helpful when handling Charstrings.

It is usually necessary to allocate dynamic memory when an operator returning a charstring value is implemented. There are two help functions that should be used in connection with allocation and de-allocation of dynamic memory. These are documented in Dynamic Memory Allocation.

Caution! 

Do not use Charstring in SDL if you want to get a correct trace output with the Cmicro Tester, or if you want to use the Cmicro Recorder. In the last case, the use of charstring may lead to a fatal error when an SDL session is replayed.

Exceptions for Directives

Selecting File Structure for Generated Code -- Directive #SEPARATE

The purpose of the separate generation feature is to specify the file structure of the generated program. Both the division of the system into a number of files and the actual file names can be specified. There are two ways this information can be given.

The Cmicro Code Generator can generate a separate file for:

Note: 

Instantiations cannot be separated. If #SEPARATE directives are used, they should be placed directly after the first semicolon in the system, block, process, or procedure heading; see the following example.


Example 430 : #SEPARATE Directive      

In the example above the two versions of separate directive, with or without file name, are shown. As can be seen a file name should be enclosed between quotes. The Cmicro Code Generator will append appropriate extensions to this name when it generates code.

If no file name is given in the directive, the name of the system, block, process, or procedure will be used to obtain a file name. In such a case the file name becomes the name of the unit with the appropriate extension (.c .h) depending on contents. The file name is stripped of characters that are not letters, digits or underscores.

The possibility to set up full, user-defined, or no separation in the Organizer's Make dialog and in the user-interface of a stand-alone Analyzer (see Generated Files), can be used in a simple manner to select certain default separation schemes. This setting will be interpreted in the following way:

Independently if No, User defined, or Full separation has been selected, the Cmicro Code Generator will use the file name specified in the Edit Separation dialog or the #SEPARATE directive, for a file that is to be generated.

An Example of the Usage of the Separate Feature

In the following example a system structure and the #SEPARATE directives are given. The same information can easily be set up in the Organizer as well. This example is then used to show the generated file structure depending on selected generation options.


Example 431 : #SEPARATE Directive      

Applying Full Separate Generation

If Full separate generation is selected then the following files will be generated:

Sfile.c      
Sfile.h 
B1.c
B1.h 
P11file.c 

P12.c 

B2.c
B2.h
P21.c 

P22.c 

The .c files contain the C code for the corresponding SDL unit and the .h files contain the module interfaces.

Applying Separate Generation

If User defined separate generation is selected then the following files will be generated:

Sfile.c
Sfile.h

Contains code for units S, B2, P21

B1.c
B1.h

Contains code for units B1, P12

P11file.c

Contains code for unit P11

P22.c

Contains code for unit P22

The user defined separate generation option thus makes it possible for a user to completely decide the file structure for the generated code. The comments on files and extensions given above are, of course, also valid in this case.

Applying No Separate Generation

If the separation option No is selected, only the following file will be generated:

Sfile.c


Contains code for all units

The comments on files and extensions earlier are valid even here.

Guidelines

Generally a system should be divided into manageable pieces of code That is, for a large system, full separate generation should be used, while for a small system, no separate generation ought to be used. The possibility to regenerate and re-compile only parts of a system usually compensate for the overhead in generating and compiling several files for a large system.

Note: 

A file name has to be specified, using the Organizer Edit Separation command or the #SEPARATE directive, if two units in the system have the same name in SDL and should both be generated on separate files. Otherwise the same file name will be used for both units.

Assigning Priorities -- Directive #PRIO

#PRIO for Processes

Priorities can be assigned to processes using the directive #PRIO. The process priorities will affect the scheduling of processes, see Scheduling. A priority is a positive integer, where low value means high priority. #PRIO directives should be placed directly after the process heading in the definition of the current process.


Example 432 : #PRIO Directive      .

Processes that do not contain any priority directive will have a user defined default priority with the name xDefaultPrioProcess.

There are some things to be kept in mind when using process priorities:

#PRIO for Signals

Priorities can be assigned to signals using the directive #PRIO. The signal priorities will also effect the scheduling of processes, see Scheduling.

Signal priorities can be specified, either:

It is impossible to specify #PRIO in a SDL input. Cmicro will ignore any occurrence of #PRIO in SDL input.

Signal priorities do affect the SDL output and the SDL create actions only.

The following rules are to be considered here:

The following example will give more explanations (note, that the values PA, PB are of sort pid):


Example 433 : #PRIO Directive      .

Assuming the following C definition:

the following priorities will then be generated:

Modifying Outputs -- Directive #EXTSIG, #ALT, #TRANSFER

There is no difference for the #EXTSIG, #ALT and #TRANSFER directives for Cmicro compared with Cadvanced, except that the use of it will sometime lead to a better performance. This is because if #EXTSIG for example is used in the case of an output to the environment, the user can prevent the Cmicro Kernel to be called (and the xOutEnv function to be executed).

Output of Code Generation

This section gives an overview of the code generated by the Cmicro Code Generator. This is useful, to make it possible to interpret the generated code. To know how the code is generated makes it quite easy to understand the program which is necessary and useful when testing and debugging erroneous executable programs.

Figure 538 : Structure of the generated C code

Extracted pic [1]

Not all the intricate details of the generated code are described here. The depth of description is sufficient to give the reader a reasonable understanding of the code generation algorithms. Explanations will illustrate what the code looks like, but not why.

The generated code contains several places where prefixes are generated, which consists of a prefix and unique numbering. The following prefix is generated for all objects: "z<nnn>_", where nnn is an incremental number.

Allowance for conditional compilation occurs in several places throughout the generated code. The generated C code is conditionally compiled, for example, for dynamic process creation (create symbol). A differentiation is made between conditional compilations generated by the Cmicro Code Generator (called automatic scaling, prefix XMK_USED_) and conditional compilations which are dependent on header files, which are to be modified by the user (called manual scaling, prefix XMK_USE_).

Note: 

Generally speaking, the ordering of the following subsections corresponds to the ordering in which the code is generated.

Each compilation unit is compiled either in one a.c file or into two files, a.c and a.h.

Only the differences are shown, when comparing the output of SDT C Code Generator with the Cmicro Code Generator. The overall differences of the both code generators are described in the section Differences between Cmicro and Cadvanced.

Header of Generated C File

Code generation on the .c file for the current unit is started by generating the following header:


Example 434 : The Head of a Generated C File      

The XSCT_CMICRO macro can be used by the user to distinguish between the different Code generators, for example within ADT bodies.

TheC_MICRO_x_y macro can be used by the user to distinguish between different versions of the Cmicro Code Generator. This is usually not but might become necessary if the output of the Cmicro Code Generator is different.

TheXMK_C_TIMEmacro is used internally when compiling and linking and executing with the Cmicro Tester takes place. With this macro, a rough consistency check for the generated files is done. The <GenerationTime> of the different files that are generated is compared in the Library, by the BodyBuilder and by the Cmicro Tester. If there is an inconsistency, compilation errors will occur.

The#include "ml_typ.h" is used to include all necessary declarations that the generated C code may use, including automatic scaling from sdl_cfg.h and predefined sorts.

SECTION Types and Forward References

As a difference to SDT C Code Generator, this section contains the definitions for the process IDs and the forward declarations used in the generated C code.

Process IDs are generated as #define values in C, like:

where the first process in the system is the value of 0 assigned, the second process gets the value 1, and so on. Please refer to Generation of Identifiers for more information.

The following forward references are generated:

Following this, the usual declarations are generated as described in The Cadvanced/Cbasic Code Generator.

No synonym variables are generated when using Cmicro.

Symbol Tables

Symbol tables are only generated for the Cmicro Tester, and not into the generated C code. The symbol tables generated for the Cmicro Tester are described within The Cmicro Tester.

Tables for Processes

Tables are used to represent the behavior of SDL objects, like processes and timers. It is not absolutely necessary to understand how these tables are generated and how the Cmicro Kernel works with them. The following subsections are only for those readers interested in the nature of the table structure.

Root Process Table

The root process table contains, for each of the defined SDL process types, a reference (i.e. a pointer) to the Process Description Table. The Cmicro Kernel is the main user of the root process table. Via this table, it can access all SDL process types and all SDL process instance data. The location of the generated root process table is directly before the yPAD-functions in the generated C file. The type definitions used in this table are located in the ml_typ.h module.

Figure 539 : Root process table

Extracted pic [2]


Example 435 : Code of Root Process Table      

C-Type definition (ml_typ.h)      :

C constants (sdl_cfg.h):

C code generation for the whole system:


Symbol Trace Table

In order to reduce the use of dynamic memory allocation, there is a table generated in the code which is used by the Cmicro Tester to store and retrieve test options, like switches, which define the trace.

The table is conditionally compiled and only included if the Cmicro Tester is contained in the target- executable.

The symbol trace table looks like:


Example 436 : Code for Symbol Trace Table      

More information can be obtained by reading The Cmicro Tester.

Instance-Data-Struct

The struct is generated in the header-section of the generated C file.


Example 437 : Code Generation of type definition for each SDL process      

Instances of a given type are represented as a C array. The code generation of variables for each SDL process looks like:


Example 438        

A reference to this array is generated in the Process Description Table which is discussed in the subsection Process Description Table.

Process State Table

This table is generated for each process in the header-section of the generated C file. It contains information about the state of each process instance. The table contains ordinary SDL state values as well as the values XSTARTUP and XDORMANT. XSTARTUP is generated for each instance which is to be statically created (in (x, N) declarations, where x is > 0), XDORMANT is the value which is used to tag a process instance as sleeping. In the case of creation this instance can be reused.


Example 439 : Code for Process State Table      

C typedef for the process state table (located in ml_typ.h):

C code generation for each process:

where <creation-tag> is either XSTARTUP or XDORMANT.



Example 440 :      

Code for a process type with 4 instances, 2 of which are to be created at SDL system start:


A reference to this table is created in the Process Description Table, which is discussed in the subsection Process Description Table.

Transition Table

This is generated in the header-section of the generated C file. It contains all transitions of a process, including asterisk states, asterisk inputs and asterisk save.

The C typedef for the transition table (located in ml_typ.h) is as follows:


Example 441 : Code for Transition Table      

C code generation:

The SymbolNr shown above is used to select the right transition in the switch generated in the yPAD function.

Where the C define

XASTERISK is an ID defining all possible SDL Inputs (asterisk Inputs),

XSAVEID is a simple ID defined in ml_typ.h which can be compared by the SDL Kernel to detect signal-save.

And where:


A reference to this table is created in the Process Description Table.

State Index Table

This is generated in the header section of the generated C file.


Example 442 : Code for State Index Table      

C typedef (ml_typ.h):

C code generation (header of generated C file):


The first value in the above table indicates the beginning of the first state in the Transition Table. If asterisk state definitions are not found in the process, this value is 0.

A reference to this table is created in the Process Description Table.

PID Table

These tables are used to store the values parent and offspring for each process. The reason an extra table is used to store this information is to simplify initialization. The Cmicro Kernel updates the values in the table according to the SDL rules.


Example 443 : Code for PID Table      

C-type definition (ml_typ.h):

C code generation for each process:


A reference to this table is created in the Process Description Table, which is discussed in the subsection Process Description Table.

Process Description Table

For each SDL process, an automatically initialized C structure is generated called process description table. This table is used in the Root Process Table to enable the Cmicro Kernel to access process type information as well as process instance data.

Inspect the following diagram to see which information is contained in the process description table:

Figure 540 : Process description table

Extracted pic [3]

Allocated to each SDL process type is one table yPDTBL_ProcessName.

The type definitions of this table are located in the ml_typ.h module.


Example 444 : Code for Process Description Table      

C typedef for the process description table (ml_typ.h):

C code generation for each process:


For each generated process description table, a new entry in the Root Process Table is generated.

Actions by Processes and Procedures

GR References

No code is generated to evaluate the graphical references during run-time of the SDL system. A large amount of memory is required to store and handle such information which normally proves too large for any real target system.

Alternatively, C comments are generated which make it possible to verify and debug the generated code as illustrated in the following example. The PR <position> indicates in which line number of the SDL-PR file the symbol can be found.

Structure of Process and Procedure Functions

The basic structure of the generated C code for process and procedure definitions remains the same as for the SDT C Code Generator although some modifications are evident.

The code generation for the PAD function is different compared with Cadvanced, in the way that code that is common in process types is copied into the PAD function for instantiated processes.

Procedures follow the same code generation as processes, with some small exceptions in macro naming conventions for variable declarations.

Each SDL process is represented in C by a C function called yPAD_ProcessName.


Example 445 : yPAD_ProcessName      

Local Variables Section

The following defines are generated in the local variables section for processes.


Example 446       

After expansion by the C preprocessor:

The following defines are generated in the local variables section for procedures:


State -- Input Selection

The selection of the appropriate SDL transition which is to be executed in the current state with the current signal in the input port goes in principle over the transition table, described in previous chapters. With this table, the Cmicro Kernel can evaluate a symbol number, which is local to a process, a unique numbering of the different possible transitions. This numbering algorithm begins at 0 (which corresponds to the start symbol) and continues until all symbols for this particular process type have been numbered.

The appropriate transition is selected by the following switch:

After pre-compiling it:

Start Transition

The start transition is included into the body of the generated yPAD function and has the same layout as transitions, with the following exceptions:

Assignment of initialization values to all local variables in the processes and procedures (if any) is executed. All DCL variables are filled with their default-values.

The start transition is selected by the special case-value zero in the switch-statement of the yPAD function.

Note: 

FPARS in dynamic process creation are not contained in this version of the Cmicro Package.

Transitions

The transitions are translated in the order they are found and are only translated to the sequence of actions they consist of. The translation of actions are discussed in the subsection Translation of Actions following a few lines below.

PAD-End-Section

Each yPAD function is finished with:

The main reason for this is to make it possible to integrate other real-time operating systems.

Note: 

Some compilers produce a warning if there is no return at the end of the yPAD function. Other compilers produce a warning "unreachable code", if there is a return at the end of the yPAD function. For this reason, a function returning macro END_PAD exists which can be expanded in accordance with the particular compiler used.

Translation of Actions

Translation of Output

SDL output statements are translated to the following basic structure:

There are a lot of different output macros generated. The main reason for this is that for each output situation an optimized code is to be generated.

One differentiation is made for signals without parameters and signals with parameters. For a signal without parameters, suffix _NPAR is used for the macro generated and for a signal with parameters, suffix _PAR is used. The relevant output macro can then be expanded to a simpler output C function called xmk_SendSimple, if no signal priority is used.

Another differentiation is made for signals which are sent to the system's environment or which are sent internally in the SDL system. The suffix _ENV is appended to the macros which are shown here, if the signal should go to the system environment.

The different directives which can be used within SDT to modify outputs are discussed in subsection Modifying Outputs -- Directive #EXTSIG, #ALT, #TRANSFER.

The other different output situations which are handled, will be described in the next subsections.

Output without TO and without VIA

If the user specifies output SignalName without TO and VIA in SDL, the Cmicro Code Generator calculates the receiver of the signal. It is also possible to have more than one receiver for the signal. During execution time, any possible receiver that are alive may be selected otherwise if no receiver can be found, the C function ErrorHandler will be called. The following code is generated:

Note: 

The ppp above stands for either PAR or NPAR for a Signal with or without parameters.

After expansion, the user will find a C function call to the xmk_SendSimple function or the xmk_Send function.

Priority is generated as xDefaultPrioSignal if no priority is specified for the signal with #PRIO.

TO_PROCESS is expanded to a function call if there is at minimum one (x, N) declaration in the system, where N is > 1. This function returns one of the possible receivers of the signal.

TO_PROCESS selects an active instance of the given process type It does not check for different types as receivers.

TO_PROCESS is expanded so that the pid is passed directly to one of the C functions xmk_Send*, if there are only (x,1) declarations in the system.

If the environment is the receiver of the signal, then the following code is generated:

Note: 

The ppp above stands for either PAR or NPAR for a Signal with or without parameters.

After expansion, the user will find that ENV is passed to one of the C functions xmk_SendSimple or xmk_Send. ENV is a special value used inside the Cmicro Kernel to detect which signals are to be passed to the C function xOutEnv.

Output with TO clause

If the user specifies the output SignalName to pid in SDL, the Cmicro Code Generator generates the following code:

Note: 

The ppp above either stands for PAR or NPAR for a Signal with or without parameters.

Expansion reveals a C function call to the xmk_SendSimple function or the xmk_Send function.

Priority is generated as xDefaultPrioSignal, if no priority is specified for the signal with #PRIO.

Possible generated values for pid variable are SDL_SENDER, SDL_PARENT, SDL_OFFSPRING and SDL_SELF or an SDL pid variable. These values are passed to the xmk_Send* functions. The name of a process as specified in SDL may also be given.

Output with VIA clause

The Cmicro Code Generator computes the possible receivers in an output with the VIA clause. If there are several possible receivers, an error message is produced.

If there is exactly one receiver, the same code is generated as for SDL output without to.

List of Generated Output Macros
Translation of Create

The create action in SDL is translated to the following C code:

Note: 

The ppp above stands for either PAR or NPAR for a Signal with or without parameters.

PriorityofCreatedProcess is generated as
xDefaultPrioProcess, if no priority is specified with #PRIO.

Translation of Set

The translation of set is restricted in a few areas in order to produce efficient code for a micro controller. For example, the SDL duration expressed by a real value in the context of timers is not implemented. The reason for this is that controllers do not have floating point operations or floating point operations are not used in order to increase the performance. For timers, such a high resolution is not necessary in most applications. The Cmicro Package uses a long value in its standard implementation to represent absolute time.

In order to make the examples below more readable, it is assumed that at least one timer with parameter is used in the system (macro XMK_USED_TIMER_WITH_PARAMS is defined in the generated file sdl_cfg.h). If the macro is not defined, then the handling for timers with parameters is not included.


Example 447       

If the following is specified in SDL-PR:

or

then the following code is generated:



Example 448       

If the following is specified in SDL-PR:

then the following code is generated:

The code after expansion then contains a function call to

TIMEEXPR is the result of the evaluation of now plus duration value.



Example 449       

If a timer with parameter is defined in SDL-PR:

then the following code is generated:

The code after expansion then contains a function call to


Restrictions in the Use of Timers
Translation of Reset

If the user specifies in SDL-PR:

then the following code is generated:

The code after expansion contains a function call to xmk_TimerReset (TimerNamewithPrefix).

For a timer with one integer parameter, the following macro call is generated:

Note: 

Timers with parameters are supported with the restriction that only one integer parameter is allowed.

Translation of Call

As SDL procedures are implemented with the restrictions explained within subsection SDL Restrictions, the following explanatory C code (to a procedure called ex_proc) is generated:

All necessary parameters are routed via the C function call stack.

Translation of Call to a Procedure Returning Value / Operator Diagram

Operator diagrams and procedures returning values are -- considering the call -- handled in the same way please see the following explanatory example:


Example 450 : Procedure Call      

Note: 

The value of returning procedure calls are transformed to C functions returning values.

Translation of Nextstate

The nextstate operation is generated at the end of each transition contained in the yPAD function, as follows:

Translation of Stop

A stop action is translated to:

which is defined as

which is good code saving. The Cmicro Kernel then enters the new state value into the Process State Table.

Note: 

This table contains ordinary SDL state values as well as the values XSTARTUP and XDORMANT. XSTARTUP is generated for each instance which is to be statically created (in (x, N) declarations, where x is > 0). XDORMANT is the value which is used to tag a process instance as sleeping. In the case of creation this instance can be reused.

Translation of Return

The macro definitions are:

where xxptr is the pointer to the procedure instance data, as given via the C function call parameter list. Note, that the memory previously allocated directly before the procedure call is freed at the end of the procedure, not outside of the procedure.

Translation of SDL Expressions

In this section some of the translation rules for expressions are described. For more information see Translation of Sorts where for example the translation rules for literals and operators in the predefined abstract data types are given.

Now

SDL now is translated to the macro SDL_NOW which is expanded to the C function xmk_NOW. This function is exported by the module mk_stim.c.

Self, Parent, Offspring, Sender

The definitions for self, parent, offspring, sender are:

All the variables above are of type xPID. All variables are maintained by the Cmicro Kernel. xRunPID is a global variable which contains the pid of the SDL process which is currently running. P_MESSAGE is a pointer to the signal instance which is currently worked on.

Timer Active

An SDL timer active expression is translated to:

which is expanded to:

A conditional expression in SDL is translated to a conditional expression in C.

Init Function

An explicit initialization function is not generated by the Cmicro Code Generator in any case.

The structure of the SDL system is not generated into the C code. What is seen in the generated code, is the behavior of the SDL system. Variables of processes are initialized during the start transition of a process and no information about the structure of the SDL system is available during run-time in the generated code.

An initialization function is generated only in that case if synonyms are used within SDL, which require an initialized C variable.

All this results in a more compact executable.

For example, the following use of an SDL synonym results in a generated initialization function:

The following C code is then generated within the C function yInit:

yInit is called by the Cmicro Kernel if the define

is generated into the file sdl_cfg.h, which is done in the case above.

Initialization of Synonyms

The Cmicro Code Generator allows SDL synonyms to be implemented as C macros and C variables.

Initialization is implemented within the C function yInit which is conditionally compiled.

Function main

The C function main is not automatically generated by the Cmicro Code Generator. This is unnecessary because the main function usually is provided from the user or the predefined main function can be used. Instead of an automatically generated main function, the user must supply the function body of main, for target applications. Guidelines can be found in the subsection Implementation of Main Function.

Symbol Table File

The structure of an SDL system can be represented by a tree diagram. In SDL the root of the tree is represented by the SDL system followed by blocks, block substructures, processes and procedures1. Channels, channel substructures and signal routes are also represented in the tree. This tree is static, which means it cannot be modified during the run-time of an SDL system.

The SDT Code Generator generates code so that this static structure is present in the generated code. This is good for debugging purposes.

The Cmicro Code Generator generates code so that this static structure is not present in the generated code, in order to spare memory. To enable debugging of the generated code, C comments are generated. Please consult the subsection GR References.

A symbol table is necessary for the Cmicro Tester running on the host or the development system.

For more information consult The Cmicro Tester.

Generation of Identifiers

Processes and Process IDs (PID)

In order to implement the environment functions, it is important to notice that process IDs in Cmicro are generated into the sdl_cfg.h file, which must be included by the user's environment C module. These IDs are coded like it is described in Generated Configuration File. More explanations are given in the following.

Since process IDs might become ambiguous, especially in block type and process type instantiations in SDL'92, the names of process IDs that are to be used in the environment functions are to be given a prefix. Using this prefix within the environment functions (xInEnv), it can be guaranteed that different process IDs (equates to "instance sets" in SDL'92) with the same name can be distinguished, which is necessary in order to send signals to the right process instance within the SDL system. On the other hand, prefixes are not necessary when all the process instance sets within the system have a different name. The Cmicro Code Generator uses an algorithm to calculate the prefixes in the most convenient way.

For example, if a process named "myprocess" exists only once within the SDL system, there will be no automatic prefix generated, e.g. the full process ID is

If, as another example, the process "myprocess" exists twice, for example once within a block called "myfirstblock" and once more within a block called "mysecondblock", the Cmicro Code Generator then creates two definitions which guarantee that the processes can be distinguished:

In this way, by adding scope names (block names), prefixes are always generated in a way so that no naming conflicts occur. Of course, for process and block type instantiations, the name of the instance is being used to generate this unambiguous prefix.

SDL process types (process instance sets in SDL'92), as well as SDL process instances are numbered consecutively beginning with zero. The ordering of these numbers is the same as the ordering of the processes in the SDL-PR file.

The values 250 to 255 are reserved for internal purposes and must not be used for process type numbering. The BodyBuilder checks this rule automatically. For small systems this does not create any problems.

The Cmicro Kernel assumes the above definitions.

In the generated C code, the SDL values self, sender, parent and offspring, and variables of this type are represented by the typedef xPID. The intention is to have unique numbering of processes and their instances in the whole SDL system. This becomes necessary because of the Cmicro Code no longer containing the structure of the SDL system (system, block...). The typedef xPID is defined as

or

There are a few macros defined to extract the process type number or the process instance number from a variable of the type xPID and to build an xPID variable from a process type number and a process instance number, the users do not have to think about the internal representation:


Example 451 : Macros to extract process type or instance number      

Signals and Timers

SDL signals and timers are numbered automatically by the Cmicro Code Generator so that they have a unique number over the complete system. Timers are represented by the values 1, 2, 3.... MT to the last timer of the MT timers in the system. After that follow ordinary SDL signal numbers beginning with MT+1, MT+2, MT+3... MT + MS.

When using the standard Cmicro Package, as delivered, then the values 0 and 251 to 255 are reserved for internal purposes. If the upper limit of 250 signals and timers is being reached, then the signal ID type has to be changed from unsigned char to unsigned int, thus allowing more than 60000 signals/timers to be handled. All these changes will be done if the flag XMK_USE_MORE_THAN_250_SIGNALS is set.

Caution! 

The Cmicro Code Generator does not check for the upper limit of 250 signals being reached for a generated SDL system. The user will get no warning if 251 or more signals are used. Normally, SDL systems grow through their development and maintenance phases and the user must ensure that this upper limit is not reached.

The BodyBuilder will check the amount of signals and timers in the SDL system and will inform the user during start-up.


Example 452 :       

C code generated for signals and timers:


Where znnn_ is the automatically generated prefix which is required to cope with the SDL scope rules. Remember, that processes in SDL can have the same name as signals, states etc. Prefixing, however, ensures uniquely named SDL objects in the generated C Code.


Example 453 :       

A system with 2 signals S1 and S2, and a timer TIMER1:


When it comes to connecting the environment to the SDL system, the automatic numbering of signal IDs and timer IDs may not be required. If the user wants to prevent the automatic numbering of signals, then it is possible to #include a file containing all the signal and timer numbers. The file may contain something like:

States

SDL states are consecutively numbered from 1 through to N for each process type. The values 0, and 250 to 255 are reserved for internal purposes in the Cmicro Package. This restriction incurs no foreseeable difficulty as processes should never have more than 50 States as a recommendation.

If there are even more states per process the flag XMK_USE_HUGE_TRANSITIONTABLES must be set.

The following C code generation is supplied for the header-section of the generated C file(s).

For each SDL process:


Example 454 :       

For a process with 2 states S1 and S2:


These values are used in the state-index-table and in the generated C functions, wherever a nextstate is referenced.

SDL Restrictions

General

The SDT Cmicro Code Generator handles SDL concepts according to the definition of SDL-92. In addition to the restrictions of all the SDT C Code Generators, the following additional restrictions are introduced for the Cmicro Code Generator:

The following restrictions are additional regarding the packages that are delivered together with SDT.

sdth2sdl

It is impossible to read in header files created with Cadvanced and use them in Cmicro and the other way around. The reason is that it is impossible to mix up C code between Cadvanced/Cbasic and Cmicro.

Combining Cadvanced / Cmicro C Code

Mixing C code from different C Code Generators is not possible as the different code generators use their own run-time model and run-time data structures. Trying to mix up the C code will lead to compilation errors.

CORBA / IDL / ITEX

There is no such interface available for Cmicro and the existing interfaces in SDT cannot be used.

Light and Tight Integrations

The Light and Tight Integrations delivered with SDT are only available for Cadvanced but not applicable to Cmicro. There are light and tight integrations for Cmicro but these are not part of the product.

Restrictions in Combination with Cmicro Tester

Scope Rules / Qualifiers

If the Cmicro Tester is to be used, then the scope rules of SDL are handled in a restrictive fashion. No information is generated for the system, block, block substructure, channel and signalroute. After applying the Cmicro Code Generator, all the structuring information is lost.

This means that it is impossible to address two different processes with the same name in different blocks. In order to avoid problems, give all processes, signals and timers in the system a different (unique) name.

Predefined Sorts

The predefined sort charstring and all the predefined sort that are based on the implementation of charstring (like predefined sorts from ASN.1) cannot be handled, if the Cmicro Tester is to be used. All predefined sorts which are generated into pointers in C cannot be used. In order to get a detailed description, please see in The Cmicro Tester.

Analyzer Restrictions

The restrictions in the SDT Analyzer, which also affects the Cmicro Code Generator, are summarized in The SDT Analyzer.


1. In SDL-92 several SDL systems can exist in parallel.


[Previous] [Next] [Contents] [Index]