Table of Contents Previous Chapter 38 The SDL to CHILL Translator

38 The SDL to CHILL Translator

The SDL to CHILL Translator, sdl2chill, translates your SDL system into a semantically equivalent CHILL program that you can compile, link, test and real-time execute by means of CHIPSY. CHIPSY is the CHILL Integrated Programming System, from KVATRO A/S. This chapter deals with the SDL to CHILL translation facilities. Description of CHIPSY and SDT tools to be used together with the translator, is given in the reference manuals for CHIPSY and SDT.

Introduction

The translation from SDL to CHILL is based on a mapping scheme in which the basic concepts of SDL such as system structure, communication, behavior, actions and data are directly mapped into matching CHILL constructs of program structuring, concurrent processing, communication, actions and data. By this scheme SDL signals are mapped to CHILL signals and concurrency is implemented by utilizing the language inherent concurrency of CHILL as provided by CHIPSY.

The CHILL code generated from an SDL system, may be viewed as a CHILL module interfaced to via signals. This makes it easy to plug in an SDL system as an application program part anywhere in your CHILL software structure. Consistent interfacing of the SDL system will be ensured by the separate compilation scheme of CHIPSY.

The application area for sdl2chill is development and maintenance of real-time application systems. By using sdl2chill, the CHILL program generated for your system will be efficient, reliable, easily readable and open for interfacing and interoperability with other software.

Application Areas for sdl2chill

The application area for sdl2chill is development and maintenance of software for real-time application systems. sdl2chill has been implemented to maximize the user benefits of the CCITT languages SDL and CHILL by combining the capabilities of the SDL design tool, SDT and CHIPSY.

The CHILL program generated from your SDL specified system by using sdl2chill, will be efficient, reliable, easily readable and open for interfacing and interoperability with other software.

In this part of the manual, the usage of sdl2chill for generating application systems is described. When it comes to detailed information on the functionality and usage of the CHIPSY tools and the SDT tools to be used together with sdl2chill, this is described in the CHIPSY Reference Manual and the SDT 3.01 Reference Manual, respectively.

Generating Application Systems

During development and the succeeding maintenance of your system, the combined functional power of SDT, sdl2chill and CHIPSY is fully available and you may conveniently design, generate, simulate, test and real-time test your application on a host computer before possibly recompiling, linking and downloading to dedicated target hardware.

Concurrent real-time execution, communication and timing as implemented by sdl2chill, are directly based on services provided by CRS, the CHIPSY Real-time Operating System. Other features of CRS such as interrupt handling, Input/Output, distributed processing and program execution control, provide additional services you need in order to implement the operational environment to which the SDL system must be interfaced in order to realize its intended purpose.

Testing and debugging are facilitated by means of conventional debuggers or by using the CHIPSY's Pilot. The Pilot is an advanced real-time test and debugging tool that is part of CHIPSY.

CHIPSY is now available on a variety of host and target platforms including Sun SPARC, 386/486 PC with SCO UNIX, and VAX/VMS.

Generating Distributed Application Systems

The CHILL code generated by sdl2chill is prepared for distributed execution by means of CDPS, the CHIPSY Distributed Processing Services of CRS. CDPS allow your programs to communicate by means of CHILL (and thus also SDL) signals in a distributed environment where programs may reside on different nodes in an heterogeneous network.

Overview of sdl2chill

To facilitate generation of CHILL source code from SDL specifications or descriptions, the SDT Analyzer contains an SDL parser, an SDL semantic checker, and the sdl2chill translator.

Creating a CHILL program

To obtain an executable program that behaves according to an SDL description, you input the SDL description into the SDT Analyzer, which contains the sdl2chill translator, using the Make dialog in the SDT Organizer (see "Make" on page 1107). If the SDL description is syntactically and semantically correct a CHILL program is generated. You then compile this program using a CHIPSY CHILL compiler(1) and link it with the precompiled CRS library including the SDL Services to form an executable program. See Figure 1.

As indicated above, sdl2chill contains two components:

Executing a CHILL Program

A CHILL program generated by sdl2chill, can (just like any other executable program) be started from an operating system shell by typing the name of the file containing the executable program.

Contents of this Chapter

You can find more details on creating and executing a CHILL program in the following sections:

Generating a CHILL Program

Creating and Starting a CHILL Program from SDT

There are four steps that you must take to create an executable CHILL program and start it from SDT:

  1. Use the SDT Analyzer and its built-in sdl2chill translator for creating a program expressed in CHILL source code. This operation is started from the Make dialog in the SDT Organizer (see "Make" on page 1107). The program may be partitioned to one or more CHILL compilation units.
  2. Compile the generated CHILL compilation unit(s).
  3. Link the resulting object file(s) together with CRS.
    The steps of native compilation and linking have been automated in SDT by means of scripts generated by sdl2chill.
  4. Start the executable program that is created in the above link operation.
A CHILL program can only be generated for a complete SDL system. The CHILL source code that constitutes the program can, however, be partitioned to several compilation units (files). This means that a local change in an SDL unit, for example a process diagram, requires regeneration and recompilation of CHILL code for that unit only. For the other unchanged units the existing object files can then be reused in the link operation to form a new executable program.

--------------------------------------------------------------------
Note:                                                                 
In SDT 3.01 the possibility to regenerate only a subsystem is not im  
plemented. ALWAYS select Full Make in the SDT Organizer's             
Make dialog.                                                          
--------------------------------------------------------------------

File Names

The files that are created during the generation phase will have the file names specified in Edit Separation dialog in the Generate menu in the Organizer. By default this is the name of the SDL unit(2).

------------------------------------------------------------------
File Extensions UNIX                                                
------------------------------------------------------------------
.chill                Compilation unit in CHILL source text form    
.cdbf                 Compilation unit in CHIPSY Data Base Format   
.o                    Object file                                   
.exe                  Executable program                            
.m                    Makefile                                      
------------------------------------------------------------------
The .chill, .cdbf and .o files are created for the system, and are also created for blocks and processes, depending on the separate generation scheme decided by the user. The .m and the .exe files are only created for the system. The file names will be the name of the units (system, block, or process) with the appropriate extension. For more information on generated files and file names see the section "Selecting File Structure for Generated Code - Directive #SEPARATE" on page 2349.

Executing a CHILL Program

A CHILL program generated by sdl2chill can be started from an operating system shell by typing the name of the file containing the executable program(3).

Errors During Code Generation

Errors that may occur during code generation are internal errors, that is, errors due to not yet implemented features of SDL, and errors related to problems with open or close operations of files.

All the error messages are listed below, together with a short explanation. Some messages contain a"#" followed by a number which is used to indicate where information, specific of the error situation, can be found.

Feature of SDL not implemented: #1
The translator cannot yet handle this SDL feature. See the list of restrictions and implementation dependencies in the section "Implementation Dependencies" on page 2377.

Cannot open outfile
A .chill, or .m file cannot be opened.

WARNING! Unique name generation failed.
The scope structure is too deep.

#1 must be a unique name.
#1 is replaced by the name of an SDL unit. During code generation sdl2chill prefixes SDL name strings to make them unique. The prefixing algorithm and the limit for the length of the prefix, might make it impossible to generate a prefix, in which case this warning is issued. It is still possible to execute the generated program if the name, without prefix, is unique.

Node = nil in #1
Incorrect node type in #1. Nodetype: #2
Internal error in the PathStructure
Line exceeded MaxLineLength
These four last errors are internal errors in sdl2chill. We would be pleased if you will report such errors to us.

Implementation

Overview

sdl2chill implements your SDL system by mapping it to a semantically equivalent CHILL program. This means that when executing the generated program, it behaves according to the SDL system specification.

The translation from SDL to CHILL is based on a direct mapping scheme. The basic concepts of SDL such as system structure, communication, behavior, actions and data are directly mapped to matching CHILL constructs of program structuring, concurrent processing, communication, actions and data.

In the first parts of this section we describe the SDL to CHILL mapping as implemented by sdl2chill. The implementation is explained in terms of CHILL and CHIPSY and a good knowledge of both is required in order to understand the mapping details. As rationale and discussion of mapping alternatives are not needed in order to use sdl2chill, this is described in a separate technical document. CHILL source code is easy to read, and as a supplement to reading this section you are recommended to study the generated code for your own system(s).

The last part of this section describes how sdl2chill implements operators and literals in abstract data types. In the general case it is not considered feasible to derive the implementation of operators (and literals) from the axioms. sdl2chill therefore provides support for implementing the operators by user-written CHILL procedures. sdl2chill also offers a simple escape mechanism for types by means of which is it possible for the sdl2chill user to utilize CHILL modes and properties of modes otherwise not accessible from SDL.

Numerous examples are used in this section to illustrate the run-time model and the SDL to CHILL mapping implemented by sdl2chill. In the examples, the prefixes, which can be added to names when they are translated to CHILL, are normally not shown. The prefixes are used to make sure that no name conflicts occur in the generated program. For more information about prefixes see "Names and Prefixes in Generated Code" on page 2357.

System Structure

System

sdl2chill maps an SDL system definition to an outermost CHILL module.

The CHILL code generated for a system may be partitioned to several compilation units. How this is facilitated is described in "Selecting File Structure for Generated Code - Directive #SEPARATE" on page 2349.

For the CHILL code to be CHIPSY compilable, sdl2chill also generates a context directive including the SDL Services of CRS.

Example 152   
SYSTEM My_System;
...
ENDSYSTEM;
maps to:

<> ENVIRONMENT
('(CRS)/_SDL/SDL_support'...)
);
...

My_System:
MODULE
GRANT ALL;
SEIZE ALL;
...
END
My_System;

Block and Block Substructure

sdl2chill maps the specifications contained in a block or in a block substructure to CHILL code without imposing any CHILL structure. The name string translation as described in "Names and Prefixes in Generated Code" on page 2357, ensures proper name binding at the CHILL level.

Example 153   
BLOCK My_Block:
...
ENDBLOCK;
maps to:

    ...
  

Process

sdl2chill maps an SDL process definition to a CHILL process definition. The SDL process name and the formal parameters map to the CHILL process name and the formal parameter list respectively.

Creating the initial number of SDL process instances, if any, maps to a sequence of CHILL start actions executed by the CHILL imaginary outer process. The default value for initial number of processes is 1.

SELF maps to THIS. PARENT maps to an additional (implicit) formal parameter of PId sort for each process definition. OFFSPRING and SENDER map to process local CHILL locations to which values are assigned by in-line CHILL assignment actions.

-------------------------------------------------------------------
Note:                                                                
sdl2chill does not support formal parameters for initially created   
processes and it is not checked that the number of simultaneous in   
stances of an SDL process is within the allowed maximum number,      
if specified.                                                        
-------------------------------------------------------------------
Example 154   
PROCESS my_process (2, );
...
ENDPROCESS;
maps to:

my_process: PROCESS(parent INSTANCE);
...
DCL
offspring INSTANCE := NULL
,sender INSTANCE := NULL
;
...
END my_process;
...

DO FOR i := 1 TO 2;
START my_process(NULL);
OD;

Procedure

sdl2chill maps an SDL procedure definition to a CHILL procedure definition. This applies both to procedure definitions with state(s) and to procedure definitions without state(s). The SDL procedure name and the formal parameters map to the CHILL procedure name and the formal parameter list respectively.

Parameter passing for SDL in-parameters map on CHILL "pass by value" IN parameters, while SDL in/out-parameters are implemented by means of bound reference mode formal parameters and in-line CHILL code for referencing (at point of call) and de-referencing (for each applied occurrence of the formal parameter).

--------------------------------------------------------------------
Note:                                                                 
sdl2chill does not support calling an SDL procedure with an empty ac  
tual parameter.                                                       
--------------------------------------------------------------------
Example 155   
PROCEDURE My_Procedure;
FPAR IN line_p PID, IN/OUT no Integer;
...
ENDPROCEDURE My_Procedure;
maps to:

...
My_Procedure:
PROC(line_p INSTANCE, no REF INT);
...
END My_Procedure;

Communication

sdl2chill implements all process communication by means of CHILL signals. The channel definitions, signal route definitions and channel to signal route connection definitions of SDL all map to empty.

Signal

An SDL signal definition maps to a CHILL signal definition statements. The SDL signal name and the sort list map to the CHILL signal name and associated list of modes.

Example 156   
SIGNAL
My_signal_1(INTEGER, PID)
,My_signal_2;
maps to:

SIGNAL
My_Signal_1 = (INT, INSTANCE)
,My_Signal_2;
This mapping enables the CHILL inherent process communication and concurrency to be fully exploited by sdl2chill. The interface between the SDL system and its environment is mapped to a set of CHILL signals and connecting the generated program to other CHILL thus code becomes very easy.

Behavior

Variables

An SDL variable definition maps to a CHILL location declaration. The SDL variable names and the sorts map to location names and modes respectively. Assignment (explicit or implicit) associated with the variable declaration map to reach-bound initialization.

Example 157   
DCL
Line_Number INTEGER := 99
,Line_P PID;
maps to:

DCL
Line_Number INT := 99
,Line_P INSTANCE := NULL;

Start

The mapping of the transition associated with start (of the SDL process body) is shown by Example 158 below.

State

The states of an SDL process definition map into CHILL as follows:

  1. The set of SDL states maps into a CHILL set mode definition (enumerated type) of which each set literal represents one state. The state names map to the set literal names and the set mode is named "states". The implicit state, "start_state", is added by sdl2chill.
  2. A CHILL location named "state'' of mode states is declared. This location is used to keep track of the current state and it is initialized to start_state.
  3. The SDL process body, including the start transition maps to a loop containing a case statement with one alternative for each state.
  4. Consumption of signal instances or waiting in a state maps to CHILL receive case action. Each signal for which input is specified in a state, maps to one signal receive alternative.
Example 158   
START;
task my_i := 0;
NEXTSTATE s2;
STATE s1;
...
STATE s2;
...
NEXTSTATE s1;
...
maps to:

...
NEWMODE
states = SET(start_state, s1, s2);
DCL
state states := start_state;

DO WHILE TRUE;
CASE state OF
(start_state):
my_i := 0;
state := s2;
GOTO SDL_next_state;
(s1):
...
(s2):
...
state := s1;
ESAC;
SDL_next_state: ;
...
OD;

Input

Each signal for which input is specified in a state, maps to a signal receive alternative of the CHILL receive case action mapped from this state. See also "Implicit Transition" on page 2312.

The values transported by CHILL signals are received in locations defined by the CHILL signal receive alternative. Copying the received values from the implicit signal reception locations required by CHILL to the variables associated with the input maps on assignment.

The location to which the SDL expression SENDER is mapped, is directly updated by the receive case action.

Example 159   
SIGNAL
My_Signal_1(INTEGER)
,My_Signal_2;
...
DCL sum INTEGER;
...
STATE s1;
INPUT My_Signal_1(sum);
...
INPUT My_Signal_2;
...
NEXTSTATE s2;
...
maps to:

. ..
SIGNAL
My_Signal_1 = (INT)
,My_Signal_2;
...
DCL sum INT;
...
CASE state OF
(s1):
RECEIVE CASE SET sender;
(My_Signal_1 IN My_signal_1_p1):
sum := My_signal_1_p1;
...
(My_Signal_2):
...
state := s2;
ESAC;
...
ESAC;

Save

Save maps on empty. The CHILL signals are persistent i.e. they are not consumed until explicitly received by a signal receive alternative. See also "Implicit Transition" on page 2312.

Label

An SDL label maps to definition of a CHILL label. The connector name maps to the CHILL label name.

Transition

A transition maps to the CHILL action statement list of the signal receive alternative that is mapped from the input to which the transition is associated. See also "Join" on page 2311.

Transition Terminator

Nextstate

Nextstate maps on assigning the set literal representing the specified nextstate to the CHILL location named state. The actual transfer of control is implemented by the enclosing case statement and loop statement. This is shown by Example 158.

Join

Join maps to CHILL goto action. Connector name maps to label name. Join from a transition to any legal connector is supported.(4)

Stop

sdl2chill maps SDL stop to CHILL stop.

Return

sdl2chill maps SDL return to CHILL return action.

Implicit Transition

The SDL semantics is that any signal (including timer signals) that is not explicitly saved or input in a state, shall be implicitly consumed when they are first in the input queue. The associated implicit transition is a nextstate action leading back to this state.

In the simplest case, sdl2chill maps the implicit transitions of a state to one empty signal receive alternative receiving the anonymous CHILL signal, else(5). If "save", however, is specified for any signal in a state the CHILL "else signal "cannot be used and explicit empty signal receive alternatives for the signals to be consumed must be generated instead. As shown in the following example, this is fully catered for by sdl2chill.

Example 160   
process P1 (1, 1);
signalset s1, s2, s3, s4;

start;
nextstate n1;
state n1;
input s1;
nextstate n2;
save s2;
state n2;
input s1;
stop;
input s2;
stop;
save*;
state n3;
input s4;
nextstate n1;
endprocess;
maps to:

P: PROCESS(parent INSTANCE);
NEWMODE
states = SET(start_state, n1, n2, n3);
DCL
offspring INSTANCE := NULL
,sender INSTANCE := NULL
,state states := start_state
;
DO WHILE TRUE;
CASE state OF
(start_state):
state := n1;
GOTO SDL_next_state;
(n1):
RECEIVE CASE SET sender;
(s1):
state := n2;
GOTO SDL_next_state;
(s3):
GOTO SDL_next_state;
/* Implicit transition */
(s4):
GOTO SDL_next_state;
/* Implicit transition */
ESAC;
(n2):
RECEIVE CASE SET sender;
(s1):
STOP;
(s2):
STOP;
ESAC;
(n3):
RECEIVE CASE SET sender;
(s4):
state := n1;
GOTO SDL_next_state;
(else):
GOTO SDL_next_state;
ESAC;
ESAC;
SDL_next_state: ;
OD;
END P

Action

Task

sdl2chill maps the assignment statements of a task body to CHILL assignment actions.

Create

sdl2chill maps the create requests to CHILL start expressions.(6) The result yielded by the start expression is assigned to the offspring location of the creating process.

---------------------------------------------------------------------
Note:                                                                  
sdl2chill requires that the actual parameters fully match all formal   
parameters, i.e. undefined parameters are not supported.               
Dynamic check to verify that the number of process instances creat     
ed is within the allowed maximum number, if specified, is not sup      
ported by sdl2chill. (If, however, all available memory has been       
used and no more processes can be created then this will of course     
be detected and reported by CRS.)                                      
---------------------------------------------------------------------
If the process definitions of the creating process and the process to be created are mapped to different (separate) CHILL compilation units then an auxiliary proc location is introduced by sdl2chill (if necessary). This is done in order to avoid cycles in the compilation graph. The details are shown in the example below.

Example 161   
-- no modularization of the generated CHILL

PROCESS My_Process_2 (0, );
FPAR line_p PID, subscriber_no INTEGER;
...
ENDPROCESS My_Process_2;
...
CREATE My_Process_2(P, I);

maps to:
...
offspring := START My_Process_2(P, I, THIS); Example 162 -- full modularization of the generated CHILL

PROCESS My_Process_2 (0, ); /*#PRIO 1024,* */
FPAR line_p PID, subscriber_no INTEGER;
...
ENDPROCESS My_Process_2;
...
CREATE My_Process_2(P, I);
maps to:

/* Compilation unit of the enclosing block */
NEWMODE par_My_Process_2 =
PROC(INSTANCE, INT, INSTANCE) (INSTANCE);

DCL var_My_Process_2 par_My_Process_2;

/* Compilation unit of process definition */
proc_My_Process_2:
PROC(line_p INSTANCE
,subscriber_no INT
,parent INSTANCE
)(INSTANCE)

RETURN START My_Process_2
(line_p
,subscriber_no
,parent
,1024
,*
);
END;

var_My_Process_2 = proc_My_Process_2;

/* Compilation unit issuing create */
offspring := CALL var_My_Process_2(P,I,THIS);

Procedure Call

SDL procedure call maps to CHILL procedure call.

In the generated CHILL procedure call the actual parameters that matches SDL in/out-parameters are preceded by the referencing operator ->.

Output

sdl2chill maps output and the associated signal parameters to a CHILL signal send action.

-------------------------------------------------------------------------
Note:                                                                      
Output without to or output with undefined actual parameters are           
not supported by sdl2chill.                                                
To denote the PId value of initially created processes, the translation    
directive #PIDLIT has been defined. By means of this directive, any        
specification relying on output without to may easily be adjusted to       
output with to, see "Identifying Initially Created Process Instances -     
  Directive #PIDLIT" on page 2364.                                         
If, in spite of this, you decide to use output without to, you will find   
that it maps to CHILL open send signal. As shown in the example            
below no error message is given, but the comment /* TO ? */ is gen         
erated in the code to inform you that the CHILL open signal send,          
in the general case, may not properly implement the semantics of           
SDL output without to.                                                     
In this case the generated program therefore may, or may not               
execute correctly.                                                         
-------------------------------------------------------------------------
Example 163   
SIGNAL
My_Signal_1(INTEGER,PID)
,My_Signal_2;
...
OUTPUT My_Signal_1(0,OFFSPRING) TO line_p;
OUTPUT My_Signal_2 TO some_p;
OUTPUT My_Signal_2;
maps to:

SIGNAL
My_Signal_1 = (INT,INSTANCE)
,My_Signal_2;
...
SEND My_Signal_1(0,offspring) TO line_p;
SEND My_Signal_2 TO some_p;
SEND My_Signal_2 /* TO ? */;

Decision

sdl2chill maps decision to CHILL if action as shown in the example below.

Example 164   
DECISION My_Integer - 1;
(2): ...
(4): ...
(6): ...
ENDDECISION;
maps to:

DCL yDcn_INT INT;
...
yDcn_INT := My_Integer - 1;

IF yDcn_INT = 2
THEN
...
ELSIF yDcn_INT = 4
THEN
...
ELSIF yDcn_INT = 6
THEN
...
ELSE
CAUSE SDL_decision_error;
FI;

Timer

SDL timers and the associated actions on timers are implemented by means of CHILL run-time library procedures utilizing the signal timing and stopwatch as provided by CRS Timing Services. More information on the run-time library can be found in "The SDL Services" on page 2324.

The mapping details are shown by Example 165 below.

---------------------------------------------------------------------
Note:                                                                  
sdl2chill restricts the timer definitions and the set and reset state  
ments to timers for which no (sort) parameters are specified.          
sdl2chill measures the SDL system time by means of the CRS stop        
watch, the unit of which is execution platform and system clock de     
pendent(a).                                                            
The precision used when computing if the system time associated        
with a timer has been reached, is a configurable, execution platform   
dependent parameter of CRS.(b)                                         
See also the CHIPSY Reference Manual for more information on           
implementation details and the CRS tuning options.                     
---------------------------------------------------------------------
(a)
On UNIX the unit is one millisecond. Depending on the system clock resolution, stopwatch read-out may be updated as infrequently as every one second.
(b)
Its default value is 1/10 second on UNIX/BSD while it is 1 second on UNIX/System V.
Example 165   
TIMER T1, T2;
...
SET (expiration_time, T1);
SET (NOW + 5, T2);
RESET T1;
TASK b := NOT ACTIVE(T2);
maps to:

SIGNAL T1, T2;
...
SDL_Set_Timer(expiration_time, ->T1);

SDL_Set_Timer
(SDL_Time_Add
(SDL_NOW()
,SDL_Duration_Lit(5,0)
)
,->T2
);
SDL_Reset_Timer(->T1);
b := NOT SDL_Active(->T2);

Synonyms

Synonyms

An SDL synonym is implemented either by a CHILL location which is initialized at program start up, or as a CHILL synonym. The implementation using a location is chosen in case the expression defining the value of the synonym:

All other synonyms are translated into CHILL synonyms.

A synonym that maps to a location cannot be used in a range condition of a syntype because SDL range conditions are mapped to CHILL range modes and boundary values of CHILL range modes cannot be locations.

External Synonyms

External synonyms can be used to parameterize an SDL system and thereby also a generated program. sdl2chill maps the definition of external synonyms on empty, this enables you to give values to external synonyms simply by using your own CHILL written definitions of these synonyms.

To give value to an external SDL synonym by means of CHILL written definitions, perform the following steps:

  1. Write the actual CHILL data statements in a compilation unit as shown in Example 166 and CHILL compile it. The synonym names are the SDL names (without any prefixes) and with any character not in letters, digits, or underline removed.
  2. Add the file name of the CDB_entry derived in the above step in an #ENVIRONMENT directive as shown in Example 167. The CHILL written definitions are then imported in the resulting CHILL program by the sdl2chill generated SEIZE ALL;
Example 166   
MY_FILE:
MODULE
SYN synonym1 INT = 255;
DCL synonym2 BOOL := FALSE;

GRANT synonym1, synonym2;
END
MY_FILE; Example 167 System S; /*#ENVIRONMENT 'MY_FILE' 'file1' 'file2'*/
If you use this structure you can change the value of an external synonym merely by changing the corresponding CHILL data statements and recompiling the system.

Abstract Data Types

In this subsection we first look at how sdl2chill translates the SDL predefined data types, see "SDL Predefined Types" below.

We then discuss how user-defined abstract data types are translated, see "Translation of Sorts" on page 2333.

Next the possibility to include CHILL written procedures as implementation of the operators in abstract data types is presented, see "User Defined Operators" on page 2339.

Last, in "More about Abstract Data Types" on page 2344, we discuss more details about operators and the possibilities to include a CHILL written mode definition to represent an SDL sort.

SDL Predefined Types

Mapping Table

Below is a table summarizing the SDL to CHILL mapping rules for the SDL predefined types and their operators (see page 2321).

--------------------------------------------------------------
SDL name/operator         CHILL name/expression/operator        
--------------------------------------------------------------
Boolean                   BOOL                                  
False, True               FALSE, TRUE                           
not                       NOT                                   
=, /=                     =, /=                                 
and                       AND                                   
or                        OR                                    
xor                       XOR                                   
=>                     <=                                 
Character                 CHAR                                  
NUL                       SDL_NUL                               
SOH                       SDL_SOH                               
...                       ... (for all unprintable characters)  
                                                                
'a'                       'a'                                   
'b'                       'b'                                   
...                       ... (for all printable characters     
                              except ')                         
''''                      ''''                                  
=, /=                     =, /=                                 
<, <=, >, >=  <, <=, >, >=              
Charstring                SDL_Charstring                        
'aa'                      [2,'aa'//(SDL_Charstring_max_le       
                          ngth-2)' ']                           
=                         =                                     
/=                        /=                                    
MkString                  SDL_Charstring_MkString               
Length                    SDL_Charstring_Length                 
First                     SDL_Charstring_First                  
Last                      SDL_Charstring_Last                   
//                        SDL_Charstring_Concat                 
SubString                 SDL_Charstring_SubString              
Extract!                  SDL_Charstring_Extract                
Modify!                   SDL_Charstring_Modify                 
Integer                   INT                                   
0, 1, 2,...               same as in SDL                        
+, -                      +, -                                  
*                         *                                     
/                         /                                     
=, /=                     =, /=                                 
<, <=, >, >=  <, <=, >, >=              
Float                     SDL_Float                             
Fix                       SDL_Fix                               
Natural                   SDL_Natural                           
Real                      SDL_Real                              
0.0,...                   SDL_Real_Lit(0, 0)                    
- (monadic)               SDL_Real_Neg                          
+                         SDL_Real_Add                          
- (dyadic)                SDL_Real_Sub                          
*                         SDL_Real_Mul                          
/                         SDL_Real_Div                          
=, /=                     =, /=                                 
<                      SDL_Real_Lss                          
<=                     SDL_Real_Leq                          
>                      SDL_Real_Gtr                          
>=                     SDL_Real_Gte                          
PId                       INSTANCE                              
NULL                      NULL                                  
=, /=                     =, /=                                 
Duration                  SDL_Duration                          
23.45                     SDL_Duration_Lit(23, 450000000)       
+                         SDL_Duration_Add                      
- (monadic)               SDL_Duration_Neg                      
- (dyadic)                SDL_Duration_Sub                      
*                         SDL_Duration_Mul                      
/                         SDL_Duration_Div                      
=, /=                     =, /=                                 
>                      SDL_Duration_Gtr                      
Time                      SDL_Time                              
23.45                     SDL_Time_Lit(23, 450000000)           
+                         SDL_Time_Add                          
- (result: Time)          SDL_Time_Sub                          
- (result: Duration)      SDL_Time_Diff                         
=, /=                     =, /=                                 
<                      SDL_Time_Lss                          
<=                     SDL_Time_Leq                          
>                      SDL_Time_Gtr                          
>=                     SDL_Time_Gte                          
--------------------------------------------------------------

The SDL Services

A small run-time(8) library supporting the execution of programs generated by sdl2chill, has been implemented. This library is called SDL Services. It is delivered as part of CRS and consists of CHILL modes, synonyms and procedures used by sdl2chill. Interfacing to the library is of course, fully catered for by sdl2chill also when it comes to generating context directive, importing the applied names and including the library in the generated link script.

We will here briefly describe the modes, synonyms and procedures of the SDL Services used by sdl2chill to implement the SDL predefined types and the associated operators.

The listing below is extracted from source code of the library.

/* CHIPSY Copyright (c) 1992 Kvatro A/S
! -------------------------------------------
! IDENTIFICATION
! CRS:SDL Support:sdl_support.chill
!
! ABSTRACT
! This module implements the SDL Services ! of CRS. ...
! -------------------------------------------
*/

<>ENVIRONMENT

...

SDL_support:
MODULE
...

TIMER

-- (Z.100 chapter 2.8, 5.5.4.1 and 5.6.4.5)
    SYNMODE
SDL_Timer_Id = PTR
;

SDL_Set_Timer:
PROC(time SDL_Time
,timer SDL_Timer_Id
)
GENERAL;
-- Implements SDL timer Set (by means -- of the Signal Timing Services
-- provided by CRS).
--
-- If the specified time value is 0 or
-- negative the timer signal will
-- be sent immediately.If active in
-- this case is applied to the timer
-- in the same transition as the timer
-- is set, the result of active is
-- undefined.

SDL_Reset_Timer:
PROC(timer SDL_Timer_Id
)
GENERAL;
-- Implements SDL timer Reset.

SDL_Now:
PROC() RETURNS(SDL_Time)
GENERAL;
-- Implements the SDL imperative
-- operator NOW by means of the CRS
-- system stopwatch.
--
-- At program start-up the system time,
-- SDL NOW, is equal to zero.

SDL_Active_Timer:
PROC(timer SDL_Timer_Id
) RETURNS(BOOL)
GENERAL;
-- Implements the SDL Active timer
-- expression.

SDL CHARACTER SORT

-- (Z.100 chapter 5.6.2)
    SYN
SDL_NUL CHAR = C'00'
,SDL_SOH CHAR = C'01'
,SDL_STX CHAR = C'02'
,SDL_ETX CHAR = C'03'
,SDL_EOT CHAR = C'04'
,SDL_ENQ CHAR = C'05'
,SDL_ACK CHAR = C'06'
,SDL_BEL CHAR = C'07'
,SDL_BS CHAR = C'08'
,SDL_HT CHAR = C'09'
,SDL_LF CHAR = C'0A'
,SDL_VT CHAR = C'0B'
,SDL_FF CHAR = C'0C'
,SDL_CR CHAR = C'0D'
,SDL_SO CHAR = C'0E'
,SDL_SI CHAR = C'0F'
,SDL_DLE CHAR = C'10'
,SDL_DC1 CHAR = C'11'
,SDL_DC2 CHAR = C'12'
,SDL_DC3 CHAR = C'13'
,SDL_DC4 CHAR = C'14'
,SDL_NAK CHAR = C'15'
,SDL_SYN CHAR = C'16'
,SDL_ETB CHAR = C'17'
,SDL_CAN CHAR = C'18'
,SDL_EM CHAR = C'19'
,SDL_SUB CHAR = C'1A'
,SDL_ESC CHAR = C'1B'
,SDL_IS4 CHAR = C'1C'
,SDL_IS3 CHAR = C'1D'
,SDL_IS2 CHAR = C'1E'
,SDL_IS1 CHAR = C'1F'
,SDL_DEL CHAR = C'7F'
;

SDL CHARSTRING SORT

-- (Z.100 chapter 5.6.4)
    SYN
SDL_Charstring_max_length INT = 100
;

NEWMODE
SDL_Charstring = STRUCT
(length INT(0:SDL_Charstring_max_length)
,string CHAR(SDL_Charstring_max_length)
)
;

SDL_Charstring_MkString:
PROC(c CHAR
) RETURNS(SDL_Charstring)
GENERAL;
-- Implements the SDL operator:
-- MkString: Char -> Charstring;

SDL_Charstring_Length:
PROC(cs SDL_Charstring
) RETURNS(INT)
GENERAL;
-- Implements the SDL operator:
-- Length: Charstring -> Integer;

SDL_Charstring_First:
PROC(cs SDL_Charstring
) RETURNS(CHAR)
GENERAL;
-- Implements the SDL operator:
-- First: Charstring -> Char;

SDL_Charstring_Last:
PROC(cs SDL_Charstring
) RETURNS(CHAR)
GENERAL;
-- Implements the SDL operator:
-- Last: Charstring -> Char;

SDL_Charstring_Concat:
PROC(cs1 SDL_Charstring
,cs2 SDL_Charstring)
) RETURNS(SDL_Charstring)
GENERAL;
-- Implements the SDL operator:
-- //: Charstring, Charstring
-- -> Charstring;

SDL_Charstring_Extract:
PROC(cs SDL_Charstring
,index INT
) RETURNS(CHAR)
GENERAL;
-- Implements the SDL operator:
-- Extract!: Charstring, Integer
-- -> Char;

SDL_Charstring_Modify:
PROC(cs SDL_Charstring
,index INT
,c CHAR
) RETURNS(SDL_Charstring)
GENERAL;
-- Implements the SDL operator:
-- Modify!: Charstring, Integer, Char
-- -> Charstring;

SDL_Charstring_SubString:
PROC(cs SDL_Charstring
,index INT
,length INT
) RETURNS(SDL_Charstring)
GENERAL;
-- Implements the SDL operator:
-- SubString: Charstring, Integer,
-- Integer -> Charstring;

SDL NATURAL SYNTYPE

-- (Z.100 chapter 5.6.6)
    SYN
SDL_max_int INT = 32_767
;

SYNMODE
SDL_Natural = INT(0 : SDL_max_int)
;

SDL REAL

-- (Z.100 chapter 5.6.7)
    SYNMODE
SDL_Real = STRUCT
(ld LONGDURATION
)
;

SDL_Float:
PROC(i INT
) RETURNS(SDL_Real)
GENERAL;
-- Implements the SDL operator:
-- Float: Integer -> Real;

SDL_Fix:
PROC(r SDL_Real
) RETURNS(INT)
GENERAL;
-- Implements the SDL operator:
-- Fix: Real -> Integer;

SDL_Real_Lit:
PROC(i LONGINT
,f LONGINT
) RETURNS(SDL_Real)
GENERAL;
-- Maps Real literal to SDL_Real mode
-- 'i' denotes the integer part.
-- 'f' denotes the fractional part
-- multiplied by 10**9.

SDL_Real_Neg:
PROC(r SDL_Real
) RETURNS(SDL_Real)
GENERAL;
-- Implements the SDL operator:
-- -: Real -> Real;

SDL_Real_Add:
PROC(l SDL_Real
,r SDL_Real
) RETURNS(SDL_Real)
GENERAL;
-- Implements the SDL operator:
-- +: Real, Real -> Real;

SDL_Real_Sub:
PROC(l SDL_Real
,r SDL_Real
) RETURNS(SDL_Real)
GENERAL;
-- Implements the SDL operator:
-- -: Real, Real -> Real;

SDL_Real_Mul:
PROC(l SDL_Real
,r SDL_Real
) RETURNS(SDL_Real)
GENERAL;
-- Implements the SDL operator:
-- *: Real, Real -> Real;

SDL_Real_Div:
PROC(l SDL_Real
,r SDL_Real
) RETURNS(SDL_Real)
GENERAL;
-- Implements the SDL operator:
-- /: Real, Real -> Real;

SDL_Real_Lss:
PROC(l SDL_Real
,r SDL_Real
) RETURNS(BOOL)
GENERAL;
-- Implements the SDL operator:
-- <: Real, Real -> Boolean;

SDL_Real_Leq:
PROC(l SDL_Real
,r SDL_Real
) RETURNS(BOOL)
GENERAL;
-- Implements the SDL operator:
-- <=: Real, Real -> Boolean;

SDL_Real_Gtr:
PROC(l SDL_Real
,r SDL_Real
) RETURNS(BOOL)
GENERAL;
-- Implements the SDL operator:
-- >: Real, Real -> Boolean;

SDL_Real_Gte:
PROC(l SDL_Real
,r SDL_Real
) RETURNS(BOOL)
GENERAL;
-- Implements the SDL operator:
-- >=: Real, Real -> Boolean;

SDL DURATION SORT

-- (Z.100 chapter 5.6.11)
    NEWMODE
SDL_Duration = STRUCT
(ld LONGDURATION
-- LONGDURATION is CRS defined.
-- The unit for representation is
-- 100 nanoseconds.
)
;

SDL_Duration_Lit:
PROC(i LONGINT
,f LONGINT
) RETURNS(SDL_Duration)
GENERAL;
-- Maps Duration literal to
-- SDL_Duration mode.
-- 'i' denotes seconds.
-- 'f' denotes nanoseconds

SDL_Duration_Add:
PROC(l SDL_Duration
,r SDL_Duration
) RETURNS(SDL_Duration)
GENERAL;
-- Implements the SDL operator:
-- +: Duration, Duration -> Duration;

SDL_Duration_Sub:
PROC(l SDL_Duration
,r SDL_Duration
) RETURNS(SDL_Duration)
GENERAL;
-- Implements the SDL operator:
-- -: Duration, Duration -> Duration;

SDL_Duration_Neg:
PROC(r SDL_Duration
) RETURNS(SDL_Duration)
GENERAL;
-- Implements the SDL operator:
-- -: Duration -> Duration;

SDL_Duration_Gtr:
PROC(l SDL_Duration
,r SDL_Duration
) RETURNS(BOOL)
GENERAL;
-- Implements the SDL operator:
-- >: Duration, Duration -> BOOL;

SDL_Duration_Mul:
PROC(l SDL_Duration
,r SDL_Real
) RETURNS(SDL_Duration)
GENERAL;
-- Implements the SDL operator:
-- *: Duration, Real -> Duration;

SDL_Duration_Div:
PROC(l SDL_Duration
,r SDL_Real
) RETURNS(SDL_Duration)
GENERAL;
-- Implements the SDL operator:
-- /: Duration, Real -> Duration;

SDL TIME SORT

-- (Z.100 chapter 5.6.12)
    NEWMODE
SDL_Time = STRUCT
(ld LONGDURATION
-- LONGDURATION is CRS defined.
-- The unit for representation is
-- 100 nanoseconds.
)
;

SDL_Time_Lit:
PROC(i LONGINT
,f LONGINT
) RETURNS(SDL_Time)
GENERAL;
-- Maps Time literal to SDL_Time mode
-- 'i' denotes seconds
-- 'f' denotes nanoseconds

SDL_Time_Lss:
PROC(l SDL_Time
,r SDL_Time
) RETURNS(BOOL)
GENERAL;
-- Implements the SDL operator:
-- <: Time, Time -> Boolean;

SDL_Time_Leq:
PROC(l SDL_Time
,r SDL_Time
) RETURNS(BOOL)
GENERAL;
-- Implements the SDL operator:
-- <=: Time, Time -> Boolean;

SDL_Time_Gtr:
PROC(l SDL_Time
,r SDL_Time
) RETURNS(BOOL)
GENERAL;
-- Implements the SDL operator:
-- >: Time, Time -> Boolean;

SDL_Time_Gte:
PROC(l SDL_Time
,r SDL_Time
) RETURNS(BOOL)
GENERAL;
-- Implements the SDL operator:
-- >=: Time, Time -> Boolean;

SDL_Time_Add:
PROC(l SDL_Time
,r SDL_Duration
) RETURNS(SDL_Time)
GENERAL;
-- Implements the SDL operator:
-- +: Time, Duration -> Time;

SDL_Time_Sub:
PROC(l SDL_Time
,r SDL_Duration
) RETURNS(SDL_Time)
GENERAL;
-- Implements the SDL operator:
-- -: Time, Duration -> Time;

SDL_Time_Diff:
PROC(l SDL_Time
,r SDL_Time
) RETURNS(SDL_Duration)
GENERAL;
-- Implements the SDL operator:
-- -: Time, Time -> Duration;
...

END
SDL_support;
----------------------------------------------------------------------
Note:                                                                   
Due to the implementation of SDL Integer using 16-bit integers in       
CHILL, there is a restriction in range for integer values. Integers     
must be in the range -215..215-1.(a) There are in the same way restric  
tions both in range and precision for Real, Time, and Duration, as      
they are implemented using the CRS defined mode                         
LONGDURATION. In the interface to SDL Services the literals of          
Real, Time, and Duration are represented by two 32-bit integers.        
The first integer of Time, and Duration represents the number of        
seconds and the second integer represents the number of nanosec         
onds. The length of charstrings cannot exceed the implementation        
defined limit of 100. (b)                                               
----------------------------------------------------------------------
(a)
In CHIPSY CHILL 32-bit integer (LONGINT) is also available, on how to use LONGINT from SDL, see "More about Abstract Data Types" on page 2344.
(b)
The above described implementation dependencies apply to Version 1.0 of the SDL Services. If needed, the range and precision for the predefined types may be extended by adapting the CRS Services.

Translation of Sorts

The following data types can be handled by sdl2chill:

Predefined Types

All the predefined data types, Integer, Natural, Boolean, Character, Charstring, Real, Time, Duration, and PId are completely handled.

The name of these types in the generated CHILL code will be INT, SDL_Natural, BOOL, CHAR, SDL_Charstring, SDL_Real, SDL_Time, SDL_Duration and INSTANCE respectively.

The translation rules for these types and their operators are described in more detail in the "SDL Predefined Types" on page 2321.

Enumeration Type

A sort which is not a struct and which does not contain any inheritance or generator instantiation, but which contains a literal list, is translated to a CHILL set mode, as can be seen in the example below. As in all examples in this subsection, the prefixes, which are added to name strings when they are translated to CHILL, are not shown. The prefixes are used to make sure that no name conflicts occur in the generated program. For more information about prefixes see "Names and Prefixes in Generated Code" on page 2357.

Example 168         
NEWTYPE EnumType  
  LITERALS Lit1, Lit2, Lit3;
ENDNEWTYPE;
is translated to:

SYNMODE EnumType = SET(Lit1, Lit2, Lit3);
  
Unfortunately this translation strategy is not always correct. Consider as an example the following sort definition.

Example 169    
NEWTYPE Enum2
  LITERALS
    Lit1, Lit2;
  OPERATORS
    Op : Enum2 -> Enum2;
  AXIOMS 
    Op(Lit1) == Lit2;
    Op(Op(Lit2)) == Lit1;
ENDNEWTYPE;
  
When evaluating this definition it is fairly easy to see that the value set of this sort contains three values, the value denoted by Lit1, the value denoted by Lit2, and the value obtained by applying Op to Lit2, that is, Op(Lit2). The latter value does not have any explicit literal denoting its value, which means that an implementation of this sort as an enumeration type in CHILL would be incorrect. In general, the set of literals of a sort and the set of values of a sort are two quite different things. Still the translation rule is included in sdl2chill, since it is valid in most situations.

Struct

An SDL struct is translated to a CHILL struct, as can be seen in the example below.

Example 170             
NEWTYPE Str STRUCT
  a Integer;
  b Boolean;
  c Character;
ENDNEWTYPE;
is translated to:

SYNMODE Str = STRUCT
  (a INT
  ,b BOOL
  ,c CHAR
  );
  
All the properties of a struct in SDL are preserved in the CHILL code. The predefined operators Extract! and Modify! are implemented as component selection in the struct in the same way as in SDL, that is, if S is a variable of type Str, then S!a in SDL is translated to S.a in CHILL. The predefined operator Make!, which is a constructor of a struct value, is implemented by means of tuples in CHILL. This means that the expression (. 12, true, `a' .) in SDL is translated to the CHILL constant tuple: [ 12, TRUE, `a' ].

The components of a struct may be of any sort that sdl2chill can handle. A component may, however, not directly or indirectly refer to the struct sort itself.

Example 171   
The sort Str above may not have a component of sort Str. In such a case the translation to a CHILL struct would not any longer be valid.

  

Array

Instantiations of the predefined generator array can be handled by sdl2chill with the following restrictions. The component sort may be any sort that sdl2chill can handle, but may not directly or indirectly refer to the array type itself (see also the previous paragraph on struct). The index sort should be a discrete sort, with one closed interval of values. This means that the following index sorts may be used:

Another way of defining the allowed index sorts is that sdl2chill can handle array generator instantiations with any index sort that maps to a CHILL discrete mode.

Example 172   
SYNTYPE Idx = Integer
  CONSTANTS 0:10
ENDSYNTYPE;
NEWTYPE Arr ARRAY(Idx, Real)
ENDNEWTYPE;
is translated to:

SYNMODE 
   Idx = INT(0:10)
  ,Arr = ARRAY(Idx)SDL_Real
  ;
  
All the properties of an array in SDL are preserved in the CHILL code. The predefined operators Extract! and Modify! are implemented as indexing of the array in CHILL in the same way as in component selection is done in SDL, so if My_Var is a variable of type Arr, and My_Index is a valid index expression, then My_Var(My_Index) in SDL maps to My_Var(My_Index) in CHILL.

The predefined operator Make!, which is a constructor of an array value, is implemented by means of CHILL tuples. This means that the expression "(. 0.22 .)" in SDL is translated to the CHILL tuple: [ (*): SDL_Real_Lit(0, 220000000) ].

Syntypes

Syntypes may be defined for any sort that sdl2chill can handle, giving a new name for the sort and possibly a new default value for variables of the sort. Range conditions that restrict the allowed range of values are also allowed by sdl2chill provided that the parent sort maps to a CHILL discrete mode and the range condition details map to a CHILL literal range.

The syntype is translated to a type equal to the parent type using SYNMODE definition. The check that a variable of a syntype with range condition is only assigned legal values, is catered for by CHILL semantic conditions. An attempt to assign an illegal value to such a variable will be reported as a CHILL RANGEFAIL exception at run-time. Similarly, if syntype is specified as index sort in an array, the CHILL semantic conditions will ensure that the index values used in array component selections are within the range conditions specified for the index sort.

Example 173    
SYNTYPE Syn1 = integer
  CONSTANTS 0:10
ENDSYNTYPE;
SYNTYPE Syn2 = integer
  CONSTANTS 0:255
ENDSYNTYPE;
SYNTYPE Arr1 = Arr
  DEFAULT (. 2.0 .);
ENDSYNTYPE;
/* Arr is defined in the previous example*/
is translated to:

SYNMODE 
Syn1 = INT(0:10)
,Syn2 = INT(0:255)
,Arr1 = Arr
;

Default Values

In sdl2chill you may initialize a variable by assigning a value to it in the variable definition or by specifying a default value in the sort definition. If neither is done, the initial value for the variable is undefined. The exception to this is that sdl2chill assigns the value NULL to those variables of PId sort that would otherwise contain an undefined initial value.

--------------------------------------------------------------------
Note: Note:                                                           
The SDL system is in error if a variable containing an undefined val  
ue is accessed. This should have been reported when executing the     
generated program, but it will not be detected because undefined      
values are (for performance reasons) generally not catered for in     
CHILL.                                                                
As a general rule you should define appropriate default values in     
sort definitions and use initial value assignment in variable defini  
tions whenever this is needed.                                        
--------------------------------------------------------------------

Operators

The default mapping of user defined operators in an SDL sort is as follows:

In "User Defined Operators" on page 2339 it is described how to include CHILL procedures as implementation of operators.

Literals

In sorts that are translated to CHILL set modes, literals are obviously handled by sdl2chill. In sorts that are not translated to CHILL set modes, literals are treated as operators without parameters and are handled exactly in the same way as user defined operators. Note that sdl2chill does not permit naming of literals using name class literals or character strings.

Axioms and Literal Mappings

Axioms and literal mappings are allowed by sdl2chill in sorts, but are completely ignored.

User Defined Operators

Including Implementation of Operators

In the previous subsection the default behavior of sdl2chill concerning operators and literals was described. To make it possible for sdl2chill to generate complete application programs, you should include CHILL procedures implementing the operators and literals. This can be done by means of sdl2chill directives.

An sdl2chill directive is an SDL comment with the first character equal to `#', followed by a sequence of letters identifying the directive. In this case the letters are ADT (for Abstract Data Type) and OP (for operator). An ADT directive and an OP directive should thus look like:

/*#ADT */ /*#OP */
The text is not case sensitive.

OP directives are recognized at two different positions in an abstract data type:

ADT directives are recognized immediately before the reserved word ENDNEWTYPE (or ENDSYNTYPE).

Example 174    
NEWTYPE Str STRUCT 
  a Integer; 
  b Boolean;
  c Real;
ADDING 
LITERALS 
  Lit1 /*#OP */,
  Lit2 /*#OP */;
OPERATORS
  Op1 :Str,Integer -> Str; /*#OP */
  Op2 :Str,Boolean -> Str; /*#OP */
/*#ADT */
ENDNEWTYPE;
  
The #OP directive can be used to specify how the applied occurrences of the associated literal or operator should be implemented. In the #ADT directive the actual implementation can be defined e.g. in the form of CHILL procedure definitions.

An OP or ADT directive specifying the implementation details of operators and literals should have the following structure:

/*#OP (B) */ /*#ADT (B) */
The letter between the parentheses should be B (body)(9). If B has been specified for an operator or literal, then CHILL code for implementing its intended function must be supplied by the user. This CHILL code should be placed in the ADT directive, according to the following example:

Example 175    
/*#ADT (B)
-- CHILL code in the form of procedure
-- definitions implementing operators
-- and literals.
*/
The CHILL code must start on a new line.

-------------------------------------------------------------------
Note:                                                                
sdl2chill does not check the consistency between the specification   
of implementation techniques and the actual CHILL code. This         
check is, together with checking the CHILL code for syntactic and    
static semantic errors, left to the CHILL compiler.                  
CHILL comments within the code that is included in a #ADT direc      
tive should be in the form of end-of-line comments. SDL and          
CHILL use the same symbols for bracketed comments and if such a      
comment is included, the SDT Analyzer will consider its closing      
bracket as the end of the SDL comment.                               
-------------------------------------------------------------------
In Example 174 the struct Str is defined and there are two literals (Lit1 and Lit2) and two operators (Op1: Str, integer --> Str; and Op2: Str, Boolean --> Str;). The procedures, which should be supplied by the sdl2chill user if B is specified in the OP or ADT directive, are ordinary CHILL procedures.

Example 176   
Lit1:
PROC() RETURNS(Str);
RETURN [ 2, FALSE, SDL_Real_Lit(2,0) ];
END;

Op1:
PROC(p1 Str, p2 INT)RETURNS(Str);
p1.a +:= p2;
RETURN p1;
END;
Before it is possible to give a complete example of an abstract data type with implementation of its operators supplied as CHILL procedures it is necessary to look at the problem of names and name strings. When a name string of an entity in SDL is translated to CHILL, a suitable sequence of characters, a prefix, is added to the SDL name string, to make the name unique in the CHILL program, see also "Names and Prefixes in Generated Code" on page 2357. This strategy is selected in sdl2chill to avoid name conflicts in the generated code, but it makes it also impossible to predict the actual name string of, for example a mode or a procedure, in the generated program. To handle this problem the user can tell sdl2chill to translate a name string in the user written CHILL code in the same way as SDL name strings are otherwise translated. This is specified by enclosing the SDL name string between "#(" and ")" in the CHILL code. The two procedures in the previous example then become:

Example 177   
#(Lit1):
PROC() RETURNS(#(Str));
RETURN [ 2, FALSE, SDL_Real_Lit(2,0) ];
END;


#(Op1):
PROC(p1 #(Str), p2 INT)RETURNS(#(Str));
p1.a +:= p2;
RETURN p1;
END;
The facilities enabling the use of SDL defined names in CHILL code is described in more detail in the section"Applying SDL Names in CHILL Code - Directive #SDL" on page 2351. A few observations concerning the example above might be appropriate:

  1. The standard sorts in SDL: integer, natural, Boolean, real, character, charstring, time, duration, and pid, have the names INT, SDL_Natural, BOOL, SDL_Real, CHAR, SDL_Charstring, SDL_Time, SDL_Duration and INSTANCE in the generated code. These mode names should not be enclosed between "#(" and ")".
  2. The component names of a struct are unchanged in the struct implementation in CHILL, which means that field names should not be enclosed between "#(" and ")" either.

Two Examples of ADTs

We now give two complete examples of abstract data types.

Example 178   
NEWTYPE Str STRUCT
 a Integer;
 b Boolean;
 c Real;
 ADDING
 LITERALS
 Lit1;
 OPERATORS
 Op1 : Str, Integer -> Str;
 Op2 : Str, Boolean -> Str;
/*#ADT (B)
#(Lit1):
PROC() RETURNS(#(Str));
RETURN [ 2, FALSE, SDL_Real_Lit(2,0) ];
END;

#(Op1):
PROC(p1 #(Str), p2 INT)RETURNS(#(Str));
p1.a +:= p2;
RETURN p1;
END;

#(Op2):
PROC(p1 #(Str), p2 BOOL)RETURNS(#(Str));
IF p2
THEN
RETURN p1;
ELSE
RETURN #(Lit1)();
FI;
END;
*/ ENDNEWTYPE; Example 179 SYNTYPE Index = Integer
CONSTANTS 1:10 ENDSYNTYPE; NEWTYPE A Array(Index, integer) ADDING LITERALS Zero /*#OP (B) */; OPERATORS Add : A, A -> A; /*#OP (B) */ Sum : A -> Integer; /*#ADT (B)
#(Zero):
PROC() RETURNS(#(A));
RETURN [ (*): 0 ];
END;
#(Add):
PROC(p1 #(A), p2 #(A)) RETURNS(#(A));
DCL Result #(A);

DO FOR i IN #(Index);
Result(i) := p1(i) + p2(i);
OD;

RETURN Result;
END;
*/
ENDNEWTYPE;
Note that no procedure definition is supplied for the operator Sum. When compiling a generated program where the operator Sum is used, the CHILL compiler will therefore give an error message saying that definition of the name Sum is missing.

For more information about CHILL synonyms, modes and procedures (supplied by the SDL Services and used in generated code) that can be useful when implementing operators in CHILL, see "SDL Predefined Types" on page 2321, and last in "More about Abstract Data Types" below.

More about Abstract Data Types

More about Operators

Previously under "User Defined Operators" on page 2339, the possibility to include implementations of operators in abstract data types was described. Here we will first discuss some additional features concerning operators and then describe how to replace the generated CHILL mode definition for an abstract data type with a user defined mode definition.

For an operator in an abstract data type not only B (body) may be specified. The following choices are available:

For each operator one of the letters B, S and one of the letters P, I should be supplied, either in a #OP directive, or in a #ADT directive, or as the defaults B and P. For literals P and I have no meaning.

Example 180   
Example of usage of S (standard)

REM : Integer,Integer->Integer; /*#ADT (SI) */
SIZE : Real -> Integer; /*#ADT (SP) */
An SDL expression using these operators:

SIZE(a) will be translated to: SIZE(zh723_a)

  
These examples show how built-in procedures and standard operators of CHILL can be directly utilized in abstract data types.

Including CHILL Mode Definitions

In "Translation of Sorts" on page 2333 it is described which CHILL mode definitions the SDL predefined types, enumeration types, struct, array and syntypes map into. By this translation scheme the general, implementation independent capabilities of the CHILL modes that matches the above SDL types are directly utilized.

When generating applications it is sometimes needed, in parts of a system, to use additional CHILL modes such as pointers, other integer modes than INT and the more implementation oriented capabilities of CHILL such as variant structure modes and packing. This is facilitated by means of the #ADT directive.

By this directive it is possible to suppress the generation of mode definitions for an abstract data type and include a CHILL written mode definition instead. Suppressing the generation of the mode definition, however, does not affect the translation of the actions related to the data type.

The #ADT directive to specify that no mode definition shall
be generated from the SDL sort has the following structure(10):

/*#ADT (T)
CHILL code (that replaces the mode definition
otherwise generated by sdl2chill).
*/
The example below shows how the #ADT directive may be used in order to use the CHIPSY defined integer mode LONGINT from SDL.

Example 181   
SYNTYPE long /*#NAME 'LONGINT' */ = Integer
/*#ADT (T)
*/
ENDSYNTYPE;
...
DCL l1 long
,l2 long := 65536;
...
TASK l1 := l2 + l1;

Maps into the following CHILL code:
...
DCL l1 LONGINT i.e. undefined initial value
,l2 LONGINT := 65536;
...
l1 := l2 + l1;
Below is another example showing how the #ADT directive may be used to facilitate packing of the components of a structure and to build a linked list of data objects by means of a CHILL defined pointer.

Example 182   
SYNTYPE nibble = Integer
CONSTANTS 0:15
ENDSYNTYPE;

NEWTYPE package STRUCT
i nibble;
j nibble;
ADDING
LITERALS
NIL
OPERATORS
SUM: package -> Integer; /*# OP (B) */
DEFAULT NIL;
/*#ADT (T)
SYNMODE
nibble = #(nibble)
,package = #(package)
;

NEWMODE #(package) =
STRUCT
(i nibble PACK
,j nibble PACK
,NEXT REF package
);

#(SUM): PROC (p1 package) (INT);

DCL p REF package := ->p1
,sum INT := 0;

DO WHILE p /= NULL;
sum +:= p->.i + p->.j;
p := p->.NEXT;
OD;

RETURN sum;
END;

#(NIL): PROC() (package);
RETURN [ 0, 0, NULL];
END;
*/
ENDNEWTYPE;

Directives to sdl2chill

Syntax of Directives

sdl2chill recognizes a number of directives given mainly in SDL comments. The #ADT and #OP used in abstract data types are examples of such directives. These directives were described in the section "User Defined Operators" on page 2339 in connection with abstract data types and are not further discussed here.

A directive has the general structure:

  1. The start of comment characters: /*
  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 183   
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.(11) After this part spaces and carriage returns may be inserted freely.

  
You may prefix a directive name by "CHILL" or "C" to condition the 
recognition of the directive to sdl2chill or to the C Code Generator re
spectively. 

Selecting File Structure for Generated Code -
Directive #SEPARATE

The purpose of the separate feature directive 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.

sdl2chill can generate separate files for the system, for a block, and for a process. The #SEPARATE directive should in all cases be placed directly after the first semicolon in the system, block, or process heading; see the following example.

Example 184   
system S; /*#SEPARATE 'filename' */ 
block B; /*#SEPARATE */
process P1; /*#SEPARATE */
process P2 (1, ); /*#SEPARATE */
  
As can be seen a file name should be enclosed between quotes. sdl2chill 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, or process will be used to obtain a file name. In such a case the file name will be the same as the name of the unit with the appropriate extension ( .chill .cdbf .o .exe .m ) depending on contents. Characters that are not letters, digits or underlines are stripped from the file name.

An Example of the Usage of #SEPARATE

In the following example a system structure and the #SEPARATE directives are given. This example is then used to show the generated file structure depending on selected generation option.

Example 185   
system S; /*#SEPARATE 'Sfile' */
  block B1; /*#SEPARATE */
    process P11; /*#SEPARATE 'P11file' */
    process P12;
  block B2;
    process P21;
    process P22; /*#SEPARATE */
  

Applying Full Separate Generation

If full separate generation is selected in the SDT Analyzer interface then the following files will be generated:

-------------
Sfile.chill    
B1.chill       
P11file.chill  
P12.chill      
B2.chill       
P21.chill      
P22.chill      
Sfile.m        
-------------
The .chill files contain the CHILL code generated for the corresponding SDL unit and the .m file is the makefile for compiling and linking the application program.

A.cdbf file for each compilation unit will be created when compiling the generated CHILL code. Interfaces between compilation units are contained in the .cdbf files derived for the system unit and for the block units. The compilation order thereby imposed is, of course, catered for by the generated compilation script.

Applying Separate Generation

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

-------------------------------------------------
Sfile.chill    Contains code for units S, B2, P21  
B1.chill       Contains code for units B1, P12     
P11file.chill  Contains code for unit P11          
P22.chill      Contains code for unit P22          
Sfile.m                                            
-------------------------------------------------
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 you select the "no separate generation" option the following files will be generated:

-----------------------------------------
Sfile.chill  Contains code for all units   
Sfile.m                                    
-----------------------------------------
The comments on files and extensions earlier are valid even here.

When Should Code Generation to Separate Files be Applied?

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 compensates for the overhead in generating and compiling several files for a large system

Applying SDL Names in CHILL Code - Directive #SDL

When you write CHILL code that is to be included in a generated program it is often necessary to refer to name strings of objects defined in SDL. The name string of an SDL object is, however, transformed when it is translated to CHILL. A prefix, which is a sequence of characters, is added to the SDL name string to make the CHILL name unique in the CHILL program. Furthermore, all characters in SDL name strings which are not allowed in a CHILL name string 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 CHILL code and use the name string of SDL objects in that code, sdl2chill provides the directive #SDL which is used in CHILL code to translate an SDL name string to the corresponding CHILL name string.

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 (in this form.

#(SDL name) 
or

#(SDL name, entity class name)
Replace SDL name with the name string 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         newtype      signal            
blockinst     operator     signallist        
blocksubst    package      signalroute       
blocktype     predef       sort (= newtype)  
channel       procedure    state             
channelsubst  process      synonym           
connect       processinst  syntype           
formalpar     processtype  system            
gate          remoteprd    systemtype        
generator     remotevar    timer             
imported      service      variable          
label         serviceinst  view              
literal       servicetype                    
-------------------------------------------
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 CHILL code, sdl2chill first identifies which SDL object is referred and then replaces the directive by the CHILL name string for that object. The search for the SDL object starts in the current scope (the scope where the CHILL 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 string and is in the specified entity class. If no entity class name is given the search is performed for all entity classes.

The table in the subsection "SDL Predefined Types" gives the direct translation between an SDL name and the corresponding CHILL name or expression (see page page 2321). For these names the #SDL directive should not be used.

Including CHILL Code in TASK -
Directive #CODE

You can include your own CHILL code in tasks by using the #CODE directive. This directive has the following syntax:

/*#CODE
CHILL code that should be included 
in the generated code.
*/
Type the directive name on the first line and the CHILL code on the following lines up to the end of comment symbol.

A #CODE directive can be placed:

The CHILL 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:                                                                 
sdl2chill handles the CHILL code in directives as text and performs   
no check that the code is valid CHILL code.                           
--------------------------------------------------------------------
The code directive is included as a facility in sdl2chill to provide experienced users an escape possibility to the target language CHILL. This increases the application range of sdl2chill.

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 task with an informal text, could be implemented in CHILL. In this case the directive #SDL described in the previous subsection probably will become useful to access variables and formal parameters defined in SDL.

Some general hints on how to write CHILL code that can be included into an application program can be found in the last part of the section "User Defined Operators" on page 2339.

SDL and CHILL use the same symbols for start and end of comments. To have CHILL comments within the code that is included in any directive, the CHILL end-of-line comment must be used.

Including CHILL Data Statements -
Directive #CODE

The #CODE directive can also be used to include CHILL definitions and declarations, for example mode definitions, locations declarations and procedure definitions into the generated CHILL program. This version of the code directive has the same syntax as the code directive for including CHILL code in task:

/*#CODE
CHILL code containing for example:
- mode definitions - location declarations - procedure definitions */
Code directives to include CHILL 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 186   
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 data statements within the directive are thus placed among the other CHILL statements generated 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.

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 definitions and 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 CHILL code that fits into a generated CHILL program given in the section "User Defined Operators" on page 2339 and in the section "Applying SDL Names in CHILL Code - Directive #SDL" on page 2351 are also applicable here.

Including CHILL Code in SDL Expressions - Operator #CODE

For each sort defined in an SDL system (both predefined sorts and user defined sorts), sdl2chill defines implicitly the prefix operator #CODE with the following signature:

#CODE : Charstring -> S;
where S denotes the actual sort name. This operator or rather these operators make it possible to access e.g. locations, procedures and built-in procedures defined in CHILL using the #CODE directive in SDL expressions without violating the syntactic and static semantic rules of SDL.

During SDL to CHILL translation, sdl2chill will just copy the actual Charstring parameter into the generated CHILL code at the place where the #CODE operator is applied.

Example 187   
Suppose that x and y are SDL variables, which are translated to z72_x and z73_y, that a and b are CHILL locations, and p is a CHILL procedure defined in #CODE directives.

----------------------------------------------
SDL expression          CHILL 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('p(a, #SDL(x))')  p(a, z72_x)             
----------------------------------------------
  
Within the Charstring parameter of a #CODE operator the #SDL directive is available in the same way as in other included CHILL code. This is shown in the expression in the last line of the example 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 decisions are given as applications of #CODE operators, then it is not possible to determine the type for the decision. One of the #CODE operators should then be qualified with a sort name to resolve the conflict.

Example 188   
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 a CHILL name, a prefix is normally added to the name string given in SDL. This prefix is used to prevent name conflicts in the generated code, as SDL has other scope rules than CHILL and also allow different objects defined in the same scope to have the same name string, 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 string defined in a process. So the purpose of the prefixes is to make each translated SDL name to a unique name in the CHILL program.

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

  1. The character "z"
  2. A sequence of characters that make the name string unique
  3. An underline "_"
  4. The SDL name string with characters not allowed in CHILL name strings stripped off.
A CHILL name string may contain letters, digits, and underline "_" and must start with a letter.

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

The total sequence making a name string unique is now constructed from the "declaration numbers" for the actual 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 declaration are present on any of the two levels).

Example 189   
Examples of generated name strings:

------------------------------------------------------------------
SDL
Position of the Declaration Generated name string name string ------------------------------------------------------------------ S1 10th declaration in the system z9_S1 Var2 3rd declaration in the process, ze42_Var2 which is the 5th declaration in the block, which is the 15th declaration is system ------------------------------------------------------------------
  
This strategy for naming objects in the generated code should be used in all normal situations, as it guarantees that no name conflicts occur. sdl2chill offers, however, possibilities to change this strategy. In the user interface of the Analyzer and sdl2chill 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. If entity class prefix is selected, then the prefix that is concatenated with the SDL name string will be in accordance with the table below and depends only on the entity class of the object.

-------------------------------------------------------------
Entity class          Prefix  Entity class             Prefix  
-------------------------------------------------------------
Block, block type,    blo     Process, Process type,   prs     
block instance                Process instance                 
Block substructure    bls     Remote procedure         rpc     
Channel               cha     Remote variable          imp     
Channel substructure  chs     Service, Service type,   ser     
                              Service instance                 
Connection            con     Signal                   sig     
Formal parameter      for     Signal list              sil     
Gate                  gat     Signal route             sir     
Generator             gen     Sort                     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 name strings are predictable and thus simplifies writing CHILL code where the SDL names are used. You only have to look for name conflicts within entity classes, for example not having two sorts with the same name string. The entity class prefixes handle the case when two objects of different entity class have the same name string. Note that the table above contains all entity classes. Not all of the items are actually used by sdl2chill.

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

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.

As was said in the beginning of this subsection, you should have a good reason for selecting anything but the full prefix, as it could be very difficult to spot name conflicts. The 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.

Specifying Name Strings in Generated Code - Directive #NAME

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

Example 190   
NEWTYPE S /*#NAME 'S' */ STRUCT
a Integer;
b Boolean; 
ADDING OPERATORS
  Op /*#NAME 'OtherName' */ :
    S, S -> Boolean;
ENDNEWTYPE;
  
The name string defined in a #NAME directive will be used everywhere that the SDL name is used in the generated code, with one exception: the name of the files for generated code are not affected by the usage of #NAME directives.

Assigning Priorities Directive #PRIO

Priorities in the CHILL and CHIPSY sense can be assigned to processes and signals using the directive #PRIO. How this will affect the behavior of the generated CHILL program is described in the CHIPSY Reference Manual.

Process Priorities

You can assign the CHIPSY implementation defined process parameters: optional stack need, execution priority and home execution processor to a process type. The #PRIO directives for processes should be placed directly after the process heading in the definition of the actual process type, as shown in Example 191.

Example 191   
Process P1; /*#PRIO 2048,3,* */ 
Process P2(1,1); /*#PRIO *,2 */ 
...
Create P1;
Create P2;
  

Signal Priorities

You can assign a CHILL defined priority to a signal type or to the output of a specific signal value. The #PRIO directives for signals should be placed in the signal definition and in the output actions as shown in Example 191. A #PRIO directive specified in an output action will override a #PRIO directive possibly specified for the actual signal type.

Example 192   
Signal S /*#PRIO 6 */;
...
Output S;
...
Output S /*#PRIO 1*/;
  

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.

Example 193   
System S;
/*#MAIN 
CHILL 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 in the reach of the outermost CHILL module of the generated program, and it will be executed after the initialization of the internal structure, but before any transitions.

Linking with Other Object Files - Directive #WITH

You can specify that a number of user defined and precompiled units (e.g. manually written CHILL modules) shall be linked together with a generated application program. You do this in a #WITH directive that should be placed in the system definition directly after the system heading.

Example 194   
System S; /*#WITH 'file1' 'file2' */
  
Within the #WITH directive the name of the object files that are to be included in the link operation should be given between quotes, as in the example above. These file names will then be included in the definition of the link operation in the generated .m or .link file.

The makefile will, however, not include any definition of how to compile the corresponding source files, as it is impossible for sdl2chill to know the compilation options or even what compiler the user wants.

--------------------------------------------------------------------
Note:                                                                 
The #WITH directive will only affect the generated make file. There   
will be no change in the generated CHILL code when a #WITH di         
rective is introduced.                                                
--------------------------------------------------------------------

Interfacing to Existing CHILL Code - Directive #ENVIRONMENT

You can specify that importing CHILL names from user defined CDB_entries shall be allowed in a generated program. You do this in a #ENVIRONMENT directive that should be placed in the system definition directly after the system heading.

Example 195   
System S;
/*#WITH 'file1' 'file2' */
/*#ENVIRONMENT 'file1' 'file2' */
  
Within the #ENVIRONMENT directive the names of the actual CDB_entries should be given between quotes, as in the example above. These file names will then be included in the CHIPSY context directive of the generated compilation unit(s). As shown by the example, the #ENVIRONMENT directive and the #WITH directive may both be used for a system.

A user that knows how to interface to routines in other languages in a CHILL program, can with this knowledge and the #ENVIRONMENT directive and the #WITH directive link modules written in another language together with the generated program.

---------------------------------------------------------------
Note:                                                            
The #ENVIRONMENT directive will only affect the generated        
CHILL code. There will be no change in the generated make file   
when a #ENVIRONMENT directive is introduced.                     
---------------------------------------------------------------

Identifying Initially Created Process Instances - Directive #PIDLIT

The #PIDLIT directive enables you to identify the PId values of initially created processes. Place the #PIDLIT directive directly after the process heading. It should contain the name of the to be associated synonym within quotes as shown in Example 196 below. In sdl2chill, because output without to is not supported, you may use a #PIDLIT directive to easily get hold of the PId value of an initially created process instance in order to output a signal to it(12).

Example 196   
Synonym Pa_lit /*#NAME 'Pa_lit'*/ PId = NULL;
...
Process Pa(1,1);/*#PIDLIT 'Pa_lit' */
...
Output my_signal to Pa_lit;
  
In case you create more than one initial instance of a process, the identifying synonym must be an array of which the item sort is PId and the number of items is equal to the number of initially created instances. See also Example 196.

Example 197   
Syntype index = integer
    Constants 1:10
Endsyntype;
Newtype PId_array Array(index, PId)
Endnewtype;
Synonym Pb_lits /*#NAME 'Pb_lits' */
PId_array = (. NULL .); ... Process Pb(1,10);/*#PIDLIT 'Pb_lits' */ ... Output my_signal to Pb_lits(10);

Applying Generated Programs

Software Structure

The application (or application part) generated with sdl2chill can be viewed as having three components:

  1. The SDL system
  2. The environment of the system
  3. The system interface module where you connect the SDL system to its environment.
In the SDL system processes are created and stopped, transitions are executed, signals are sent from one process to another initiating new transitions, timer signals are sent, and so on. These are examples of internal actions that only affect the execution of the SDL system. An SDL system communicates with its environment by sending signals to the environment and by receiving signals from the environment.

The SDL system may be viewed as a CHILL module interfaced to via signals. This makes it easy to plug in a system as an application program part anywhere in your CHILL software structure and as the interface definition is also generated by sdl2chill, consistency check is fully catered for by CHILL.

The environment of the SDL system consists of CRS, other application program parts, the hardware, a network of computers and so on. In this world other actions than just signal sending and receiving are required. Examples of some actions that an application may want to perform are:

Such actions can efficiently and reliably be implemented in CHILL.

The system interface module is the place where the two worlds, the SDL system and the environment, meet. Here signals sent from the SDL system to the environment can induce all kinds of events in the environment, and events in the environment might cause signals to be sent into the SDL system. The system interfacing code may be collected in a separate interface module or, if more convenient, embedded in the application program part(s) which the SDL system is connected to. Definitions of the signals connecting the SDL system to its environment is provided by sdl2chill, but the actual functionality of the system interface module, of course, you must provide yourself because sdl2chill has no knowledge of this. How to write the system interface module is described in the next section.

When it comes to system architecture, utilization of the application (parts) generated by sdl2chill is very flexible. In a distributed system an application might consist of several communicating SDL systems. Each SDL system will become one executable program. It might execute either as an operating system process (e.g. UNIX process), or it might execute in a processor of its own, communicating over a network with other processors. There can of course also be combinations of these. Distribution is facilitated by means of the CHIPSY Distributed Processing Services as described in the CHIPSY Reference Manual.

The System Interface Module

With sdl2chill, interfacing to an SDL system as shown in the below example, is very simple:

Example 198   
SDL/PR specification

system DemonGame;
  signal
    Newgame,
    Probe,
    Result,
    Endgame,
  ...
endsystem DemonGame;
Generated CHILL

<> ENVIRONMENT ...
DemonGame:
MODULE
  GRANT ALL;
...
END
DemonGame;
System interface module

<> ENVIRONMENT('DemonGame');
ApplyDemonGame:
MODULE
    SEIZE
         Newgame
        ,Probe
        ,Result
        ,Endgame
...
END
ApplyDemonGame;
  

A Complete Example

This section is a complete example showing the SDL specification for a system called Demongame, and the CHILL code for connecting to it for the purpose of playing the game by giving commands from the workstation keyboard and showing results on the screen. The generated CHILL code for Demongame is also shown. The latter is not needed in order to write the system interface module, but it is included here anyhow in order to show the actual SDL to CHILL mapping for a non-trivial example.

SDL Specification for Demongame

system DemonGame;

signal Newgame, Probe, Result, Endgame, Win, Lose, Score(integer), Game_Ack(pid), Bump, Game_Id(pid); synonym Main_P pid = NULL; synonym Demon_P pid = NULL; channel C3 from DemonBlock to GameBlock with Bump; from GameBlock to DemonBlock with Game_Id; endchannel C3; channel C2 from GameBlock to env with Win, Lose, Score, Game_Ack; endchannel C2; channel C1 from env to GameBlock with Newgame, Probe, Result, Endgame; endchannel C1; block DemonBlock referenced; block GameBlock referenced; endsystem DemonGame; block DemonBlock; connect C3 and R1, R2; signalroute R1 from Demon to env with Bump; signalroute R2 from env to Demon with Game_Id; process Demon (1, 1) referenced; endblock DemonBlock; block GameBlock; signal GameOver; connect C1 and R1, R2; connect C2 and R3, R7; connect C3 and R4, R6; signalroute R2 from env to Game
with Probe, Result; signalroute R4 from env to Game
with Bump; signalroute R5 from Main to Game
with GameOver; signalroute R3 from Game to env
with Win, Lose, Score; signalroute R6 from Game to env
with Game_Id; signalroute R7 from Main to env
with Game_Ack; signalroute R1 from env to Main
with Newgame, Endgame; process Game (0, 1) referenced; process Main (1, 1) referenced; endblock GameBlock; process Demon; /*#PIDLIT 'Demon_P' */ timer T; dcl game_p pid := NULL; start; set( now + 5, T); nextstate generate; state generate; input T; decision game_p = NULL; ( false) : output Bump to game_p; set( now + 0.5, T); nextstate -; ( true) : set( now + 10, T); nextstate -; enddecision; input Game_Id( game_p); nextstate -; endprocess Demon; process Game; dcl Count integer; start; task Count := 0; output Game_Id( self) to Demon_P; nextstate Losing; state Losing; input Probe; output Lose; task Count := Count - 1; nextstate -; input Bump; nextstate Winning; state Winning; input Bump; nextstate Losing; input Probe; output Win; task Count := Count + 1; nextstate -; state * ; input Result; output Score( Count); nextstate -; input GameOver; output Game_Id( NULL) to Demon_P; stop; endprocess Game; process Main; /*#PIDLIT 'Main_P' */ dcl GameP pid; start; nextstate Game_Off; state Game_Off; input Newgame; create Game; task GameP := offspring; output Game_Ack( offspring); nextstate Game_On; state Game_On; input Endgame; output GameOver to GameP; task GameP := NULL; nextstate Game_Off; endprocess Main;

System Interface Module

<> ENVIRONMENT
    ('DemonGame'
    ,'BasicIo'
    ,'(CRS)pgh_terminate_program'
    );
ApplyDemonGame:
MODULE
    SEIZE
        -- from DemonGame
         Newgame
        ,Probe
        ,Result
        ,Endgame
        ,Win
        ,Lose
        ,Score 
        ,Game_Ack
        ,Main_P
        -- from pgh_terminate_program
        ,TS_Normal
        ,Terminate_Program
        ;
    NEWMODE
        Commands =  SET
           (Do_Quit
         ,S_Newgame
           ,S_Probe
           ,S_Result
           ,S_Endgame
           ); 
    DCL 
        Menu ARRAY (1:5) CHAR(10):=
           ['Newgame: 1'
           ,'Probe  : 2'
           ,'Result : 3'
           ,'Endgame: 4'
           ,'Quit   : 0']
        ,Win_txt CHAR(3) := 'Win'
        ,Lose_txt CHAR(4) := 'Lose'
        ,Score_txt CHAR(10):= 'Score is: '
        ;
    Read_Command: PROC() (Commands);
        DCL
            choice_no INT := 0
           ;
        new_line();
        DO FOR menu_line IN Menu;
            out_text(-> menu_line);
        OD;
        choice_no := in_int();
        IF choice_no < 0 OR choice_no > 4
        THEN
            RETURN Read_Command();
        ELSE
            RETURN Commands(choice_no);
        FI;
    END Read_Command;
    Report_Win: PROC();
        out_text(-> Win_txt);
    END Report_Win;
    Report_Lose: PROC();
        out_text(-> Lose_txt);
    END Report_Lose;
    Report_Score: PROC(Score INT);
        out_string(-> Score_txt);
        out_int(Score);
        new_line();
    END Report_Score;
    DemonGameInterface: PROCESS();
        DCL
           Game_P INSTANCE := NULL;
           ;
  
        DO FOR EVER;
            CASE Read_Command() OF
           (S_Newgame):
               SEND Newgame TO Main_P;
               RECEIVE CASE;
               (Game_Ack IN pid_parm):
                  Game_P := pid_parm;
               ESAC;
           (S_Probe):
               IF Game_P /= NULL
               THEN
                   SEND Probe TO Game_P;
                   RECEIVE CASE;
                   (Win):
                       Report_Win();
                   (Lose):
                       Report_Lose();
                   ESAC;
               FI;
           (S_Result):
               IF Game_P /= NULL
               THEN
                   SEND Result TO Game_P;
                   RECEIVE CASE;
                   (Score IN int_parm):
                       Report_Score(int_parm);
                   ESAC;
               FI;
           (S_Endgame):
               SEND Endgame TO Main_P;
               Game_P := NULL;
           (Do_Quit):
                Terminate_Program(TS_Normal);
            ESAC;
        OD;
  END DemonGameInterface;
  START DemonGameInterface();
END ApplyDemonGame;

Generated CHILL program

<> ENVIRONMENT
    ('(ROOT_CD)/crs/_sdl/sdl_support'
    ,'(CRS)/sih_else_signal'
    );
DemonGame:
MODULE
  GRANT ALL;
  SEIZE ALL;
  DCL Main_P INSTANCE STATIC := NULL;
  DCL Demon_P INSTANCE STATIC := NULL;
  SIGNAL
     Newgame
    ,Probe
    ,Result
    ,Endgame
    ,Win
    ,Lose
    ,Score = (INT)
    ,Game_Ack = (INSTANCE)
    ,Bump
    ,Game_Id = (INSTANCE)
    ,T
    ,GameOver
    ;
  Demon: PROCESS(parent INSTANCE);
    NEWMODE
       states = SET(start_state, generate)
      ;
    DCL
       offspring INSTANCE := NULL
      ,sender INSTANCE := NULL
      ,state states := start_state
      ,game_p INSTANCE := NULL
      ;
    DCL
       yDcn_BOOL BOOL
      ;
    DO WHILE TRUE;
      CASE state OF
      (start_state):
        SDL_Set_Timer
            (SDL_Time_Add
                 (SDL_Now()
                 ,SDL_Duration_Lit(5, 0)
                 )
            , -> T
            );
        state := generate;
        GOTO SDL_next_state;
      (generate):
        RECEIVE CASE SET sender;
        (Game_Id IN yP1):
          game_p := yP1;
          GOTO SDL_next_state;
        (T):
          IF game_p=NULL
          THEN
            SDL_Set_Timer
                (SDL_Time_Add
                    (SDL_Now()
                    ,SDL_Duration_Lit(10, 0)
                    )
                ,-> T
                );
            GOTO SDL_next_state;
          ELSE
            SEND Bump TO game_p;
            SDL_Set_Timer
                (SDL_Time_Add(SDL_Now()
                ,SDL_Duration_Lit(0, 500000000))
            ,-> T
            );
            GOTO SDL_next_state;
          FI;
        ESAC;
      ESAC;
    SDL_next_state: ;
    OD;
  END Demon;
  Demon_P := START Demon(NULL);
  Game: PROCESS(parent INSTANCE);
    NEWMODE
       states = SET(start_state, Losing, Winning)
      ;
    DCL
       offspring INSTANCE := NULL
      ,sender INSTANCE := NULL
      ,state states := start_state
      ,Count INT
      ;
    DO WHILE TRUE;
      CASE state OF
      (start_state):
        Count := 0;
        SEND Game_Id(THIS) TO Demon_P;
        state := Losing;
        GOTO SDL_next_state;
      (Losing):
        RECEIVE CASE SET sender;
        (Probe):
          SEND Lose /* TO ? */;
          Count := Count-1;
          GOTO SDL_next_state;
        (Result):
          GOTO L_xxLabel1;
        (Bump):
          state := Winning;
          GOTO SDL_next_state;
        (GameOver):
          GOTO L_xxLabel2;
        ESAC;
      (Winning):
        RECEIVE CASE SET sender;
        (Probe):
          SEND Win /* TO ? */;
          Count := Count+1;
          GOTO SDL_next_state;
        (Result):
          GOTO L_xxLabel1;
        (Bump):
          state := Losing;
          GOTO SDL_next_state;
        (GameOver):
          GOTO L_xxLabel2;
        ESAC;
      ESAC;
    L_xxLabel1: ;
      SEND Score(Count) /* TO ? */;
      GOTO SDL_next_state;
    L_xxLabel2: ;
      SEND Game_Id(NULL) TO Demon_P;
      STOP;
    SDL_next_state: ;
    OD;
  END Game;
  Main: PROCESS(parent INSTANCE);
    NEWMODE
       states =
SET(start_state, Game_Off, Game_On) ; DCL offspring INSTANCE := NULL ,sender INSTANCE := NULL ,state states := start_state ,GameP INSTANCE := NULL ; DO WHILE TRUE; CASE state OF (start_state): state := Game_Off; GOTO SDL_next_state; (Game_Off): RECEIVE CASE SET sender; (Newgame): offspring := START Game(THIS); GameP := offspring; SEND Game_Ack(offspring) /* TO ? */; state := Game_On; GOTO SDL_next_state; (else): GOTO SDL_next_state; ESAC; (Game_On): RECEIVE CASE SET sender; (Endgame): SEND GameOver TO GameP; GameP := NULL; state := Game_Off; GOTO SDL_next_state; (else): GOTO SDL_next_state; ESAC; ESAC; SDL_next_state: ; OD; END Main; Main_P := START Main(NULL); END DemonGame;

Implementation Dependencies

SDL Implementation Dependencies

sdl2chill handles the majority of SDL concepts according to the definition of SDL88. There are, however, a set of implementation dependencies and restrictions that are discussed in this section.

The restrictions in the SDT Analyzer, which of course also affect sdl2chill, are summarized below. For more information see the chapter The Analyzer.

sdl2chill introduces additional implementation dependencies on the allowed set of SDL concepts:

Implementation Dependencies on Integer

Due to the implementation of Integer using 16-bit integers in CHILL, there is a restriction in range for Integer values. Integers must be in the range -215..215-1. There are in the same way restrictions both in range and precision for Real, Time, and Duration, as they are implemented using the CRS defined mode LONGDURATION. In the interface to the SDL Services the literals of Real, Time, and Duration are represented by two 32-bit integers. The first integer of Time, and Duration represents the number of seconds and the second integer represents the number of nanoseconds.

This page intentionally left blank


Footnotes

(1)
In CHIPSY, CHILL compiling is done in two steps: a generic front-end called the CHILL Analyzer, performs syntactic and static semantic analysis before a target specific back-end is invoked in order to produce the resulting object code.
(2)
Report files and temporary intermediate files used by CHIPSY during compiling and linking are not shown.
(3)
The CHILL program executes on its own and no connection to other tools in SDT or in CHIPSY is established by sdl2chill. See also the CHIPSY Reference Manual.
(4)
This forces textually relocating and goto-chaining the CHILL code generated for transitions containing labels to which goto is made from other transitions. To the user of sdl2chill, a "structured SDL specification" thus translates to a structured CHILL program while an "unstructured specification" maps to a CHILL program relying heavily on the use of goto.
(5)
The "else signal" is a CHIPSY implementation defined CHILL signal.
(6)
The #PRIO directive may be used to override the default values for the CHIPSY CHILL implementation defined process parameters. See "Assigning PrioritiesDirective #PRIO" on page 2361.
(7)
An expression can be evaluated at analysis time if it only contains literals and operators defined in the predefined SDL sorts and other synonyms which are possible to calculate at analysis time.
(8)
For the advanced sdl2chill user it is possible to adapt the SDL Services to meet specific needs. This may be done without affecting the sdl2chill tool itself provided that the library interface is unchanged. The exporting CDB entry of the CRS Services is (CRS)/_SDL/SDL_support.
(9)
At this point the usage of (B) may seem redundant. This syntax, however, is introduced here to prepare for specifying other implementation techniques as described in "More about Abstract Data Types" on page 2344.
(10)
This is an escape mechanism that should be used only when it is really needed e.g. for interfacing to an existing system, as a means to define implementation details or to remove bottlenecks during the final performance tuning.
(11)
In case a space is erroneously inserted e.g. before the # character, the intended directive is treated as an ordinary comment. and it has no impact on the SDL to CHILL translation at all.
(12)
Using the #PIDLIT directive can usually be replaced by a start-up protocol in which the PId values of the initially created processes are exchanged. To facilitate SDL to CHILL translation of a specification without enforcing you to introduce such a protocol, the #PIDLIT directive has, however, been implemented as a pragmatic extension to SDL.
 
Table of Contents Next Chapter