![]() |
![]() |
![]() |
![]() |
![]() |
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.
- Switches defining properties of the compiler.
- Switches defining a library version.
- Switches defining a property of a library version.
- Switches defining the implementation of a property.
The first group will be discussed in Adaptation to Compilers.
The following switches define the library version:
SCTDEBCOM SCTDEBCLCOM SCTAPPLCLENV SCTDEBCLENVCOM SCTPERFSIMPerformanceSimulation
(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:
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.
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.
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 XNOMAINextern 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);#endifThe 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 XCONNECTPMxMainInit(yInit, argc, argv);#elsexMainInit(yInit);#endifThe 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:
while (1) {#ifdef XMONITORxCheckMonitors();#endifif ( 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.
SIGNALS1 /*#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.
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.
xDefaultPrioProcessxDefaultPrioSignalxDefaultPrioTimerSignalxDefaultPrioContSignalxDefaultPrioCreateXOPT
This compilation switch will turn on full optimization (except XOPTCHAN), that is, it will define the following switches:
XOPTSIGPARA XOPTDCL XOPTFPAR XOPTSTRUCT XOPTLIT XOPTSORTFor 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.
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:
- 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).
- 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:
- The two ChannelIdNodes for each channel, signal route, and gate are removed.
- The ToId component in the xPrsIdNodes representing processes is removed.
- A number of functions in the library (sctsdl.c) are no longer needed and are removed.
When the information about channels, signal routes, and gates is not present two types of calculations can no longer be performed:
- 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.
- 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:
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 XTRACHANNELLISTshould 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,0i.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.
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 constThis 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:
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 |
![]() |
![]() |
![]() |
![]() |