Contribution INRIA Rocquencourt au rapport nal du Contrat C2A A/S Generation d'executifs distribues optimises pour les langages Synchrones Y. Sorel INRIA, Rocquencourt, Domaine de Voluceau B.P.105 - 78153 LE CHESNAY CEDEX email: [email protected] septembre 1992 1 Introduction Les langages synchrones ESTEREL, LUSTRE, SIGNAL, STATECHARTS [1], permettent d'eectuer la specication et la verication temporelle d'un algorithme d'application decrivant un systeme reactif. La complexite sans cesse croissante et les contraintes temps-reel des applications de traitement du signal et de contr^ole de processus conduisent a utiliser des architectures multi-processeurs. SynDEx (acronyme pour EXecutif Distribue SYNchrone) est un environnement graphique interactif de developpement pour ce type d'application. Il fournit une heuristique parametrable d'optimisation du temps de reponse permettant de trouver parmi les implantations realisables, celles satisfaisant les contraintes tempsreel. A partir d'une implantation satisfaisante, il genere automatiquement un executif dedie, liberant ainsi l'utilisateur des t^aches lourdes de programmation bas niveau. SynDEx ore les services suivants : { description graphique d'un algorithme d'application sous la forme d'un graphe ot de donnees { description graphique d'un multi-processeur sous la forme d'un graphe { placement et ordonnancement optimisant le temps de reponse de l'algorithme sur le multi-processeur { calcul et visualisation d'un diagramme temps-reel d'execution de l'algorithme sur le multi-processeur { generation de l'executif SynDEx pour fonctionnement en temps-reel sur un multi-Transputer 2 Specication d'algorithmes avec les langages synchrones Pour SynDEx un algorithme d'application est decrit sous la forme d'un graphe ot de donnees (graphe logiciel) dont chaque sommet represente un processus deni par des ports entree-sorties types et dont les arcs orientes connectent des ports de sortie a des ports d'entree de m^eme type. On peut distinguer des processus de calcul, de memoire et de contr^ole. Ce modele est celui utilise dans LUSTRE et SIGNAL, dans le cas d'ESTEREL il est necessaire d'eectuer une transformation sur le programme. Celui-ci pouvant ^etre vu comme la mise en parallele de programmes communicants, il faudrait eectuer un decoupage de ces programmes au niveau des communications de maniere a obtenir un graphe de processus ot de donnees. Une etude concernant ces techniques est a faire. 1 Chaque processus de calcul appelle une procedure de calcul denie par l'utilisateur et compilee separement dans une bibliotheque (l'utilisateur denit ainsi la grosseur des grains sequentiels indivisibles). Les valeurs des sorties ne doivent dependre que des valeurs des entrees, la procedure de calcul ne peut comporter de memoire et doit se terminer dans un temps borne (pas de recursion ni de boucles innies). Les processus memoire ('$' et 'window' pour SIGNAL, 'pre' pour LUSTRE, pas d'equivalent explicite en ESTEREL, il faudrait donc les rendre explicites) permettent le recyclage de valeurs sans creer de cycle de dependance. La valeur portee par la sortie d'un processus memoire est la valeur precedente portee par son entree. Les processus de contr^ole ('when' et 'default' de SIGNAL, expressions conditionnelles 'if' de LUSTRE et les instructions conditionnelles 'if', 'present' et 'watching' d'ESTEREL) permettent d'exprimer le conditionnement d'autres processus. La gure 1 represente graphiquement un exemple d'algorithme d'application. $ Adap FiltA Sub In Filt Out processus Fig. communication inter-processus 1 - Un exemple d'algorithme d'application 3 Transformation synchrone-asynchrone de la specication en vue d'une implantation multi-processeur Actuellement, les langages synchrones generent du code executable mono-processeur. Nous decrivons dans ce chapitre l'interface qui a ete realisee entre le langage SIGNAL [2] et l'environnement SynDEx [3] [4] qui, lui, permet de generer du code executable multi-processeur optimise. La specication du multi-processeur, le placement ordonnancement de l'algorithme sur le multi-processeur et la generation d'executif optimise font l'objet des chapitres suivants. 3.1 Principes de l'interface SIGNAL-SynDEx Les principes de base communs a SIGNAL et SynDEx sont le concept synchrone et l'utilisation du ot de donnees conditionne. L'interface d'un systeme avec le monde exterieur au systeme est decrite par un ensemble de signaux d'entree et un ensemble de signaux de sortie. A chaque signal est associee une sequence de valeurs ayant toutes le m^eme type. Cette sequence denit un temps logique local au signal associant un instant logique a chaque valeur de la sequence. L'ensemble des instants logiques d'un signal est appele horloge du signal. Le comportement du systeme peut ^etre decrit a l'aide de memoires d'etat et d'une relation globale transformationnelle combinant les valeurs des signaux d'entree du systeme et de sortie des memoires pour produire les valeurs des signaux de sortie du systeme et d'entree des memoires. Le signal de sortie d'une memoire d'etat 2 est obtenu a partir de son signal d'entree en ajoutant une valeur initiale a sa sequence de valeurs decalee d'un instant logique. Le concept synchrone consiste a considerer comme simultanes un instant logique d'un signal de sortie et un instant logique d'un signal d'entree lorsque la valeur de la sortie depend de la valeur de l'entree par la relation globale. Relativement a un instant logique d'un signal, un autre signal est dit present s'il a un instant logique simultane (resp. absent s'il n'en a pas). Deux signaux sont synchrones s'ils ont la m^eme horloge, c'est-a-dire si leurs instants logiques sont simultanes deux a deux. Dans ce cadre, la relation globale se decompose, en introduisant des signaux intermediaires, en relations elementaires de trois types. Chaque type de relation est decrit relativement a un instant logique d'un de ses signaux d'entree : { relation avec calcul introduisant des dependances inconditionnelles entre entree(s) et sortie(s). La valeur du signal d'entree est utilisee dans le calcul de la valeur du signal de sortie. La valeur de la sortie est simultanee avec la valeur de l'entree et de toutes les autres entrees qui participent a la relation. Les signaux d'entree et de sortie sont synchrones. Ces relations correspondent aux fonctions immediates de SIGNAL. { relation sans calcul introduisant une dependance conditionnelle (dans l'instant logique considere, il y a ou non une dependance). La valeur de la sortie est egale a la valeur de l'entree lorsque la valeur de l'autre entree (signal booleen) qui conditionne la dependance lui est simultanee et vraie. L'horloge du signal de sortie est incluse dans l'intersection des horloges des deux signaux d'entree. Ces relations correspondent aux when de SIGNAL. { relation sans calcul introduisant une dependance inconditionnelle. La valeur de la sortie est egale a la valeur de l'entree si l'autre entree ne lui est pas simultanee. Si les deux entrees sont simultanees, l'une des deux est prioritaire, c'est elle qui est choisie. L'horloge du signal de sortie est egale a l'union des horloges des deux signaux d'entree. Ces relations correspondent aux default de SIGNAL. La relation globale peut ^etre modelisee par un graphe ot de donnees dont les sommets sont les relations elementaires et dont les arcs sont les signaux intermediaires que l'on peut voir comme des relations de dependance entre sommets. Les signaux d'entree (resp. de sortie) de la relation globale sont produits (resp. consommes) par des processus d'entree sortie (lecture resp. ecriture) sans entrees (resp. sans sorties) eux aussi representes par des sommets. L'absence de valeur en entree d'une relation entra^ne une absence de valeur en sortie et donc une absence de dependance entre entree et sortie. Cette absence de dependance peut ^etre provoquee soit par l'absence d'une entree externe soit par une relation when. Le compilateur SIGNAL transforme ce graphe conditionne en graphe conditionne avec hierarchisation des conditionnements, note par la suite GCH, de la maniere suivante: 1. Pour chaque ensemble synchrone de signaux d'entrees externes (synchrones parce que lies par des relations de dependances) le compilateur ajoute un signal d'entree externe booleen (produit par un processus de lecture supplementaire) qui conditionnera l'execution des processus de lecture de ces signaux d'entree. Les processus de lecture de ces signaux booleens seront executes inconditionnellement. Ces signaux booleens sont donc synchrones et denissent l'entrelacement des horloges des ensembles de signaux d'entrees externes synchrones. L'horloge de ces signaux booleens est donc \la plus ne" car elle inclut toutes les autres horloges (des signaux d'entree, des signaux intermediaires et des signaux de sortie). 2. A chaque signal de type booleen (intermediaire ou d'entree externe) entree de conditionnement d'une (ou plusieurs) relation(s) when, on associe l'ensemble des sommets transitivement successeurs de ce(s) relation(s) when. 3. Lorsque deux de ces ensembles sont en intersection sans que l'un soit inclus dans l'autre, on leur soustrait leur intersection qu'on associe a un nouveau signal booleen genere par un nouveau sommet ajoute par le compilateur au graphe initial. Ce nouveau sommet, soit un when soit un default, prend pour entrees les deux signaux booleens auxquels sont associes les deux ensembles. Si les deux ensembles sont inclus dans un troisieme, le nouveau sommet est associe au booleen auquel est associe ce troisieme ensemble. 3 4. Tous les ensembles resultant de cette transformation sont deux a deux soit disjoints soit inclus l'un dans l'autre, ce qui permet de denir une arborescence des inclusions a laquelle correspond la hierarchie du GCH. Actuellement, le GCH est produit par le compilateur SIGNAL sous la forme d'un chier texte suivant la syntaxe SIGNAL, note \GCH.sig" par la suite (ce chier est celui suxe par TRA.SIG genere par le compilateur). S'interfacer avec SynDEx consiste pour le compilateur SIGNAL a produire un autre chier texte contenant une liste d'instructions SynDEx decrivant le GCH. Ce chier, note \GCH.syn" par la suite, sera importe dans l'environnement SynDEx. 3.2 Description et interpretation du GCH Le GCH est un des resultats de la compilation d'un programme SIGNAL sous la forme d'un graphe ot de donnees conditionne avec hierarchisation des conditionnements. Le GCH est presente informellement ci-dessous a travers ses deux formes GCH.sig et GCH.syn. Pour plus de precision sur la syntaxe de SIGNAL, voir [5] et pour la syntaxe de SynDEx, voir l'annexe A. Ici on donne pour chaque exemple une version en SIGNAL suivie d'une version en SynDEx separees par un signe ). 3.2.1 Les sommets du GCH Les types des signaux d'entree-sortie dans les instructions SynDEx de declaration des sommets du GCH sont les m^emes que ceux de SIGNAL. Le GCH est constitue des types de sommets suivants : { fonction immediate (expressions arithmetiques ou logiques ou appels de fonctions externes). (| x:=a+b |) where integer a,b (| c:=x<0 |) where integer x (| x:=sin a |) where dpreal a fg ) (function N1 add 10 integer ?a ?b !x) ) (function N2 less 5 integer ?x ?'0', logical !c) ) (function N3 sin 20 dpreal ?a !x) { retard et fen^etre glissante sur un signal (memoire). (| zx:=x$1 |) where real zx init 0.0 (memory M1 real ?x $1 !zx init 0.0) (| znx:=x$2 |) where real znx init [[1]:0.0, [2]:1.0] (memory M2 real ?x $2 !znx init [[1]:0.0, [2]:1.0]) (| zwx:=x window 4 |) where [4]real zwx init [ to 3 :0.0] (memory M3 real ?x window 4 !zwx init [ to 3 :0.0]) (| znwx:=x$2 window 4 |) where [4]real znwx init [ to 5 :0.0] (memory M4 real ?x $2 window 4 !znwx init [ to 5 :0.0]) ) ) ) ) f { dependance conditionnee (sous-echantillonage). f g f g g f g (| y:=x when c |) where [4]integer x, y; logical c (when W5 logical ?c, [4]integer ?x !y) ) { dependance inconditionnelle avec priorite (melange). (| z:=x default y |) where real x, y, z ) (default D6 real ?x ?y !z) { intersection de signaux booleens de conditionnement, sommet rajoute par le compilateur. (| H 3 H:=H 2 H when H 1 H |) ) (hmul H3 logical ?H2H ?H1H !H) { union de signaux booleens de conditionnement, sommet rajoute par le compilateur. (| H 6 H:=H 5 H default H 4 H |) ) (hadd H6 logical ?H5H ?H4H !H) { presence d'un signal d'entree externe representant de l'ensemble des entrees externes qui lui sont synchrones, sommet rajoute par le compilateur. (| H 7 H:=event ext |) ) (hinput H7 hext logical !H) { sommet compose (sous-graphe) permettant de faire ressortir par encapsulation la hierarchisation dans le GCH.sig. Ce type de sommet est inutilise dans le GCH.syn car la hierarchisation y est mise en evidence autrement (voir ci-dessous). 4 3.2.2 Les arcs du GCH Les arcs representent des transferts de donnees entre sommets. Chacun des sommets a un ensemble de ports d'entree et de sortie, qui sont les points de connexion inter-sommets. Les ports interconnectes portent le m^eme signal. Un port de sortie peut ^etre connecte a plusieurs ports d'entree (diusion). Les connexions intersommets se font implicitement par identite de noms entre instructions SIGNAL. Elles se font explicitement en SynDEx au moyen de l'instruction connect. f g | y:=ffxg | z:=gfxg | s:=y+z |) ) (| x:=abs a (function N1 abs 5 real ?a !x) (function N2 f 20 real ?e !s) (function N3 g 15 real ?e !s) (function N4 add 5 real ?a ?b !s) (connect N1/x N2/e N3/e) (connect N2/s N4/a) (connect N3/s N4/b) 3.2.3 La hierarchisation des conditionnements Dans le GCH.sig, la hierarchisation appara^t implicitement d'une part a travers les expressions de \calcul d'horloge" qui generent des \signaux d'horloge" (when unaires sur signaux booleens et when et default entre signaux d'horloge) et d'autre part a travers les instructions synchro entre les signaux d'horloge et les autres signaux. La hierarchisation est par ailleurs mise en evidence par une encapsulation regroupant dans un sommet compose les sommets ayant la m^eme horloge (l'horloge d'un sommet est l'union des horloges de ses entrees). Dans le GCH.syn, la hierarchisation appara^t explicitement a travers les instructions exec dont chacune represente l'association entre un signal booleen et un ensemble de sommets, comme decrit a la n du paragraphe 3.1. Les sommets hinput ainsi que les sommets hadd et hmul qui ne sont associes a aucun signal booleen, en somme tous les sommets qui n'apparaissent pas dans les instructions exec, constituent les racines de la hierarchie des conditionnements (ils generent tous des signaux booleens) et sont regroupes dans une instruction execroots (voir exemple complet en annexe B). 3.2.4 Interpretation du GCH.syn A chaque execution du graphe, les sommets de l'instruction execroots sont executes inconditionnellement et chaque signal booleen dans une instruction exec conditionne l'execution de l'ensemble des sommets qui lui sont associes. L'ordre d'execution est determine par les precedences entre sommets. Les precedences du graphe ot de donnees etablissent un ordre partiel qui laisse de la liberte pour le repartir et l'ordonnancer sur une architecture multi-processeur. 4 Specication du multi-processeur Le multi-processeur est modelise par un hypergraphe (graphe materiel ) dont chaque sommet represente un nud processeur et chaque hyper-arc une liaison physique de communication connectant plusieurs nuds processeurs (deux ou plus). Chaque nud processeur est decrit a partir des elements suivants: - processeur de calcul - processeur de communication (un par hyper-arc adjacent) - processeur d'entree sortie - memoire de donnees partagee entre elements processeurs Chaque element processeur inclut sa memoire de programme qui recevra les instructions de calcul et l'executif genere par SynDEx. La cooperation entre processeurs de communication d'un m^eme hyper-arc permet le transfert de donnees entre les memoires donnees des nuds processeurs connectes. Les processeurs d'entree sortie permettent au multi-processeur programme de communiquer avec son environnement, c'est-a-dire de reagir (sorties) aux stimuli (entrees) de l'environnement. 5 CAL E/S MEM COM COM COM COM COM CAL CAL MEM MEM COM COM E/S Noeud Processeur CAL = Processeur de Calcul COM = Processeur de Communication Hyper-Arc MEM = Memoire partagee E/S = Processeur d’Entree-Sortie Fig. 2 - Un exemple de multi-processeur 5 Placement ordonnancement Le placement ordonnancement est precalcule et statique (pas de migration ni d'ordonnancement de processus a l'execution). Il consiste a placer (aecter) et ordonnancer (sequentialiser) les processus de calcul (resp. d'entree sortie) sur les processeurs de calcul (resp. d'entree sortie). Ce placement produit des communications inter-processeur qu'il faut egalement placer et ordonnancer sur les processeurs de communication. Pour cela on choisit un chemin (route) dans l'hypergraphe materiel, on cree entre les deux processus (de calcul ou d'entree sortie) communiquant un processus de communication pour chaque hyper-arc de la route et on place chacun de ces processus de communication sur l'hyper-arc correspondant, c'est-a-dire sur chacun de ses processeurs de communication. Cette derniere operation consiste a diviser le processus de communication en sous-processus de communication cooperants, place chacun sur un processeur de communication. Les sous-processus de communication issus de communications inter-processeur dierentes sont ordonnances sur chaque processeur de communication. L'optimisation du placement ordonnancement actuellement eectuee consiste a minimiser le temps de reponse, c'est-a-dire la longueur du chemin critique du graphe logiciel value par les durees d'execution des processus de calcul et de communication. L'algorithme de placement ordonnancement actuellement implante dans SynDEx est une heuristique [6] (probleme NP-complet) dont la complexite est une fonction lineaire du produit du nombre de processus et de processeurs. Le diagramme temporel calcule pendant l'optimisation permet une visualisation dans l'environnement graphique SynDEx [7] (voir gure 4 page 8) faisant appara^tre les communications inter-processeur et pour chaque processeur l'ordonnancement des processus qui y sont places. 6 Generation d'executif optimise Contrairement aux systemes d'exploitation distribues standards (du genre de MACH et CHORUS) qui fournissent des services a travers une copie d'un noyau residant sur chaque processeur, SynDEx produit un executif dedie, taille sur mesure pour l'application [8]. L'utilisateur n'a pas d'autre code a ecrire que celui de ses processus de calcul et d'entree sortie. Tout le reste (ordonnancement et appel des processus de calcul et d'entree sortie, allocation de la memoire necessaire aux communications inter-processus {intra- ou inter- processeur{ et code des processus de communication) est genere automatiquement par SynDEx a partir des graphes logiciel et materiel, des resultats du placement 6 $ Adap FiltA Sub In Filt Out processus communication inter-processus processus de communication inter-processeurs frontiere du partitionnement Fig. 3 - Graphe logiciel apres placement ordonnancement et du noyau generique de l'executif SynDEx. La simplicite du noyau facilite son portage sur de nouveaux composants materiels. La methode de generation de code garantit que le comportement entrees-sorties de l'application sera le m^eme sur une architecture multi-processeur que sur l'architecture mono-processeur sur laquelle l'application aura ete prealablement deboguee. Alors que dans un environnement classique, le portage sur un multiprocesseur d'une application deboguee sur un mono-processeur demande plusieurs jours (voire plusieurs semaines) de codage et de deboguage, avec l'environnement SynDEx, ce portage est l'aaire de quelques minutes, au plus de quelques heures si le graphe representant l'algorithme est de taille importante et que plusieurs cycles de placement ordonnancement sont necessaires pour obtenir un placement satisfaisant. L'executif genere pour chaque processeur par SynDEx supporte l'ordonnancement et le conditionnement des processus qui y ont ete places, c'est-a-dire les processus d'entree sortie et de calcul (tires d'une bibliotheque fournie par l'utilisateur) et les processus de communication (tires du noyau generique de l'executif SynDEx). 6.1 Gestion des signaux echanges avec l'environnement: transformation asynchrone-synchrone Les processus associes aux sommets de lecture des signaux externes, comme les processus associes aux sommets de calcul, doivent ^etre ecrits par l'utilisateur. Par contre, la transformation asynchrone-synchrone, c'est-a-dire la denition de la simultanete des signaux d'entree externes, est realisee par l'execution inconditionnelle des sommets de lecture apparaissant dans l'instruction execroots qui conditionnent l'execution des autres sommets de lecture qui apparaissent dans les instructions exec. 6.2 Gestion de l'ordonnancement et du conditionnement Pour chaque processeur, les processus d'entree sortie et de calcul qui y ont ete places sont ordonnances et conditionnes en fonction des resultats de l'heuristique de placement ordonnancement. L'ordonnancement et le conditionnement sont realises en utilisant les instructions de sequencement et de branchement conditionnel et inconditionnel fournies par tous les processeurs. Les communications inter-processus intra-processeur sont realisees par l'intermediaire de la memoire. 7 Fig. 4 - Environnement graphique SynDEx 6.3 Gestion des communications inter-processeurs Les communications inter-processus inter-processeur sont realisees par des processus de communication assurant le transfert des donnees entre processeurs par passage de messages. Ces processus realisent les fonctions suivantes : - formatage et deformatage des messages - routage des messages a l'interieur des processeurs - transfert des messages a travers les liaisons physiques de communication Ces fonctions realisent les protocoles de communication des principaux niveaux de la norme ISO [9]. 6.4 Chronometrage L'ecacite de l'execution en temps reel de l'algorithme sur le multi-processeur depend essentiellement de l'optimisation du placement ordonnancement base comme on l'a dit au paragraphe 5 sur le calcul de la duree du chemin critique du graphe value par les durees des processus de calcul et de communication. Si le multi-processeur n'est pas disponible, ces durees doivent ^etre estimees, sinon elles peuvent ^etre mesurees en temps reel. Une option de la generation d'executif permet d'inserer des instructions de chronometrage pour obtenir les durees d'execution des processus [10]. Le chronometrage est realise en enregistrant les dates de debut et de n de tous les processus de calcul et de tous les processus de communication en utilisant comme chronometres les horloges temps-reel des processeurs. Ceci permet d'une part d'enregister le diagramme temporel reel pour 8 le comparer au diagramme temporel calcule par l'algorithme de placement ordonnancement et d'autre part de repartir equitablement les perturbations d^ues aux chronometrages. A Syntaxe SynDEx L'hypergraphe speciant l'algorithme d'application est decrit par une sequence d'instructions SynDEx de deux sortes : { instructions de declaration de sommets (sommets de l'hypergraphe) { instructions de connexion ou d'execution (arcs orientes de l'hypergraphe) Une instruction de connexion doit suivre les instructions de declaration des sommets qu'elle connecte. Chaque instruction SynDEx est delimitee par des parentheses et commence par un mnemonique designant l'instruction, suivi des parametres de l'instruction. Dans le cas des instructions de declaration de sommets, le premier parametre est un identicateur (cha^ne de caracteres alpha-numerique commencant par un alpha) du sommet declare. Tous les identicateurs de sommets doivent ^etre dierents. De m^eme, tous les identicateurs de ports d'un m^eme sommet doivent ^etre dierents. SynDEx distingue les majuscules des minuscules dans les identicateurs. Tout texte apparaissant entre guillemets est ignore (commentaires). A.1 Instruction de declaration de sommet de calcul Syntaxe : (function <id> { { <proc> <duree> <interface>) est l'identicateur du sommet de calcul. <proc> est l'identicateur de la proc edure de calcul appelee par le processus, ecrite et compilee separement par l'utilisateur. { <duree> est la duree d'execution de la procedure de calcul en microsecondes (entier positif, mettre 10 par defaut) utilisee pour le placement-ordonnancement. { <interface> est une liste de declarations des ports d'entree-sortie connectables et des ports constants (ports d'entree non connectables a une sortie). L'identicateur <proc> ainsi que l'ordre et le type des entree-sorties de l'interface doivent correspondre a la denition compilee de la procedure de calcul. Chaque declaration d'entree-sortie est constituee de : { un identicateur de type, soit logical, soit integer, soit real, soit dpreal (reel double precision), soit un tableau mono- ou multi-dimensionnel compose de ces types primitifs (ex: [2,6]integer) { un caractere ? pour une entree ou ! pour une sortie { un identicateur nommant l'entree-sortie ou bien, dans le cas d'une entree constante, sa valeur entre apostrophes Les identicateurs de la liste <interface> doivent ^etre tous dierents pour un sommet donne. Si plusieurs entree-sorties successives sont du m^eme type, celui-ci peut n'^etre donne qu'une fois. Chaque fois qu'un nouveau type appara^t dans la liste, il doit ^etre precede d'une virgule. Exemple: <id> (function gain "calls" mul "dt" 10 "i/o" real ?'0.1' ?i !o) La valeur d'une entree constante doit ^etre compatible avec son type (ex: integer ?'1' ou real ?'3.14'). La valeur d'une entree constante de type tableau est speciee sequentiellement, par indice ou par intervalle, avec les mots cle in (optionnel), to et step (optionnel) speciant respectivement la borne inferieure, la borne superieure et l'increment de l'intervalle. Par exemple, les deux entrees constantes suivantes sont equivalentes : [2,6]integer ?'[[1]:[{to 6}:0], [2]:[{to 6}:1, {in 2 to 6 step 2}:2]]' [2,6]integer ?'[[1]:[[1]:0, [2]:0, [3]:0, [4]:0, [5]:0, [6]:0], [2]:[[1]:1, [2]:2, [3]:1, [4]:2, [5]:1, [6]:2]]' 9 A.2 Instruction de declaration de sommet memoire Syntaxe : (memory <id> { { { { { { <type> ?<entree> <mem> !<sortie> init <init>) est l'identicateur du sommet memoire <type> est le type de l'entr ee <entree> est le nom du port d'entr ee <sortie> est le nom du port de sortie <init> est la valeur initiale de la m emoire <mem> d enit avec <type> les types du port de sortie et de la valeur initiale de la memoire: 1. $1 type sortie = <type> = type init, ex: <id> 2. 3. 4. (memory M1 real ?i $1 !o init 0.0) $<n> type sortie = <type>, type init = [<n>]<type>, ex: f g (memory M2 integer ?i $5 !o init [ to 5 :0]) window <m> type sortie = [<m>]<type>, type init = [<m>-1]<type>, ex: f g (memory M3 real ?i window 8 !o init [ to 7 :0.0]) $<n> window <m> [<m>]<type> [<n>+<m>-1]<type> (memory M4 integer ?i $5 window 8 !o init [ to 12 :0]) type sortie = , type init = f g , ex: Pour la syntaxe de <type> et de <init>, voir l'instruction de declaration de sommet de calcul. A.3 Instruction de declaration de sommet \when" Syntaxe : (when { { { { { <id> logical ?<cond>, <type> ?<entree> !<sortie>) est l'identicateur du sommet when <cond> est l'identicateur du port d'entr ee de conditionnement <type> est le type commun a <entree> et a <sortie> <entree> est le nom du port d'entr ee ou une valeur constante <sortie> est le nom du port de sortie, prenant la valeur de <entree> lorsque <cond> porte la valeur logique vraie. <id> Pour la syntaxe de <type> et de <entree> quand c'est une constante, voir l'instruction de declaration de sommet de calcul. Exemple: (when W1 logical ?c, integer ?i !o) 10 A.4 Instruction de declaration de sommet \default" Syntaxe : (default <id> <type> ?<prio> ?<def> !<sortie>) { <id> est l'identicateur du sommet default { <type> est le type commun a <prio>, a <def> et a <sortie> { <prio> est le nom du port d'entree prioritaire { <def> est le nom du port d'entree par defaut ou une valeur constante { <sortie> est le nom du port de sortie, prenant la valeur de <prio> ou a defaut celle de <def> Pour la syntaxe de <type> et de <def> quand c'est une constante, voir l'instruction de declaration de sommet de calcul. Exemple : (default D2 dpreal ?ip ?id !o) A.5 Instruction de declaration de sommet \hinput" Syntaxe : (hinput <id> { { <proc> logical !<sortie>) est l'identicateur du sommet hinput <proc> est l'identicateur de la proc edure de lecture de l'entree externe booleenne, ecrite et compilee separement par l'utilisateur. { <sortie> est le nom du port de sortie Exemple: <id> (hinput H0 getH0 logical !o) A.6 Instruction de declaration de sommet \hmul" Syntaxe : (hmul <id> logical ?<entree1> ?<entree2> !<sortie>) { <id> est l'identicateur du sommet hmul { <entree1> et <entree2> sont les noms des deux ports d'entree { <sortie> est le nom du port de sortie Exemple: (hmul H1 logical ?i1 ?i2 !o) A.7 Instruction de declaration de sommet \hadd" Syntaxe : (hadd <id> logical ?<entree1> ?<entree2> !<sortie>) { <id> est l'identicateur du sommet hadd { <entree1> et <entree2> sont les noms des deux ports d'entree { <sortie> est le nom du port de sortie Exemple: (hadd H2 logical ?i1 ?i2 !o) 11 A.8 Instruction de connexion de sommets Syntaxe : (connect <idSom1>/<idSor> <idSom2>/<idEnt> : : :) Le port de sortie <idSor> du sommet <idSom1> est connecte au(x) port(s) d'entree <idSom2>/<idEnt> . Tous ces ports doivent avoir ete declares avec le m^eme type. Exemple: ::: (hinput H0 getH0 logical !o) (hadd H1 logical ?i1 ?i2 !o) (hmul H2 logical ?i1 ?i2 !o) (connect H0/o H1/i1 H2/i1) A.9 Instruction d'execution inconditionnelle Syntaxe : (execroots <idSom1> Les sommets <idSom1> : : :) : : :) doivent ^etre executes inconditionnellement a chaque instant logique. A.10 Instruction d'execution conditionnelle Syntaxe : (exec <idSom1>/<idSortieLogical> <idSom2> :::) Les sommets <idSom2> ) ne sont executes que si le port de sortie <idSortieLogical> (de type logical) du sommet <idSom1> porte la valeur logique vraie. ::: B Exemple de transformation synchrone-asynchrone L'exemple suivant est un compteur avec remise a zero qui presente tous les cas de gure. Source SIGNAL chier cpt.sig process cpt = { ? event top, raz ! integer s } (| s := (1 when top when raz) default (0 when raz) default (zs + 1) | zs := s $ 1 | synchro{s, top default raz} |) where integer zs init 0 end Source GCH.sig chier CPT TRA.SIG process CPT_TRA= { ? event TOP_1, RAZ_2 ! integer S_3 } (| H_7_H:= RAZ_2 when TOP_1 | H_9_H:= when( ( not H_7_H )default RAZ_2 ) | H_13_H:= when( ( not RAZ_2 )default TOP_1 ) | H_18_H:= RAZ_2 default TOP_1 | synchro { H_18_H, S_3 } | H_18_H( ) |) where event H_18_H, H_13_H, H_9_H, H_7_H process H_18_H= { ? event H_18_H, H_13_H, H_9_H, H_7_H ! integer S_3 } (| synchro { H_18_H, ZS_5 } | ZS_5:= S_3 $1 | S_3:= ( 1 when H_7_H )default( 0 when H_9_H ) default( ( ZS_5+1 ) when H_13_H ) |) where integer ZS_5 init 0 end end 12 Source GCH.syn chier CPT.syndex (hinput TOP1 RTOP logical !top) (hinput RAZ2 RRAZ logical !raz) (function WS3 WS 10 integer ?s) (hmul H7H logical ?raz ?top !h7h) (hadd H18H logical ?raz ?top !h18h) (memory ZS5 integer ?s $1 !zs init 0) (when X6X logical ?h7h, integer ?'1' !x6x) (default X7X integer ?x6x ?'0' !x7x) (function X8X add 10 integer ?zs ?'1' !x8x) (default S3 integer ?x7x ?x8x !s) (connect TOP1/top H7H/top H18H/top) (connect RAZ2/raz H7H/raz H18H/raz) (connect H7H/h7h X6X/h7h) (connect ZS5/zs X8X/zs) (connect X6X/x6x X7X/x6x) (connect X7X/x7x S3/x7x) (connect X8X/x8x S3/x8x) (connect S3/s ZS5/s WS3/s) (execroots TOP1 RAZ2 H7H H18H) (exec H7H/h7h X6X) (exec RAZ2/raz X7X) (exec H18H/h18h WS3 ZS5 X8X S3) Fig. 5 - Graphe logiciel CPT.syndex 13 References [1] A. Benveniste, G. Berry The synchronous approach to reactive and real-time systems Rapports de Recherche INRIA no 1445 (Juin 1991) [2] P. Le Guernic, M. Le Borgne, T. Gautier, C Le Maire Programming real-time applications with SIGNAL Rapports de Recherche INRIA no 1446 (Juin 1991) [3] C. Lavarenne, O. Seghrouchni, Y. Sorel, M. Sorine SynDEx, un environnement de programmation pour applications de traitement du signal distribuees. Treizieme Colloque GRETSI (Septembre 1991). [4] C. Lavarenne, O. Seghrouchni, Y. Sorel, M. Sorine The SynDEx software environment for real-time distributed systems design and implementation. Proc. of the European Control Conference (Juillet 1991). [5] P. Bournai, B. Cheron, B. Houssais, P. Le Guernic Manuel SIGNAL Rapports Techniques INRIA no 128 (Avril 1991) [6] C. Lavarenne, Y. Sorel Partitionning and scheduling of data-ow algorithms on multi-processors taking into account communication delays Article a para^tre [7] C. Lavarenne, Y. Sorel SYNDEX, un environnement de programmation pour multi-processeur de traitement du signal Manuel de l'utilisateur version v.0. Rapports Techniques INRIA no 113 (1989) [8] N. Ghezal, S. Matiatos, P. Piovesan, Y. Sorel, M. Sorine SYNDEX, un environnement de programmation pour multi-processeur de traitement du signal Mecanismes de communication. Rapports de Recherche INRIA no 1236 (1990) [9] P. Rolin Reseaux locaux, normes et protocoles Hermes (1988) [10] F. Ennesser, C. Lavarenne, Y. Sorel Methode chronometrique pour l'optimisation du temps de reponse des executifs SynDEx Rapport INRIA a para^tre 14