• Aucun résultat trouvé

Nous avons expérimenté l’ordonnanceur présenté sur plusieurs circuits de taille réelle dépassant les 5000 blocs. L’outil élémentaire associé est l’ordonnan- ceur officiel distribué avec la version libre du générateur de code GeneAuto. Nous présentons ici une application automobile étudiée parmi plusieurs.

6.6.1

Cas d’étude : Contrôleur automobile

Il s’agit d’un système de contrôle automobile issu du système de régulation moteur de Continental Automobile. Ce cas d’étude est un extrait d’un système développé au sein de Continental. Il décrit la fonction de détection du cliquetis (Knock en anglais) dans un calculateur de contrôle moteur (gasoil pour ce sys- tème). Le cliquetis est décrit dans la figure6.27. Le circuit de ce cas d’étude est trop volumineux pour présenter son ordonnancement ici. Nous nous conten- tons de décrire ce système.

Le cliquetis est une inflammation spontanée et incontrôlée du mélange air- carburant. L’automobile dispose d’éléments pour détecter ce phénomène, il s’agit de capteurs de cliquetis associés à un logiciel de détection. Le capteur de cliquetis «Knock » détermine lorsque le carburant brûle dans le moteur de façon inégale en causant des vibrations irrégulières dans le moteur. Il se compose d’une bobine électrique qui est enroulée autour de deux tiges en cé- ramique avec un aimant dans le centre. Les vibrations du moteur provoquent la vibration des tiges. Cela perturbe le champ magnétique de la bobine et mo- difie le courant traversant la bobine. Cette perturbation se traduit par un signal particulier qui peut être analysé pour déterminer si les vibrations sont caracté- ristiques de cliquetis du moteur.

Le circuit correspondant au cliquetis est illustré dans la figure6.28. Il com- bine des flots de données et de contrôle. Les signaux de contrôle sont repré- sentés par des fils discontinus. Le circuit Simulink entier est composé de 9 couches hiérarchiques. Ce circuit contient plus de 5790 blocs (en comptant les sous-systèmes, les blocs atomiques ainsi que les ports enable/trigger). L’or- donnancement de la totalité du circuit automobile dure une seconde. Tandis

Fig. 6.27 – Dégâts du moteur causés par le cliquetis ADAPTIVE 3 DD 2 GAIN_OUT 1 operation1 In1 In2 Out1 operation In1 In2 Out1 init fcn_call() Out1 if_then_else1 cond_if cond_if1 trig_subsys_1 trig_subsys_2 trig_subsys_3 trig_subsys_4 > READARRAY READ ARRAY C0 [..] Merge mod LOOP_2 f() CC_M2 GAIN DD GAIN_OUT LOOP_1 SimMode:FXP f() CC_M2 ENGINE NN DD [CC_M2] [CC_M2] [CC_M2] [CC_M2] [CC_M2] Constant3 2 Constant1 0 Constant CYLINDER Adaptative Calculation f() In1 In2 In3 Out2 ADAPTIVE_IN 6 GAIN 5 NN 4 ENGINE 3 CC 2 ENA 1

Fig. 6.28 – Contrôleur d’un moteur automobile

que la génération de code globale qui utilise les outils élémentaire développés formellement dure moins de 18 secondes.

6.6.2

Autres cas d’études

Nos outils élémentaires ont été expérimentés avec différentes applications in- dustrielles de taille réelle [TIN+, RD]. Le générateur de code a été appliqué avec succès en incluant l’outil élémentaire ordonnanceur sur des cas d’études industriels critiques. Quelques exemples de cas d’études sont présentés dans la figure6.29.

Cas d’étude Blocs du circuit Profondeur

Satellite AOCS 1085 8

(Attitude and Orbit Control System)

Automotive power train software controler 5793 9 Airplane Flight Control System 2800 7 Satellite Agile Control System 1931 6

Sensor Networks 1108 7

Fig. 6.29 – Récapitulatif des tailles d’autres études de cas industriels

Blocs du circuit représente la taille du circuit étudié en termes de nombre de blocs considérés atomiques. Le nombre de niveaux hiérarchiques est représenté par l’entité Profondeur. Le coûts de l’outil élémentaire Ordonnanceur est com- parable au reste des outils élémentaires du générateur de code. Nous avons également appliqué l’ordonnanceur à un circuit particulier qui constitue un «pire cas» : un «pipeline» de 5000 blocs dans un seul niveau hiérarchique. Ce pire cas exécuté sur un processeur Core 2 Duo à 2.6 GHz de fréquence avec 2Go de RAM a duré 45 minutes. Nous avons vérifié avec nos partenaires industriels qu’il n’existait aucun circuit d’une telle longueur (le nombre de bloc le plus grand entre une entrée et une sortie dans un circuit déplié). La plupart des circuits ont une longueur inférieure à 100 avec une moyenne comprise entre 10 et 20 selon le type de circuits.

6.7

Synthèse

La spécification de l’ordonnanceur, le raffinement des exigences et la formali- sation des dépendances n’étaient pas des tâches simples. En effet, les exigences étaient ambiguës, incomplètes voire incohérentes.

Ceci est dû à la complexité du langage Simulink et à la forme de sa docu- mentation composée d’exemples et de contre exemples.

Nous avons spécifié formellement l’ordonnanceur à partir des exigences et avons implanté l’ordonnanceur en nous appuyant sur les dépendances évé- nementielles d’entrée et de sortie. Cette implantation permet de prendre en compte tout type de circuit combinant les flots de données et de contrôle. Les équations de dépendances proposées expriment naturellement les événements liés aux blocs qui doivent se produire avant d’exécuter un bloc. La construction de cet algorithme a été prouvée en démontrant les propriétés de monotonie des fonctions de propagation et de terminaison du calcul du point fixe. Le ré- sultat obtenu par l’algorithme est également validé en vérifiant la correction de l’ordre obtenu par rapport aux exigences sur les flots de données et de contrôle. En outre, la propriété de détection de boucles algébriques permet de valider également que les équations événementielles proposées sont complètes et que les fonctions de propagation transmettent bien les informations.

7

7.1

Motivation

Le typage est le second cas d’étude qui exploite le cadre général dans Ge- neAuto. Il s’agit d’un algorithme pour associer un type à chaque port des blocs d’un circuit Simulink donné en entrée du générateur de code.

Nous parlerons dans ce chapitre d’inférence de type [Mil78,DM82] au lieu de propagation de type. L’inférence de type, dans un circuit, permet de recher- cher automatiquement un type pour les ports des blocs qui le composent. Ceci est effectué à partir des informations données explicitement dans le circuit, des règles de typage des blocs ainsi que des règles de propagation des types dans le circuit.

Notre objectif à travers ce cas d’étude est, d’une part, d’assurer que les types calculés sont corrects par rapport à la nature des blocs et, d’autre part, de valider les types donnés par le concepteur du circuit.

L’inférence de type en Simulink est un mécanisme relativement simple à réaliser, notamment quand tous les types des signaux du circuit sont explicités par l’utilisateur. Tel est le cas des circuits communs à plusieurs partenaires industriels car leurs calculateurs n’utilisent pas tous les types prédéfinis par Simulink, mais exploitent des types différents définis par les utilisateurs. Le concepteur du circuit fixe au préalable les types de tous les signaux pour mieux contrôler les types par lui-même. Dans ce cas, il ne s’agit plus d’inférence de type mais de vérification de types qui est réalisée en une seule étape sans propagation.

Soit le circuit illustré dans la figure 7.1. La sortie du bloc Constant est définie par l’utilisateur de type int32 [2] (tableau de deux entiers à 32 bits). L’inférence de type depuis l’entrée vers la sortie du circuit permet de déduire les types mentionnés dans la figure7.1. Par exemple, le bloc Add a une seule entrée de type int32 [2], sa sortie est donc un scalaire de type int32. Cela signifie que les types des ports définis par l’utilisateur doivent être au mini- mum, dans le système de types considéré, les types produits par inférence en avant.

int32 [ 2] int32 [ 2] int32 int32

Out 1 Constant

(13 10)

Add

Inversement, si l’entrée du bloc Out est spécifiée par l’utilisateur de type double (réel de 64 bits), alors l’inférence de type depuis la sortie du circuit vers son entrée produit les types annotés dans la figure 7.2. Par exemple, la sortie du bloc Add a le type double (déduit par inférence arrière), donc le type de son unique entrée est un vecteur double [ ]?. Cela signifie que le bloc Out doit lire, lors de son exécution, au maximum (dans le système de types considéré) une valeur de type double. Ainsi, les types des ports définis par l’utilisateur doivent être au maximum ceux produits par inférence en arrière.

double [ ] * double [ ]* double double Out

1 Constant

(13 10)

Add

Fig. 7.2 – Exemple d’inférence de type depuis les sorties vers les entrées

Le fait d’effectuer seulement l’inférence en avant impose à l’utilisateur de tester son circuit à chaque fois qu’il précise un type de port d’un bloc interne (hors les blocs source et cible des librairies respectives Source et Sink). Il en est de même pour l’inférence en arrière, ce qui devient vite fastidieux, notam- ment quand le circuit est de taille importante. Or, en pratique, les utilisateurs ont le libre choix de préciser ou non les types des ports (d’entrée et/ou de sortie) des blocs. Que ce soit en Simulink ou encore en GeneAuto, le circuit est respectivement simulé ou testé à chaque fois que l’utilisateur change les initialisations des types.

Dans le but d’offrir une solution générique, permettant de limiter certains des tests des circuits à chaque nouvelle initialisation des types, et de déterminer les contraintes de type des différents ports, nous proposons un algorithme pour typer les ports d’un circuit Simulink en effectuant deux inférences de type : une en avant et une en arrière. De plus, nous ne considérons les initialisations ou annotations de types, effectuées par les utilisateurs, que pour les blocs d’entrée et de sortie du circuit qui doivent être définis dans GeneAuto. Cela permet de prendre en compte un grand nombre d’alternatives de typage correct des ports du circuit, indépendamment des types des ports explicités autres que les ports des blocs source et cible.