IBM
Contents Index Previous Next



Common Features


This section describes the parts of the integration that are common to the different models, but also some important differences.

Note:

Many of the data structures and macros described in this section are described in more detail in The Master Library. That chapter is, however, focused on a Light Integration. Some things, especially the listings of data structures, are not correct in every detail for Tight Integrations but should still be very useful.

The Use of Macros

A source file generated by an SDL to C compiler is independent from the choice of integration model and operating system. Instead of system calls, it uses macros that have to be defined elsewhere when the system is built. Each SDL concept is represented by one or more C macros. These macros will have different definitions for different integration models and operating systems. The SDL Suite provides a number of integration packages for this purpose. In a Light Integration, many macros are expanded into functions of the standard kernel. A Tight Integration has lower level macros that are defined in separate files for each operating system, and finally expanded into OS primitives or certain OS dependent constructions.

Below is an example of generated code for signal sending. Code in capital letters are the SDL Suite macros. The bracketed numbers indicate corresponding lines of code. For a description of the different macros, see The Master Library.

SDL symbol: Output

Generated code before macro expansion:


[1]   ALLOC_SIGNAL(sig2, ySigN_z3_sig2,
TO_PROCESS(Env, &yEnvR_env),
XSIGNALHEADERTYPE)
SIGNAL_ALLOC_ERROR
[2] SDL_2OUTPUT_COMPUTED_TO(
xDefaultPrioSignal,
(xIdNode *)0, sig2,
ySigN_z3_sig2,
TO_PROCESS(Env, &yEnvR_env),
0, "Sig2")
SIGNAL_ALLOC_ERROR_END

Generated code after macro expansion for a Light Integration:


[1]   yOutputSignal = xGetSignal
((&ySigR_z3_sig2),
(*(&yEnvR_env)->
ActivePrsList !=
(xPrsNode) 0 ?
(*(&yEnvR_env)->
ActivePrsList)->Self :
xSysD.SDL_NULL_Var),
yVarP->Self);
[2] SDL_Output (yOutputSignal,
(xIdNode *) 0);

File Structure

Note:

The source file and examples for Tight Integration are not included in the standard delivery. They are available as free downloads from IBM Rational Support web site.

The Generated Files

An integration uses one or more of four files that can be generated by the Code Generator. All integrations require the C source file <systemname>.c, whereas the interface file <systemname>.ifc is optional. For a Tight Integration the signal number file <systemname>.hs may be used, and for a Light Integration the file sctenv.c, representing the environment, can be used.

The source file uses the highest level set of macros, that are defined in the different integration packages.

The Integration Packages

The files containing the necessary macro definitions and support functions are organized as shown in Figure 571. For each operating system there is one package for the Light Integration, and one for the Tight Integration. Although the files in different packages may have the same name they do not necessarily contain the same code. The principles for Tight Integration packages are described more thoroughly in Tight Integration. Details about each operating system can be found in the annexes.

Figure 571 : File structure for the RTOS integrations

There is also an INCLUDE directory containing source files common to all supported operating systems. These files are described in File Structure. Below are some additional comments on these files:

The Examples directory contains a simple SDL system that also uses an external process (a separate OS task). For each supported operating system there is an implementation of this, demonstrating how to hook into the integration package. Further description of the example can be found in A Simple Example.

Naming Conventions

Names of variables, datatypes and support functions in generated code and package files often start with one of the letters x, y and z.

The general rules (there are some exceptions) are:

The Symbol Table

All signals, blocks, processes, channels, etc. in an SDL system have a corresponding representation in the symbol table described in The Master Library. This symbol table consists of nodes (IdNodes) each representing one entity of the system. The IdNodes are pointers to structs. See the following example:

extern XCONST struct xPrsIdStruct yPrsR_z02_dynpr1;
#define yPrsN_z02_dynpr1  (&yPrsR_z02_dynpr1)

The N_ and the R_ just before z02_dynpr1 indicate if it is a node (N_) or a record (R_).

Memory Allocation

The xAlloc function is always used when allocating dynamic memory. The function is placed in the sctos.c file, but in the Tight Integrations the body of the function is found in the sct<RTOS>.h file.

Start-up

The yInit function is called during start-up of the SDL system. It is responsible for creating all static processes and for initializing SDL synonyms.

Implementation of SDL Concepts

SDL Processes

An SDL process consists of three parts in generated code: Instance set common data, instance specific data and dynamic behavior.

Instance set common data

Variables and structures that are common to all instances of a process are stored in a record of the type xPrsIdStruct, defined in scttypes.h. This record is referenced by a node in the symbol table.

Instance specific data

Variables and structures of the process instance are declared via the macro PROCESS_VARS. This macro is defined in different ways in the Light and the two models of Tight Integration. It contains state information, local variables, pointers to parent and offspring, etc. One important entry is the RestartAddress, pointing out which transition to execute when the PAD function runs (see below).

Dynamic behavior

The dynamic behavior of an SDL process is implemented in a PAD function (Process Activity Definition). The PAD function is used somewhat differently in the different integration models:

Below is the code for ending a transition, before and after macro expansion for a Light Integration.

SDL symbol: Nextstate

Generated code before macro expansion:


      /*-----
* NEXTSTATE -
* #SDTREF(SDL,/ti/RTOS/MANUAL/SDL/simple.spr(1),
143(55,100),1)
------*/
#ifdef XCASELABELS
[1] case 6:
#endif
[2] XAT_LAST_SYMBOL
[3] SDL_DASH_NEXTSTATE

Generated code after macro expansion for a Light Integration:


      /*-----
* NEXTSTATE -
* #SDTREF(SDL,/ti/RTOS/MANUAL/SDL/simple.spr(1),
143(55,100),1)
------*/
[1]     case 6:
[2]       xGRSetSymbol (-1);
[3] SDL_NextState (VarP, yVarP->State);
return;

Signal Queues

Basically, every process has at least one signal queue.

All signals that are sent to a process arrive in the input queue. The save queue is used to keep signals that cannot be handled in the current state but should be saved for future use. This is tightly connected to the SDL Save concept, but is also used in the implementation of timers. For a Light Integration there are no save queues. Instead, all signals that should be saved will remain in the input queue until they can be received.

Process Priorities

The use of process priorities requires some caution. Priorities can be set with the #PRIO directive in the SDL Suite, but there is no mapping of priorities for different platforms. The generated code will use exactly the values specified in the SDL system. This will not be a problem in a Light Integration, but for Tight Integrations the result may not be the expected.

Example 556 : Process priority problems

Assume that Process1 has its priority set to 100 using the #PRIO 100 directive and Process2 has #PRIO 50. These priority values will be used as-is by the underlying scheduler.

In the SDL Suite simulators and Light integrations, the highest priority is 0. In VxWorks, 0 is the highest priority, whereas in pSOS the highest priority is 255.

Thus the simulated system, a Light integration for any operating system and a Tight integration for VxWorks will all run Process2 at a higher priority than Process1. In contrast, a Tight integration for pSOS will run Process1 at a higher priority than Process2!

Process Creation

Regardless of the integration model there are a number of things that have to be done when an SDL process instance is created. The structs that represent the instance have to be created. It needs a representation in the symbol tree and a signal queue, except in the Instance Set Model of Tight Integration where the signal queue belongs to the instance set. A start-up signal is also always allocated and sent to the process.

SDL symbol: SDL Static Create

Generated code before macro expansion:


      /**********************************************************
SECTION Initialization
**********************************************************/

      extern void yInit XPP((void))
{
int Temp;
........
INIT_PROCESS_TYPE(pr1,z01_pr1,yPrsN_z01_pr1,"z01_pr1",
SDL_INTEGER_LIT(2),SDL_INTEGER_LIT(2),
yVDef_z01_pr1, xDefaultPrioProcess,
yPAD_z01_pr1)
#ifdef SDL_STATIC_CREATE
[1] for (Temp=1; Temp<=SDL_INTEGER_LIT(2); Temp++) {
[2] SDL_STATIC_CREATE(pr1,z01_pr1,yPrsN_z01_pr1,
"pr1",ySigN_z01_pr1,
yPDef_z01_pr1,yVDef_z01_pr1,
xDefaultPrioProcess,yPAD_z01_pr1,1)
}
#endif

Generated Code after macro expansion for a Light Integration:


      /**********************************************************
SECTION Initialization
**********************************************************/
      extern void
yInit ()
{
int Temp;
..........
[1] for (Temp = 1; Temp <= 2; Temp++) {
[2]       SDL_Create (xGetSignal ((&ySigR_z01_pr1),
xSysD.SDL_NULL_Var, xSysD.SDL_NULL_Var),
(&yPrsR_z01_pr1), 1);
}

SDL Signals

Signal Sending

In generated code a signal sending is handled by two macros: ALLOC_SIGNAL (or ALLOC_SIGNAL_PAR for a signal with parameters) and SDL_2OUTPUT_xxxx (there are different macros depending on how the SDL output was defined, e.g. with or without an explicit TO).

SDL symbol: Output

Generated code before macro expansion:


[1]   ALLOC_SIGNAL(go,ySigN_z03_go,TO_PROCESS(p,yPrsN_z09_p),
XSIGNALHEADERTYPE)
SIGNAL_ALLOC_ERROR
[2] SDL_2OUTPUT_COMPUTED_TO(xDefaultPrioSignal,(xIdNode*)0, go,
ySigN_z03_go,TO_PROCESS(p, yPrsN_z09_p), 0, "Go")
SIGNAL_ALLOC_ERROR_END
XBETWEEN_SYMBOLS(4, 579)

Generated code after macro expansion for a VxWorks Tight Integration:


[1]   yOutputSignalPtr = xAlloc(sizeof(xSignalHeaderRec));
[1] yOutputSignalPtr->SignalCode = 2;
[1] yOutputSignalPtr->Sender = yVarP->Self;
[2] Err = msgQSend (xTo_Process ((&yPrsR_z09_p)),
[2] (char*)*&yOutputSignalPtr,
[2] sizeof(xSignalHeaderRec) + 0, 0, 0);
[2] xFree ((void **) &yOutputSignalPtr);
[2] if (Err == (-1)) {
[2] taskLock ();
[2] printf ("Error during %s found in VXWORKS
[2] function %s. Error code %s\n", "OUTPUT",
[2] "msgQSend", strerror ((*__errno ())));
[2] taskUnlock ();
[2] }

In this example the signal is called go and has no parameters. The SDL_2OUTPUT_COMPUTED_TO macro indicates that it was sent without an explicit TO.

SDL Procedures

An SDL procedure is represented by a function similar to a PAD function. Before a procedure is called there are two support functions that need to be called: xGetPrd and xAddPrdCall.

The xGetPrd function allocates an xPrdStruct for the called procedure and returns an xPrdNode pointing to the struct.

The xAddPrdCall function adds the new procedure call in the calling process' ActivePrd list (an element in the xPrsStruct).

The procedure is called with a pointer to the instance data of the calling SDL process. This is because the procedure must be able to use internal variables in the calling process.

Before a procedure returns to the caller it performs an xReleasePrd call. This function removes the call from the ActivePrd list.

SDL Timers

SDL timers are represented by signals. All active timer signals are kept in a sorted list, either within the single task of a Light Integration or in a certain timer task in a Tight Integration. When a timer expires, the signal representing it is sent to the SDL process that set it.

SDL symbol: SET Timer

Generated code before macro expansion:


      /*-----
* SET T1
* #SDTREF(SDL,/ti/RTOS/MANUAL/SDL/dynpr1.spr(1),
119(55,25),1)
------*/
#ifdef XCASELABELS
[1] case 2:
#endif
[2] SDL_SET_DUR(xPlus_SDL_Time(SDL_NOW,
[3] SDL_DURATION_LIT(5.0, 5, 0)),
[4] SDL_DURATION_LIT(5.0, 5, 0), t1, ySigN_z021_t1,
yTim_t1, "T1")

Generated code after macro expansion for a Light Integration:


      /*-----
* SET T1
* #SDTREF(SDL,/ti/RTOS/MANUAL/SDL/dynpr1.spr(1),
119(55,25),1)
------*/
[1]     case 2:
[2]       SDL_Set (xPlus_SDL_Duration (SDL_Now (),
[3] SDL_Duration_Lit (5, 0)), xGetSignal
[4] ((&ySigR_z021_t1), yVarP->Self,
yVarP->Self));


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