SynDEx v7 Tutorial
Nicolas Dos Santos, Christophe Gensoul, Kim-Hwa Khoo |
This tutorial respects some writing conventions:
To create an application workspace, launch SynDEx with option -libs libs. See the SynDEx v7 User Manual for more information.
The examples presented in this tutorial are located in the sub-folder examples/tutorial. Each example is located in its sub-folder. The example 7 is located in the examples/tutorial/example7, examples/tutorial/example7_mono, and examples/tutorial/example7_bi folders.
Algorithm, architecture, and adequation:
Hierarchy in algorithm:
Delay in algorithm:
Repetition and library in algorithm:
Condition and nested condition in algorithm:
Algorithm, architecture, adequation, and code generation:
Definition of the source code into the code editor window:
Definition of the source code in separate C files:
A complete realistic application from adequation to execution:
A multiperiodic application:
From the principal window, choose the File / Save as option and save your first application under a new folder (e.g. my_tutorial) with the name example1.
Choose Algorithm / New Algorithm Window (cf. figure 1.1). It opens the edition window for algorithm definitions.
To create an input sensor definition:
To create an output actuator definition:
To create a computation function definition:
To create an AlgorithmMain function definition:
To create an Uinout operator definition:
computation = 2 input = 1 output = 3
To create an ArchiOneOperator architecture definition:
The architecture looks like the figure 1.16.
To create Uin and Uout definitions:
MediumSamPointToPoint x MediumSamMultiPoint y MediumRam z
computation = 2 input = 2 output = 5
MediumSamPointToPoint x MediumSamMultiPoint y MediumRam z
computation = 2 input = 5 output = 3
To create a MediumSamPointToPoint medium definition:
float = 2 int = 2 uchar = 1 ushort = 1
To create an ArchiSamPointToPoint architecture definition:
In the main architecture window, to create a connection between the u1 operator and the medium_sampp medium, point the cursor on the port x of the operator, middle click, and drag it to the communication medium. It draws an edge between the operator and the communication medium. After creating the other connection, the main architecture looks like the figure 1.18.
To create an ArchiSamMultiPoint architecture definition:
float=2 int=2 uchar=1 ushort=1
The architecture looks like the figure 1.19
To create the ArchiRam architecture definition:
float=2 int=2 uchar=1 ushort=1and create a reference medium_ram in the main architecture;
The architecture looks like the figure 1.20.
Define the architecture with three operators and a medium of type SAM MultiPoint (cf. 1.4) as main architecture (Edit / Set As Main Architecture).
From the principal window, choose Adequation / Launch Adequation, then choose Adequation / Display schedule.
It opens the schedule window (cf. figure 1.21) in which you can see the schedule of the algorithm on the architecture and the schedule of the different inter-operator communications on the medium.
To contraint the ArchiSamMultiPoint architecture:
The algorithm with constraints looks like the figure 1.25.
From the principal window, choose File / Close. In the dialog window, click on the Save button.
From the principal window, choose File / Save as and save your second application under your tutorial folder with the name example2.
To create the A function definition:
The function A looks like the figure 2.2.
To create the B function definition:
The function B looks like the figure 2.3.
To create the Main algorithm:
The algorithm looks like the figure 2.4.
From the principal window, choose File / Close. In the dialog window, click on the Save button.
From the principal window, choose File / Save as and save your third application under your tutorial folder with the name example3.
Create a sensor input, an actuator output, and the function calc, like in the Examples 1 and 2. (cf. 1.1.3 and calcul1 in 2.1)
To create the calcPrec delay:
Create an algorithm algorithmMain. Create a reference in1 to the definition input, a reference calc to the definition calc, a reference out1 to the definition output, and a reference calcPrec<0;1> to the definition calcPrec. Create dependences between the references.
The algorithm looks like the figure 3.1.
From the principal window, choose File / Close. In the dialog window, click on the Save button.
From the principal window, choose File / Save as and save your fourth application under your tutorial folder with the name example4.
In this section, we create a multiplication function of a N elements vector by a scalar by repeating N times a multiplication function on scalars.
In a new algorithm window:
To create the vectors:
To create the AlgorithmMain1 algorithm:
The repetition consists in multiplying each of the 3 elements of the v_input vector with the s_input scalar and placing the result in the 3 elements v_output vector.
The parameter N is here the repetition factor of the mul function.
In this section, we create a multiplication function of a vector by a scalar by using the int library.
From the principal window choose File / Specify Library Directories and add the SYNDEXPATH/libs where SYNDEXPATH is the absolute path of the SynDEx distribution.
From the principal window, choose File / Included Libraries / int (cf. figure 4.3).
Notice that this library contains input, mul, and output definitions parameterized with length.
We will need to set it to 1 for the scalar and the multiplication function, and to N for the vectors:
Notice the difference of the mul reference when it is seen from the AlgorithmMain2 definition mode or from the main mode (Main button).
In this section, we create a multiplication function of a N*M matrix by a M elements vector by repeating N times a multiplication function on vectors.
Include the library float (File / Included Libraries / Float).
This function is a multiplication function on scalars with an accumulator:
Notice that acc is an input port and an output port of the function. It will be used as an accumulator to store the partial sum.
This function is a multiplication function on vectors with an accumulator:
The repetition consists in multiplying two dpaccn elements vectors by calling dpaccn times the dpacc multiplication function on scalars with accumulator. The initial value of its accumulator is given by the zero constant and the following are given by the accumulator itself.
This function is a multiplication function of a matrix by a vector:
The repetition consists in multiplying a a*b matrix by a b elements vector by calling a times the dp multiplication function on vectors.
To create the AlgorithmMain3 algorithm:
From the principal window, choose File / Close. In the dialog window, click on the Save button.
From the principal window, choose File / Save as and save your fifth application under your tutorial folder with the name example5.
To create the sensors and the actuator:
To create the switch1 function:
The algorithm looks like the figure 5.6.
Use previous definitions (cf. 5.1.1).
To create the switch2 function:
The algorithm looks like the figure 5.9.
From the principal window, choose File / Close. In the dialog window, click on the Save button.
From the principal window, choose File / Save as and save your sixth application under a new folder of your tutorial folder (e.g. my_example6) with the name example6.
Create the main algorithm algo (cf. figure 6.1) using the library int for the operations In<1> (input), cste2<{2}> (cst), add<1> (Arit_add), mul<1> (Arit_mul), visuadd<1>, and visumul<1> (output). For the operation conv, create a function definition conv, create a reference to this definition, and give it a duration. Create the dependences between the references. Set it as main.
Warning: it is necessary that the sensor “in” should be distributed onto the processor “root”, i.e. on the local machine, in order that it operates properly.
To define and constraint the main architecture:
To perform the adequation and to generate the code:
dnl (c)INRIA 2001-2009 dnl SynDEx v7 executive macros specific to application tutorial/example6/example6 divert(-1) define(‘NOTRACEDEF’) define(‘NBITERATIONS’,3) define(‘BINPWD’, ‘pwd’) define(‘RSHELL’, ‘ssh’) define(‘conv’,‘ifelse( MGC,‘INIT’,‘dnl’, MGC,‘LOOP’,‘$2[0] = $1[0] + 1;’, MGC,‘END’,‘dnl’)’) divert divert(-1) divert‘’dnl—————- end of file ——————
dnl (c)INRIA 2001-2009 define(‘P1_hostname_’, HOSTNAME)dnlwhere HOSTNAME is the name of the remote workstation, as indicated in the Readme file under
Warning: the characters ‘ and ’ are different.
Warning: if you increase the number of processors in your architecture,
you must add other define statements with the corresponding “processor
name”, “remote worksation name” association.
dnl (c)INRIA 2001-2009 include(example6.m4m)
# (c)INRIA 2001-2009 A = example6 M4 = m4 export SynDEx_Path = SYNDEXPATH export Algo_Macros_Path = $(SynDEx_Path)/macros/algo_libraries export Archi_Macros_Path = $(SynDEx_Path)/macros/archi_libraries export M4PATH = $(Algo_Macros_Path):$(Archi_Macros_Path) CFLAGS = -DDEBUG VPATH = $(M4PATH) .PHONY: all clean all : $(A).mk $(A).run clean :: $(RM) $(A).mk $(A).mk : $(A).m4 syndex.m4m U.m4m $(A).m4m $(M4) $< >$@ root.libs = P1.libs = include $(A).mk
where SYNDEXPATH is the absolute path of the SynDEx distribution.
Warning: in the previous makefile the statements $(RM)
$(A).mk and $(M4) $< >$@ must begin with a tab character.
The folder of the Example 6 must contain the following files:
To launch the execution, type the command make in the folder of the Example 6. To delete the file created during the compilation, type the command gmake clean.
From the principal window, choose File / Close. In the dialog window, click on the Save button.
In the previous Example 6, we have learnt that a m4 file, called with the name of the application plus the m4x extension, must be manually written. It contains all the source code associated with all operations present in a SynDEx application. For example, in the example6 application, the conv function increments of one the value of the input and stores the result in the output. Thus example6.m4x file contains:
define(‘conv’,‘ifelse( MGC,‘INIT’,‘dnl’, MGC,‘LOOP’,‘$2[0] = $1[0] + 1;’, MGC,‘END’,‘dnl’)’)
where $1 and $2 correspond respectively to the input port named i and the output port named o of the conv function.
You may read the comments written in the example6.m4x.
Handwriting this kind of code is not very easy, for several reasons:
It should be more convenient to write @OUT(o)[0] = @IN(i)[0] + @PARAM(P) and let SynDEx interpret it and generate the associated m4x file than to write the specification with the m4 syntax. SynDEx (version ≥ 7.0.0) is able to do that thanks the code editor which is a tool integrated in the graphical user interface (GUI). In the following example, we will show how to use this tool.
In this example, we show how to modify some functions by adding parameters in order to expand parameters into m4 arguments.
We have two solutions:
We need to launch the code editor of the selected operation. Let us consider the case of the conv_ref function. We have to do the following operations:
printf("Init phase of function $0 for default processor.\n");
@OUT(o)[0]=@IN(i)[0]*@PARAM(T)+@PARAM(P); printf("Loop phase of function $0 for default processor = %i.\n", @OUT(o)[0]);
printf("End phase of function $0 for default processor.\n");
Notice the following points:
We create a new reference to the conv function:
conv(2,3,_algo_cste2_P1_o,_algo_conv_ref_o) conv(8,9,_algo_conv_ref_o,_algo_conv_ref_bis_o)
Sometimes it is interesting for an operation to have different source codes depending on the type of processor. For example, a given processor type X may only offer assembly language as a programming interface. In such case, we must be able to provide (for example) C code for processors that support it, and assembly language for the X processor type. To support heterogeneous architecture, the code editor associates code to a triplet (phase, processor, operation). A special processor type Default is provided for processors that have not been associated with dedicated code. Its use allows to share a code between different processor types.
From the principal window, choose File / Included Libraries → Select c40
/* Hi, I am $0 function, in init phase for C40 processor */
@OUT(out)[0] = @IN(in)[0]; /* Hi, I am $0 function, in loop phase for C40 processor */
/* Bye, I am $0 function, in end phase for C40 processor */
/* Hi, I am $0 function, in init phase for U processor */
@OUT(out)[0] = @IN(in)[0] * 42; /* Hi, I am $0 function, in loop phase for U processor */
/* Bye, I am $0 function, in end phase for U processor */
Add c40/C40 = 1 at the end of the Durations text area for each definition referenced in algo2
The code editor comes with a set of predefined macros that alleviate the user from knowing the black magic of m4 processing.
The more useful ones are names translation macros.
These macros translate port and parameter names
to their internal representation as m4 parameters.
We have already encountered such macros in what we have just done:
@IN
, @OUT
and @INOUT
are port name translation macros,
and @PARAM
is the parameter name translation macro.
As a rule of thumb, you should use @PARAM(x)
when you want to refer to a parameter x
and @IN(i)
(resp. @OUT(o)
/ @INOUT(io)
)
when you refer to an input port i
(resp. output port o
/ input-output port io
).
The code editor recognizes three more macros:
@NAME
, @QUOTE
and @TEXT
.
These advanced macros are not used in this tutorial
and the reader is refered to SynDEx user manual
to learn more about it.
Before performing the code generation we have to perform the adequation:
Two cases are possible:
These two files constitute the Applicative kernel:
The example7_sdc.m4x file contains the following code:
divert(-1) # (c)INRIA 2001-2009 divert(0) define(‘example7_bar’,‘bar’) define(‘bar’,‘ifelse( processorType_,‘C40’,‘ifelse( MGC,‘INIT’, “/* Hi, I am $0 function, in init phase for C40 processor */”, MGC,‘LOOP’,“$2[0] = $1[0]; /* Hi, I am $0 function, in loop phase for C40 processor */”, MGC,‘END’, “/* Bye, I am $0 function, in end phase for C40 processor */”)’)’) processorType_,‘U’,‘ifelse( MGC,‘INIT’,“/* Hi, I am $0 function, in init phase for U processor */”, MGC,‘LOOP’,“$2[0] = $1[0] * 42; /* Hi, I am $0 function, in loop phase for U processor */”, MGC,‘END’, “/* Bye, I am $0 function, in end phase for U processor */”)’, define(‘example7_conv’,‘conv’) define(‘conv’,‘ifelse( processorType_,processorType_,‘ifelse( MGC,‘INIT’,“printf("Init phase of function $0 for default processor.\n");”, MGC,‘LOOP’,“$5[0]=$3[0]*$2+$1; printf("Loop phase of function $0 for default processor =%i.\n", $4[0]);”, MGC,‘END’,“printf("End phase of function $0 for default processor.\n");”)’)’)
If the example7.m4x file did not exist at code generation time then it will contain the following code:
divert(-1) # (c)INRIA 2001-2009 divert(0) define(‘dnldnl’,“// ”) define(‘NOTRACEDEF’) define(‘NBITERATIONS’,“5”) include(‘example7_sdc.m4x’) divert #include <stdio.h> /* for printf */ divert(-1) divert‘’dnl
Deeper insights about the m4 macro language can be found in SynDEx user manual and GNU M4 manual.
$(A).mk : $(A).m4 syndex.m4m U.m4m C40.m4m $(A).m4m $(M4) $< >$@
Notice that:
From the principal window, choose File / Close. In the dialog window, click on the Save button.
From the principal window, choose File / Save as and save your eighth application under a new folder of yout tutorial folder (e.g. my_example8) with the name example8.
In the seven previous examples we have learnt how to use SynDEx’s GUI to create architectures, algorithms, launch adequation, obtain executive files... Now, we have sufficient knowledge to perform a simple automatic control application that will be executed on a multiprocessor architecture.
First the application is described and the system is defined in Scicos (the block diagram editor of the Scilab software1). Second the corresponding SynDEx application is created (using the Example 1 to 3 of the tutorial). This needs the generation of some C code following the method discussed in Example 7. Finally, we compile the application to obtain executable for several processors as it has been shown in Examples 6 and 7. SynDEx generates the code necessary to the communication between the processors.
We consider a system of two cars. The second car C2 follows the car C1 trying to maintain the distance l while the acceleration and the deceleration of C1. We call: x1(t) the position of the first car; x2(t) the position of the second car plus l; x_1(t) and x_2(t) the speeds of two cars. We denote k1 and k2 the inverse of the car masses. We call r(t) the reference speed chosen by the first driver. We suppose that we are able to observe the speed of the first car and the distance between the cars.
We have the following fourth order (four degrees of liberty) system:
x1= k1 u1 x2= k2 u2 y1= x_1 y2= x1 − x2 (1) |
We will decompose the system into mono-input mono-output system S1 (u1,y1) and S2 (u2,y2). Denoting by uppercase letter the Laplace transform of the variables, we have Y1=k1 U1/s and Y2=(k1 U1 − k2 U2)/s2 where U1 is seen as a perturbation that we want reject in the second system.
A first proportional feedback U1=ρ1(R−Y1) will insure the first car to follow the reference speed. The second controller will be proportional derivative U2=ρ2 Y2+ρ3 s Y2 (in fact we will suppose in the following diagram that the derivative of y2 is also observed). The coefficient ρ1 is obtained by placing the pole of the first loop:
Y1=ρ1k1R/(s+ρ1k1). |
The coefficient ρ2 and ρ3 are obtained by placing the pole of the transfer from U1 to Y2 in the closed loop system which is given by:
Y2=U1k1/(s2+k2ρ3s +k2ρ2). |
The purpose of the controller of the C1 car is to follow the reference in speed given the first driver. It stabilizes the C1 speed around its reference speed by using pole placement. For example, gains are respectively: (0, -5, 0, 0, -5). The controller of second car stabilizes the distance between the two cars. It stabilizes y2 around 0 by pole placement. For example, gains are respectively: (4, 4,-4,-4).
The controler of C2 knows these informations and sends them electronically to C1. This remark is available for C1.
Our controllers are simple. They are represented in figures 8.1 and 8.3 in Scicos and figures 8.2 and 8.4 in SynDEx:
We associate C source code to each function definition: gain and nary-sums. The code is inserted for the default processor.
A gain is a function that multiplies its input by a coefficient given as a parameter, named GAIN. After adding this parameter, open the code editor of the gain definition and write the following code in the loop phase of the default processor:
@OUT(out_1)[0] = @IN(in_1)[0] * @PARAM(GAIN);
We have three different forms of sum depending of its arity: two, four or five input ports:
@OUT(out_1)[0] = @IN(in_1)[0] + @IN(in_2)[0];
@OUT(out_1)[0] = @IN(in_1)[0] + @IN(in_2)[0] + @IN(in_3)[0] + @IN(in_4)[0];
@OUT(out_1)[0] = @IN(in_1)[0] + @IN(in_2)[0] + @IN(in_3)[0] + @IN(in_4)[0] + @IN(in_5)[0];
In a real application, our job stops with the SynDEx’s adequation of the two controllers on their associated architectures. Nevertheless, for pedagogic reasons, we will simulate the whole system (with the dynamics of the cars) in the aim to verify that our application does the same job that Scicos.
SynDEx is only used in discrete time model (not continuous time) and is not able to manage implicit algebraic loop. That is, in SynDEx, any loop contains at least a delay 1/z. Therefore, our application which is a continuous time dynamic system described in Scicos, must be discretized in time to be used in SynDEx.
The differential equation ẋ=u is discretized using the simplest way: the Euler scheme. Let us denote by h the step of the discretization and x0 an arbitrary initial value, the discretized system can be written as:
xn+1 − xn= uh (2) |
Finally, the system is given in Scicos in the figure 8.5 and 2 is given in SynDEx in the figure 8.6. Notice that the variable h is stored in the Scicos context, and used in the input of the gain and the clock definition. In SynDEx, h is defined as parameter in the definition of a gain and the clock definition is directly used in the source code associated with operations.
Create the integrale_discrete_sup algorithm (cf. figure 8.6). Notice that pas is of type gain_def with parameter GAIN equal to 0.001, sommateur is of type sommateur2_def, and retard is of type float/delay<{0};1>.
The car dynamics are given with Scicos block diagrams
in the figure 8.7
and with SynDEx operations
in the figure 8.8,
where the input 1 (ref)
is the acceleration of the car.
The first integral gives the speed of the car and the second its position.
Create the mecanique_sup algorithm (cf. figure 8.8). Notice that puissancemoteur is of type gain_def with parameter GAIN equal to 1 whereas integrale1 and integrale2 are of type integrale_discrete_sup.
In the following diagrams (from 8.9 to 8.12), the blocks (operations) denoted by meca are the car dynamics. Let us get the controllers of the two cars.
Create the voiture1_sup and voiture2_sup algorithms (cf. figures 8.10 and 8.12). Notice that meca1 and meca2 are references to mecanique_sup whereas control1 (resp. control2) is a reference to controleur1_sup (resp. controleur2_sup).
Create the following definitions (definitionName<PARAM>):
Then create algomain. Create the reference speed ref_vit of definition senseur_def<0>, the reference vitesse x_1 of definition vitesse_def<1>, the reference distance between the two cars of definition scope_def<2>, the reference vehicule1 of definition voiture1_sup and the reference vehicule2 of definition voiture2_sup, connect them according to the figure 8.13.
We associate C source code to each function definition: input and two kinds of output.
In our Scicos application an input is a square wave generator. As a rule, we will simulate a square wave generator by reading values in a text file (named ref_vitesse.txt). We will use the fopen, the fclose and the fscanf functions (stdio.h library). We will also use assertions (assert.h library) to ensure that the opening of a file has been successful.
For the moment, let suppose that it exists an array of FILE* (the structure returned by the fopen function) called fd_array and a variable called timer to simulate a pseudo-timer. Our sensor has a parameter called POSI_ARRAY to remember the position of the FILE* structure in the array.
Now, open the code editor of the senseur_def sensor and write the following code in the init phase of the default processor:
timer = 0; fd_array[@PARAM(POSI_ARRAY)] = fopen("ref_vitesse.txt", "r"); assert(fd_array[@PARAM(POSI_ARRAY)] != NULL);
In the Scicos application, we have defined the clock period of the square wave generator to the value 5 and the step of discretization h to the value 0.001. Thus we need, in the SynDEx application, to send 5000 times the same value. To count, we use the variable timer. All the 5000-th times, we read a new value in the file.
Write the following code in the loop phase of the default processor:
timer = (timer + 1) % 5000; if (timer == 1) fscanf(fd_array[@PARAM(POSI_ARRAY)], "%f\n", &data); @OUT(out_1)[0] = data;
We need to free memory by closing the file. Write the following code in the end phase of the default processor:
fclose(fd_array[@PARAM(POSI_ARRAY)]);
An output saves in a file the values of the system states. Thus, an output has a parameter called POSI_ARRAY to remember the position of the array where the stream has been saved. Open the code editor of the vitesse_def actuator and write the following code in the init phase of the default processor:
fd_array[@PARAM(POSI_ARRAY)] = fopen("actuator_@TEXT(@PARAM(POSI_ARRAY))", "w"); assert(fd_array[@PARAM(POSI_ARRAY)] != NULL);
The loop phase, allows to save the values:
fprintf(fd_array[@PARAM(POSI_ARRAY)], "%E\n", @IN(in_1)[0]);
We need to free the memory by closing the file. Write the following code in the end phase:
fclose(fd_array[@PARAM(POSI_ARRAY)]);
Contrary to the first type of output, this output has two input ports but the init and end source codes are identical. The loop phase differs. Open the code editor of the scope_def actuator and write the following code in the init phase of the default processor:
fprintf(fd_array[@PARAM(POSI_ARRAY)], "%E\n", (@IN(in_1)[0] - @IN(in_2)[0]));
SynDEx’s code generation will create the example8_sdc.m4x file (as explained in Example 7):
define(‘example8_algomain’,‘algomain’) define(‘algomain’,‘ifelse( processorType_,processorType_,‘ifelse( MGC,‘INIT’,“”, MGC,‘LOOP’,“WARNING: empty code for macro $0 in loop phase”, MGC,‘END’,“”)’)’) define(‘example8_controleur1_sup’,‘controleur1_sup’) define(‘controleur1_sup’,‘ifelse( processorType_,processorType_,‘ifelse( MGC,‘INIT’,“”, MGC,‘LOOP’,“WARNING: empty code for macro $0 in loop phase”, MGC,‘END’,“”)’)’) define(‘example8_controleur2_sup’,‘controleur2_sup’) define(‘controleur2_sup’,‘ifelse( processorType_,processorType_,‘ifelse( MGC,‘INIT’,“”, MGC,‘LOOP’,“WARNING: empty code for macro $0 in loop phase”, MGC,‘END’,“”)’)’) define(‘example8_gain_def’,‘gain_def’) define(‘gain_def’,‘ifelse( processorType_,processorType_,‘ifelse( MGC,‘INIT’,“”, MGC,‘LOOP’,“WARNING: empty code for macro $0 in loop phase”, MGC,‘END’,“”)’)’) define(‘example8_integrale_discrete_sup’,‘integrale_discrete_sup’) define(‘integrale_discrete_sup’,‘ifelse( processorType_,processorType_,‘ifelse( MGC,‘INIT’,“”, MGC,‘LOOP’,“WARNING: empty code for macro $0 in loop phase”, MGC,‘END’,“”)’)’) define(‘example8_scope_def’,‘scope_def’) define(‘scope_def’,‘ifelse( processorType_,processorType_,‘ifelse( MGC,‘INIT’,“”, MGC,‘LOOP’,“WARNING: empty code for macro $0 in loop phase”, MGC,‘END’,“”)’)’) define(‘example8_senseur_def’,‘senseur_def’) define(‘senseur_def’,‘ifelse( processorType_,processorType_,‘ifelse( MGC,‘INIT’,“”, MGC,‘LOOP’,“WARNING: empty code for macro $0 in loop phase”, MGC,‘END’,“”)’)’) define(‘example8_sommateur2_def’,‘sommateur2_def’) define(‘sommateur2_def’,‘ifelse( processorType_,processorType_,‘ifelse( MGC,‘INIT’,“”, MGC,‘LOOP’,“WARNING: empty code for macro $0 in loop phase”, MGC,‘END’,“”)’)’) define(‘example8_sommateur4_def’,‘sommateur4_def’) define(‘sommateur4_def’,‘ifelse( processorType_,processorType_,‘ifelse( MGC,‘INIT’,“”, MGC,‘LOOP’,“WARNING: empty code for macro $0 in loop phase”, MGC,‘END’,“”)’)’) define(‘example8_sommateur5_def’,‘sommateur5_def’) define(‘sommateur5_def’,‘ifelse( processorType_,processorType_,‘ifelse( MGC,‘INIT’,“”, MGC,‘LOOP’,“WARNING: empty code for macro $0 in loop phase”, MGC,‘END’,“”)’)’) define(‘example8_vitesse_def’,‘vitesse_def’) define(‘vitesse_def’,‘ifelse( processorType_,processorType_,‘ifelse( MGC,‘INIT’,“”, MGC,‘LOOP’,“WARNING: empty code for macro $0 in loop phase”, MGC,‘END’,“”)’)’) define(‘example8_voiture1_sup’,‘voiture1_sup’) define(‘voiture1_sup’,‘ifelse( processorType_,processorType_,‘ifelse( MGC,‘INIT’,“”, MGC,‘LOOP’,“WARNING: empty code for macro $0 in loop phase”, MGC,‘END’,“”)’)’) define(‘example8_voiture2_sup’,‘voiture2_sup’) define(‘voiture2_sup’,‘ifelse( processorType_,processorType_,‘ifelse( MGC,‘INIT’,“”, MGC,‘LOOP’,“WARNING: empty code for macro $0 in loop phase”, MGC,‘END’,“”)’)’)
You will not can use directly the SynDEx’s generated example8.m4x generic file because both the creation of local variable and the call of libraries is missing. After the code generation, you will must handwrite it to obtain the following code:
define(‘dnldnl’,“// ”) define(‘NOTRACEDEF’) define(‘NBITERATIONS’,“20000”) define(‘BINPWD’, ‘pwd’) define(‘RSHELL’, ‘ssh’) define(‘proc_init_’,‘ FILE *fd_array[10]; float data; int timer;’) include(‘example8_sdc.m4x’) divert divert(-1) divert‘’dnl
Where the macro proc_init_ allows the local variable declaration to be declared because it inserts its source code between the main function and the operations initialization. Notice that the main loop of the program is defined generically with a loop of NBITERATIONS where NBITERATIONS is initialized with the size of the input file (ref_vitesse.txt). Finally, the call of libraries is inserted after the include of the example8_sdc.m4x file.
Scicos software allows to simulate models in a window (cf. figure 8.14), where the values of three states are plotted (ordinate axle) according to the time (abscissa axle). We have:
Thanks the diagram, the system is stable (plots do not grow exponentially) and so it works. We do not continue to ameliorate the controllers job.
In this subsection, we suppose that the architecture is constituted of an only operator named root:
float/delay = 1 gain_def = 1 scope_def = 1 senseur_def = 2 sommateur2_def = 2 sommateur4_def = 1 sommateur5_def = 2 vitesse_def = 1
First, launch the adequation. It modifies example8.sdc and example8.sdx files.
Then, generate the executive and applicative files (setting Code / Generate m4x Files). It creates example8.m4, example8.m4x, example8_sdc.m4x, and root.m4 files.
Finally, handwrite the example8.m4x file as explained in 8.4.6.
First, generate manually a GNUmakefile containing:
A = example8 M4 = gm4 export ArchiMacros_Path = ../../../macros/archi_libraries export AlgoMacros_Path = ../../../macros/algo_libraries export M4PATH = $(ArchiMacros_Path):$(AlgoMacros_Path) CFLAGS = -DDEBUG VPATH = $(M4PATH) .PHONY: all clean all : $(A).mk $(A).run clean :: $(RM) $(A).mk *~ *.o *.a *.c actuator_* $(A).mk : $(A).m4 syndex.m4m U.m4m $(M4) $< >$@ root.libs = P1.libs = include $(A).mk
Where:
Then, copy-paste the ref_vitesse.txt file from the Example 8 folder to yours.
Then, type the command gmake in a shell commands interpreter. It creates actuator_1, actuator_2, example8.mk, root, root.c, and root.root.o files:
In this subsection, we suppose that the architecture is constituted of two operators named root and pc1, of type U and linked with a medium tcp1 of type TCP:
First, launch the adequation. It modifies example8.sdc and example8.sdx files.
Then, generate the executive and applicative files (setting Code / Generate m4x Files). It creates example8.m4, example8.m4x, example8_sdc.m4x, root.m4, and pc1.m4 files.
Finally, handwrite the example8.m4x file as explained in 8.4.6.
First, generate manually the GNUmakefile, the example8.m4m, and the root.m4x files:
$(A).mk : $(A).m4 syndex.m4m U.m4mis changed by:
$(A).mk : $(A).m4 syndex.m4m U.m4m $(A).m4m
Then, copy-paste the ref_vitesse.txt file from the Example 8 folder to yours.
Then, type the command gmake in a shell commands interpreter. It creates actuator_1, actuator_2, example8.mk, root, root.c, root.root.o, pc1, pc1.c, and pc1.pc1.o files:
In this subsection, we suppose that the architecture is constituted of five operators named root,cont1, cont2, dyna1, and dyna2, of type U and linked with a medium bus of type TCP:
First, launch the adequation. It modifies example8.sdc and example8.sdx files.
Then, generate the executive and applicative files (setting Code / Generate m4x Files). It creates example8.m4, example8.m4x, example8_sdc.m4x, root.m4, cont1.m4, cont2.m4, dyna1.m4, and dyna2.m4 files.
Finally, handwrite the example8.m4x file as explained in 8.4.6.
First, generate manually the Makefile.ocaml, the example8.m4m, the root.m4x, the cont1.m4x, the cont2.m4x, the dyna1.m4x, and the dyna2.m4x files:
define(‘cont1_hostname_’, HOSTNAME)dnl define(‘cont2_hostname_’, HOSTNAME)dnl define(‘dyna1_hostname_’, HOSTNAME)dnl define(‘dyna2_hostname_’, HOSTNAME)dnlwhere HOSTNAME is substituted with the name of your remote station;
Then, copy-paste some files from the Example 8 folder to yours:
You will probably need to install camlp5 (see at http://pauillac.inria.fr/ ddr/camlp5/).
Then, type the command make -f Makefile.ocaml in a shell commands interpreter. It creates example8.cmi, example8.o, pa_example8.cmi, and <processor>.cmi, <processor>.cmx, <processor>.o, <processor>.opt for each processor.
Finally, launch separatly the five script files. At the end of their execution, the actuator_1 and actuator_2 files are created:
From the principal window, choose File / Close. In the dialog window, click on the Save button.
From the principal window, choose File / Save as and save your ninth application under a new folder of yout tutorial folder (e.g. my_example9) with the name example9.
Create the main algorithm basicAlgorithm (cf. figure 9.1) using the library int for the operations input<1> (int/input) and output<1> (int/output). For the operation compute, create a function definition compute and create a reference to this definition. Create the dependences between the references. Set the periods to 4 for input, 8 for compute, and 8 for output by selecting each reference and filling the Period field.
Open the architecture monoProc from the library u. Define it as main. The durations for the U operator are by default:
int/input = 3 Implode_int = 1 compute = 1 int/output = 3
Implode_int is an internal operation automatically generated
by SynDEx to collect the different data produced by the different occurences
of the int/input operation.
In this case, the system is not schedulable.
Modify the durations for the U operator:
int/input = 1 Implode_int = 1 compute = 1 int/output = 1
Launch the adequation (Adequation / Launch Adequation). Display the schedule (Adequation / Display Schedule) (cf. figure 9.2).
Notice the new operation added by SynDEx (Wait) to respect the period of the input operations.
Notice that because of the periods, during a cycle two input operations are executed (input#1 and input#2) whereas only one compute and one output operations are executed.
Notice the new operation added by SynDEx (Implode_compute) to provide the data from the input operations to the compute one.
Modify the durations for the U operator:
int/input = 1 Implode_int = 1 compute = 2 int/output = 1
Launch the adequation (Adequation / Launch Adequation). Display the schedule (Adequation / Display Schedule). The computed schedule has two phases: a transitory phase (red) and a permanent phase (green) (cf. figure 9.3).
The transitory phase is executed only once. It contains the first occurrence of the input#1 operation, the first occurrence of the input#2 operation, the first occurrence of the Implode_compute operation, and the first occurrence of the compute operation. The compute operation provide data consumed by the output operation schedule at time 9 in the permanent phase.
The permanent phase is the one that is executed infinitely. It contains the second occurrence of the input#1 operation (and its following occurrences). It contains the first occurrence of the output operation (and its following occurrences).
This document was translated from LATEX by HEVEA.