Académique Documents
Professionnel Documents
Culture Documents
Ouassila Labbani-Narsis
2 ouassila.labbani@u-bourgogne.fr
Introduction - Historique
Lustre est un langage de spécification particulièrement
adapté pour la conception des systèmes de contrôle-
commande temps réel
⚫ Début de sa conception en 1984 dans le Laboratoire
de recherche VERIMAG à Grenoble (P. Caspi & N. Halbwachs)
⚫ Langage de programmation formel
⚫ But : simplifier et automatiser l’implémentation de
lois de commandes
⚫ Origine : notation graphique permettant la
représentation de circuits logiques en automatique
⚫ Coopération : informaticiens et automaticiens ont
mis la main à la pâte pour formaliser le tout...
2
Approche flot de données
⚫ Lustre travaille sur des flots de données
⚫ Si X est une variable Lustre, alors elle désigne le flot
X =(x1,x2,...), xn étant la valeur de x à l’instant n
Exemple :
3
Approche flot de données
L’approche flot de données consiste à représenter un
programme par un graphe où les noeuds sont des
opérateurs qui transforment des flots de données
Exemple:
Interprétation synchrone :
4
Avantages de l’approche flot de
données
1. Approche fonctionnelle qui possède toutes les
propriétés mathématiques associés et en
particulier :
L’absence d’effets de bord
➔ absence d’ordre dans l’écriture des instructions
➔ cela facilite la vérification, la réutilisation et la
transformation de programmes
7
Système d’équations
déterministes
La résolution d’un système d’équations en
mathématique aboutit à trois types de solutions
possibles :
8
Système d’équations
déterministes
⚫ Afin d’ écrire uniquement des systèmes déterministes
(une seule solution...), Lustre n’accepte que les
systèmes d’équations de la forme :
9
Système d’équations
déterministes
⚫ Une équation définit une égalité mathématique, pas
une affectation : un flot peut être remplacé par sa
définition dans toutes les équations du nœud
signifie :
pour tout n 0, Xn = Yn + Zn et Zn = Un
10
Programme Lustre
⚫ Un programme Lustre définit un réseau de
composants travaillant sur des flots. En Lustre il
est possible de définir ses propres composants, on les
appelle nœuds
⚫ Un programme Lustre consiste en un noeud principal
et éventuellement d’autres noeuds auxiliaires
⚫ On appelle prototype du noeud la déclaration des
flots d’entrées et de sorties du noeud. Ces flots
doivent être typés
⚫ Des flots internes peuvent être définis
⚫ Le corps d’un noeud contient les équations
définissant les flots de sorties et internes en fonction
des flots d’entrées
11
Programme Lustre
Schéma représentant un programme Lustre
12
Structure d’un programme Lustre
13
Exemple d’un programme Lustre
14
Les types de données
Les types de base
⚫ booléen (bool), entier (int), flottant (real)
Les constantes
⚫ 2 ≡ 2, 2, 2, 2, ...
⚫ 1.0 ≡ 1.0, 1.0, 1.0, 1.0, …
⚫ true ≡ true, true, true, true, ...
Les tableaux
⚫ int^ 3, (real^ 5)^ 2, [int, bool, [int,real]] , ...
Remarque :
En vue de tenir l’hypothèse de synchronisme fort le
langage ne contient aucune structure qui pourrait
rendre non borné le temps de calcul (fonctions
récursives, types récursifs, les boucles, etc...) 15
Les opérateurs classiques
Les opérateurs “point à point”
⚫ Opérateurs arithmétiques et logiques classiques
X ≡ x0, x1, x2, x3 , … Y ≡ y0, y1, y2, y3 , …
X + Y ≡ x0 + y0 , x1 + y1 , x2 + y2 , x3 + y3 , …
Les opérateurs arithmétiques
⚫ Binaire : +, -, *, div, mod, /
⚫ Unaire : -
Les opérateurs logiques
⚫ Binaire : or, xor, and, =>
⚫ Unaire : not
Exécution :
17
L’opérateur if-then-else
⚫ L’opérateur de contrôle : if-then-else peut se
traduire par “quand-alors-sinon”
Exemple :
Erreur classique :
19
Contraintes logicielles
⚫ Temps-réel : par hypothèse synchrone le
système réagit suffisamment rapidement
21
Correction : Addition et
Soustraction de flot d’entiers
22
Un autre exercice …
Écrire un programme Lustre qui prend en entrée
un flot réel E, en sortie deux flots : un flot de
sortie booléen B qui devient vrai quand l’entrée
dépasse 100 et un flot de sortie réel S qui renvoie
0 quand B est faux et qui renvoie la différence E -
100 quand B est vrai
23
Correction …
node diff(E:real)returns(B:bool;S:real);
let
B = E>100.0 ;
S = if B then 0.0 else E-100.0 ;
tel
24
Les flots de données et les
horloges
25
Les flots de données et les
horloges
26
Les flots de données et les
horloges
Remarques :
⚫ Une horloge est un flot elle possède une horloge
et ainsi de suite... jusqu’à l’horloge de base
⚫ Tout flot booléen définit une nouvelle horloge
➔ La suite des instants où le flot vaut true
32
Exemple1 : Détection des fronts
montants
Exécution :
33
Exemple2 : Minimum et
maximum d’une séquence
Exécution :
Définitions incorrectes :
⚫ X = 1 / (2 - X);
⚫ Il y a bien une unique solution : X = 1
⚫ MAIS pas constructible pas-à-pas
⚫ Refusée par le(s) compilateur(s)
Exemple :
36
Échantillonnage : opérateur when
Exemple :
⚫ Soit B un flot booléen, soit X un flot de type T
38
Projection : opérateur current
X 4 -1 3 0 2 7 8
C vrai faux faux vrai vrai faux vrai
Y = X when C 4 - - 0 2 - 8
Z = current(Y) 4 4 4 0 2 2 8
current(X when C) ≠ X
39
Projection : opérateur current
Exemple :
⚫ Soit X un flot semi-continu de type T when B,
⚫ Soit Y un flot de type T
⚫ L’équation Y = current X définit un flot Y de
type T égale à X quand X est définie, égale à la
dernière valeur définie de X quand X est indéfinie, ou
nil s’il n’y a pas de dernière valeur
40
Sous-échantillonnage
⚫ On peut sous-échantillonner un flot déjà échantillonné
⚫ X when C correct X et C ont la même horloge
⚫ current projette sur l’horloge immédiatement plus
rapide
41
Noeuds et horloges
⚫ Horloge effective d’une instance de noeud =
l’horloge de ses paramètres effectifs d’entrée
42
Calcul d'horloges
⚫ L'exécution d'un programme Lustre est une
évaluation paresseuse
43
Calcul d'horloges
But :
Attribuer statiquement à chaque flot une horloge
unique
node Moyenne(…)
…
46
Exemple de noeud “multi-
horloges”
node MultiHorloge(X, Y : int; C : bool; horloge de base
(Z : int) when C horloge d’interface)
returns (S : int) when C horloge d’interface);
⚫ Types tableaux
bool^4
int^n avec n constante
(real^4)^8
...
Mais …
un programme Lustre doit s'exécuter en temps
et espace borné. Les dimensions et indices des
tableaux doivent donc être statiques et connus à
la compilation
48
Les tableaux
⚫ Exemple :
node Tdelay (const d:int; x:bool) returns (y:bool);
var A : bool^(d+1);
let
A[0] = X;
A[1..d] = false^d -> pre(A[0..d-1]);
Y = A[d];
tel
50
Exemple d’un programme Lustre
node MUX (M:int) returns (C:bool; Y:int);
var (X:int) when C;
let
Y = if C then current (X) else pre (Y) - 1;
C = true -> (pre (Y) = 0);
X = M when C;
tel
Exemple d’exécution du nœud MUX :
51
Exercice 1 …
Le but est de réaliser un noeud qui cumule les
données d’entrées ...
Soit X un flot d’entrées entier
Soit Y un flot de sorties entier
(Y1,Y2,Y3,...) = (X1,X1+X2,X1+X2+X3,...)
Prototype du noeud :
node CumSum(X :int) returns (Y :int) ;
(Y1,Y2,Y3,...) = (X1,X1+X2,X1+X2+X3,...)
54
Correction : un compteur
⚫ Soit RAS (remise à zéro) un flot d’entrées booléen
⚫ Soit N un flot de sorties entier
⚫ A chaque instant le flot de sortie N s’incrémente
de 1, quand RAS est vrai N revient à zéro
55
Utilisation du noeud Compteur
node dec(RAZ :bool) returns(N :int) ;
let
N = -compteur(RAZ) ;
tel
node IncDec(RAZ,ID :bool) returns(N :int) ;
let
N = if ID then compteur(RAZ) else dec(RAZ);
tel
56
Exemple d’un compteur
intermitant : when et current
Soit RAZ et B deux flots d’entrées booléens, N un flot
de sorties entier. Quand B est vrai le compteur
incrémente la sortie N
node compteurCond(RAZ,B :bool)returns(N :int);
let
N = current(compteur(RAZ when B)) ;
tel
57
Exemple d’un compteur
intermitant : when et current
Exécution :
node compteurCond(RAZ,B :bool)returns(N :int);
let
N = current(compteur(RAZ when B)) ;
tel
58
Exemple d’un compteur
intermitant : when et current
Exécution :
node compteurCond(RAZ,B :bool)returns(N :int);
let
N = current(compteur(RAZ when B)) ;
tel
59
Exemple d’un compteur
intermitant : when et current
Exécution :
node compteurCond(RAZ,B :bool)returns(N :int);
let
N = current(compteur(RAZ when B)) ;
tel
60
Exemple d’un compteur
intermitant : when et current
Exécution :
node compteurCond(RAZ,B :bool)returns(N :int);
let
N = current(compteur(RAZ when B)) ;
tel
61
Exemple d’un compteur
intermitant : when et current
Exécution :
node compteurCond(RAZ,B :bool)returns(N :int);
let
N = current(compteur(RAZ when B)) ;
tel
62
Exemple d’un compteur
intermitant : when et current
Exécution :
node compteurCond(RAZ,B :bool)returns(N :int);
let
N = current(compteur(RAZ when B)) ;
tel
63
Exemple d’un compteur
intermitant : when et current
Exécution :
node compteurCond(RAZ,B :bool)returns(N :int);
let
N = current(compteur(RAZ when B)) ;
tel
64
Exemple d’un compteur
intermitant : when et current
Exécution :
node compteurCond(RAZ,B :bool)returns(N :int);
let
N = current(compteur(RAZ when B)) ;
tel
65
Exemple d’un compteur
intermitant : when et current
Exécution :
node compteurCond(RAZ,B :bool)returns(N :int);
let
N = current(compteur(RAZ when B)) ;
tel
66
Exemple d’un compteur
intermitant : when et current
Exécution :
node compteurCond(RAZ,B :bool)returns(N :int);
let
N = current(compteur(RAZ when B)) ;
tel
67
Exemple d’un compteur
intermitant : when et current
Exécution :
node compteurCond(RAZ,B :bool)returns(N :int);
let
N = current(compteur(RAZ when B)) ;
tel
68
Remarque …
69
Erreur classique :
défaut d’initialisation
70
Remarques
⚫ f(x when c) ≠ f (x) when c
⚫ current (x when c) ≠ x
Exemple :
node somme(i:int) returns (s:int);
let
s = i -> pre s + i
tel
71
Autres exemples …
⚫ Détection de fronts montants
Soit X un flot d'entrée booléen
Soit Y un flot de sortie booléen
node EDGE (X : bool) returns (Y : bool) ;
let
Y = X -> (X and not pre(X));
tel
pre
→ Y
X Horloge
Y 72
Autres exemples …
⚫ Détection de fronts descendants
Réutilisation du nœud EDGE
node Falling_EDGE (X : bool) returns (Y : bool) ;
let
Y = EDGE(not X);
tel X EDGE Y
X Horloge
Not X Horloge
Y Horloge
73
Autres exemples …
⚫ Un « switch »
Soient set et reset des flots d'entrée booléen
Soit level un flot de sortie booléen
node SWITCH (reset,set : bool) returns (level : bool);
let
level = true -> if set and not pre(level)
then true else if reset then false
else pre(level);
tel P1
reset
false
Exemple : Un bouton-poussoir
BOUTON = → level
true
SWITCH (change, change);
pre true
set
74
Mémo Récapitulatif
75
Mémo Récapitulatif
76
Mémo : Utilisation de Lustre
Un programme Lustre possède l’extension .lus. Nous noterons
prog pour désigner le nom d’un programme et NOEUD pour
désigner le nom d’un noeud définit dans ce même programme
poc NOEUD.oc
ou
ec2c NOEUD.oc
Minimalisation de l’Automate :