4.2. Programming technology

advertisement
4.2. Programming technology
Technology of working with ANSI C in the system P-Cube is as follows. Files with the
source text (*.c, .h) are processed by the compiler icc with outputting the object files (*.tco),
which are further linked by the linker ilink with library files under governing of the batch files
(*.lnk). Further configured files, representing program processes, and source file with the
description of configuration (*.cfs) are processed by a configurator, which issues a binary file of
the configuration (*.cfb). Finally, binary file of the configuration and linked (*.lku) files are
processed by collector icollect, which forms a load module (*.btl), loaded to the system by the
program iserver.
Let’s consider a program on language C, which outputs "Hello, WORLD" (for
performing on one transputer).
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
void Hello (process *p)
{
procwait(10000); // tick – 1 μs
printf("\Hello,\n")
}
void world (process *p)
{printf("\n WORLD!\n");
}
int main (){
process *p1, *p2;
p1=ProcAlloc(Hello,0,0);
p2=ProcAlloc(world,0,0);
ProcPar(p1, p2, NULL); //2 processes are launched in parallel
// program terminates when both launched processes will terminate
}
The following actions are necessary to start this program (from file hello.c):
icc hello object file hello.tco is got; it is linked further with the full library, connected by means of
startup.lnk batch file (startrd.lnk is used not for the root transputer, reduced library), key /f
defines following it batch file:
ilink hello.tco /f startup.lnk
Configuration file is not needed for uniprocessor configuration, so immediately do an assembly:
icollect hello.lku
and start a program on execution on the root transputer:
iserver hello.btl
4.3. Configuration description language
Configuration description language (CDL) is used to describe processors network,
processes network and to map processes network on processors network, i.e. to create source file
with configuration description. CDL is C-based language.
4.3.1. Data types
Let’s consider data types in CDL. Nodes of the network of processors and network of processes
have a common parental type Node, which generates two subtypes:
- Process - for the description of nodes of the network of processes;
- Processor - for the description of nodes of the processor network.
Types Input/Output describe inputs and outputs of the program channels (program edges). Type
Edge describes inputs/outputs of the hardware channels (hardware edges). Type Connection
describes program or hardware channels. Besides enumerated specific types conventional types
are also used:
Char
Int
Float
Double
Symbols
Integers
Real numbers of Real numbers of
the standard size the double size
Symbol strings are double quoted:"string", single symbols are quoted: 'I’. Symbolic
constants are defined with the keyword val, for instance:
val gridsize 4;
defines a constant with the value 4.
Similarly it is possible to define arrays of constants:
val POWERS {
{1,1,1},
{2,4,8},
{3,9,27}
};
Logical constants are defined on the base of integers: TRUE – 1, FALSE – 0.
Expressions satisfy to C language rules.
4.3.2. Operators
Declaration operators are used to define networks of processors and processes, for example:
T414 (memory=1M) grid[4];
– here is declared 4-element array of T414 processors with 1M of the RAM memory.
Edge freelink [4];
–here is defined 4-elements array of hardware edges
Replicator and conditional operators are used to define regular connections and irregular parts of
them.:
rep i=0 to 2 –replicator operator
{connect grid[i].link[2] to grid [i+1].link[3] //– connects 2nd link of i-th processor
// with the 3rd link of (i+1)-st processor
if (i= =0)
connect grid[1].link[1] to host
else
connect grid[i].link[1] to freelink[i]
}
It is possible to introduce new nodes types with the help of operator DEFINE using
previously defined types, for example:
define processor (type = "T414") T414;
Here new type is obtained by specifying of the value of the attribute TYPE of the PROCESSOR
type; other attributes of this type are array LINKS and MEMORY. Attribute LINKS is available
only for reading and determines number of physical links (it may be obtained by size (links)).
New processes types are defined similarly:
define process (stacksize = 10K,
interface (INT count, input command, output result)) work package;
Here is defined process type with stack of 10К and with 3 parameters: first is integer, 2nd
is input channel, 3rd is output channel.
Networks of processes are defined as follows. Statement (graphically depicted in Fig. 20)
connect control.command to work_package.command –
declares connection (program channel). For naming of the declared channel may be used optional
part by connection:
connect item to item [by connection];
Сontrol
Сommand
Work_package
Сommand
Fig. 20
Connection’s name can be used for mapping of program channel on hardware channel
with the help of operator place:
place channel on link;
The same operator is also used to map processes on processors:
place process on processor;
Configurator automatically maps program channels on links basing on mapping of
processes on processors. Explicit mapping of channels on links is required in special cases, for
example, if it is desirable to increase rate of information transfer by using separate links for input
and output.
To receive parameters declared in the interface of a process by program code it may be
used function get_param, for example, get_param(1) will return value of the 1st parameter count;
to work with channels (2nd and 3rd parameters) it is necessary to use the following C code:
{
channel *ch;
ch=(channel *) get_param(2);
If we shall output information into channel ch in the program corresponding message will be
transferred via channel given in the configuration file for processes connections. CDL has
operator USE intended for binding processes defined in configuration file with program processes
represented by C codes:
filter x, y, z;
use "filter.lku" for filter
– binds configuration processes of the type filter with program file filter.lku obtained from C file
filter.c; the same as previous may be declared by separate statements:
use "filter.lku" for x;
use "filter.lku" for y;
use "filter.lku" for z;
4.3.3. Example of configuration description
Let’s consider example (Fig. 21) in which 2 processes are to be mapped on 2-processor
network:
host
T425
2-processor
T800
network
From_server
command
feed
host
To_server
reply
response
controller
process
task
process
Fig. 21
One process (controller) performs interaction with the host, the 2nd performs calculations. Name
host is predefined by default and denotes hardware edge intended for communication with the
host-computer:
T425 (memory=1m) root;
T800(memory=1m) worker;
connect root.link[1] to host;
connect root.link[2] to worker.link[1];
Iinput from_server; // input edge
output to_server; // output edge
process (stacksize=8k, heapsize=50k, interface(
input command, output reply, output feed, input response)) controller;
connect from_server to controller.command;
connect to_server to controller.reply;
process (stacksize=16k, heapsize=512k, interface(input feed, output response)) task;
connect controller.feed to task.feed; //output with input
use “compute.lku” for task;
place controller on root;
connect task.response to controller.response;
use “control.lku” for controller;
place task on worker;
place from_server on host;
place to_server on host;
4.3.4. Example of the full program
Let’s consider example of the full ANSI C program including C-codes and configuration
file for 4 processes and 2 processors application providing transmission of the message along the
ring of processes and printing sent message on the terminal display. On Fig. 22 are shown in one
rectangle processes which are to mapped on the corresponding processor, for each process
represented by circle there are given as callouts program files (*.lku) from which these processes
are originated.
From_server
To_server
Pr(pr.lku)
Host
Pr(pr.lku)
Pr0 (pr0.lku)
Tr0
Pr3(pr3.lku)
Tr1
Fig. 22
File pr0.c:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <channel.h>
#include “common.h”
int main(){
channel *c_in1=NULL, *c_out1=NULL;
char buffer[LenCadr];
c_in1=(Channel *)get_param(3); //1st and 2nd parameters are got by default
c_out1=(Channel*)get_param(4);// and are used by functions
strcpy(buffer, “Hello!”); // printf, scanf, getchar и т.п.
printf(“\nBegin process”);
ChanOut(c_out1,buffer,LenCadr);
printf(“\nmessage out”);
ChanIn(c_in1,buffer,LenCadr);
printf(“\n%s”,buffer);
printf(“end process”);
}
File pr3.c has the same header files, we shall give only function main:
int main(){
Channel*c_in1=NULL, *c_out1=NULL;
Char buffer[LenCadr];
c_in1=(Channel *)get_param(1);
c_out1=(Channel*)get_param(2);
ChanIn(c_in1,buffer,LenCadr);
ChanOut(c_out1,buffer,LenCadr);
}
For file pr.c we give also only function main:
int main(){
Channel*c_in1=NULL, *c_out1=NULL, *c_in2=NULL, *c_out2=NULL;
Char buffer[LenCadr];
int i;
c_in1=(Channel *)get_param(1);
c_out1=(Channel*)get_param(2);
c_in2=(Channel *)get_param(3);
c_out2=(Channel*)get_param(4);
while(1){
i=ProcAlt(c_in1,c_in2,NULL);
switch(i){
case 0: ChanIn(c_in1,buffer,LenCadr);
ChanOut(c_out1,buffer,LenCadr);
break;
case 1: ChanIn(c_in2,buffer,LenCadr);
ChanOut(c_out2,buffer,LenCadr);
break;
}
}
}
Configuration file follows:
#include “setup.inc”
T805(memory=1M)Tr[2]
connect tr[0].link[0] to host;
connect Tr[0].link[1] to Tr[1].link[1];
input from_server;
output to_server;
process(interface(input FromHost, output ToHost, input From1, output To1)) Pr0;
process(interface(input From0, output To2, input From2, output To0)) Pr1;
process(interface(input From1, output To3, input From3, output To1)) Pr2;
process(interface(input From2, output To2)) Pr3;
connect from_server to pr0.FromHost;
connect To_server to Pr0.ToHost;
connect Pr0.To1 to Pr1.From0;
connect Pr0.From1 to Pr1.To0;
connect Pr1.From2 to Pr2.To1;
connect Pr2.From1 to Pr1.To2;
connect Pr2.From3 to Pr3.To2;
connect Pr3.From2 to Pr2.To3;
use “pr0.lku” for Pr0;
use “pr.lku” for Pr1;
use “pr.lku” for Pr2;
use “pr3.lku” for Pr3;
place Pr0 on Tr[0];
place Pr1 on Tr[0];
place Pr2 on Tr[1];
place Pr3 on Tr[1];
place from_server on host;
place to_server on host;
File “common.h”:
#define LenCadr 2047
File “setup.inc”:
val Bootlink 0;
process(stacksize=4K, heapsize=16K);
Download