IBM
Contents Index Previous Next



Directives to the Cadvanced/Cbasic SDL to C Compiler


Syntax of Directives

The Cadvanced/Cbasic SDL to C Compiler recognizes a number of directives given mainly in SDL comments. The #ADT, #OP, #UNION, and #REF directives used in abstract data types are examples of such directives. The directives #ADT and #OP were described in the section Implementation of User Defined Operators, Union, and Directive #REF, in connection with abstract data types and are not further discussed here.

A directive has the general structure:

  1. The start of comment character: /*
  2. A `#' character.
  3. The directive name.
  4. Possible directive parameters given in free syntax. That is, spaces and carriage returns are allowed here.
  5. The end of comment characters */.

Upper and lower case letters are considered to be equal in directive names.

Example 395 : #OP Directive

Take 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.

Selecting File Structure for Generated Code - Directive #SEPARATE

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

The Cadvanced/Cbasic SDL to C Compiler can generate a separate file for:

Note:

Instantiations cannot be separated, i.e. an instance of a block type cannot be generated on a file of its own.

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

Example 396 : #SEPARATE Directive

system S; /*#SEPARATE 'filename' */ 
block B; /*#SEPARATE */
process type P1 inherits PType; /*#SEPARATE */
process P2 (1, ); /*#SEPARATE */
procedure Q; /*#SEPARATE */

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

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

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

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

An Example of the Usage of the Separate Feature

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

Example 397 : #SEPARATE Directive

system S; /*#SEPARATE 'Sfile' */
  block B1; /*#SEPARATE */
    process P11; /*#SEPARATE 'P11file' */
    process P12;
  block B2;
    process P21;
    process P22; /*#SEPARATE */
Note that #SEPARATE directives can only be used in SDL/PR files. Normally this information is given in the Organizer.

Applying Full Separate Generation

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

Sfile.c

Sfile.h 

B1.c

B1.h 

P11file.c 



P12.c 



B2.c

B2.h

P21.c 



P22.c 



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

Applying Separate Generation

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

Sfile.c

Sfile.h

Contains code for units S, B2, P21

B1.c

B1.h

Contains code for units B1, P12

P11file.c



Contains code for unit P11

P22.c



Contains code for unit P22

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

Applying No Separate Generation

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

Sfile.c



Contains code for all units

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

Guidelines

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

Note:

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

Accessing SDL Names in C Code - Directive #SDL

When writing C code that is to be included in a generated program it is often necessary to refer to names of objects defined in SDL. The name of an SDL object is, however, transformed when it is translated to C. A prefix, which is a sequence of characters, is added to the SDL name to make the C name unique in the C program. Furthermore, all characters in SDL name which are not allowed in a C name are removed. The prefixes are calculated by looking at the structure of definitions in the actual scope and in all scopes above. This means that adding a declaration at the system level might change all prefixes in blocks and processes contained in the system. As a consequence it is almost impossible to know the prefix of an object in advance.

To be able to write C code and use the name of SDL objects in that code, the Cadvanced/Cbasic SDL to C Compiler provides the directive #SDL which is used in C code to translate an SDL name to the corresponding C name.

The syntax of the #SDL directive is as follows:

#SDL (SDL name)

or

#SDL (SDL name, entity class name)

There is also a short form for the directive. No characters are allowed between the # character and the left parentheses in this form:

#(SDL name) 

or

#(SDL name, entity class name)

Replace SDL name with the name of an object in the SDL definition and entity class name by any of the following identifiers (upper and lower case letters are considered to be equal):

block

blockinst

blocksubst

blocktype

channel

channelsubst

connect

formalpar

gate

generator

label

literal

newtype

operator

package

predef

procedure

process

processinst

processtype

remoteprd

remotevar

service

serviceinst

servicetype

signal

signallist

signalroute

sort (= newtype)

state

synonym

syntype

system

systemtype

timer

variable

view

This list contains all entity classes, which means that not all of the entries are relevant for practical use. When a #SDL directive is found in included C code, the code generator first identifies what SDL object is referred to and then replaces the directive by the C name for that object. The search for the SDL object starts in the current scope (the scope where the C code is included), and follows the scope hierarchy outward to the system definition, until an appropriate SDL object is found. An appropriate SDL name is considered to be found if it has the specified name and is in the specified entity class. If no entity class name is given the search is performed for all entity classes.

It is also possible to use a qualifier in front of the SDL name to limit the search scope:

#(<<qualifier>>SDL name)

The use of a qualifier is optional, but sometimes a qualifier is necessary to resolve name conflicts. A conflict may occur for a choice field reference when there are two choices with the same field name. #SDL(choicefieldname) reference a literal from the implicit <choicename>present type which is used to check presence of choice fields, and it clashes with a literal generated for another choice. In addition, there is also name clash between the choice field itself and the corresponding implicit literal. A qualified literal reference should look like this:

#SDL(<<PACKAGE Pac/TYPE ChoiceT/TYPE present>>choicefieldname)

where TYPE present denotes the implicit ChoiceTpresent type generated for ChoiceT.

The qualifier facility in the #SDL directive is extended with a special entity class FIELD, which allows to point to a type in some structure or choice field. This is useful for inline types translated from ASN.1 (they get name with INLINE_<number> postfix where the number may change if ASN.1 specification is updated). For example, for the following ASN.1 type:

FrequencyInfo1 ::= SEQUENCE {
	 modeSpecificInfo CHOICE {
	 	 fdd INTEGER,
	 	 tdd INTEGER
	 }
}

The choice type is defined inline and does not have a name. It will be translated to the following in SDL:

newtype FrequencyInfo1_INLINE_0 /*#SYNT*/ choice
fdd Integer;
tdd Integer;
endnewtype;

newtype FrequencyInfo1 struct
modeSpecificInfo FrequencyInfo1_INLINE_0;
endnewtype;

It is possible to use the name of the structure field to denote inline choice type and reference <choicename>present literals like this:

#(<<PACKAGE MyDefs/TYPE FrequencyInfo1/FIELD 
modeSpecificInfo/TYPE present>>tdd)

Note:

In types, especially in block types, #SDL should be used with care. The reason is that some of the objects in a block type are generated for each instantiation of the block. A #SDL directive on such an object might lead to overloading of names in C. Sensitive objects are processes, process instantiations, signal routes, channels, remote definitions.

The table in the subsection SDL Predefined Types gives the direct translation between an SDL name and the corresponding C name or expression. For these names the #SDL directive should not be used.

Escaping # in inline C code

In inline C code # is in some circumstances used for a special meaning.

#(name)
#SDL(name)
#0, #1, ..., #9
##0, ##1, ..., ##9

The above constructs are all replaced by the C name for some appropriate unit defined in the source. In all other cases a # will just represent a #. However there are some rare situations when some of the translation rules above makes it impossible to include the intended C code. In format strings it is, for example, possible to have a # followed by a digit. To facilitate this it is possible to escape a # and override the translation rules above.

A sequence of three #, that is ###, will always be copied as one #. The reason for three # is that two # is already used by the translation rules given above.

Example 398 : Use of ### in inline code

Consider the following construction.

###1

will become:

#1

Including C Code in Task - Directive #CODE

The user's own C code may be included in tasks by using the #CODE directive. This directive has the following syntax:

/*#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. Note that text on the same line as the #CODE directive are not handled.

A #CODE directive can be placed:

The C code in the directives is textually included in the generated code at the position of the directive. If, for example, a code directive is placed between two assignment statements, the code in the directive is inserted between the translated version of the assignment statements.

Note:

The Cadvanced/Cbasic SDL to C Compiler 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 code generator to provide experienced users an escape possibility to the target language C. This increases the application range of the code generator.

An example of a possible use of the code directive is: An algorithm for some computation, which in the SDL description is only indicated as a task with an informal text, could be implemented in C. In this case the directive #SDL described in the previous subsection will probably become useful to access variables and formal parameters defined in SDL. See also the section on Escaping # in inline C code.

Some general hints on how to write C code that can be included into a simulation program, especially when charstrings or sorts containing charstrings as components are used, can be found in the last part of the section Implementation of User Defined Operators.

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 377 which illustrates the possibility to use the C macro COMMENT.

#CODE directives in compound statements

#CODE directives are recognized after a semicolon that ends a statement of one of the following kinds:

Example 399

{
  ;  /*#CODE
       #(i) = #(i)+1; */
  i := i+2;  /*#CODE
       #(i) = #(i)+3; */
}

This example contains first an empty statement followed by a directive and then an assignment followed by a directive. The empty statement can, as above, be used to insert #CODE directives at places that otherwise would not be possible, like at the beginning of a compound statement or directly after a compound statement.

Note that the code in the #CODE directive is associated to the statement just before the directive and is included in the scope of that statement.

Example 400

{
  if (true)
    i := i+4; /*#CODE
       #(i) = #(i)+5; */
}

In this case the code in the directive is included in the "if-part" of the if statement, just like the assignment it is associated with. This will be treated as:

  if (true) {
    i := i+4;
    i := i+5;
  }

To put the code directly after the if statement the following structure, with an empty statement after the if statement, can be used:

{
  if (true)
    i := i+4;
  ; /*#CODE
       #(i) = #(i)+5; */
}

Including C Declarations - Directive #CODE

The #CODE directive can also be used to include C declarations; for example types, variables, functions, #define, and #include in the declaration parts of the C program. This version of the code directive has the following structure:

/*#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.

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:

In the following small PR example the allowed positions are marked with an * followed by a number.

Example 401 : #CODE Directive

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 among the other C declaration 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.

Note:

A variable declared in a #CODE directive that belongs to a process will be shared between the process instances of the process instance set. Such a variable should only be used to represent some common property of all the process instances. To have a variable that is local to a process instance, the variable should be defined in SDL using DCL.

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:

  1. Type sections in 1, 2, 3
  2. Type generated for newtype n
  3. Type sections in 4, 12

As the Cadvanced/Cbasic SDL to C Compiler will generate the SDL sorts in the correct order, definition before usage, in C, the full algorithm is as follows.

The heading sections are placed in the order of their appearance in SDL. This applies to the body sections as well. All body sections will be placed after the sequence of heading sections and the heading section will be placed after all the type definitions. The SDL declarations made in the corresponding unit are available in the code directives and can as usual be reached using the #SDL directive. All declarations made in code directives are of course available in code directives in tasks in the corresponding unit or in its subunits.

The general hints on how to write C code that fits into a generated C program given in the section Implementation of User Defined Operators and in the section Accessing SDL Names in C Code - Directive #SDL are also applicable here.

Including C Code in SDL Expressions - Operator #CODE

For each sort defined in an SDL system, both predefined and user defined, the Cadvanced/Cbasic SDL to C Compiler includes an operator #CODE with the following signature:

#CODE : Charstring -> S;

where S is replaced by the 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 code generator will just copy the Charstring parameter at the place of the #CODE operator.

Example 402 : #CODE Directive

Suppose that x and y are SDL variables, which are translated to z72_x and z73_y, 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

z72_x*(a+b)* z73_y

#CODE('f(a,#SDL(x))')

f(a, z72_x) 

Within the Charstring parameter of a #CODE operator the #SDL directive is available in the same way as in other included C code. This is also shown in the last of the examples above.

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 decision 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 403 : Code Directive

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');

Names and Prefixes in Generated Code

When an SDL name is translated to an identifier in C, a prefix is normally added to the name given in SDL. This prefix is used to prevent name conflicts in the generated code, as SDL has other scope rules than C and also allow different objects defined in the same scope to have the same name, if the objects are of different entity classes. It is, for example, allowed in SDL to have a sort, a variable and a procedure with the same name defined in a process. So the purpose of the prefixes is to make each translated SDL name to a unique name in the C program.

A generated name for an SDL object contains four parts in the following order:

  1. The character "z"
  2. A sequence of characters that make the name unique. If the object is part of a package, the package name will appear in this sequence.
  3. An underscore "_"
  4. The SDL name stripped from characters not allowed in C identifiers

Sequence of Characters

A C identifier may contain letters, digits, and underscore "_" and must start with a letter.

The sequence of characters that make the name unique is determined by the position of the declaration in structure of declarations in the system:

The total sequence making a name unique is now constructed from the "declaration numbers" for the unit and its parents, that is the units in which it is defined, starting from the top.

If, for example, a sort is defined as the 5th declaration in a block that in turn is the 12th declaration in the system, then the total sequence will be b4 (if not more than 36 declarations are present on any of the two levels).

Example 404 : Generated Names in Code

Examples of generated names:

SDL Name Position of the Declaration Generated Name

S1

10th declaration in the system

z9_S1

Var2

3rd declaration in the process, which is the 5th declaration in the block,

which is the 15th declaration is system

ze42_Var2

There will also be other generated names using the prefixes. If, for example, a sort MySort is translated to za2c_MySort, then the equal function connected to this type (if it exists) will be called yEq_za2c_MySort.

Prefixes

Note:

If the OO diagram types in SDL-92 are used (system type, block type, process type), full prefix should always be used, as the OO concepts in itself most likely mean the name conflicts will be introduced in C.

This strategy for naming objects in the generated code should be used in all normal situations, as it guarantees that no name conflicts occur. The Cadvanced/Cbasic SDL to C Compiler offers, however, possibilities to change this strategy. In the Make dialog in the Organizer (see Make) and in the user interface an Analyzer running stand-alone (see The Analyzer Command Line UI), it is possible to select one of the following strategies: full prefix, entity class prefix, no prefix, or special prefix. Full prefix is default and is the strategy described above.

Entity Class Prefix

If entity class prefix is selected, then the prefix that is concatenated with the SDL name will be in accordance with the table below and depends only of the entity class of the object.

Entity class Prefix Entity class Prefix

Block, block type, block instance

blo

Process, Process type, Process instance

prs

Block substructure

bls

Remote procedure

rpc

Channel

cha

Remote variable

imp

Channel substructure

chs

Service, Service type, Service instance

ser

Connection

con

Signal

sig

Formal parameter

for

Signal list

sil

Gate

gat

Signal route

sir

Generator

gen

Sort = Newtype

sor

Import

imp

State

sta

Label

lab

Syntype

syt

Literal

lit

Synonym

syo

Operator

ope

System, System type

sys

Package

pac

Timer

tim

Predef

pre

Variable

var

Procedure

prd

View

vie

Using entity class prefix means that the user must guarantee that no name conflict occurs. It also means, however, that the generated names are predictable and thus simplifies writing C code where the SDL names are used. It is only necessary to look for name conflicts within entity classes, for example not having two sorts with the same name. The entity class prefixes handle the case when two objects of different entity class have the same name. Note that the table above contains all entity classes. Not all of the items are actually used by the code generator.

No Prefix

The third alternative, no prefix, means of course that no prefixes are added to the SDL name. The name in the C program will then be the SDL name stripped form characters that are not allowed in C identifiers (everything except letters, digits, and underscore). In this case, the user must guarantee that no name conflict occurs and that the stripped name is allowed as a C identifier, that is, that it begins with a letter.

Special Prefix

In the fourth alternative, special prefix, full prefixes are used for all entity classes except variable, formal parameter, sort, and syntype. For these entity classes no prefix is used.

Conclusion

As was said in the beginning of this subsection, the user should have a good reason for selecting anything but the full prefix, as it could be very difficult to spot name conflicts. The C compiler will in some cases find a conflict, but may in other cases consider the program as legal and generate an executable program with a possibly unwanted behavior. The note above about OO concepts is also a strong argument for full prefix.

Case Sensitivity

Another aspect concerning identifiers is that SDL is case insensitive, while C is case sensitive. The Cadvanced/Cbasic SDL to C Compiler has two translation schemes for identifiers, one is to use the capitalization used in the declaration of the object of concern (default), and one is to use lower case identifiers. The translation scheme is selected in the Make dialog in the Organizer (see Make) or in the user interface of the Analyzer, when it is executed stand-alone (The Analyzer Command Line UI).

Specifying Names in Generated Code - Directive #NAME

If you wish to decide the name of an object in generated code yourself you can use the #NAME directive. Place the directive directly after the name in the declaration of the object. It should contain the desired name to be used in the generated code within quotes.

Example 405 : #NAME Directive

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 two exceptions:

There are, however, some restrictions on where #NAME directives can be placed. Some objects in, for example, a block type are generated in each instantiation of the block type. If a name directive is placed at such an object, the name will probably be overloaded in C, resulting in a C compilation error. The sensitive objects are processes, process instantiations, signal routes, channels, remote variables, and remote procedures.

Assigning Priorities - Directive #PRIO

Priorities can be assigned to processes and process instantiations using the directive #PRIO. The process priorities will affect the scheduling of processes in the ready queue, see Time. A priority is a positive integer, where low value means high priority. #PRIO directives can be placed directly after the process heading in the definition of the actual process or last in the reference symbol (in SDL/GR).

Example 406 : #PRIO Directive in process headings .

Process P1; /*#PRIO 3 */ 
Process P2(1,1); /*#PRIO 5 */ 

Process P3 : P3Type; /*#PRIO 3 */ 
Process P4(1,1) : P4Type; /*#PRIO 5 */ 

Processes that do not contain any priority directive will have the default priority 100.

Initialization - Directive #MAIN

The #MAIN directive is used to include initialization code that should be executed before any process transitions are started. The directive should be placed in the system definition directly after the system heading.

In a System diagram the comment with the #MAIN directive should be placed in the additional heading symbol, see The Additional Heading Symbol.

Example 407 : #MAIN Directive

System S;
/*#MAIN 
C code for initialization */

The #MAIN directive has exactly the same structure as the #CODE directive for including code in tasks. The included code will, however, be placed last in the yInit function, after the initialization of the internal structure, but before any transitions are executed.

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

The purpose of these directives is to modify the standard behavior of an SDL output. The #EXTSIG directive can be used to build applications with the SDL Suite run-time library. The directives #ALT and #TRANSFER are only useful together with other real-time operating systems.

The directive #EXTSIG is used to replace the code for an SDL output with any appropriate in-line C code. This is an optimization and an alternative to the OutEnv function (see Building an Application). The #EXTSIG directive can be specified:

In the first case the #EXTSIG is valid for the signal(s) sent in the output symbol, and in the second case for all outputs of the defined signal.

Example 408 : #EXTSIG Directive

signal
  Signal1          /*#EXTSIG */,
  Signal2(integer) /*#EXTSIG */;

output Signal3 To Sender /*#EXTSIG */;

For each output of a signal with a #EXTSIG directive (in either way described above) the following code is generated:

#ifndef EXT_SignalName
  "the normal implementation of an output"
#else
  EXT_SignalName(
    SignalName, ySigN_SignalNameWithPrefix,
    ToExpression, SignalParameters)
#endif

where SignalName is the name of the signal in SDL. The parameter ToExpression is a translated version of the SDL expression after TO in the output. If no TO expression is given in the output, this parameter will be xNotDefPId. The entry SignalParameters will be replaced by the list of signal parameter values given in the output.

The intention of this code is to give the user the possibility of introducing a macro with the same name as the signal, where the implementation of the output is expanded to in-line code. By just having a compilation switch which selects if this macro is visible or not, the same generated code can be used both for simulation and for highly optimized applications. An appropriate switch is probably XENV, which governs the normal way of connecting an SDL system to the environment.

Example 409 : #CODE Directive

The following #CODE directive can be included in a text symbol in the system diagram (assuming a signal called SigName with one parameter).

/*#CODE
#TYPE
#ifdef XENV
#define EXT_SigName(Name, IdNode, ToExpr, Param1) \
   suitable macro code
#endif
*/

The other two directives, #ALT and #TRANSFER, can be used together with appropriate real-time operating systems, to have two different interpretations of an output (internal or external output for example) and to specify that a received signal should be immediately retransmitted (#TRANSFER). These kinds of features are not uncommon in real-time operating systems, and can be modeled and simulated by the Cadvanced/Cbasic SDL to C Compiler using these directives. Both these directives should be placed last in the output symbol.

The presence of an #ALT directive will be reflected in the generated code in the way described below.

In the Master Library, the macros with and without ALT are expanded identically. In an OS integration they might be handled differently to implement two classes of signal sending.

The presence of a #TRANSFER directive indicates that a signal should be directly retransmitted to some other receiver. This can of course be performed in SDL by an input-output, but then it is necessary to create a new signal and copy the contents of the received signal to the new signal. Using the #TRANSFER directive this copying can be avoided.

In generated code the macros

are generated to allocate the data area for a new signal. If a #TRANSFER directive is present in the output statement, these macros are replaced by:

Note:

In the master library #TRANSFER will still be implemented as a signal copy. It may be possible in an OS integration to avoid the copying if the OS supports such actions.

Normally the #TRANSFER directive should be used in the following way:

INPUT signal1(,,,);
OUTPUT signal1(,,,) /*#TRANSFER*/;

That is, receive none of the signal parameters in the input and retransmit the signal unchanged. If you want to receive, for example, the second parameter (in variable Var1) and retransmit the signal unchanged except for parameter 3, that should have a new value (73), the following code can be used:

INPUT signal1(,Var1,,);
OUTPUT signal1(,,73,) /*#TRANSFER*/;

Linking with Other Object Files - Directive #WITH

Note:

This feature is only valid for SDL/PR as input, when the Analyzer is executed stand-alone. Similar features are available in the Organizer's Make dialog among the Generate makefile options, see Generate makefile.

You can tell the Cadvanced/Cbasic SDL to C Compiler that a number of user defined and precompiled units should be linked together with a generated simulation program. You do this in a #WITH directive that should be placed in the system definition directly after the system heading.

Example 410 : #WITH Directive

System S; /*#WITH 'file1.o' 'file2.o' */

Within the #WITH directive the object files that are to be part in the link operation should be given between quotes, as in the example above. These files will be included in the definition of the link operation in the generated .m file.

The make file will, however, not include any definition of how to compile the corresponding source files, as it is impossible for the code generator to know the compilation options or even what compiler the user wants. A user that knows how to interface routines in other languages in a C program, can with this knowledge and the #WITH directive link modules written in another language together with the generated program.

Note:

The #WITH directive will only affect the generated make file. There will be no change in the generated C code when a #WITH directive is introduced.

Naming Tasks in Trace Output - Directive #ID

To simplify the identification of a TASK in a trace printout, the Cadvanced/Cbasic SDL to C Compiler uses the variable on the left hand side of the first assignment statement or the first informal text in the task symbol. A user that is not satisfied with this can name the tasks using #ID directives. An ID directive should contain the character string that is to be used as identification in trace printouts.

Example 411 : #ID Directive

/*#ID 'Identification of task' */

The code generator will use the first ID directive it finds in a TASK (if any). An ID directive may be placed:

Directive #C, #SYNT, #SYNTNN, #ASN1

These directives are used to pass information from the tools generating SDL from other languages, for example for C (a .h file) or ASN.1.

The #C and the #ASN.1 directive will be inserted after the semicolon ending the package definition or after the package name.

package asn1_module; /*#ASN.1 `Module_Name' */
package asn1_module /*#ASN.1 `Module_Name' */;

The #ASN.1 directive contains the ASN.1 module name and the #C directive contains the name of the originating .h file.

The #SYNT directive and its special form the #SYNTNN directive are used in a package generated from C, to indicate which SDL sorts that are synthesized, i.e. which sorts that where needed in SDL but do not have a name and definition in C. As the originating .h file is included in the generated code (with a #include), no typedefs should be generated for the non-#SYNT sorts, while typedefs have to be generated for the synthesized sorts. The #SYNT directive is inserted directly after the name of the newtype or syntype.

Alternative Implementations of the String Generator - Directive #STRING

An instantiation of the string generator can be translated to either a linked list or an array when implemented in C. The #STRING directive is used to determine which translation method to select. The directive should be inserted in a NEWTYPE definition, directly after the string name, when defining a new string data type.

If the #STRING directive is not included in the NEWTYPE definition, the string is implemented as a linked list. This is the default translation method. However, just adding the directive to the NEWTYPE definition is not enough to implement the string as an array. The length of the array must also be defined. This can be done either by using a directive parameter or by using a size constraint in the NEWTYPE definition of the string generator. How this is done is presented in the examples below.

Linked List Implementations

The following examples show how to translate an instantiation of the string generator to a linked list.

Example 412 : No #STRING Directive

NEWTYPE Example_String
    string(integer, empty)
    constants size (0:10)
ENDNEWTYPE;

If the #STRING directive is missing from the NEWTYPE definition, the string will be implemented as a linked list. The length of the list is unlimited, unless a size constraints is defined. In this case the length of the string is within the range of 0 and 10.

Example 413 : #STRING Directive without Limited String Size

NEWTYPE Example_String /*#STRING */ 
    string(integer, empty)
ENDNEWTYPE;

In this example the string is also implemented as a linked list. The reason for this is that we have not defined a maximum length of the string.

Example 414 : #STRING Directive with Parameter Value 0

NEWTYPE Example_String /*#STRING 0*/ 
    string(integer, empty)
    constants size (0:10)
ENDNEWTYPE;

If the parameter value of the #STRING directive is 0, the directive is ignored. Therefore the string will be implemented as a linked list. The size constant will still decide the length of the string.

This example, however, shows how to gradually migrate from a linked list implementation to an array implementation. By just changing the parameter value to anything larger than 0, this NEWTYPE definition creates an array implementation.

Array Implementations

The following examples show how to translate an instantiation of the string generator to an array.

Example 415 : #STRING Directive with Limited String Size

NEWTYPE Example_String /*#STRING */ 
    string(integer, empty)
    constants size (0:10)
ENDNEWTYPE;

In this case the string is implemented as an array with the maximum length of 10.

Example 416 : #STRING Directive with Parameter Value

NEWTYPE Example_String /*#STRING 100*/ 
    string(integer, empty)
    constants size (0:10)
ENDNEWTYPE;

In this example the string will be implemented as an array with the length of 100. The parameter value in the #STRING directive overrides the size constant, which in this case is redundant.

Size constraint

The size constraint is decided by adding a constant in the NEWTYPE definition. The following declarations are valid when defining a maximum size of the string:

constants size (a:b)
constants size (a)
constants size (=a)
constants size (<a)
constants size (<=a)

Differences between the Implementations Methods

The different implementation methods affect the behavior and performance of the generated code. The following general statements apply to the methods:

Selecting implementation Methods

It is of course hard to advice which method to select, but the following recommendations apply:


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