IBM
Contents Index Previous Next



Output of Code Generation


This section gives an overview of the code generated by the Cmicro SDL to C Compiler. 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 586 : Structure of the generated C code

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 SDL to C Compiler (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 SDL to C Compiler with the Cmicro SDL to C Compiler. 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 584 : The Head of a Generated C File

/* Program generated by the SDL Suite.Cmicro, 
version x.y */
#define XSCT_CMICRO

#define C_MICRO_x_y
#define XMK_C_TIME <GenerationTime>
#include "ml_typ.h"

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

The C_MICRO_x_y macro can be used by the user to distinguish between different versions of the Cmicro SDL to C Compiler. This is usually not but might become necessary if the output of the Cmicro SDL to C Compiler is different.

The XMK_C_TIME macro is used internally when compiling and linking and executing with the SDL Target 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 and by the SDL Target 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 SDL to C compiler, 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:

#define XPTID_<UniquePrefix>_MyProcess 0

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:

extern XCONST XPDTBL yPDTBL_<UniquePrefix>_MyProcess;

Following this, the usual declarations are generated as described in The Cadvanced/Cbasic SDL to C Compiler.

No synonym variables are generated when using Cmicro.

Symbol Tables

Symbol tables are only generated for the SDL Target Tester, and not into the generated C code. The symbol tables generated for the SDL Target Tester are described within The SDL Target 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 587 : Root process table

Example 585 : Code of Root Process Table

C-Type definition (ml_typ.h) :

extern xPDTBL yPDTBL [];/* for the Cmicro Kernel */
#define X_END_ROOT_TABLE/* Table-End Marker of yPDTBL*/

C constants (sdl_cfg.h):

#define MAX_SDL_PROCESS_TYPES <N>

/* <Process-type-id´s>  Process Types are numbered */
/* from 0 to N-1(see chapter "Generating PID") */
#define XPTID_Process1Name 0
#define XPTID_Process2Name 1
#define XPTID_ProcessnName N-1

C code generation for the whole system:

XPDTBL yPDTBL [MAX_SDL_PROCESS_TYPES+1] =
{
  yPDTBL_ Process1Name,
  yPDTBL_ Process2Name,
  ......
  yPDTBL_ ProcessnName,
  X_END_ROOT_TABLE
}

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 SDL Target Tester to store and retrieve test options, like switches, which define the trace.

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

The symbol trace table looks like:

Example 586 : Code for Symbol Trace Table

/*************************************************************
**  Symbol trace table
*************************************************************/
#ifdef XMK_ADD_TEST_OPTIONS
XSYMTRACETBL *xSYMTRACETBL[MAX_SDL_PROCESS_TYPES+1] =
{
  (XSYMTRACETBL_ENTRY *)  NULL, /* for first Processtype */
  (XSYMTRACETBL_ENTRY *)  NULL, /* for second Processtype */
  ........
  ........
  (XSYMTRACETBL_ENTRY *)  NULL, /* for last Processtype */
  X_END_SYMTRACE_TABLE /* table end marker */
};
#endif

More information can be obtained by reading The SDL Target Tester.

Optimized Decision Trace information

An option to reduce the trace information for SDL decisions by showing only the first ten characters of the decision expression during trace. Setting the environment variable CMICRO_SHORT_DECISION_TRACE to any value prior to the Cmicro code generation is started, will have the effect on the generated C code that all xTraceDecision<parameter> statements will contain a parameter that is the first ten characters of the decision expression instead of the complete expression. This will reduce the trace information for systems that contain a lot of decisions.

Instance-Data-Struct

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

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

typedef struct {
  PROCESS_VARS
  TypeName1  FPAR_var1;
  TypeName2  FPAR_var1;
  TypeName3  DCL_var1;
  TypeName4  DCL_var2;
  TypeName4  yExp_DCL_var2;
  TypeName5  FPAR_var1;
} yVDef_ProcessName;

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

Example 588

#define X_MAX_INST_ProcessName 	 upperlimitofprocessinstances1

static yVDef_ ProcessName
yINSTD_ProcessName[X_MAX_INST_ProcessName];

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 589 : Code for Process State Table

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

typedef u_char xSTATE; /* see defines below */
#define XSTARTUP 0xff  /* valid only if xSTATE is */
                       /* u_char else 0xffff */
#define XDORMANT 0xfe  /* valid only if xSTATE is */
                       /* u_char, else 0xfffe */

C code generation for each process:

static xSTATE yPSTATETBL_znn_ProcessName  
                                [X_MAX_INST_znn_ProcessName] = 
{
  <creation-tag>  /* Instance 0 */
  <creation-tag>  /* Instance 1 */

  <creation-tag>  /* Instance M-1 */
};

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

Example 590 :

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

static xSTATE yPSTATETBL_znn_ProcessName [4] = 
{
  XSTARTUP, /* Create at SDL-system-start */
  XSTARTUP, /* Create at SDL-system-start */
  XDORMANT, /* Create later               */
  XDORMANT  /* Create later               */
};

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 591 : Code for Transition Table

typedef struct {
  xINPUT    SignalID; /* Input, Asterisk-Input. */
                      /* Input is Timer */

                      /* and/or ordinary Signal */
  xSYMBOLNR SymbolNr; /* Symbolnumber to be used */
                      /* in yPAD-function */
} xTR_TABLE_ENTRY;

C code generation:

static XCONST xTR_TABLE_ENTRY   yTRTBL_znn_ProcessName 	 
                                [XMAX_TRANS_znn_ProcessName]= 
{
  /* state_0-table */
  input_1, SymbolNr,
  input_2, SymbolNr,
  XASTERISK,XSAVEID /* asterisk save */

  input_N, SymbolNr,

  /* state_1-table */
  ...............
  ...............
  /* state_j-table */
  input_1, SymbolNr,
  input_2, SymbolNr,

  input_N, trans_jN,
  XASTERISK,XSAVEID /* asterisk save */
};

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:

#define XASTERISK	    -1
#define XSAVEID	      xSave

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 592 : Code for State Index Table

C typedef (ml_typ.h):

typedef   u_char xSTATE_INDEX;

C code generation (header of generated C file):

static xCONST xSITBL   xSTATE_INDEX_znn_ProcessName 
                         [<count_transitions_of_ProcessName] =
{
  0, /* i.e.a process with 3 states, but no asterisk states */
     /* state_0 has 2 transitions */
  2, /* state_1 has 5 transitions */
  7, /* state_2 has 3 transitions */
  10 /* table-end-index XI_TABLE_END */
};

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 593 : Code for PID Table

C-type definition (ml_typ.h):

#ifdef XMK_USE_PID_ADDRESSING
  typedef struct
  {
    #ifdef XMK_USE_SDL_PARENT
      xPID            Parent;
    #endif

    #ifdef XMK_USE_SDL_OFFSPRING
      xPID            Offspring;
    #endif

  } xPIDTable;
#endif

C code generation for each process:

/*-----------Process-PID-Values-------------*/
#ifdef XMK_USE_PID_ADDRESSING
  static xPIDTable yPID_TBL_z00_P1[X_MAX_INST_z00_P1];
#endif

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 588 : Process description table

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 594 : Code for Process Description Table

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

typedef struct {
  #ifdef XMK_USE_PID_ADDRESSING
    xPIDTable  *pPIDTable; /* Table with */
                           /* Parent/OffspringValues */
  #endif

  xINSTD      *pInstanceData ; /* Pointer to Instancedata*/
                               /* Vector                    */
  xINSTDLEN    DataLength ;  /* Length of Instancedata  */
                               /* for 1 Instance            */
                               /* (used by SDL-BS)          */
  unsigned char MaxInstances ; /* Max.Number of Instances*/

  #ifdef XMK_USE_TIMESLICE
    /* Time-Slices can be individually specified by the user*/
    /* The value stored in TimeSlice is measured in ticks   */
    /* The Cmicro Kernel has to be scaled to handle     */
    /* timeslicing */
    xmk_T_TIMESLICE TimeSlice;
  #endif

  #ifdef XMK_USE_PREEMPTIVE
    /* Process-Priority can be specified with #PRIO on the */
    /* SDL-Level. It is available only, if the Cmicro    */
    /* Kernel is scaled to handle preemption. */
    xmk_T_PRIOLEVEL PrioLevel;/*Priority of this processtype*/
  #endif

  xmk_T_TRANS_ADDRESS yPAD_Function ; /* Address of the */
                                      /* yPADFunction */
  xTRTBL TransitionTable ;  /* Pointer to transition table */
  xSITBL *StateIndexTable ; /* Pointer to state index table */
  xSTATE *ProcessStateTable;/* Pointer to process state table 
*/
} XPDTBL;

C code generation for each process:

#define X_MAX_INST_ProcessName 	 1

xPDTBL yPDTBL_ProcessName = 
{
  yPID_TBL_znn_<process:N>,
(xINSTD*) yINSTD_znn_ProcessName,
  X_MAX_INST_znn_ProcessName,
  (xmk_T_TRANS_ADDRESS) yPAD_znn_ProcessName,
  yTRTBL_znn_ProcessName;
  xSTATE_INDEX_znn_ProcessName,
  yPSTATETBL_znn_ProcessName;
};

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.

For processes : 
/*************************************************************
**  PROCESS <process-name>
**  <<SYSTEM <system-name>/BLOCK <block-name>>
**  #SDTREF(<reference>)
*************************************************************/

For signals :
/*************************************************************
**  SIGNAL S1
**  <<SYSTEM <system-name>/BLOCK <block-name>>
**  #SDTREF(<reference>)
*************************************************************/

For yPAD-function
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
** Function for process <process-name>
** #SDTREF(<reference>)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

For output :
/*-----
** OUTPUT <signal-name>
** #SDTREF(<reference>)
------*/

For nextstate :
/*-----
** NEXTSTATE <state-name>
** #SDTREF(<reference>)
------*/

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 SDL to C compiler 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 595 : yPAD_ProcessName

/* Function for process ProcessName */
#ifndef XNOPROTO
extern YPAD_RESULT_TYPE yPAD_ProcessName ( YPAD_ANSI_PARAM )
#else
extern YPAD_RESULT_TYPE yPAD_ProcessName ( YPAD_KR_PARAM )
  YPAD_KR_DEF
#endif
{
  local variable section
  State-input-selection
  {
    start-transition including nextstate
    transition-1 including nextstate
    transition-2 including nextstate
    .......
    transition-n including nextstate
  }
  pad-end-section
}

/* Function for procedure ProcedureName */
#ifndef XNOPROTO
extern YPRD_RESULT_TYPE yPAD_ProcedureName ( YPRD_ANSI_PARAM )
#else
extern YPRD_RESULT_TYPE yPAD_ProcedureName ( YPRD_KR_PARAM )
  YPRD_KR_DEF
#endif
{
  local variable section
  section representing procedure body
}

Local Variables Section

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

Example 596

YPAD_YSVARP             /* used for signal variable pointers 
*/
YPAD_YVARP(yVDef_z00_P1)/* used for process variables	  */
YPAD_TEMP_VARS          /* used for temporary variables */
YPRSNAME_VAR("P1")      /* can be used for printf */
BEGIN_PAD               /* used for some preparations */
                        /* to handle signals, or Integration*/
                        /* of any Realtime operating system */

After expansion by the C preprocessor:

yVDef_z00_ProcessName *yVarP
                          =(yVDef_z00_ProcessName *)pRunData;
unsigned char *yOutputSignal; 
unsigned char *ySVarP; 
                   
(void) printf(("PROCESS:%s\n", "ProcessName"));

if((P_MESSAGE != ((void *) 0))
    && (P_MESSAGE->mess_length > 4))
{ 
  ySVarP = (unsigned char *) P_MESSAGE->mess_ud.pt_ud; 
} 
else 
{ 
  ySVarP = (unsigned char *) P_MESSAGE->mess_ud.ud; 
} 

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

YPRD_YVARP(yVDef_znnn_ProcedureName)
/* used for procedure variables */

YPRD_TEMP_VARS
/* used for temporary variables */

YPRDNAME_VAR("ProcedureName")
/* can be used for printf */

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:

switch (XSYMBOLNUMBER) {
{
  case 0:. start-transition
  nextstate;

  case 1: transition-1 
  nextstate;
}

After pre-compiling it:

switch (_xSymbolNumber_ ) 
{
  .....
}

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:

END_PAD (yPAD_ProcessName);

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 the SDL Suite 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 SDL to C Compiler 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:

ALLOC_SIGNAL_ppp(SignalNamewithoutPrefix,
                 SignalNamewithPrefix,
                 SignalParameterTypeStructureName)

ordinary assignment of Signal Parameters, if there are some...

SDL_OUTP_ppp(Priority,
             SignalNamewithoutPrefix,
             SignalNamewithPrefix,
             TO_PROCESS(ProcessNamewithoutPrefix,
                        ProcessNamewithPrefix), 
             SignalParameterTypeStructureName,
             "SignalNamewithoutPrefix") 

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:

ALLOC_SIGNAL_ppp(SignalNamewithoutPrefix,
                 SignalNamewithPrefix,
                 SignalParameterTypeStructureName)
ordinary assignment of Signal Parameters, if there are any...
SDL_OUTP_ppp_ENV(Priority, 
                 SignalNamewithoutPrefix,
                 SignalNamewithPrefix,
                 ENV,
                 SignalParameterTypeStructureName,
       "SignalNamewithoutPrefix")

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 SDL to C Compiler generates the following code:

ALLOC_SIGNAL_ppp(SignalNamewithoutPrefix,
                 SignalNamewithPrefix,
                 SignalParameterTypeStructureName)
ordinary assignment of Signal Parameters, if there are some...
SDL_OUTP_ppp(Priority, 
             SignalNamewithoutPrefix,
             SignalNamewithPrefix,
             pid-variable,
             SignalParameterTypeStructureName,
             "SignalNamewithoutPrefix") 

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 SDL to C Compiler 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:

ALLOC_STARTUP_ppp(ProcessNamewithoutPrefix,
                  ProcessNamewithPrefix,
                  "ProcessNamewithoutPrefix, 0);

....assignment of start-up values (cannot be used in this version of the Cmicro Package)
SDL_CREATE(ProcessNamewithoutPrefix,
           ProcessNamewithPrefix,
           "ProcessNamewithoutPrefix, 0,
           VariableofCreatedProcess,
           PriorityofCreatedProcess,
           yPAD-functionNameofCreatedProcess);

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 597

If the following is specified in SDL/PR:

Timer TimerName;
	 ......
Set (now + durationvalue, TimerName) ;

or

Set (now + 22222, TimerName) ;

then the following code is generated:

SDL_SET_DUR  \
(xPlus_SDL_Time(SDL_NOW,SDL_DURATION_LIT(22222.0,22222,0)),
            SDL_DURATION_LIT(22222.0, 22222, 0), 
            TimerName, 
            TimerNamewithPrefix, 
            yTim_timer2,
            "TimerNamewithoutPrefix")

Example 598

If the following is specified in SDL/PR:

Timer TimerName := TimerGroundValue ;---> see Note:!

then the following code is generated:

SDL_SET_TICKS
(xPlus_SDL_Time(SDL_NOW, TICKS(SDL_INTEGER_LIT(22222))),
              TICKS(SDL_INTEGER_LIT(22222)), 
              TimerName, 
              TimerNamewithPrefix, 
              yTim_timer2,
              "TimerNamewithoutPrefix")

The code after expansion then contains a function call to

 xmk_TimerSet (TIMEEXPR,TimerNamewithPrefix,0). 

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

#define SDL_SET_DUR(TIME_EXPR, DUR_EXPR, TIMER_NAME,  
        TIMER_IDNODE, TIMER_VAR, TIMER_NAME_STRING) \
xmk_TimerSet(TIME_EXPR, TIMER_IDNODE,0);

#define SDL_SET_TICKS(TIME_EXPR, DUR_EXPR, TIMER_NAME, 
        TIMER_IDNODE, TIMER_VAR, TIMER_NAME_STRING) \
xmk_TimerSet(TIME_EXPR,TIMER_IDNODE,0);

Example 599

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

Timer TimerName (integer);
...
set (now+1, TimerName (4711));


then the following code is generated:

SDL_SET_DUR_WITH_1IPARA(xPlus_SDL_Time(SDL_NOW,
                       SDL_DURATION_LIT(1.0, 1, 0)), 
                       SDL_DURATION_LIT(1.0, 1, 0), TimerName,
                       TimerNamewithPrefix, 
                       yPDef_z262_twp1,
                       yTim_TimerName,
                       "TimerName",
                       SDL_INTEGER_LIT(4711))

The code after expansion then contains a function call to

 xmk_TimerSet (TIMEEXPR,TimerNamewithPrefix,4711). 

Restrictions in the Use of Timers
Translation of Reset

If the user specifies in SDL/PR:

Reset (TimerName) ;

then the following code is generated:

SDL_RESET(TimerNamewithoutPrefix,
          TimerNamewithPrefix,
          yTim_TimerName)

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:

SDL_RESET_WITH_1IPARA(TimerNamewithoutPrefix,
                      TimerNamewithPrefix,
                      TimerParStruct,
                      yTim_TimerName,
                      TimerValue)

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:

ex_proc (....C parameters ...);

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 600 : Procedure Call

TASK i := (call p(1)) + (call Q(i,k));

is translated to something like:
i = p(1) + Q(i,k);

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:

SDL_STOP

which is defined as

return (XDORMANT);

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
#ifdef XFREEVARS
  FREE_PROCESS_VARS ()
#endif

SDL_RETURN

The macro definitions are:

#define SDL_RETURN \
        if (_xxptr != (unsigned char*) NULL) \
        { \
          XMK_MEM_FREE ((unsigned char *)_xxptr); \
        } \
        return ;

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:

#ifdef  XMK_USED_SELF
#define SDL_SELF               xRunPID
#endif

#ifdef  XMK_USED_PARENT
#define SDL_PARENT             pRunPIDTable->Parent
#endif

#ifdef  XMK_USED_OFFSPRING
#define SDL_OFFSPRING          pRunPIDTable->Offspring
#endif

#ifdef  XMK_USED_SENDER
#define SDL_SENDER             P_MESSAGE->send
#endif

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:

SDL_ACTIVE(TimerName, TimerName,
  yTim_TimerName)

which is expanded to:

xmk_TimerActive(TimerName)

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 SDL to C Compiler 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:

synonym a integer := /*#CODE anyUserFunction () */

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

yAssF_SDL_Integer(a, anyUserFunction (), XASS);

yInit is called by the Cmicro Kernel if the define

XMK_USED_INITFUNC

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

Initialization of Synonyms

The Cmicro SDL to C Compiler 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 SDL to C Compiler. 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.


http://www.ibm.com/rational
Contents Index Previous Next