![]() |
![]() |
![]() |
![]() |
![]() |
Reference Section
Representation of Signals and Processes
In this first section, the representation of signals and processes is presented. The symbol table, which is a representation of the static structure of the system, will also be discussed. The information given here will be used in the next part of this section where the environment functions, which should be provided by the user, are described.
Types Representing Signals
A signal is represented by a C struct containing general information about the signal followed by the parameters carried by the signal.
A general typedef xSignalRec for a signal without parameters and for a pointer to such a signal, xSignalNode, are given below. These types may be found in the file scttypes.h. These types may be used for type casting of any signal to access the general components.
typedef struct xSignalRec *xSignalNode;typedef struct xSignalRec {xSignalNode Pre;xSignalNode Suc;SDL_PId Receiver;SDL_PId Sender;xIdNode NameNode;int Prio;} xSignalRec;A xSignalRec contains the following components:
- Pre and Suc. These components are used to link the signal in the input port list of the receiving process instance. The input port is implemented as a double linked list. When a signal has been consumed and the information contained in the signal is no longer needed, the signal will be returned to an avail list to be re-used in future outputs. The component Suc is used to link the signal into the avail list, while Pre will be (xSignalNode)0 as long as the signal is in the avail list.
- Receiver. The receiving process instance.
- Sender. The sending process instance.
- NameNode. This component is a pointer to the node in the symbol table that represents the signal type. The symbol table is a tree with information about the SDL system and contains, among other things, one node for each signal type that is defined within the SDL system.
- Prio. This component represents the priority of the signal and is used in connection with continuous signals.
In the generated code there will be types to represent the parameters of the signals according to the following example:
Example 428 : Generated C Code for Signal Definition
Assume the following signal definitions in SDL:
SIGNALS1(Integer),S2,S3(Integer, Boolean, OwnType);then the C code below will be generated:
typedef struct {SIGNAL_VARSSDL_Integer Param1;} yPDef_z0f_S1;typedef yPDef_z0f_S1 *yPDP_z0f_S1;typedef struct {SIGNAL_VARSSDL_Integer Param1;SDL_Boolean Param2;z09_OwnType Param3;} yPDef_z0h_S3;typedef yPDef_z0h_S3 *yPDP_z0h_S3;where SIGNAL_VARS is a macro defined in scttypes.h that is expanded to the common components in a signal struct.
For each signal with parameters there are two generated types, a struct type and a pointer type. The struct type contains one component for each parameter in the signal definition and the components will be named Param1, Param2 and so on. The components will be placed in the same order in the struct as the parameters are placed in the signal definition.
There are no generated types for a signal without parameters.
Types Representing Processes
A PId value is a struct consisting of two components, a global node number, which is an integer (see also Function xGlobalNodeNumber and The Basic Idea) and a local PId value, which is a pointer.
typedef xLocalPIdRec *xLocalPIdNode;typedef struct {int GlobalNodeNr;xLocalPIdNode LocalPId;} SDL_PId;The global node number identifies the SDL system that the process instance belongs to, while the local PId value identifies the process instance within the system. The local PId pointer value should not be referenced outside the SDL system where it is defined.
By introducing a global node number in the PId values, these values are possible to interpret throughout an application consisting of several SDL systems. You can also define your own PId values in non-SDL defined parts of the application and still use communication with signals.
The variable SDL_NULL, which represents a null value for PIds and which is defined in the runtime library and available through the file scttypes.h, contains zero in both the global node number and the local PId component. Note that the global node number should be greater than zero in all PId values except SDL_NULL.
The Symbol Table
The symbol table is a tree built up during the initialization phase in the execution of the generated program and contains information about the static structure of the SDL system. The symbol table contains, for example, nodes which represent signal types, blocks, channels, process types, and procedures. The C type that are used to represent for example signals in the symbol table is given below.
typedef struct xSignalIdStruct *xSignalIdNode;typedef struct xSignalIdStruct {/* components */} xSignalIdRec;It is the nodes that represent the signal types, for signals sent to and from the environment of the SDL system, that are of major interest in connection with the environment functions. For each signal type there will be a symbol table node. That node may be referenced using the name ySigN_ followed by the signal name with prefix. Such references may be used in, for example, xOutEnv to find the signal type of the signal passed as parameter.
In some cases the symbol table nodes for channels from the environment to a block in the system are of interest to refer to. In a similar way as for signals such nodes may be referenced using the name yChaN_ followed by the channel name with prefix.
The Environment Functions
An SDL system communicates with its environment by sending signals to the environment and by receiving signals from the environment. As no information about the environment is given in the SDL system, the Cadvanced SDL to C Compiler cannot generate the actions that should be performed when, for instance, a signal is sent to the environment. Instead you have to provide a function that performs this mapping between a signal sent to the environment and the actions that then should be performed. Examples of such actions are writing a bit pattern on a port, sending information over a network to another computer and sending information to another OS process using some OS primitive.
You should provide the following functions to represent the environment of the SDL system:
- xInitEnv and xCloseEnv, which are called during initialization and termination of the application
- xOutEnv which should treat signals sent to the environment
- xInEnv which should treat signals sent into the SDL system from the environment
There are two ways to get a skeleton for the env functions:
- You can copy the file sctenv.c from the directory
<installation directory>/sdt/sdtdir/<machine dependent dir>/INCLUDE
where <machine dependent dir> is for example sunos5sdtdir on SunOS 5 and wini386 in Windows. (In Windows, / should be replaced by \ in the path above.)
This file also contains some trace mechanisms that may be used to trace the execution in a target computer. This trace can, however, only be used if you have the source code for the run-time library (included in the Cadvanced SDL to C Compiler) and can produce a new object library with the appropriate switches.- You can generate a skeleton by using the Generate environment functions option in the Make dialog in the Organizer. In very simple cases you might obtain executable env functions by just tuning the macros in this generated file, but in the general case you must use it as a skeleton and edit it. Remember then to copy the file so that it is not overwritten when code is generated the next time.
An advantage with the generated env functions is that the SDL to C Compiler knows about the signal interface to be implemented in the env functions, and can therefore insert code or macros for all signals in the interface. To calculate this information is not that easy, especially if partitioning (generating code for a part of a system) is used.
The env functions are thoroughly discussed below, but first we will introduce the system interface header file which considerably simplifies writing the environment functions.
System Interface Header File
The system interface header file contains code for objects that are defined in the system diagram. Included are all type definitions and other external definitions that are needed in order to implement external C code. These object definitions simplify the implementation of the environment functions. Therefore the system interface header file is also known the environment header file. This file is generated if:
- Code is generated for the complete system.
- The Generate environment header file option is selected in the Make dialog in the Organizer (see Code Generation Options).
The default name of the generated interface header file is <system_file_name>.ifc.
The system interface header file, has the following structure:
- Macros for all synonyms that are translated to macros.
- All type definitions generated from newtypes and syntypes. This includes #TYPE and #HEADING sections in #ADT directives and in #CODE directives.
- External definitions of variables for all synonyms that are translated to variables.
- For each signal defined in the system diagram there will be an extern definition for the xSignalIdRec variable representing the signal.
- For each signal with parameters defined in the system diagram, there will be definitions of the types yPDef_SignalName and yPDP_SignalName, i.e. of the types used to represent a signal.
- For each remote procedure (that can be sent to or from the environment), code will be generated exactly as for two signals named pCALL_procedurename and pREPLY_procedurename.
- For each channel defined in the system diagram there will be extern definitions for the xChannelIdRec representing the channel.
Together with these definitions, macros that simplify the translation of SDL names to C names are also be generated.
Names of SDL Objects in C
Due to differences in naming rules in SDL and C, prefixing is used to make C identifiers unique (see section Names and Prefixes in Generated Code). These prefixes, however, may change when you update your SDL diagrams and cannot be predicted. Therefore you should not use the prefixed object names in the environment functions. Instead macros, generated in the system interface header file, assist you by mapping static names to the prefixed names. This means that you must regenerate the system interface header file each time you regenerate code for the system. The good part is that you do not have to make any changes in the environment functions, as the interface names are static.
Example 429 : Macro in the system interface header file
If an SDL signal called Sig1 is defined in the system, the following macro is created:
extern XCONST struct xSignalIdStruct ySigR_z5_Sig1;#ifndef Sig1#define Sig1 (&ySigR_z5_Sig1)#endifThis macro allows you to refer to the xIdNode by using the static name Sig1 rather than the prefixed name, ySigR_z5_Sig1.
Macros generate static names for the following SDL types:
- Synonyms (both translated to macros and variables).
- Newtypes and Syntypes. If the newtype is translated to an enumeration type, all the literals are available directly in C using their SDL names.
- xSignalIdNode representing signals. (No ySigN_ prefix).
- xChannelIdNode representing channels. (Use prefix xIN_ or xOUT_ to access the incoming or outgoing direction of the channel).
- The yPDP_SignalName pointer type. This type may be referred to using the name yPDP_SignalName, where SignalName is the SDL name.
You must always generate the system interface header file before editing or generating the environment functions.
Avoiding name clashes
In SDL it is allowed to give the same name to different objects. This is not allowed in C. For instance, in SDL you can give a signal and a Newtype the same name. In order to distinguish between the names in the system interface header file, you must define static unambiguous names. Using the Env. Header File Generation tab in the Targeting Expert, you can do this by using available general identifiers. The identifiers are:
- %n - This identifier is the SDL name
- %s - This identifier is the SDL name of the scope.
- sdlobject - In order to identify the type of object, you can type the object name as a prefix, e.g. signal, literal, etc.
Any combination of the identifiers can be used and they are all optional. However, in order to create a useful system interface header file, it is recommended that the %n identifier is always included. Leaving the field empty means that no objects of that type is included in the system interface header file at all.
If you select to include all objects and use the %n identifier only, the system interface header file will become compatible with earlier versions.
Example 430 : Name Mapping in an system interface header file
If the signal Signal1 is in the system System2 you should type the following in the Signal field in the TAEX.
The result in the system interface header file will be:
This approach helps you to avoid name clashes in the ifc file. Literals, for example, are often given the same name when defined in different types. The following example shows how this can be solved.
Example 431 : Avoiding Name Clashes
In an SDL system the following two newtypes are defined:
NewType sliterals red, greenNewType tliterals red, yellowAs the literal red appears in both newtypes, the C code cannot distinguish between them. However, by using the identifiers in the literals field,
lit_%n_%sthe literals are given the following names:
lit_red_slit_red_tThus we will avoid a possible name clash.
Structure of File for Environment Functions
The file containing the environment functions should have the following structure:
#include "scttypes.h"#include "file with macros for external synonyms"#include "systemfilename.ifc"void xInitEnv XPP((void)){}void xCloseEnv XPP((void)){}#ifndef XNOPROTOvoid xOutEnv (xSignalNode *S)#elsevoid xOutEnv (S)xSignalNode *S;#endif{}#ifndef XNOPROTOvoid xInEnv (SDL_Time Time_for_next_event)#elsevoid xInEnv (Time_for_next_event)SDL_Time Time_for_next_event;#endif{}int xGlobalNodeNumber XPP((void)){}The last function, xGlobalNodeNumber, will be discussed later, see Function xGlobalNodeNumber. The usage of the macros XPP and XNOPROTO makes the code possible to compile both with compilers that can handle prototypes and with compilers that cannot. If you do not need this portability, you can reduce the complexity of the function headings somewhat. In the minor examples in the remaining part of this section, only versions with prototypes are shown.
Functions xInitEnv and xCloseEnv
There are two functions among the environment functions that handle initialization and termination of the environment. These functions, as well as the other environment functions, should be provided by the user.
void xInitEnv ( void );void xCloseEnv ( void );In the implementation of these functions you can place the appropriate code needed to initialize and terminate the software and the hardware. The function xInitEnv will be called during the start up of the program as first action, while the xCloseEnv will be called in the function SDL_Halt. Calling SDL_Halt is the appropriate way to terminate the program. The easiest way to call SDL_Halt is to include the call in a #CODE directive in a TASK. SDL_Halt is part of the runtime library and has the following definition:
void SDL_Halt ( void );
xInitEnv will be called before the SDL system is initialized, which means that no references to the SDL system are allowed in this function. To, for example, send signals into the system during the initialization phase, the #MAIN directive should be used (see Initialization - Directive #MAIN). This directive code can be used after the initialization of the SDL system, but before any transitions are executed.
If you use the generated environment file, you could also define the symbols XENV_INIT and XENV_CLOSE to be the bodies of xInitEnv and xCloseEnv.
Function xOutEnv
Each time a signal is sent from the SDL system to the environment of the system, the function xOutEnv will be called.
void xOutEnv ( xSignalNode *S );The xOutEnv function will have the current signal as parameter, so you have all the information contained in the signal at your disposal when you implement the actions that should be performed. The signal contains the signal type, the sending and receiving process instance and the parameters of the signal. For more information about the types used to represent signals and processes, see section Types Representing Signals and Types Representing Processes.
Note that the parameter of xOutEnv is an address to xSignalNode, that is, an address to a pointer to a struct representing the signal. The reason for this is that the signal that is given as parameter to xOutEnv should be returned to the pool of available memory before return is made from the xOutEnv function. This is made by calling the function xReleaseSignal, which takes an address to an xSignalNode as parameter, returns the signal to the pool of available memory, and assigns 0 to the xSignalNode parameter. Thus, there should be a call
xReleaseSignal(S);before returning from xOutEnv. The xReleaseSignal function is defined as follows:
void xReleaseSignal ( xSignalNode *S );In the generated environment skeleton file, the macro RELEASE_SIGNAL releases the signal as described above and returns from xOutEnv.
In the function xOutEnv you may use the information in the signal that is passed as parameters to the function. First it is usually suitable to determine the signal type of the signal. This is best performed by if statements containing expressions of the following form, assuming the use of the system interface header file and that the signal has the name Sig1 in SDL:
(*S)->NameNode == Sig1The above expression is captured in the macro IF_OUT_SIGNAL in the generated environment skeleton file.
Suitable expressions to reach the Receiver, the Sender, and the signal parameters are:
(*S)->Receiver(*S)->Sender((yPDP_Sig1)(*S)) -> Param1((yPDP_Sig1)(*S)) -> Param2Sender will always refer to the sending process instance, while Receiver is either a reference to a process in the environment or the value xEnv. xEnv is a PId value that refers to an environment process instance, which is used to represent the general concept of environment, without specifying an explicit process instance in the environment.
Receiver will refer to the process xEnv if the PId expression in an output TO refers to xEnv, or if the signal was sent in an output without a TO clause and the environment was selected as receiver in the scan for receivers.
Remote procedure calls to or from the environment should in the environment functions be treated a two signals, a pCALL_procedurename and a pREPLY_procedurename signal.
Recommended Structure of the xOutEnv Function
You can, of course, write the xOutEnv function as you wish - the structure discussed below may be seen as an example - but also as a guideline of how to design xOutEnv functions.
Example 432 : Structure of xOutEnv Function
void xOutEnv ( xSignalNode *S ){if ( (*S)->NameNode == Sig1 ) {/* perform appropriate actions */xReleaseSignal(S);return;}if ( (*S)->NameNode == Sig2 ){/* perform appropriate actions */xReleaseSignal(S);return;}/* and so on */}Function xInEnv
To make it possible to receive signals from the environment and to send them into the SDL system, the user provided function xInEnv is repeatedly called during the execution of the system (see section Program Structure). During such a call you should scan the environment to see if anything has occurred which should trigger a signal to be sent to a process within the SDL system.
void xInEnv (SDL_Time Time_for_next_event);To implement the sending of a signal into the SDL system, two functions are available: xGetSignal, which is used to obtain a data area suitable to represent the signal, and SDL_Output, which sends the signal to the specified receiver according to the semantic rules of SDL. These functions will be described later in this subsection.
The parameter Time_for_next_event will contain the time for the next event scheduled in the SDL system. The parameter will either be 0, which indicates that there is a transition (or a timer output) that can be executed immediately, or be greater than Now, indicating that the next event is a timer output scheduled at the specified time, or be a very large number, indicating that there is no scheduled action in the system, that is, the system is waiting for an external stimuli. This large value can be found in the variable xSysD.xMaxTime.
You should scan the environment, perform the current outputs, and return as fast as possible if Time has past Time_for_next_event.
If Time has not past Time_for_next_event, you have a choice to either return from the xInEnv function at once and have repeated calls of xInEnv, or stay in the xInEnv until something triggers a signal output (a signal sent to the SDL system) or until Time has past Time_for_next_event.
The function xGetSignal, which is one of the service functions suitable to use when a signal should be sent, returns a pointer to a data area that represents a signal instance of the type specified by the first parameter.
xSignalNode xGetSignal( xSignalIdNode SType,SDL_PId Receiver,SDL_PId Sender );The components Receiver and Sender in the signal instance will also be given the values of the corresponding parameters.
- SType. This parameter should be a reference to the symbol table node that represents the current signal type. Using the system interface header file, such a symbol table node may be referenced using the signal name directly.
- Receiver. This parameter should either be a PId value for a process instance within the system, or the value xNotDefPId. The value xNotDefPId is used to indicate that the signal should be sent as an output without TO clause, while if a PId value is given the output, it is treated as an output with TO clause. Note that PId values for process instances in an SDL system cannot be calculated, but have to be captured from the information (sender or parameter) carried by signals coming from the system. This is the normal procedure in SDL to establish direct communication.
- Sender. Sender should either be a PId value representing a process instance in the environment of the current SDL system or the value xEnv. xEnv is a PId value that refers to an environment process instance, which is used to represent the general concept of the SDL environment, without specifying an explicit process instance in the environment.
The function SDL_Output takes a reference to a signal instance and outputs the signal according to the rules of SDL.
void SDL_Output( xSignalNode S,xIdNode ViaList[] );
- S. This parameter should be a reference to a signal instance with all components filled in.
- ViaList. This parameter is used to specify if a VIA clause is or is not part of the output statement. The value (xIdNode *)0 (a null pointer), is used to represent that no VIA clause is present. For information about how to build a via list, please see below.
We now have enough information to be able to write the code to send a signal. Suppose we want to send a signal S1, without parameters, from xEnv into the system without an explicit receiver (without TO). The code will then be:
Example 433 : C Code to Send a Signal to the Environment
SDL_Output( xGetSignal(S1, xNotDefPId, xEnv),(xIdNode *)0 );If S2, with two integer parameters, should be sent from xEnv to the process instance referenced by the variable P, the code will be:
xSignalNode OutputSignal; /* local variable */...OutputSignal = xGetSignal(S2, P, xEnv);((yPDP_S2)OutputSignal)->Param1 = 1;((yPDP_S2)OutputSignal)->Param2 = 2;SDL_Output( OutputSignal, (xIdNode *)0 );For the details of how to reference the parameters of a signal see the subsection Types Representing Signals.
To introduce a via list in the output requires a variable, which should be an array of xIdNode, that contains references to the symbol table nodes representing the current channels (or signal routes) in the via list. In more detail, we need a variable
ViaList xIdNode[N];where N should be replaced by the length of the longest via list we want to represent plus one. The components in the variable should then be given appropriate values, such that component 0 is a reference to the first channel (its symbol table node) in the via list, component 1 is a reference to the second channel, and so on. The last component with a reference to a channel must be followed by a component containing a null pointer (the value (xIdNode)0). Components after the null pointer will not be referenced. Below is an example of how to create a via list of two channels, C1 and C2.
Example 434 : Via List of two Channels.
ViaList xIdNode[4];/* longest via has length 3 */.../* this via has length 2 */ViaList[0] = (xIdNode)xIN_C1;ViaList[1] = (xIdNode)xIN_C2;ViaList[2] = (xIdNode)0;The variable ViaList may then be used as a ViaList parameter in a subsequent call to SDL_Output.
Guidelines for the xInEnv Function
It is more difficult to give a structure for the xInEnv function, than for the xOutEnv function discussed in the previous subsection. A xInEnv function will in principle consist of a number of if statements where the environment is investigated. When some information is found that means that a signal is to be sent to the SDL system, then the appropriate code to send a signal (see above) should be executed.
The structure given in the example below may serve as an idea of how to design the xInEnv function.
Example 435 : Structure of xInEnv Function
void xInEnv (SDL_Time Time_for_next_event){xSignalNode S;if ( Sig1 should be sent to the system ) {SDL_Output (xGetSignal(Sig1, xNotDefPId,xEnv), (xIdNode *)0);}if ( Sig2 should be sent to the system ) {S = xGetSignal(Sig1, xNotDefPId, xEnv);((xPDP_Sig2)S)->Param1 = 3;((xPDP_Sig2)S)->Param2 = SDL_True;SDL_Output (S, (xIdNode *)0);}/* and so on */}This basic structure can be modified to suit your own needs. The if statements could, for example, be substituted for while statements. The signal types might be sorted in some "priority order" and a return can be introduced last in the if statements. This means that only one signal is sent during a xInEnv call, which reduces the latency.
In the generated environments skeleton file, there are three macros defined to help with allocating and sending a signal; IN_LOCAL_VARIABLES that declares a signal variable SignalIn, IN_SIGNAL1 that calls xGetSignal and assigns it to SignalIn, and IN_SIGNAL2 that calls SDL_Output for SignalIn.
The macros XENV_IN_START and XENV_IN_END can also be defined to be the top and bottom part of the xEnvIn function body.
Alternative to OutEnv - Directive #EXTSIG
To speed up an application it is sometimes possible to use the directive #EXTSIG instead of the xOutEnv function. The decision to use #EXTSIG or xOutEnv may be taken individually for each signal type.
The usage of the #EXTSIG directive is described in the section Modifying Outputs - Directive #EXTSIG, #ALT, #TRANSFER. This information is not repeated here.
By using the #EXTSIG directive the following overhead can be avoided:
- Calling SDL_Output (the library function for outputs)
- SDL_Output determines that the signal is to be sent to the environment
- SDL_Output calls xOutEnv
- xOutEnv executes nested "if" statements to determine the signal type.
Including the Environment Functions in the SDL System Design
Apart from having the environment functions on a file of their own, it is of course possible to include these function directly into the system diagram in a #CODE directive.
Example 436 : Including Environment Functions in SDL System
/*#CODE#BODY... code for the environment functions ...*/In this case you cannot use the system interface header file, but instead you have all the necessary declarations already at your disposal, as the functions will be part of the SDL system. The only problem you will encounter is the prefixing of SDL names when they are translated to C. The #SDL directive should be used to handle this problem (or the #NAME directive), see sections Accessing SDL Names in C Code - Directive #SDL and Specifying Names in Generated Code - Directive #NAME. The following table shows how to obtain C names for some SDL objects of interest:
#(Synonym name)#(Newtype or syntype name)ySigN_#(Signal name)yPDP_#(Signal name)yChaN_#(Channel name)SDL Data Encoding and Decoding, ASCII coder
Communication between nodes often requires data encoding and decoding between node internal representations and a common format in a protocol buffer. The sending node writes information in the common format and the receiving node reads information from the common format. Data encoding is the transformation from a node internal representation into a common format and data decoding is the transformation from a common format into a node internal representation.
BER (Basic Encoding Rules) is specified in ITU standard X.690 and PER (Packed Encoding Rules) is specified in ITU standard X.691. BER and PER are based on ASN.1 specifications of data types and can only be used for types specified in ASN.1 specifications. See ASN.1 Encoding and De-coding in the SDL Suite and Tutorial: Using ASN.1 Data Types.
ASCII is a format where the data is represented as ASCII characters. It is easy to read and analyze. The ASCII format is specified in appendix A.
Example 437 ASCII common format
newtype Person structnm Charstring;nr Integer;fm Boolean;endnewtype Person;dcl boss Person := (.'Joe',5,false.);ASCII format:{`Joe',5,F}The ASCII coder uses the same buffer management and error management as the BER and PER coders, see ASN.1 Encoding and De-coding in the SDL Suite.
Type description nodes for SDL types
SDL data encoders and data decoders need information about types and signals, information that is stored in type descriptions nodes. Type description nodes for an SDL system are generated if the Generate SDL coder option is selected in the organizer, see The Organizer, or in the targeting expert, see The Targeting Expert. Declarations to access the type nodes are in the system interface header files and in a file with the name <system_file_name>_cod.h. Type nodes can be found in any generated c-file from a system or a package and also in the <system_file_name>_cod.c file.
A type description node for SDL is implemented as a static variable with the type information. The variable can be accessed by using the name ySDL_<type_name> or ySDL_<signal_name>, where <type_name> and <signal_name> are the names used in the interface header file. See Names of SDL Objects in C for more information.
Encoding signal and signal parameters into a buffer
You can use an encode function to encode signal parameters into a buffer. There is one encoding function for each common format. For ASCII, it is accessed by using the macro ASCII_ENCODE. An encoding function has a buffer reference as the first parameter, a pointer to a type node as the second parameter and a pointer to the variable to encode as the third. The encoding function returns an integer value, which is 0 if the encoding was successful and error code if it was not. More details about encoding functions, the buffer reference, type nodes and error codes can be found in ASN.1 Encoding and De-coding in the SDL Suite.
Function declarations are in the file "ascii/ascii.h" ("ascii\ascii.h" on Windows platforms) in the coder directory.
Example 438 ASCII encoding of signal parameters
In SDL:SIGNAL Sig1(Integer,Person,Boolean);In xOutEnv:BufInitWriteMode(buf);result = ASCII_ENCODE(buf,(tSDLTypeInfo *)&ySDL_Integer,
(void *)&((yPDP_Sig1)(*S))->Param1));if (result!=0) /* handle error */;result = ASCII_ENCODE(buf,(tSDLTypeInfo *)&ySDL_Person
(void *)&((yPDP_Sig1)(*S))->Param2));if (result!=0) /* handle error */;result = ASCII_ENCODE(buf,(tSDLTypeInfo *)&ySDL_Boolean
(void *)&((yPDP_Sig1)(*S))->Param3));if (result!=0) /* handle error */;BufCloseWriteMode(buf);Example 439 ASCII encoding of whole signal (all signal parameters)
In SDL:SIGNAL Sig1(Integer,Person,Boolean);In xOutEnv:BufInitWriteMode(buf);result = ASCII_ENCODE(buf,(tSDLTypeInfo *)&ySDL_Sig1,
(void *)(*S));if (result!=0) /* handle error */;BufCloseWriteMode(buf);
The names of the type nodes in the examples, the second parameter in ASCII_ENCODE, depend on the settings for generating system interface header files.
Decoding into signal parameters from a buffer
You can use a decode function to decode from a buffer into a signal parameter. There is one decoding function for each common format. For ASCII, it is accessed by using the macro ASCII_DECODE. A decode function has a buffer reference as the first parameter, a pointer to a type node as the second parameter and a pointer to the variable to decode as the third. The decoding function returns an integer value, which is 0 if the decoding was successful and an error code if it was not. More details about decoding functions, the buffer reference, type nodes and error codes can be found in ASN.1 Encoding and De-coding in the SDL Suite.
Function declarations are in the file "ascii/ascii.h" ("ascii\ascii.h" on Windows platforms) in the coder directory.
Example 440 ASCII decoding into signal parameters
In SDL:SIGNAL Sig1(Integer,Person,Boolean);In xInEnv:BufInitReadMode(buf);result = ASCII_DECODE(buf,(tSDLTypeInfo *)&ySDL_Integer,
(void *)&((yPDP_Sig1)(S))->Param1));if (result!=0) /* handle error */;result = ASCII_DECODE(buf,(tSDLTypeInfo *)&ySDL_Person
(void *)&((yPDP_Sig1)(S))->Param2));if (result!=0) /* handle error */;result = ASCII_DECODE(buf,(tSDLTypeInfo *)&ySDL_Boolean
(void *)&((yPDP_Sig1)(S))->Param3));if (result!=0) /* handle error */;BufCloseReadMode(buf);Example 441 ASCII decoding of whole signal (all signal parameters)
In SDL:SIGNAL Sig1(Integer,Person,Boolean);In xInEnv:BufInitReadMode(buf);result = ASCII_DECODE(buf,(tSDLTypeInfo *)&ySDL_Sig1,
(void *)S);if (result!=0) /* handle error */;BufCloseReadMode(buf);
The names of the type nodes in the examples, the second parameter in ASCII_DECODE, depend on the settings for generating system interface header files.
Encoding and decoding signal identifier for ASCII encoding
When sending signals between nodes it is often important to put a signal identifier first in the buffer. The signal identifier must be a unique identifier of the signal in the distributed system. Decoding is then a two step process, first decode signal identifier and find signal information and second decode signal parameters.
You can use any representation of signal identifiers in the environment functions.
For SDL types there is a special signal id type node that supports character string signal ids. The type node can be used for ASCII encoding.
Example 442 Using signal identifier
In SDL:SIGNAL Sig1(Integer);In xOutEnv:void xOutEnv ( xSignalNode *S ){char * signalId;BufInitWriteMode(buf);if ( (*S)->NameNode == Sig1 ) {/* encode signal id into buffer */signalId="Sig1";result = ASCII_ENCODE(buf,(tSDLInfo *)&ySDL_SignalId,(void *)signalId);if (result!=0) /* handle error */;/* encode signal parameter */result = ASCII_ENCODE(buf,(tSDLTypeInfo *)&ySDL_Sig1,
(void *)(*S));if (result!=0) /* handle error */;/* send buffer using protocol*//* release memory */xReleaseSignal(S);return;}BufCloseWriteMode(buf);}In xInEnv:void xInEnv (SDL_Time Time_for_next_event) {char SId[100];BufInitReadMode(buf);/* decode signal id */result = ASCII_DECODE(buf,(tSDLTypeInfo *)&ySDL_SignalId,SId) );if (result!=0) /* handle error */;/* signal Sig1 in buffer */if ( strcmp(SId,"Sig1") ) {S=xGetSignal(Sig1,xNotDefPId, xEnv);result = ASCII_DECODE(buf,(tSDLTypeInfo *)&ySDL_Sig1,
(void *)S);if (result!=0) /* handle error */;SDL_Output(S, (xIdNode *)0 );}BufCloseReadMode(buf);}Function xGlobalNodeNumber
You should also provide a function, xGlobalNodeNumber, with no parameters, which returns an integer that is unique for each executing system.
int xGlobalNodeNumber ( void )The returned integer should be greater than zero and should be unique among the communicating SDL systems that constitutes an application. If the application consists of only one application then this number is of minor interest (it still has to be set). The global node number is used in PId values to identify the node (OS process / processor) that the process instance belongs to. PId values are thereby universally accessible and you may, for example, in a simple way make "Output To Sender" work between processes in different SDL systems (OS processes / processors).
If you use the generated environment file you could also define XENV_NODENUMBER to be the wanted node number.
When an application consisting of several communicating SDL systems is designed, you have to map the global node number to the current OS process or processor, to be able to transmit signals addressed to non-local PIds to the correct OS process or processor. This will be part of the xOutEnv function.
Program Structure
The generated code will contain two important types of functions, the initialization functions and the PAD functions. The PAD functions implement the actions performed by processes during transitions. There will be one initialization function in each generated.c file. In the file that represents the system this function will have the name yInit. Each process in the system will be represented by a PAD function, which is called when a process instance of the current instance set is to execute a transition.
The example below shows the structure of the main, MainInit, and MainLoop functions.
Example 443 : Start up structure
void main ( void ){xMainInit();xMainLoop();}void xMainInit ( void ){xInitEnv();Init of internal data structures in theruntime library;yInit();}void xMainLoop ( void ){while (1) {xInEnv(...);if ( Timer output is possible )SDL_OutputTimerSignal();else if ( Process transition is possible )Call appropriate PAD function;}}The function xMainLoop contains an endless loop. The appropriate way to stop the execution of the program is to call the runtime library function SDL_Halt. The call of this C function should normally be included in an appropriate task, using the directive #CODE. SDL_Halt which has the following structure:
void SDL_Halt ( void ){xCloseEnv();exit(0);}To complete this overview, which emphasizes the usage of the environment functions, we have to deal with the xOutEnv function. Within PAD functions, the runtime library function SDL_Output is called to implement outputs of signals. When SDL_Output identifies the receiver of a signal to be a process instance that is not part of the current SDL system, SDL_Output will call the xOutEnv function.
Dynamic Errors
In the library for applications SDL runtime errors will not be reported. The application will just perform some appropriate actions and continue to execute. These actions are in almost all cases the same as the actions at dynamic errors described in the Dynamic Errors.
- Output warnings: If a signal is sent to NULL or to a stopped process instance, or if no receiver is found in an output without a "to" clause, the signal will not be sent, that is, the output statement is a null action. If a signal is sent to a process instance and there is no path between the sender and the receiver, the signal will be sent anyway (actually, no check will be performed).
- If the error was a decision error, that is, no path exists for the current decision value, the execution of the program will continue in an unpredictable way. To avoid these kind of problems you should always have else paths in decisions (if not all values in the current data type are covered in other paths).
- If the error occurred during an import or view action, a data area of the correct size containing zero in all positions is returned.
- No checks of assignment or index out of range will be performed. This means that if an array index is out of bounds, then the corresponding C array will be indexed out of its bounds.
- No checks when accessing struct, #UNION, or choice components are performed. No checks are performed when de-referencing a pointer value (Ref generator). These operations will just be executed.
- If the dynamic error occurred within an SDL expression, the operator that found the error will return a default value and the evaluation of the expression is continued. The default values returned depend on the result type of the operator and are given in the section Default Values.
http://www.ibm.com/rational |
![]() |
![]() |
![]() |
![]() |