The CSDL Code Generator is designed to make it possible to generate applications using the CSDL tool, but at the same time to use the C Code Generator in SDT to simulate the SDL system at the SDL level.
------------------------------------------------------------------- Note: The CSDL Code Generator always generate complete files that can be used as input to the CSDL tool, and then compiled and linked by the C compiler. The user should never change anything in the generated files. Instead an appropriate change should be made at the SDL level and the files should be regenerated. -------------------------------------------------------------------Note also that the CSDL Code Generator only accepts the SDL-88 subset of SDL-92 as input. Any usage of the new SDL-92 concept, like the OO concepts or RPC, will be reported as "Feature not implemented" and no code will be generated.
A CSDL program can only be generated for a complete SDL system. It is, however, possible to regenerate only a selected part of the SDL system. If, for example, a local change is made in an SDL block it is possible to regenerate only the code for that block.
-------------------------------------------------------------------- Note: In SDT 3.01 the possibility to regenerate only a subsystem is not im plemented. ALWAYS select Full Make in the SDT Organizer's Make dialog. --------------------------------------------------------------------
---------------------------------- File type File name ---------------------------------- signal library: unitname_s.csm csp files: unitname.csp generated c files: unitname_c.c generated h files: unitname_d.h make file: systemname.mk dependency files: systemname.str systemname.d ----------------------------------
---------------------------------------------------------------------- Caution! There is a potential risk that generated files may overwrite each other. As, for example, file names for csp files are unitname.csp, overwriting will occur if there are more than one unit (in this case process, procedure, or state) with the same name. The user has to take the responsibility to avoid such situations by having a strategy for naming the units of interest (system, block, substructure, pro cess, procedure, state). ----------------------------------------------------------------------The CSDL Code Generator will assist the user and will find and report situation when files become overwritten. This test can only be performed among the files that are generated in this particular execution. If you for example regenerate code for a process, the code generator cannot report that a state in this process has the same name as a state in another process, and thus that a file will be overwritten. When you regenerate the complete system, the code generator has full control, and can report any file name problems.
If the CSDL Code Generator detects a file name problem according to the discussion above, it will refuse to generate any code at all.
setenv sctdir some_appropriate_pathor by adding the definition of sctdir to the make command:
make -f systemname.mk sctdir=some_appropriate_pathThe following symbols should be defined in the makeoptions file:
------------------------------------------------- Symbol Description ------------------------------------------------- csdlCSDL Name of the CSDL tool csdlCSDLFLAGS Flags passed to the CSDL tool. csdlCC Name of the C compiler csdlCPPFLAGS Flags passed to the C preprocessor csdlCCFLAGS Flags passed to the C compiler csdlIFDEF Compilation switches -------------------------------------------------
Example 199 csdlCSDL = csdl csdlCSDLFLAGS = -r csdlCC = cc csdlCPPFLAGS = -I. -I/proj/example/test csdlCCFLAGS = -O csdlIFDEF = -DCOMP_SWITCH_EXAMPLEBy using different makeoptions files, different versions of the executable program can be obtained, for example with or without debugging information (usually -g option in C compiler).
All the error messages are listed below, together with a short explanation. Some messages contain a `#' followed by a number which is used to indicate where information, specific of the error situation, can be found.
Feature of SDL not implemented: #1The translator cannot handle this SDL feature. See the list of restrictions in "Restrictions" on page 2463.
Cannot open outfileA file that should be generated cannot be opened.
WARNING! Unique name generation failed.This warning can be ignored in the CSDL Code Generator.
Node = nil in #1 Incorrect node type in #1. Nodetype: #2 Internal error in the PathStructure Line exceeded MaxLineLengthThese four last errors are internal errors in the CSDL Code Generator, which we would be pleased if you reported to us. The telephone and facsimile numbers to Telelogic Customer Support can be found at the beginning of this manual.
#include "processname_d.h"
SIGNAL name1 CODE NAME1_CODE { }; SIGNAL name2 CODE NAME2_CODE { parameters in C };where name1 is a signal with no parameters and name2 is a signal with parameters. The signal parameters given in the SDL declaration of the signal, are named Param1, Param2, and so on. A user can specify his own name for a signal parameter using the directive #SIGFIELD.
Example 200 SIGNAL Sig2(Type1, Type2 /*#SIGFIELD 'MyName'*/, Type3);This will be translated to
SIGNAL Sig2 CODE SIG2_CODE { Type1 Param1; Type2 MyName; Type3 Param3; };A timer definition (without parameters) is translated to:
SIGNAL timername CODE TIMERNAME_CODE { SYHEADER sy; }
#define STATENAME numberwhere number is 0, 1, 2, ...
#define PROCESSNAME_CAT 0which is used as default CATEGORY within the process.
Example 201 DCL i1, i2 Integer, J Boolean, /*#GLOBAL*/ k Character, /*#OWN 'state1'*/ L Integer; /*#OWN 'start'*/The first two variables, i1 and i2, are private variables, the third variable, J, is a GLOBAL variable, while k and L are OWN variables; k to the state unit for state state1 and L for the start up unit. Given the DCL above in a process called P1, the generated declarations will look like:
typedef struct { SDL_Integer i1; SDL_Integer i2; } P1_DCL; #define P1_DCL_PTR ((P1_DCL *)SDLprivate_data_ptr) #define _I1 P1_DCL_PTR->i1 #define _I2 P1_DCL_PTR->i2There will also be one component in the struct and one macro for each timer defined in the process. The struct component will look like:
SYSIGNAL_TYPE * timername_to_key;while the macro will be:
#define TIMERNAME_TO_KEY \ P1_DCL_PTR->timername_to_key
START_UNIT processname; seized objects own objects startup actions
SEIZE contents ENDSEIZE;where the contents is described below.
#include "processname_d.h"
GLOBAL type1 varname1; GLOBAL type2 varname2;If the variable has a default value, either in the DCL clause or as default value given in the sort definition, this value is assigned in the GLOBAL declaration.
OUTSIGNAL FROM file1.csm : sig1, sig2, sig3 ITSELF EXTERN; FROM file2.csm : sig4, sig5 ITSELF EXTERN;
PROCEDURE FROM procedurename.csp USING {void} procedurename;
STATEUNIT STATENAME FROM statename.csp
OWN own variables ENDOWN;where the OWN variables are described below.
For each own variable (see also "Private Variables" on page 2395) for the start up file, that is variable with directive
/*#OWN 'start'*/a C variable declaration is generated. If the variable has an initial value in SDL, either by an assignment in the declaration or as a default value for all variables of a given type, this initial value is assigned in the C declaration.
Example 202Assume the following declarations in SDL:
SYNTYPE NewInteger = Integer DEFAULT 10; ENDSYNTYPE; DCL I1 Integer = 1, /*#OWN 'start'*/ I2, I3 Integer, /*#OWN 'start'*/ I4 NewInteger = 20, /*#OWN 'start'*/ I5 NewInteger; /*#OWN 'start'*/The DCL is then translated to:
OWN STATIC SDL_Integer I1 = 1; STATIC SDL_Integer I2; STATIC SDL_Integer I3; STATIC NewInteger I4 = 20; STATIC NewInteger I5 = 10; ENDOWN;
PROCESS processname; STARTUP; initialization of private and global variables initialization of timers start up transition ENDSTARTUP; ENDPROCESS processname;
TASK 'initialisation of private data'; { RES_PRIV_DATA(processname_DCL); }This is followed by a TASK where each private variable that should have a start value is assigned this value. Initial values can either be specified in the DCL of as default value in the type declaration.
TASK 'initialisation of timers'; { TIMER_EX_TO_KEY = NULL; }
STATE_UNIT statename; seized objects own objects state actions
SEIZE contents ENDSEIZE;where the contents is described below.
#include "processname_d.h"
IMPORT type1 varname1; IMPORT type2 varname2;
INSIGNAL PROCESSNAME_CAT FROM file1.csm : sig1, sig2; PROCESSNAME_CAT FROM file2.csm : sig3;If the same transition should be executed for several state-signal combination, only one of them can be found in the generated code, while for the other combinations it is described in the INSIGNAL section how to find the appropriate transition.
Example 203 sig4(State1, Sig3)If the state contains an INPUT *, then the following is generated last in the INSIGNAL section:
PROCESSNAME_CAT FROM "SYLOCK_CSM" : SYlOCK;If the #CATEGORY directive is used in input or save statements, then each combination of category name - file name will only occur once, containing the list of all the signals for this combination. The #define for all category names except PROCESSNAME_CAT have to be supplied by the user, for example in a #CODE directive. For more information about the #CATEGORY directive please see "#CATEGORY Directive" on page 2462.
OUTSIGNAL FROM file1.csm : sig1, sig2, sig3 ITSELF EXTERN; FROM file2.csm : sig4, sig5 ITSELF EXTERN;
PROCEDURE FROM procedurename.csp USING {void} procedurename;
OWN contents ENDOWN;where the contents is described in "Own Objects" on page 2398, except that the #OWN directive should contain the state name, instead of `start'.
Example 204 /*#OWN 'state1'*/
Example 205 STATE statename; contents ENDSTATE statename;The contents in the state description contains a number of INPUT sections. Details can be found below.
For each input symbols in SDL there will be an INPUT statement containing the same signal, except for signal that in the INSIGNAL section (see page 2400) refers to another state-signal combination.
Example 206 INPUT signalname;The corresponding transition is then generated, possibly starting with a TASK where the signal parameters are copied to process variables. The translation of action within transitions are discussed in "CSDL Statements and Terminators" on page 2406, while the signal parameter assignment is treated later in this section.
The SDL input INPUT *; is generated as:
INPUT SYlOCK;This is placed last among the INPUT statements in the file. Please note that INPUT * in SDL and INPUT SYlOCK in CSDL do not have exactly the same meaning. INPUT SYlOCK means "all other signals", while INPUT * means "all other signals in the signalset of the process".
A save of a signal will be translated to:
INPUT signalname; TASK 'save signalname'; { SDL_SAVE; } NEXTSTATE *;that is, a transition that just saves the signal. In each state file there will only be one such transition, using mappings in the INSIGNAL section to this state-input combination.
In SDL the signal parameters are copied to the process variables mentioned in the input.
Example 207 INPUT Sig1(Var1, Var2);means that the first signal parameter is at the input of the signal, assigned to the variable Var1, while the second signal parameter is assigned to Var2. After the input the signal parameters are not available in SDL any longer.
It is in SDL also allowed to have an empty position in the variable list, indicating that the corresponding signal parameter should not be copied.
Example 208 INPUT Sig1(, Var2) INPUT Sig1(Var1, )This means that the value of the corresponding signal parameter is lost (in SDL).
In the CSDL Code Generator an input is followed by a TASK where the signal parameter are copied to the variables specified in the input. If no parameters should be copied, no task is generated.
Example 209The following SDL input:
INPUT Sig2(Var1, , Var3, );will be translated to:
INPUT Sig2; TASK 'copy signal parameters' { Var1 = Sig1->Param1; Var3 = Sig1->Param3; }The user has now two possible strategies that he can choose between for each signal parameter reception. The first is to follow SDL and copy the signal parameter to an SDL variable. The second is to leave the corresponding position in the list of variables empty. It is then of course possible to refer to the signal parameter in included CSDL (C) code in #CODE directives in TASK.
Note that the second approach makes the code faster, but also that the SDL system cannot directly be simulated using the SDT C Code Generator. It is however possible to refer to signal parameters in TASKs in a similar way in the generated C code (C Code Generator) as it is in the generated CSDL code. This information will be provided by Telelogic at request.
PROCEDURE_UNIT procedurenameproc; seized objects own objects SDLPROC section
SEIZE contents ENDSEIZE;where the contents is described below.
#include "processname_d.h"
IMPORT type1 varname1; IMPORT type2 varname2;
OUTSIGNAL FROM file1.csm : sig1, sig2, sig3 ITSELF EXTERN; FROM file2.csm : sig4, sig5 ITSELF EXTERN;
PROCEDURE FROM procedurename.csp USING {void} procedurename;
SDLPROC {void} procedurename (parameter1, parameter2) { typename1 parameter1; typename2 *parameter2; }; local procedure variables transition ENDSDLPROC procedurename;An SDL IN parameter is passed as a value, while an SDL IN/OUT parameter is passed as the address to the variable. In the example above the first parameter is IN and the second is IN/OUT.
Each variable defined in the SDL procedure (DCL) will generate a variable in CSDL.
Example 210Assuming the following SDL DCL in a procedure:
DCL i1, i2 : Integer; k : mytype;the code generator will generate
SDL_Integer i1; SDL_Integer i2; mytype k;Any start value will be assigned in a task immediately after the variables.
The actions contained in the transition will be translated according to "CSDL Statements and Terminators", next.
Example 211 CALL Proc1(var+1, var2);is, assuming that the first parameter is IN and the second is IN/OUT and assuming that var and var2 are private variables, translated to:
PROCEDURE Proc1(_VAR+1, &_VAR2);
Restriction: It is not allowed to use SDL outputs without TO clause. See also the discussion on the DEST operator below.
Example 212 OUTPUT Sig1 TO DEST(Sender,1,1,1); OUTPUT Sig2(Var1, Var2+7) TO DEST(Sender,I,J,K);is translated to:
OUTPUT Sig1 TO DEST(1,1,1); OUTPUT Sig2 TO DEST(I,J,K) DOING { Sig2->Param1 = Var1; Sig2->Param2 = Var2+7; };By having the directive #TRANSFER (see also "#TRANSFER Directive" on page 2460) immediately before or after the semi-colon ending the output statement in SDL, the keyword TRANSFER is included in CSDL.
Example 213 OUTPUT Sig1 TO DEST(Sender,1,1,1) /*#TRANSFER*/;is translated to:
OUTPUT Sig1 TO DEST(1,1,1) TRANSFER;To address signals, PId values are used in SDL. In CSDL, however, a macro with a number of parameters are used (parameters like RTFG_ID, RTFE_TYPE, and so on).
The CSDL Code Generator assumes that the TO expression, which is mandatory, consists of an operator call to the SDL operator DEST. This operator has to be included in an abstract data type preferably at the system level, to be available in SDL.
To be able to use both the CSDL and C Code Generator for the same SDL system, the DEST operator is assumed to have one first parameter which should be used for simulation (C Code Generator) and a number of other parameters used for CSDL.
The CSDL Code Generator will therefore remove the first parameter of any operator that it find in a TO expression. That is, if the CSDL Code Generator finds:
DEST(a,b,c,d,e)it will generate
DEST(b,c,d,e)in CSDL. Note, this translation rule is only used in TO clauses and is valid for any operator, not only for DEST.
The DEST operator should in SDL be defined as
DEST : PId, x, y, z, v -> PId;where x, y, z, v should be some appropriate types. When the system is simulated the DEST operator should just return the first parameter, while when the CSDL Code Generator is used a suitable macro definition of the DEST operator should be included in the definition of the operator.
The name DEST and the number of parameters of the operator are not fixed, but can be tailored to suit users.
Example 214The SDL create statements
create P2; /*#PROCPAR (x, y, z)*/ create P2 /*#PROCPAR (a, b, c)*/;is translated to
TASK 'Create of process P2'; { SDL_CREATE (x, y, z); } TASK 'Create of process P2'; { SDL_CREATE (a, b, c); }Note that the #PROCPAR directive is mandatory. It will be described in "#PROCPAR Directive" on page 2457.
Example 215 stop /*#PROCPAR (x, y, z)*/;is translated to
TASK 'Stop'; { SDL_KILL (x, y, z); }Note that the #PROCPAR directive is mandatory. It will be described in "#PROCPAR Directive" on page 2457.
Example 216The SDL decision:
decision (I=10 or I=20); (true) : statement_list1; (false) : statement_list2; enddecision;is translated to:
DECISION ' ' IS (I==10 || I==20); WHEN (YES) : statement_list1; WHEN (NO) : statement_list2; ENDDECISION;
Example 217The following SDL decision
decision (C); ('a') : task C := 'A'; ('b') : task C := 'B'; ('c') : task C := 'C'; enddecision;is translated to
DECISION ' ' IS (C); WHEN (' ' IS ('a')) : TASK 'C := ...'; { C = 'A'; } WHEN (' ' IS ('b')) : TASK 'C := ...'; { C = 'B'; } WHEN (' ' IS ('c')) : TASK 'C := ...'; { C = 'C'; } ENDDECISION;
Example 218SDL decision, where I is an integer variable:
decision (I); (<1) : statement_list1; (=1) : statement_list2; (>1) : statement_list3; enddecision;This is translated to:
DECISION ' '; WHEN (' ' IS (I<1)) : statement_list1; WHEN (' ' IS (I=1)) : statement_list2; WHEN (' ' IS (I>1)) : statement_list3; ENDDECISION;An ELSE path in an SDL decision is translated to an OTHERWISE: in CSDL.
Example 219Example of SDL decision identified as a LOOP:
L1 : DECISION (I>5); (true) : statement_list1; JOIN L1; (false) : statement_list2; ENDDECISION;This is translated to:
L1 : LOOP L_L1 WHILE (I>5); statement_list1; ENDLOOP L_L1; statement_list2;Note that the LOOP name will be L_ followed by the SDL label name.
A decision within a LOOP might under some circumstances be identified as an EXIT_LOOP.
The decision should:
Example 220The following SDL statements:
la: decision (I>10); (true) : task I:=I-1; decision (I>100); (true) : join E_la; (false) : enddecision; output Sig1(I,1,I) to DEST(Sender, 1, 1); join la; (false) : enddecision; E_la:will be translated to:
la : LOOP L_la WHILE (I>10); TASK 'I := ...'; { I = I-1; } EXIT_LOOP L_la ON (I>100); OUTPUT Sig1 TO DEST(1, 1) DOING { Sig1->Param1 = I; Sig1->f2 = 1; Sig1->Param3 = I; }; ENDLOOP L_la; E_la :
Restrictions:
set(now + mybase*myunits, timername);where mybase should be a variable, synonym, or value of type duration, and myunits should be of type real (in SDL), is translated to:
START_TIMER SDLTIMER UNITS myunits BASE mybase SIGNAL timername KEY TIMERNAME_TO_KEY;For information about TIMERNAME_TO_KEY please see "Private Variables" on page 2395.
Using the directive #TIMERTYPE it is possible to replace SDLTIMER in the START_TIMER. Please see "#TIMERTYPE Directive" on page 2459 for more information.
reset(timername);is translated to:
STOP_TIMER KEY TIMERNAME_TO_KEY;Note the semantic difference between reset and STOP_TIMER: A reset action will remove the timer signal from the signal queue if the timer signal has been sent but have not yet caused a transition. This is not true for STOP_TIMER.
An SDL label is translated to a CSDL label:
labelname :It is the responsibility of the user only to introduce join - label combinations that will become local in one .csp file, that is local within one transition. Note the joining two flow-lines in GR is the same as introducing join - label.
Unitname_c.c Unitname_d.h Unitname_s.csmmay however be generated (Unitname should be replaced with the name of the SDL unit). The .c file contains C code included in #ADT and #CODE directives, while the .h file contains translations of synonyms and data types, as well as C code for #ADT and #CODE directives. The .csm file contains the signal library for the SDL signals defined in the current unit.
Files generated from processes and procedures:
Processname.csm Processname_d.h Processname_c.c Processname.csp Statename.csp Procedurename.cspThe Processname.csm will contain the signal library for signals and timers defined within the process.
The Processname_d.h contains macros representing synonyms, typedefs from abstract data types, #TYPE and #HEADING sections from #ADT and #CODE directives, and state codes for all the states in the process. The file also contains a struct representing all the private variables in the process. For more information about variables see "Process Variables" on page 2416.
The file Processname_c.c contains #BODY sections of #ADT and #CODE directives found in the process.
The files Processname.csp and Procedurename.csp contain the start transition of the process or procedure.
The files of type Statename.csp contain the implementation of the transitions starting from the state.
Restrictions:
A timer definition in a process will in the same way introduce a signal declaration in the signal library for the process. For each timer there will also be a variable among the private variables of the process. For more information please see "Private Variables" on page 2395.
Restriction:
SDL restrictions:
Restrictions:
Example 221 SYNONYM S1 Integer = 7; SYNONYM S2 Integer = S1+3; SYNONYM S3 Integer = UserFunc(1, 5);will be generated as:
#define S1 7 #define S2 10 #define S3 UserFunc(1, 5)External synonyms can be used to parameterize an SDL system and thereby also a generated program. No code will be generated in CSDL for the external synonyms. The values that should be used for the external synonyms should be included as macro definitions into the generated code. To use a macro definition in C to specify the value of an external synonym, perform the following steps:
Example 222 #define synonym1 value1 #define synonym2 value2
Example 223 /*#CODE #TYPE #include "filename" */If you use this structure you can change the value of an external synonym merely by changing the corresponding macro definition and recompiling the system.
Next the possibility to include hand-coded C functions as implementation of the operators in abstract data types is presented, see "Implementation of User-Defined Operators" on page 2433.
Last, in "More about Abstract Data Types" on page 2440, we discuss more details about operators and the possibilities to include a hand-coded type definition in C to represent the SDL sort.
---------------------------------------------------------------------- SDL name/operator C name/expression/operator ---------------------------------------------------------------------- Boolean SDL_Boolean False, True SDL_False, SDL_True not ! =, /= ==, != and && or || xor != => <= Character SDL_Character NUL SDL_NUL SOH SDL_SOH ... ... (for all unprintable characters) 'a' 'a' 'b' 'b' ... ... (for all printable characters except ' ) '''' '\'' =, /= ==, != <, <=, >, >= <, <=, >, >= Charstring SDL_Charstring 'aa' "Laa" = xEq_SDL_Charstring /= ! xEq_SDL_Charstring MkString xMkString_SDL_Charstring Length xLength_SDL_Charstring First xFirst_SDL_Charstring Last xLast_SDL_Charstring // xConcat_SDL_Charstring SubString xSubString_SDL_Charstring Extract! xExtr_SDL_Charstring Modify! xMod_SDL_Charstring Integer SDL_Integer 0, 1, 2,... same as in SDL +, - +, - * * / xDiv_SDL_Integer =, /= ==, != <, <=, >, >= <, <=, >, >= Float xFloat_SDL_Integer Fix xFix_SDL_Integer Natural SDL_Natural Real SDL_Real 0.0,... same as in SDL +, - +, - * * / xDiv_SDL_Real =, /= ==, != <, <=, >, >= <, <=, >, >= PId SDL_PId NULL SDL_NULL =, /= xEq_SDL_PId, !xEq_SDL_PId Duration SDL_Duration 23.45 SDL_Duration_Lit(23, 450000000) + xPlus_SDL_Duration - (monadic) xMonMinus_SDL_Duration - (dyadic) xMinus_SDL_Duration * xMult_SDL_Duration / xDiv_SDL_Duration =, /= xEq_SDL_Duration, ! xEq_SDL_Duration > xGT_SDL_Duration Time SDL_Time 23.45 SDL_Time_Lit(23, 450000000) + xPlus_SDL_Time - (result: Time) xMinusT_SDL_Time - (result: Duration) xMinusD_SDL_Time =, /= xEq_SDL_Time, ! xEq_SDL_Time < xLT_SDL_Time <= xLE_SDL_Time > xGT_SDL_Time >= xGE_SDL_Time ----------------------------------------------------------------------
typedef int SDL_Boolean; #define SDL_False 0 #define SDL_True 1 typedef int SDL_Integer; typedef int SDL_Natural; typedef float SDL_Real; typedef struct { xint32 s, ns; } SDL_Time; typedef SDL_Time SDL_Duration; typedef char *SDL_Charstring; typedef char SDL_Character; #define SDL_NUL '\000' #define SDL_SOH '\001' #define SDL_STX '\002' #define SDL_ETX '\003' #define SDL_EOT '\004' #define SDL_ENQ '\005' #define SDL_ACK '\006' #define SDL_BEL '\007' #define SDL_BS '\010' #define SDL_HT '\011' #define SDL_LF '\012' #define SDL_VT '\013' #define SDL_FF '\014' #define SDL_CR '\015' #define SDL_SO '\016' #define SDL_SI '\017' #define SDL_DLE '\020' #define SDL_DC1 '\021' #define SDL_DC2 '\022' #define SDL_DC3 '\023' #define SDL_DC4 '\024' #define SDL_NAK '\025' #define SDL_SYN '\026' #define SDL_ETB '\027' #define SDL_CAN '\030' #define SDL_EM '\031' #define SDL_SUB '\032' #define SDL_ESC '\033' #define SDL_IS4 '\034' #define SDL_IS3 '\035' #define SDL_IS2 '\036' #define SDL_IS1 '\037' #define SDL_DEL '\177' #define SDL_PId ??? #define SDL_NULL ??? #define xDef_SDL_PId(V) *(V) = SDL_NULL
extern SDL_Integer xFix_SDL_Integer (SDL_Real Re); #define xFloat_SDL_Integer(I) ((SDL_Real)I)These two functions convert between integer and real values and are used to represent the SDL operators Fix and Float. The function xFix_SDL_Integer checks if the value of the real parameter is too large to be converted to an integer (if it would cause integer overflow). In that case an SDL dynamic error is reported and the function returns the value 0. Fix can be a macro if no error check should be performed.
extern SDL_Integer xDiv_SDL_Integer (SDL_Integer i, SDL_Integer k);This function performs integer division, i.e. returns the value of the expression i / k. The function, however, first checks if k is 0, in which case an SDL dynamic error is reported and the function returns the value 0. If no check is necessary this function is best implemented as a macro.
extern SDL_Real xDiv_SDL_Real (SDL_Real i, SDL_Real k);This function performs real division, that is, it returns the value of the expression i / k. The function first checks if k is 0.0, in which case an SDL dynamic error is reported and the function returns the value 0.0. If no check is necessary this function is best implemented as a macro.
extern SDL_Charstring xMkString_SDL_Charstring (SDL_Character C);The function returns a charstring of length 1 with the component value equal to the character parameter value. This function is used to represent the operator MkString in sort charstring.
extern SDL_Charstring xConcat_SDL_Charstring (SDL_Charstring C1, SDL_Charstring C2);The function concatenates two charstring values to one charstring and is used to represent the operator "//" in sort charstring.
extern SDL_Character xFirst_SDL_Charstring (SDL_Charstring C);The function returns the first character in the charstring parameter and is used to represent the operator First in sort charstring.
extern SDL_Character xLast_SDL_Charstring (SDL_Charstring C);The function returns the last character in the charstring parameter and is used to represent the operator Last in sort charstring.
extern SDL_Integer xLength_SDL_Charstring (SDL_Charstring C);The function returns the number of characters in the charstring parameter and is used to represent the operator Length in sort charstring.
extern SDL_Charstring xSubString_SDL_Charstring (SDL_Charstring C, SDL_Integer Start, SDL_Integer SubLength);The function returns a charstring which is a substring of C, starting at index Start and with length SubLength. This function is used to represent the operator Substring in sort charstring.
extern void xAss_SDL_Charstring (SDL_Charstring *CVar, SDL_Charstring CExpr);This function is used to assign the charstring value CExpr to the charstring variable that corresponds to the formal parameter CVar. This routine should be used instead of the ordinary C assignment.
extern SDL_Boolean xEq_SDL_Charstring (SDL_Charstring C1, SDL_Charstring C2);The function returns true if two charstrings are equal, otherwise false. This function is used to represent the operator "=" in sort charstring and should be used instead of the ordinary C == operator.
extern SDL_Charstring xMod_SDL_Charstring (SDL_Charstring C, SDL_Integer Index, SDL_Character Value);The function returns a charstring which is equal to C, but where the character value at index Index is changed to Value. This function is used to represent the operator Modify! in sort charstring.
extern SDL_Character xExtr_SDL_Charstring (SDL_Charstring C, SDL_Integer Index);The function returns the character value at the given index and is used to represent the operator Extract! in sort charstring.
extern SDL_Boolean xEq_SDL_PId (SDL_PId A, SDL_PId B);This function is used to check if two PId values are equal.
extern SDL_Duration xPlus_SDL_Duration (SDL_Duration D1, SDL_Duration D2);
#define xMinus_SDL_Duration(P1, P2) \ xPlus_SDL_Duration \ (P1,xMonMinus_SDL_Duration(P2))
extern SDL_Duration xMonMinus_SDL_Duration (SDL_Duration D);
extern SDL_Duration xMult_SDL_Duration (SDL_Duration D, SDL_Real R);
extern SDL_Duration xDiv_SDL_Duration (SDL_Duration D, SDL_Real R);
#define xGT_SDL_Duration(P1, P2) \ xLT_SDL_Time (P2, P1)
extern SDL_Boolean xEq_SDL_Duration (SDL_Duration D1, SDL_Duration D2);
extern SDL_Duration SDL_Duration_Lit (xint32 s, xint32 ns);
#define xPlus_SDL_Time(P1, P2) \ xPlus_SDL_Duration(P1, P2)
#define xMinusD_SDL_Time(P1, P2) \ xPlus_SDL_Duration(P1, xMonMinus_SDL_Duration(P2))
#define xMinusT_SDL_Time(P1, P2) \ xPlus_SDL_Duration \ (P1, xMonMinus_SDL_Duration(P2))
#define xEq_SDL_Time(P1, P2) \ xEq_SDL_Duration(P1, P2)
extern SDL_Boolean xLT_SDL_Time (SDL_Time T1, SDL_Time T2);
extern SDL_Boolean xLE_SDL_Time (SDL_Time T1, SDL_Time T2);
#define xGT_SDL_Time(P1, P2) \ xLT_SDL_Time(P2, P1)
#define xGE_SDL_Time(P1, P2) \ xLE_SDL_Time(P2, P1)
#define SDL_Time_Lit(P1, P2) \ SDL_Duration_Lit(P1, P2)
Example 224 NEWTYPE EnumType LITERALS Lit1, Lit2, Lit3; ENDNEWTYPE;is translated to:
typedef enum {Lit1, Lit2, Lit3} EnumType;
Example 225 NEWTYPE Str STRUCT a integer; b Boolean; c real; ENDNEWTYPE;is translated to:
typedef struct { SDL_Integer a; SDL_Boolean b; SDL_Real c; } Str;All the properties of a struct in SDL are preserved in the CSDL and C code. The predefined operators Extract! and Modify! are implemented as component selection in the struct in the same way as in SDL, that is, if S is a variable of type Str, then S!a in SDL is translated to S.a in C. The predefined operator Make!, which is a constructor of a struct value, is implemented by generating a Make function in C. This means that the expression (. 12, true, 0.22 .) in SDL is translated to the C function call Make(12, true, 0.22). The Make function will of course be given a name that makes it unique.
The components of a struct may be of any sort that the CSDL Code Generator can handle. A component may, however, not directly or indirectly refer to the struct sort itself.
Example 226The sort Str above may not have a component of sort Str. In such a case the translation to a C struct would not any longer be valid.
An instantiation of the generator array, if it does not violate the restrictions above, is translated to a struct containing an element A which is an array in C. The reason for this translation strategy is that an array may not be result type of a C function (only the address of an array may be result type), which is necessary as SDL operators may have arrays as result. By embedding the C array in a C struct this problem is avoided.
Example 227 SYNTYPE Syn = integer CONSTANTS 0:10 ENDSYNTYPE; NEWTYPE Arr ARRAY(Syn, real) ENDNEWTYPE;is translated to:
typedef SDL_Integer Syn; typedef struct { SDL_Real A[11]; } Arr;All the properties of an array in SDL are preserved in the CSDL and C code. The predefined operators Extract! and Modify! are implemented as component selection of the array in C in the same way as in SDL, so if AVar is a variable of type Arr, and Index is a valid index expression, then AVar(Index) in SDL is translated to AVar.A[Index] in C.
The predefined operator Make!, which is a constructor of an array value, is implemented by generating a Make function in C. This means that the expression "(. 0.22 .)" in SDL is translated to the C function call Make(0.22). The Make function will of course be given a name that makes it unique.
The syntype is translated to a type equal to the parent type using typedef.
Example 228 SYNTYPE Syn = integer CONSTANTS 0:10 ENDSYNTYPE; SYNTYPE Syn2 = integer CONSTANTS <0, =2, >=10 ENDSYNTYPE; SYNTYPE Arr1 = Arr DEFAULT (. 2.0 .); ENDSYNTYPE; /* Arr defined above */is translated to:
typedef SDL_Integer Syn; typedef SDL_Integer Syn2; typedef Arr Arr1;
STATIC typename variablename = expression;which means that this form of initialization must be valid in C for the current type.
Variables with no default value will not be initialized automatically as it will be using the SDT simulation facility.
In sorts that are translated to enumeration types in C, literals are obviously handled by the CSDL Code Generator. In sorts that are not translated to enumeration types in C, literals are treated as operators without parameters and are handled exactly in the same way as user defined operators. Note that the CSDL Code Generator does not permit naming of literals using name class literals or character strings.
Note that the C functions are divided into a function heading (extern or static declaration) and a function body. An example of a function heading (extern declaration) is:
Example 229 extern SDL_Integer Max (SDL_Integer Para1, SDL_Integer Para2);while the corresponding function body is:
SDL_Integer Max (SDL_Integer Para1, SDL_Integer Para2) { if (Para1 > Para2) return Para1; return Para2; }The main reason for this division of functions into heading and body is the separate compilation scheme used in C. If, for example, an abstract data type is defined in a system and used in a process in the system, then there has to be a module interface file (a .h file) for the system containing the external interface (types, extern declarations of functions and so on). The interface file should then be included in the file generated for the process.--------------------------------------------------------------------- Note: In all examples of this manual, prototypes as defined in ANSI-C, are used. If the actual compiler in use does not support prototypes, you have to transform the examples to the old C-style for functions. ---------------------------------------------------------------------
Even if separate compilation is not used, the division of functions into heading and body is useful. By having static declarations of the functions, the order in which functions must be defined is relaxed. If static declarations were not used, a function could only call the functions that are defined textually before the actual function.
To select the way the CSDL Code Generator should generate code for operators and literals, CSDL Code Generator directives are used. A CSDL Code Generator directive is an SDL comment with the first characters equal to #, followed by a sequence of letters identifying the directive. In this case the letters are ADT (for Abstract Data Type) and OP (for operator). An ADT directive and an OP directive should thus look like:
/*#ADT */ /*#OP */The text is not case sensitive.
OP directives are recognized at two different positions in an abstract data type:
Example 230 NEWTYPE Str STRUCT a integer; b Boolean; c real; ADDING LITERALS Lit1 /*#OP */, Lit2 /*#OP */; OPERATORS Op1 :Str,integer -> Str; /*#OP */ Op2 :Str,Boolean -> Str; /*#OP */ /*#ADT */ ENDNEWTYPE;At each of the positions after a literal name or operator definition, you can specify how this literal or operator should be implemented. In the directive immediately before ENDNEWTYPE the default implementation technique can be given. When the CSDL Code Generator determines how to generate code for a literal or an operator, it first looks for an OP directive after the literal name or operator definition. If no such directive is found it looks for a directive immediately before ENDNEWTYPE. If no ADT directive is found here, the generation technique B (for body) is assumed. The B should be interpreted as:
B: The CSDL Code Generator will generate extern definitions (headings) in C for the SDL operator, while the user is supposed to include the C function bodies.
An OP or ADT directive specifying a generation technique should have the following structure:
/*#OP (B) */ /*#ADT (B) */The code for the functions implementing the SDL operators should be placed in the #BODY section in the ADT directive, according to the following example.
Example 231 /*#ADT (B) #BODY C code, representing bodies of functions */The section name, i.e. #BODY, must be given on a line of its own and must have the # character in the first position of the line. Uppercase and lower case letters are as usual considered to be equal. If the section is empty, the section name can also be removed.
--------------------------------------------------------------------- Note: The CSDL Code Generator will not check the consistency between the specification of implementation techniques and the actual code included in the body section. This check is, together with checking the C code for syntactic and semantic errors, left to the C compiler. ---------------------------------------------------------------------Unfortunately it is not possible to have C comments within the code that is included in a #ADT directive, as SDL and C use the same symbols for start and end of comments. If a C comment is included, the SDT Analyzer will consider the end of the C comment as the end of the SDL comment. Instead a C macro called COMMENT can be used according to the examples below.
Example 232By introducing the macro:
#define COMMENT(p)it is possible to use comments in the following form:
COMMENT(This is a comment) COMMENT(These comments may not contain \ commas and should have a backslash at\ each line break) COMMENT((By having double parenthesis, any text can be entered into the comments))The function headings representing literals and operators are to a large extent determined by their corresponding definition in SDL. The only thing that is not specified in SDL is the names of the formal parameters. The number of parameters, there types, the result type of the function and function name are all defined in SDL.
Example 233In Example 230 on page 2435, where the struct Str is defined, there are two literals (Lit1 and Lit2) and two operators (Op1: Str, integer -> Str; and Op2: Str, Boolean -> Str;). The function heading of the corresponding C functions should be:
extern Str Lit1 (void); extern Str Lit2 (void); extern Str Op1 (Str yParam1, SDL_Integer yParam2); extern Str Op2 (Str yParam1, SDL_Boolean yParam2);The CSDL Code Generator will, as can be seen in the example above, name the formal parameters yParam1, yParam2 and so on, when it generates a function heading for an operator.
The function bodies, which should be supplied by the user if B is specified in the OP or ADT directive, are ordinary C functions.
Example 234 Str Lit1 (void) { Str Temp; Temp.a = 2; Temp.b = false; Temp.c = 10.0; return Temp; } Str Op1 (Str yParam1, SDL_Integer yParam2) { yParam1.a = yParam1.a + yParam2; return yParam1; }
Example 235 NEWTYPE Str STRUCT a integer; b Boolean; c real; ADDING LITERALS Lit; OPERATORS Op1 : Str, integer -> Str; Op2 : Str, Boolean -> Str; /*#ADT (B) #BODY Str Lit1 (void) { return yMake_Str (2,false,10.0); } Str Op1 (Str yParam1, SDL_Integer yParam2) { yParam1.a = yParam1.a + yParam2; return yParam1; } Str Op2 (Str yParam1, SDL_Boolean yParam2) { if (yParam2) return yParam1; return Lit1(); } */ ENDNEWTYPE;The only thing in this example which has not been discussed earlier is the use of the make function in the function for literal Lit1. Each struct in SDL has an implicit operator Make!, which is a constructor for struct values from the struct components. The CSDL Code Generator generates a function that corresponds to this operator with the name yMake_ followed by the sort name. The function has one parameter for each struct component and returns a value of the struct sort. The returned value is the struct value that is obtained when each component is assigned the value of the corresponding parameter. This make function is often very useful when literal functions in struct sorts are to be implemented.
Example 236 SYNTYPE Index CONSTANTS 1:10 ENDSYNTYPE, NEWTYPE A Array(Index, integer) ADDING LITERALS Zero /*#OP (B) */; OPERATORS Add : A, A -> A; /*#OP (B) */ /*#ADT() #BODY A Zero (void) { return yMake_A (0); } A Add (A yParam1, A yParam2) { Index I; A Result; for (I = 1; I<=10; I++) Result.A[I] = yParam1.A[I] + yParam2.A[I]; return Result; } */ ENDNEWTYPE;
For an operator in an abstract data type not only B (body) may be specified. The following choices are available:
---------------------------------------------------------------------- Note: As C does not include the possibility to have user defined operators, I (infix) is only adequate together with S (standard). ----------------------------------------------------------------------
The purpose of S is straight forward and easy to understand, but H might require some explanation. H means that the CSDL Code Generator will not generate any code for the operator, which leaves you with a number of possibilities:
Example 237Example of usage of S (standard)
"+" : integer, real -> real; /*#OP (SI) */ sin : real -> real; /*#OP (SP) */An SDL expression using these operators:
sin(a + 7.0) will be translated to: sin(a + 7.0)These examples show how standard functions in the target language can be directly utilized in abstract data types.
/*#ADT (T(x) A(x) E(x) D(x) K(x) X(x) xy 'file name') #TYPE C code #HEADING C code #BODY C code */where each x on the first line should be replaced by one of the characters B, H, S, or G. Replace y by P or I. The interpretation of these characters is similar to the their interpretation for operators.
----------- B Body H Heading S Standard G Generate P Prefix I Infix -----------The reason why G (generate) is not allowed for operators or literals is of course that it would mean to generate the implementation of the operators from the axioms, which is, at least in the general case, an impossible task.
The specifications, given in ADT directives, of how to generate code for type definition, assignment, test for equal, and default values should be interpreted according to the table below. More details about the functions can be found in "Help Functions" on page 2446.
-------------------------------------------- Type Interpretation -------------------------------------------- T(G) Generate type definition from SDL sort T(B) Do not generate type definition T Same as T(B) - Same As T(G) --------------------------------------------
------------------------------------------------------------ Type Interpretation ------------------------------------------------------------ A(B) Use the assign function yAss_SortName Generate heading but not body A(H) Use the assign function yAss_SortName
Generate no code for function A(G) · If the type definition is generated:
------------------------------------------------------------ Type Method ------------------------------------------------------------ E(B) Use the equal function yEq_SortName. Generate heading but not body. E(H) Use the equal function yEq_SortName. Generate no code for function. E(G) · If the type definition is generated:
----------------------------------------------------------------- Type Interpretation ----------------------------------------------------------------- D(B) Generate heading, but no body of default function yDef_SortName. D(H) Generate neither heading nor body of default function. D(G) Generate both heading and body of default function, or use macro if adequate. D(S) Same as D(G) D Same as D(B) - Same as D(G) -----------------------------------------------------------------
------------------------------------------------------------- Type Interpretation ------------------------------------------------------------- K(B) Generate heading, but no body of the make function yMake_SortName. K(H) Generate neither heading nor body of the make function. K(G) Generate the make function K Same as K(B) - Same as K(G) -------------------------------------------------------------
---------------------------------------------------------------------- Type Interpretation ---------------------------------------------------------------------- X(B) Use `->' instead of `.' as struct component selec tor. X (B, 'string') Use parameter string as struct component selec tor. If array type, then insert string between vari able name and [. X(G) Use component selection according to SDL data type. X Same as X(B) - Same as X(G) ----------------------------------------------------------------------When generate is specified for a function, the C Code Generator might decide not to generate the heading of the function, as in some cases it is not needed. It might also decide to use a macro implementation instead of a function.
All code that is not generated, is of course assumed to be included by the user in the #TYPE, #HEADING, and #BODY sections in the #ADT directive.
You can use another name for an assign function, an equal function and so on, by including the desired name within quotes together with the generation options in the #ADT directive.
If for example the name of a certain assign function should be AssX, this can be obtained by specifying: A(B `AssX') for the assign function. This name will then be used throughout the generated code, both in generated declaration and at the places where the function is called. Note that the name should be last in the specification for the function.
You can have an include statement generated together with or replacing the type definition by giving a file name within quotes last in the specification part of the #ADT directive, immediately before the first section with code.
Example 238If the directive
/*#ADT (T(B) A(S) E(S) 'file name') */is used, the following include statement will be generated:
#include "file name"This facility is introduced to facilitate separately defined and precompiled implementations of abstract data types. By using this include facility to include a .h file containing the type definition and the extern declarations of the appropriate functions and by using the #NAME directive to decide the name that should be used in the generated code, you can achieve this. You just have to link with the appropriate module.-------------------------------------------------------------------- Note: You have to turn off the generation of the objects contained in the include file yourself. --------------------------------------------------------------------
void yAss_SortName (SortName *yVar, SortName yExpr)It should assign the value passed as second parameter to the variable passed as first parameter. The SDL predefined sorts Charstring, Time and Duration use assign functions xAss_SDL_Charstring, xAss_SDL_Time and xAss_SDL_Duration, while all the other predefined types use =. Sorts translated as enum types can always use =, while array and struct sorts can use = if all components can use =. A syntype in SDL uses = if its father type can use =, otherwise it uses the assign function of the father type.
An equal function has the following heading:
SDL_Boolean yEq_SortName (SortName yExpr1, SortName yExpr2);It should return true or false depending on if the two values passed as parameters are equal or not. The SDL predefined sorts Charstring, Time, Duration and PId have equal functions:
xEq_SDL_Charstring xEq_SDL_Time xEq_SDL_Duration xEq_SDL_PIdwhile all the other predefined types can use ==. Sorts translated as enum types can always use ==, while array and struct sorts always have equal functions. A syntype in SDL uses == if its father type can use ==, otherwise it uses the equal function of the father type.
All sorts defined in an SDL system that contains a default value, will have a default function which is used to initialize variables of the actual sort. A default function has the following heading:
void yDef_SortName (SortName *yVar)It should assign the default value to the variable passed as parameter. The default function will in many cases be implemented using a macro.
For each array and struct sort (not Syntypes) there will be a generated make function, which is used as constructor of array or struct values out of there respective components, according to the rules for the Make! operator in SDL.
ArraySortName yMake_ArraySortName ( ComponentSortName yExpr ) StructSortName yMake_StructSortName ( ComponentSortName1 yComponentName1; ComponentSortName2 yComponentName2 )The number of parameters in a struct make function is the same as the number of components in the struct.
A directive has the general structure:
Example 239Take as an example the directive:
/*#OP (B) */This comment will be recognized as a directive only if no other character is inserted in the sequence /*#OP. After this part spaces and carriage returns may be inserted freely.
There are two versions of all directives, one with the name presented in this manual and the other with the letters CSDL first in the directive name. It is possible, for example, to use either #ADT or #CSDLADT as name for the ADT directive. When just one translator, the CSDL Code Generator, is used it does not matter which version of the name that is used. However, if the same SDL system is used as input both to the CSDL Code Generator for generating an application, and to the C Code Generator for simulation, the #ADT directive will be seen by both code generators. As the C Code Generator also recognizes two versions of the directives, the directive name and the directive name preceded by C, it is possible to have two different ADT directives, using #CADT and #CSDLADT, and having each code generator to only see its own directive.
---------------------------------------------------------------------- Caution! Note especially that objects forming files, processes, procedures, and states, must have distinct names. Otherwise one file will over write another file! This means, for example, that all states names in all processes have to be different. See also "File Names" on page 2389. ----------------------------------------------------------------------To include code in the generated code from the C Code Generator, the directive #SDL sometimes have to be used (see "Accessing SDL Names in C Code - Directive #SDL" on page 2027 in chapter 34, The C Code Generator). To simplify the usage of the same code for C and for CSDL, in a common #ADTs for example, the CSDL Code Generator can also handle the #SDL directive. As this directive is only of interest when the CSDL Code Generator is used together with the C Code Generator, it is not further described here.
This strategy normally works very well, as each occurrence of a CSDL or C name is generated in the same way. If you, however, are about to use the SDL name in included C code, in for example a #CODE directive, then you need to know how upper and lower case letters are used in the C name. This might be a problem if you have multiple occurrences of the name using different combinations of upper and lower case letters.
As a solution for this and for other potential problems concerning upper and lower case letters in CSDL and C names, the CSDL Code Generator, as well as the C Code Generator, has an option to translate all SDL names to lower case. This option can be set in the Make dialog in the Organizer (see "Make" on page 1107).
Another way of removing this problem is to specify the name for an SDL object that should be used in generated code. This is described in the next section.
Example 240 NEWTYPE S /*#NAME 'S' */ STRUCT a integer; b Boolean; ADDING OPERATORS Op /*#NAME 'OtherName' */ : S, S -> Boolean; ENDNEWTYPE;The name defined in a #NAME directive will be used everywhere that the SDL name is used in the generated code, with one exception: The name of the files for generated code are not affected by the usage of #NAME directives.
/*#CODE C code that should be included in generated code */Type the directive name on the first line and the C code on the following lines up to the end of comment symbol.
A #CODE directive can be placed:
----------------------------------------------------------------- Note: The CSDL Code Generator handles the C code in directives as text and performs no check that the code is valid C code. -----------------------------------------------------------------The code directive is included as a facility in the CSDL Code Generator to provide experienced users an escape possibility to the target language C. This increases the application range of the CSDL Code Generator.
Unfortunately it is not possible to have C comments within the code that is included in any directive, as SDL and C use the same symbols for start and end of comments. See also Example 232 on page 2436 which illustrates the possibility to use a C macro COMMENT.
/*#CODE #TYPE C code containing: Types and variables #HEADING C code containing: Extern or static declarations of functions #BODY C code containing: Bodies of functions */The separation of functions into HEADING and BODY sections serves the same purpose as in the #ADT directive, see "Implementation of User-Defined Operators" on page 2433.
Code directives to include C declarations may, generally speaking, be placed immediately after a semicolon that ends a declaration in SDL. More precisely it is allowed to place a #CODE directive after the semicolon that ends:
Example 241 system s; *1 signal s1, s2(integer); *2 channel c1 from env to b1 with s1, s2; *3 newtype n ... endnewtype n; *4 block b1; *5 signalroute sr1 from env to p1 with s1, s2; *6 connect c1 with sr1; *7 process p1 (1,1); *8 signalset s1, s2; *9 dcl a n; *10 start; ... state ...; ... endprocess p1; *11 endblock b1; *12 endsystem s1;A code directive is considered to belong to the unit where it is defined and the declarations within the directive are thus placed unitname_d.h or unitname_c.c for that unit. In the example above directives at positions 1, 2, 3, 4, 12 belong to system s, directives at positions 5,6,7,11 belong to block b1, while directives at positions 8, 9, 10 belong to process p1. Only one code directive may be placed at each available position.
In the generated code the type sections are included in the order of appearance in SDL. However, the type sections are also sensitive for their relative position comparing with SDL sort definitions. This means that the order of the type definitions in the system in the example above will be as follows:
#CODE : Charstring -> S;where S is replaced by the actual sort name. This operator or rather these operators make it possible to access variables and functions defined in C using the #CODE directive in SDL expressions and still have syntactically and semantically correct SDL expressions.
During code generation, the C Code Generator will just copy the Charstring parameter at the place of the #CODE operator.
Example 242Suppose that x and y are SDL variables, that a and b are C variables, and f is a C function defined in #CODE directives.
-------------------------------- SDL expression C expression -------------------------------- x + #CODE('a') z72_x + a x + #CODE('a*b') z72_x + a*b x*#CODE('(a+b)')*y x*(a+b)*y #CODE('f(a, x)') f(a, x) --------------------------------
As there is one #CODE operator for each sort in the system, it is sometimes necessary to qualify the operator with a sort name to make it possible for the SDL Analyzer to resolve which operator that has been used. If, for example, the question and all answers in a decisions are given as applications of #CODE operators, then it is not possible to determine the type for the decision. One of the #CODE operators should then be qualified with a sort name to resolve the conflict.
Example 243 DECISION #CODE('a'); (#CODE('1')) : TASK ...; (#CODE('2')) : TASK ...; ENDDECISION;In this case the sort of the decision cannot be resolved. To overcome this problem the question could be written as
DECISION TYPE integer #CODE('a');
#OWN #GLOBAL #PROCPAR #TIMERTYPE #TRANSFER #SIGFIELD #CATEGORY
The variables defined in an SDL process (using DCL) are mapped to the three variable types own variables, global variables, and private variables using directives according to the example below.
Example 244 DCL i1, i2 Integer, J Boolean, /*#GLOBAL*/ k Character, /*#OWN 'state1'*/ L Integer; /*#OWN 'start'*/The first two variables, i1 and i2, are private variables, the third variable, J, is a GLOBAL variable, while k and L are OWN variables; k to the state unit for state state1 and L for the start up unit.
Note that the #OWN variable takes a parameter which either should be start or the name of a state. If a user wants to indicate private variables by a directive
/*#PRIVATE */that is OK, as this will be seen just as a comment by the CSDL Code Generator.
The example below shows the structure of the directive and how to place it in SDL. The directive should be last in the create or stop action, just before or after the semi-colon. In SDL-GR the directives are best placed in a text-extension box attached to the create or stop symbol. It can also be placed last in a create symbol.
Example 245The following actions in SDL
create P2; /*#PROCPAR (x,y,z)*/ create P2 /*#PROCPAR (a,b,c)*/; stop /*#PROCPAR (1,1,1)*/;are translated to:
TASK 'Create of process P2'; { SDL_CREATE (x,y,z); } TASK 'Create of process P2'; { SDL_CREATE (a,b,c); } TASK 'Stop'; { SDL_KILL (1,1,1); }Note that the parameters in the #PROCPAR directive have just been copied to the generated CSDL code.
Example 246The following Set statements
set (now+Sec*Ival, Timer_ex); set (now+Sec*Ival, Timer_ex); /*#TIMERTYPE 'SDLTIMER_REP'*/ set (now+Sec*Ival, Timer_ex) /*#TIMERTYPE 'SDLTIMER_REP_UNEVEN' 'REP'*/;are translated to the following CSDL code:
START_TIMER SDLTIMER UNITS Ival BASE Sec SIGNAL Timer_ex KEY TIMER_EX_TO_KEY; START_TIMER SDLTIMER_REP UNITS Ival BASE Sec SIGNAL Timer_ex KEY TIMER_EX_TO_KEY; START_TIMER SDLTIMER_REP_UNEVEN UNITS Ival BASE Sec SIGNAL Timer_ex DATA REP KEY TIMER_EX_TO_KEY;The directive parameters are introduced into the START_TIMER statement as timer type and DATA component.
Note that it is possible to simulate, using the SDT simulation facility, only the SDLTIMER timer type.
Example 247The following output statements:
output Sig2 to DEST(Sender, 1, 1); output Sig to DEST(Sender, 1, 1) /*#TRANSFER*/; output Sig to DEST(Sender, 1, 1); /*#TRANSFER*/will be translated to:
OUTPUT Sig TO DEST(1, 1); OUTPUT Sig TO DEST(1, 1) TRANSFER; OUTPUT Sig TO DEST(1, 1) TRANSFER;If the signal contains parameters it is possible to specify in SDL that the parameters should not be copied to process variables by not having any variables in the INPUT statement. An example of an input statement of a signal with four parameters, where no parameter should be received is given below.
INPUT Sig( , , , );This is useful in connection with TRANSFER, not to unnecessarily copy the signal parameters.
Example 248The SDL signal definition below:
signal Sig1(integer, integer /*#SIGFIELD 'f2'*/, integer),will be translated to the following declaration in the signal library:
SIGNAL Sig1 CODE SIG1_CODE { SDL_Integer Param1; SDL_Integer f2; SDL_Integer Param3; };
The directive in inserted directly after the signal name in the input or save statement (or after the comma or semi-colon), see the example below. The CSDL Code Generator will use the directive parameters as CATEGORY in the generated INSIGNAL clause. The code generator will not check if the CATEGORY name are valid but will just copy them to the generated file.
Example 249The SDL code below
state State1; input Sig2 /*#CATEGORY 'CAT_1'*/, Sig3 /*#CATEGORY 'CAT_2'*/; nextstate State1; input Sig5, Sig6; /*#CATEGORY 'CAT_2'*/ nextstate State1; save Sig4 /*#CATEGORY 'CAT_1'*/;might generate the following CSDL code in the INSIGNAL clause, depending on where signals are defined.
INSIGNAL Process1_CAT FROM Block1_s.csm : Sig5; CAT_2 FROM Block1_s.csm : Sig6 (State1, Sig5); CAT_1 FROM System1_s.csm : Sig2, Sig4; CAT_2 FROM System1_s.csm : Sig3 (State1, Sig2);
The restrictions in the SDT Analyzer, which of course also affect the CSDL Code Generator, are summarized below. For more information see chapter 31, The Analyzer.
Only the SDL-88 subset of SDL-92 are supported with the following general restrictions:
Example 250Assume that we have an SDL system with the following structure:
system sys block B1 process P1 procedure Proc1 procedure Proc2 state State1 process P2 state State2 state State3 state State4that is, a system called sys with one block (B1) that contains two processes (P1 and P2). P1 contains two procedures (Proc1 and Proc2) and one state (State1), while P2 contains three states (State2, State3, and State4).
For this example the following .d file might be generated:
C1=sys_c.c C2=P1_c.c CSP1=P1.csp,State1.csp,Proc1.csp,Proc2.csp CSP2=P2.csp,State2.csp,State3.csp,State4.cspThe .d file will contain all the generated .c and .csp files for the system. Each line in the file will begin with either CX or CSPX, where X is an unique number within each group (C - CSP).
The number is followed by a = sign and a list of files separated by commas. No spaces or carriage returns are present within the file list. A list will never contain more than 20 file names. In such case a new list is started, with a new unique number.
Each line will contain the list of all files (.c or .csp) generated for one SDL unit (system, block, substructure, or process). C files might be generated for any SDL unit, while CSP files are only generated for processes (process, procedure, and state).
The .str file for the system above might look like:
SYSTEM:sys: sys_d.h, sys_c.c, sys_s.csm BLOCK:B1: B1_d.h, B1_s.csm PROCESS:P1: P1_d.h, P1.csp, State1.csp, P1_c.c, P1_s.csm PROCEDURE:P1: Proc1.csp, Proc2.csp PROCESS:P2: P2_d.h, P2.csp, State2.csp, State3.csp, State4.cspThe file will contain references to all generated files, and will be structured in such a way that the files generated for a certain SDL unit are listed after the name of the unit. Note that all procedures for a process are listed on the same line and that it is the process name that is given after the word PROCEDURE.
This page intentionally left blank