IBM
Contents Index Previous Next



Compilation Switches


The compilation switches are used to decide the properties of the Master Library and the generated C code. Both in the library and in generated code #ifdefs are used to include or exclude parts of the code.

The switches that are used can be divided into four groups.

  1. Switches defining properties of the compiler.
  2. Switches defining a library version.
  3. Switches defining a property of a library version.
  4. Switches defining the implementation of a property.

The first group will be discussed in Adaptation to Compilers.

The following switches define the library version:

Switch Corresponds to Library
SCTDEBCOM

Simulation

SCTDEBCLCOM

RealTimeSimulation

SCTAPPLCLENV

Application

SCTDEBCLENVCOM

ApplicationDebug
(Simulation with environment)

SCTPERFSIM

PerformanceSimulation
(Library with simulated time, no environment functions, no monitor.)

The definition of the properties of these libraries can be found in scttypes.h and will be discussed below. Each library version is specified by the switches in the group property switches that it defines.

New library versions, containing other combinations of property switches, can easily be defined by introducing new library definitions in the scttypes.h file.

The property switches discussed below can be used to form library versions. If not stated otherwise for a certain property, all code, variables, struct components, and so on, are either included or excluded using conditional compiling (#ifdef), depending on whether the property is used or not.

This means, for example, that all code for the monitor interface will be removed in an application not using the monitor, which makes the application both smaller and faster.

Description of Compilation Switches

XCLOCK

If this compilation switch is not defined then simulated time is used, otherwise the system time is connected to a real clock, via the sctos.c function SDL_Clock.

XCALENDARCLOCK

This is the same as XCLOCK (it will actually define XCLOCK), except that if XCLOCK is used, time will be zero at system start up, while if XCALENDARCLOCK is used, time will be whatever the clock returns at system start up.

XPMCOMM

Define this compilation switch if the application should be able to communicate with signals via the SDL Suite communication mechanism. This facility is used to accomplish communicating simulations and simulations communicating with, for example, user interfaces.

XITEXCOMM

This switch should be defined if a generated simulator should be able to communicate with a TTCN simulator.

XENV

If this compilation switch is defined the environment functions xInitEnv, xCloseEnv, xInEnv, and xOutEnv will be called at appropriate places.

XTENV

This is the same as XENV (it will actually define XENV), except that xInEnv should return a time value which is the next time it should be called (a value of type SDL_Time). The main loop will call xInEnv at the first possible occasion after the specified time has expired, or when the SDL system becomes idle.

XENV_CONFORM_2_3

This switch make signals using a compatible data structure as in SDT 2.3. This means that an extra and unnecessary component yVarP is inserted in each signal.

XSIGLOG

This facility makes it possible for a user to implement his own log of the major events in the system. This compilation switch is normally not defined. By defining this switch, each output of a signal, i.e. each call of the function SDL_Output, will result in a call of the function xSignalLog. Each time a transition is started, the function xProcessLog will be called.

These functions have the following prototypes:

extern void xSignalLog
  (xSignalNode  Signal,
   int          NrOfReceivers,
   xIdNode    * Path,
   int          PathLength);

extern void xProcessLog
  (xPrsNode P);

which are included in scttypes.h if XSIGLOG is defined.

Signal will be a pointer to the data area representing the signal instance.

NrOfReceivers will indicate the success of the output according to the following table:

NrOfReceivers Output Statement Contents

-1:

A TO clause, but no path of channels and signal routes were found between the sender and the receiver.

0:

No TO clause, and no possible receivers were found in the search for receivers.

1:

If the output statement contains a TO clause, a path of channels and signal routes was found between the sender and the receiver.
If the output statement contains no TO clause, exactly one possible receiver was found in the search for receivers.
The output was thus successful. The only error situation that still might be present is if an output with a TO clause is directed to a process instance that is stopped.

The third parameter, Path, is an array of pointer to IdNodes, where Path[0] refers to the IdNode for the sending process, Path[1] refers to the first signal route (or channel) in the path between the sender and the receiver, and so on, until Path[PathLength] which refers to the IdNode for the receiving process.

The parameter P in the xProcessLog function will refer to the process just about to start executing.

The fourth parameter, PathLength, represents thus the number of components in the Path array that are used to represent the path for the signal sent in the output. If the signal is sent to or from the environment, either Path[0] or Path[PathLength] will refer to xEnvId, that is to the IdNode for the environment process.

In the implementation of the xSignalLog and xProcessLog functions which should be provided by the user, the user has full freedom to use the information provided by the parameters in any suitable way, except that it is not possible to change the contents of the signal instance. The functions are provided to make it possible for a user to implement a simple log facility in environments where standard IO is not provided, or where the monitor system is too slow or too large to fit. A suitable implementation can be found in the file sctenv.c

XTRACE

If this compilation switch is defined, traces of the execution can be printed.

This facility is normally used together with the monitor, but can also be used without the monitor. The file stdout must of course be available for printing.

Setting trace values must, without the monitor, be performed in included C code, as the monitor interface is excluded. The trace components are called Trace_Default and can be found in IdNodes representing system, blocks, and processes, and in the struct xPrsRec used to represent a process instance. The values stored in these components are the values given in the Set-Trace command in the monitor. The value undefined is represented by -1.

When the monitor is excluded all trace values will be undefined at startup, except for the system which has trace value 0. This means that no trace is active at start up.

Example 512

Suitable statements to set trace values in C code:

xSystemId->Trace_Default = value;
   /* System trace */
xPrsN_ProcessName->Trace_Default = value;
   /* Process type trace */ 
PId_Var.LocalPId->PrsP->NameNode->Trace_Default =
  value
   /* Process type trace */
PId_Var.LocalPId->PrsP->Trace_Default = value;
   /* Process instance trace */

PId_Var is assumed to be a variable of type PId.

Note:

Note that the variable xPrsN_ProcessName is declared, and therefore only available, in the file containing the block where the process is defined (and in files representing processes contained in the block).

XGRTRACE

If this compilation switch is defined it is possible for a simulation to communicate with the Organizer and the SDL Editor to highlight SDL symbols in the graphical representation.

This feature is used together with the monitor to implement graphical trace and commands like Show-Next-Symbol and Show-Previous-Symbol. It is possible to use graphical trace without the monitor in the same way as the ordinary trace (substitute Trace_Default with GRTrace in the description above). However the graphical trace is synchronized which means that the speed of the application is dramatically reduced.

XCTRACE

Defining this compilation switch makes information available to the monitor about where in the source C code the execution is currently suspended. This facility, which is used together with the monitor, makes it possible to implement the monitor command Show-C-Line-Number.

XMONITOR

If this compilation switch is defined, the monitor system is included in the generated application.

XCOVERAGE

This compilation switch makes it possible to generate coverage tables. It should be used together with XMONITOR.

MAX_READ_LENGTH

This macro controls the length of the char * buffers used to read values of SDL sorts. A typical usage is when the monitor commands Assign-Value is entered. If large data types are used, it is possible to redefine the sizes of the buffers from their default size (10000 bytes) to something more appropriate.

XSIMULATORUI

This compilation switch should be defined if the generated simulator is to be executed from the Graphical User Interface to the simulator monitor.

XMSCE

This compilation switch should be defined if the generated simulator should be able to generate Message Sequence Charts.

XSDLENVUI

This compilation switch should be defined if it should be possible to start and communicate with a user interface (or another application) from the simulation. This feature should be used together with the monitor and will define the switch XPMCOMM (see also this switch).

XNOMAIN

When this compilation switch is defined the functions main and xMainLoop are removed using conditional compiling. This feature is intended to be used when a generated SDL application should be part of an already existing application, that is when the SDL system implements a new function in an existing environment. The following functions are available for the user to implement scheduling of SDL actions:

extern void xMainInit(
  void (*Init_System) (void)
#ifdef XCONNECTPM
 ,int argc,
  char *argv[]
#endif
  );

#ifdef XNOMAIN
extern void SDL_Execute (void);

extern int SDL_Transition_Prio (void);

extern void SDL_OutputTimer (void);

extern int SDL_Timer_Prio (void);

extern SDL_Time SDL_Timer_Time (void);
#endif

The behavior of these functions are as follows:

xMainInit: This function should be called to initialize the SDL system before any other function in the runtime library is called. An appropriate way to call xMainInit is:

#ifdef XCONNECTPM
xMainInit(yInit, argc, argv);
#else
xMainInit(yInit);
#endif

The compilation switch XCONNECTPM will be defined if the any switch that requires communication via the SDL Suite communication mechanism is defined (XPMCOMM or XGRTRACE).

SDL_Execute: This function will execute one transition by the process instance first in the ready queue.

Before calling this function it must be checked that there really is at least one process instance in the ready queue. This test can be performed using the function SDL_Transition_Prio discussed below.

SDL_Transition_Prio: This function returns the priority of the process first in the ready queue (if signal priorities are used it is the priority of the signal that has caused the transition by the actual process instance). If the ready queue is empty, -1 is returned.

SDL_OutputTimer: This function will execute one timer output and may only be called if there is a timer ready to perform a timer output. This test can be performed with either SDL_Timer_Prio or SDL_Timer_Time described below.

SDL_Timer_Prio: This function returns the priority of the timer first in the timer queue if the timer time has expired for this timer. That is, if Now is greater than or equal to the time given in the Set statement for the timer.

If the timer queue is empty or the timer time for the first timer has not expired, -1 will be returned.

If signal priorities are used, the priority returned is the priority assigned to the timer type (in the timer definition) or the default timer priority; while if process priorities are used the priority returned is the priority of the process that has set the timer.

SDL_Timer_Time: This function returns the time given in the set statement for the first timer in the timer queue. If the timer queue is empty, the largest possible time value (xSysD.xMaxTime) is returned.

Depending on how the SDL system is integrated in an existing environment it might be possible to also use the monitor system. In that case the function xCheckMonitors should be called to execute monitor commands.

extern void xCheckMonitors (void);

To give some idea of how to use the functions discussed above, an example reflecting the way the internal scheduler in the runtime library works is given below:

Example 513

  while (1) {
#ifdef XMONITOR
    xCheckMonitors();
#endif
    if ( SDL_Timer_Prio() >= 0 )
      SDL_OutputTimer();
    else if ( SDL_Transition_Prio() >= 0 )
      SDL_Execute();
  }

XMAIN_NAME

Sometimes when integrating generated application or simulations in larger environments the main function can be useful but cannot have the name main. This name can be changed to something else by defining the macro XMAIN_NAME. The main function came be found in the file sctsdl.c.

XSIGPRIO

The XSIGPRIO compilation switch defines that priorities on signals (set in Output statements) should be used. This switch and the three other switches for priorities given below are, of course, mutually exclusive.

A signal priority is specified with a priority directive (see Assigning Priorities - Directive #PRIO, that is by a comment with the following outline:

 /*#PRIO 5 */. 

A priority can be assigned to a signal instance in an output statement by putting a #PRIO directive last in the output symbol. In SDL/PR it is possible to put the #PRIO directive both immediately before and immediately after the semicolon ending the output statement. The Cadvanced/Cbasic SDL to C Compiler will first look for #PRIO directives in the output statement. If no directive is found there it will look in the signal definition for the signal for a priority directive. A #PRIO directive should be placed directly before the comma or semicolon ending the definition of the signal.

Example 514

SIGNAL
  S1 /*#PRIO 3 */,
  S2 (Integer) /*#PRIO 5 */;

If no priority directive is found in the output symbol or in the definition of the signal, the default value for signal priority is used. This value is 100. Timers can be assigned priorities in timer definitions in the same way as signals in signal definitions.

The signal priorities will be used to sort the input port of process instances in priority order, so that the signal with highest priority (lowest priority value) is at the first position. Two signals with same priority are placed in the order they arrive. The priority of the signal that can cause the next transition by a process instance is used to sort the ready queue in priority order, so that the process with a signal of highest priority is first. With equal priority, the processes are placed in the order they are inserted into the ready queue. If a continuous signal caused a processes to be inserted into the ready queue, it is the priority of the continuous signal that will be used as signal priority for this "signal".

Note that a start transition also have a "signal priority". This is by default also 100 and is set by the macro xDefaultPrioCreate described below.

Caution!

Signal priority is not included in SDL according to ITU Recommendation Z.100, and that sorting the signals in the input port of a process instance according to priorities is a direct violation of the SDL standard. This feature is however included for users that need such a behavior to implement their applications.

XPRSPRIO

This compilation switch defines that process priorities should be used. For more information see The Cadvanced/Cbasic SDL to C Compiler, section Assigning Priorities - Directive #PRIO.

XSIGPRSPRIO

This compilation switch defines that priorities on signals should be used as first key for sorting in priority order, and process priorities should be used as second key.

XPRSSIGPRIO

This compilation switch defines that process priorities should be used as first key for sorting in priority order, and priorities on signals should be used as second key.

xDefaultPrio...

It is possible to redefine the default priorities for processes, signals, timer signals, continuous signals and start-up signals by defining the symbols below to appropriate values. The default value for these defaults are 100.

xDefaultPrioProcess
xDefaultPrioSignal
xDefaultPrioTimerSignal
xDefaultPrioContSignal
xDefaultPrioCreate

XOPT

This compilation switch will turn on full optimization (except XOPTCHAN), that is, it will define the following switches:

XOPTSIGPARA

XOPTDCL

XOPTFPAR

XOPTSTRUCT

XOPTLIT

XOPTSORT

For more information, see these switches below. The XOPT switches should not be used together with the monitor.

XOPTSIGPARA

In the symbol table tree (see section Symbol Table Tree Structure) there will be one node for each parameter to a signal. These nodes are not necessary in an application and can be removed by defining the compilation switch XOPTSIGPARA.

XOPTDCL

There will be a VarIdNode in the symbol table tree for each variable declared in processes, procedures, or operator diagram. These nodes are not used in an application (without the monitor) and can be removed by defining the compilation switch XOPTDCL.

XOPTFPAR

There will be a VarIdNode in the symbol table tree for each formal parameter in a processes, procedures, or operator diagram. These node are not used in an application and may be removed by defining the compilation switch XOPTFPAR.

XOPTSTRUCT

For each component in an SDL struct there will be one VarIdNode defining the properties of this component. These VarIdNodes are not used in an application and can be removed by defining the compilation switch XOPTSTRUCT.

XOPTLIT

For each literal in a newtype that will be translated to an enum type, there will be an LitIdNode representing the literal. These nodes will not be used in an application and can be removed by defining the compilation switch XOPTLIT.

XOPTSORT

Each newtype and syntype, including the SDL standard types, will be represented by an SortIdNode. These nodes are not used in an application if all the other XOPT... mentioned above are defined.

XNOUSEOFREAL

Defining this compilation switch will remove all occurrences of C float and double types, and means for example that the SDL type Real is no longer available.

This switch is intended to be used in situations when it is important to save space, to see to that the library functions for floating type operations are not necessary to load. It cannot handle situations when the user includes floating type operations in C code, for example #CODE directives. Another consideration is if BasicCTypes.pr, or other ADTs, are included in the system. If so, it is required that types dependent on SDL Real be removed from these packages.

XNOUSEOFOBJECTIDENTIFER

Defining this switch will remove all code for the SDL predefined sort Object_identifier.

XNOUSEOFOCTETBITSTRING

Defining this switch will remove all code for the SDL predefined sorts Bit_string, Octet, and Octet_string.

Special consideration needs to be taken if BasicCTypes.pr, or other ADTs, are included in the system. If so, it is required that types dependent on these types be removed from these packages.

XNOUSEOFEXPORT

By defining this switch the user states that he is not going to use the export - import concept in SDL.

Caution!

An attempt to perform an import operation when
XNOUSEOFEXPORT is defined will result in a compilation error, as the function xGetExportAddr is not defined.

XNOUSEOFSERVICE

This compilation switch can be defined to save space, both in data and in the size of the kernel, if the SDL concept service is not used. If services are used and this switch is defined, there will be compilation errors (probably many!), when the generated code is compiled.

XPRSOPT

Section Create and Stop Operations describes how xLocalPIdRec structs are allocated for each created process instance, and how these structs are used to represent process instances even after they have performed stop actions. This method for handling xLocalPIdRecs is required to be able to detect when a signal is sent to a process instance that has performed a stop operation.

In an application that is going to run for a "long" period of time and that uses dynamic processes instances, this way of handling xLocalPIdRecs will eventually lead to no memory being available.

By defining the compilation switch XPRSOPT, the memory for the xLocalPIdRecs will be reused together the yVDef_ProcessName structs. This has two consequences:

  1. The need for memory will not increase due to the use of dynamic processes (the memory need depends on the maximum number of concurrent instances).
  2. It will no longer be possible to always find the situation when a signal is sent to a process instance that has performed a stop action.

More precisely, if we have a PId variable that refers to a process instance which performs a stop operation and after that a create operation (on the same process instance set) is performed where the same data area is reused, then the PId variable will now refer to the new process instance.

This means, for example, that signals intended for the old instance will be sent to the new instance. Note that it is still possible to detect signal sending to processes in the avail list even if XPRSOPT is defined.

XOPTCHAN

This switch can be used to remove all information about the paths of channels and signal routes in the system. The following memory optimization will take place:

When the information about channels, signal routes, and gates is not present two types of calculations can no longer be performed:

  1. To check if there is a path of channels and signal routes between the sender and the receiver in an OUTPUT statement with a TO clause. This is no problem as this is just an error test that we probably do not want to be performed in an application.
  2. To calculate the receiver in an OUTPUT without TO clause, if the Cadvanced/Cbasic SDL to C Compiler has not performed this calculation at generate time (see Calculation of Receiver in Outputs). This is more serious, as it means that OUTPUT without TO cannot always be used. The restrictions are:
    • No outputs without to in process types, or in process in block or system types.
    • No outputs without to, designated to a process in a SEPARATE unit.

Caution!

If the XOPTCHAN switch is defined and still OUTPUT without TO clause are used (which the Cadvanced/Cbasic SDL to C Compiler cannot optimize), there will be a C compilation error saying that the name xNotDefPId is not defined.

In an ordinary SDL system OUTPUTs without TO must be used to start up the communication between different parts of the system, as there is no other way in SDL to distribute the PId values needed for OUTPUTs with TO.

This problem is solved if the Cadvanced/Cbasic SDL to C Compiler can calculate the receiver. Otherwise the data type PIdList in the library of abstract data types is intended to solve this problem. It is described in The ADT Library. When this data type is used, global PId literals my be introduced, implemented as SDL synonyms. These literals can then be used to utilize OUTPUT statements with TO clauses from the very beginning.

X_LONG_INT

The SDL sort Integer is translated to int in C. To translate the Integer sort to long int instead, just define the compilation switch X_LONG_INT.

XENVSIGNALLIMIT

If this switch is defined, only a limited number of signals will be stored in the input port of the Env function. The limit is equal to the value defined for XENVSIGNALLIMIT and is normally set to 20.

XEALL

This switch will define all error handling switches (XE...) and XASSERT given below.

XECREATE

This switch will report if the initial number of instances of a process type is greater than the maximum number.

XECSOP

This switch will report error situations in ADT operator.

XEDECISION

This switch will report if no path out from a Decision is found.

XEEXPORT

This switch will report errors during Import actions.

XEFIXOF

This switch will report overflow when an SDL Real value is converted to an SDL Integer value using the operator Fix.

XEINDEX

This switch will report value out of range for array index.

XEINTDIV

This switch will report division by zero in an integer division.

XEOUTPUT

This switch will report errors during Output operations.

XERANGE

This switch will report range errors when a value is assigned to a variable of a sort containing range conditions.

XEREALDIV

This switch will report division by zero in a real division.

XEVIEW

This switch will report errors in View operations

XECHOICE

This switch will turn on error reports when accessing non-active choice components.

XEOPTIONAL

This switch will turn on error reports when accessing non-present optional struct components.

XEUNION

This switch will turn on error reports when accessing non-active union components.

XEREF, XEOWN

These switches turn on error checking on pointers (generator Ref and Own).

XASSERT

By defining this switch the possibility to define user assertions which is described in Assertions.

XTRACHANNELSTOENV

When using partitioning of a system a problem during the redirection of channels is that the number of channels going to the environment is not known at code generation time, which means that the size of the data area used for the connections is not known. This problem is solved in two ways.

Either the function handling redirections allocates more memory, which is the default, or the user specifies how many channels that will be redirected (which could be difficult to compute, but will lead to less need of memory).

In the first case (allocation of more memory) the macros:

#define XTRACHANNELSTOENV  0
#define XTRACHANNELLIST

should be defined like above. This is the standard in scttypes.h. If the user wants to specify the number of channels himself then

#define XTRACHANNELSTOENV  10
#define XTRACHANNELLIST    ,0,0,0,0,0,0,0,0,0,0

i.e. XTRACHANNELSTOENV should be the number of channels, while XTRACHANNELLIST should be a list of that many zeros.

XDEBUG_LABEL

It is for debugging purposes sometimes of interest to introduce extra labels. The macro XDEBUG_LABEL is inserted in the code for each input symbol. As macro parameter it has a name which is the name of the state concatenated with an underscore concatenated with the signal name.

Example 515

state State1; input Sig1;
state State2; input *;
state *; input Sig2;

In the generated code for these input statements the following macros will be found:

XDEBUG_LABEL(State1_Sig1)
XDEBUG_LABEL(State2_ASTERISK)
XDEBUG_LABEL(ASTERISK_Sig2)

A suitable macro definition to introduce label would be:

#define XDEBUG_LABEL(L)  L: ;

To use these label the usage of SDL must be restricted in one area. The same state may not receive two different signals with the same name! This is allowed and handled by the SDL Suite. The signal have to be defined at different block or system level and the outermost signal must be referenced with a qualifier.

XCONST, XCONST_COMP

Using these compilation switches most of the memory used for the IdStructs can be moved from RAM to ROM. This depends of course on the compiler and what properties it has.

The following macro definitions can be inserted:

#define XCONST const
#define XCONST_COMP const

This will introduce const in the declaration of most of the IdStructs. It is then up to the compiler to handle const.

The XCONST_COMP macro is used to introduce const on components within a struct definition. This is necessary for some compilers to accept const on the struct as such.

If const is successfully introduced, there is a lot of RAM memory that will be saved, as probably 90% of the data area for IdStructs can be made const.

XAVL_TIMER_QUEUE

This compilation switch changes the timer queue data structure from the default sorted double linked list to an AVL tree. Each node in the tree represents a specific TimerTime and holds all timers scheduled to fire at that time. Insertions grow logarithmically with the total number of scheduled timers, instead of linearly as is the case with the ordered list. For models with a large number of timers the AVL tree can offer a significant performance boost. The AVL tree requires slightly more memory and is not recommended for models with few timers.

Compilation Switches - Summary

The property switches are in principle independent, except for the relations given in the descriptions above, and it should always be possible to any combination.

The number of combinations is, however, so huge that it is impossible for us to even compile all combinations. If you happen to form a combination that does not work, please let us know, so that we either can correct the code, or, if that is not possible, publish a warning against that combination.

The switches defining a standard library version will define the following property switches:

SCTDEBCOM

XPRSPRIO
XPARTITION
XEALL
XMONITOR
XTRACE
XCTRACE
XMSCE
XCOVERAGE
XGRTRACE
XPMCOMM
XSDLENVUI
XITEXCOMM
XSIMULATORUI

SCTDEBCLCOM

XCLOCK
XPRSPRIO
XPARTITION
XEALL
XMONITOR
XTRACE
XCTRACE
XMSCE
XCOVERAGE
XGRTRACE
XPMCOMM
XSDLENVUI
XSIMULATORUI

SCTAPPLCLENV

XCALENDARCLOCK
XENV
XPRSPRIO
XOPT
XPRSOPT

SCTDEBCLENVCOM

XCALENDARCLOCK
XPRSPRIO
XPARTITION
XENV
XPRSOPT
XEALL
XMONITOR
XTRACE
XCTRACE
XMSCE
XCOVERAGE
XGRTRACE
XPMCOMM
XSDLENVUI
XSIMULATORUI

SCTPERFSIM

XEALL
XPRSPRIO

The lowest layer of switches (that handle the implementation details) are set up using the three layers above. These switches will not be discussed here. Please refer to the source code files scttypes.h and sctsdl.c for more details.


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