• Aucun résultat trouvé

2.2 Analyse statique pour le WCET

2.2.3 La méthode IPET pour le WCET

L’Énumeration Implicite des Chemins ou Implicit Path Enumeration Technique (IPET) [64, 84] est une méthode numérique pour estimer le WCET d’un programme à partir d’un CFG. Chaque bloc de base b ∈ V est annoté par un temps tbcorrespondant à

son temps d’exécution maximum, et par un entier naturel xb correspondant au nombre

d’exécutions maximum de ce bloc. Le but est d’obtenir dans un premier temps un système de contraintes numériques entières modélisant le flot du programme, puis de chercher le maximum possible de la somme des temps d’exécution tb de chaque bloc b

fonction objectif

X

b∈V

xbtb

pour obtenir une surestimation du WCET. Si cette technique ne permet pas d’identifier le WCEP, elle nous permet toutefois d’obtenir un surensemble de chemins le contenant.

2.2.3.1 Évaluation du temps d’exécution d’une instruction

L’estimation du temps maximum pris pour l’exécution de chaque instruction du pro- gramme est à première vue une tâche assez simple pour des systèmes critiques : nous pouvons nous appuyer sur les renseignements du manuel d’instruction du constructeur pour évaluer cette borne supérieure. Il suffirait donc d’extraire ces informations pour calculer automatiquement le temps d’exécution maximal d’un bloc de base. En pra- tique, l’architecture d’un système est en beaucoup trop complexe pour être modélisée fidèlement, en particulier pour des machines modernes. Les processeurs sont souvent aidés par plusieurs couches de mémoire cache, et les mécanismes qui dictent les po- litiques d’éviction dans ces caches rendent souvent l’état du système à un point du programme difficile à prévoir. C’est sans compter les problèmes de pipeline (l’exécu- tion des instructions se chevauche), de prédiction de branchement, d’ordonnancement, etc.

De très nombreuses techniques [6, 38, 72, 40] existent pour la modélisation d’archi- tectures plus ou moins complexes [81]. Plutôt que de chercher à modéliser exactement l’état du système à tout moment, des approximations conservatives sont faites. Ainsi, une approche naïve pour prendre en compte les temps d’accès aux caches est de consi- dérer tous les accès comme des miss. Cette approche, sauf en présence d’anomalies temporelles2 [48], ne met pas en danger la validité du WCET obtenu, mais elle produit

un WCET très surestimé. Le sujet des caches est largement traité dans la littérature ; souvent, afin de modéliser plus précisément les effets de cache, les points d’accès à la mémoire sont classifiées selon des catégories [40] : always hit, always miss, persistent (la donnée reste dans le cache une fois chargée, et ne cause donc qu’un seul miss), ou not classified (on considérera le pire-cas, soit always miss). Il est ensuite aisé de déduire de cette catégorisation les pénalités de temps d’accès à appliquer.

2. Les anomalies temporelles sont des comportements contre-intuitifs du programme où un scénario d’exécution peut avoir un temps d’exécution localement faible mais majorer le WCET du programme entier.

Une fois le temps d’exécution pire-cas de chaque instruction déterminé (ou plutôt, surestimé), les contraintes correspondantes sont générées. Par exemple, si le bloc b est garanti s’exécuter en au plus 140 cycles, la contrainte tb = 140 apparaît.

2.2.3.2 Système de contraintes numériques de flot

La génération du système de contraintes représentant les informations de flot issues du CFG se base sur le principe de la loi des nœuds. Pour l’énoncer, chaque arc e du CFG sera également également annoté par un compteur xe.

Théorème 2.1. Pour tout bloc du CFG, le nombre d’exécutions de ce bloc est égal

à la somme du nombre d’exécutions de chaque arc y entrant, et à la somme du nombre d’exécutions de chaque arc en sortant.

Si G = (V, E, , ω) est un CFG, alors ∀v ∈ V, X v0∈V, (v→v0)∈E xv→v0 = xv = X v0∈V, (v0→v)∈E xv0→v

Il est naturel que, pour chaque exécution du programme, le bloc d’entrée  et le bloc de sortie ω du CFG soient chacun exécutés exactement une fois.

x= xω = 1

Nous cherchons maintenant une technique pour encoder ces contraintes et maximi- ser le temps d’exécution représenté par la fonction objectif P

bxb.tb. Ce problème est

efficacement traité par la méthodologie de Programmation Linéaire en Nombres Entiers (PLNE) ou Integer Linear Programming (ILP) [27]. Différents outils apportent déjà une solution à ce problème, comme lp-solve [15], opbdp [13], ou encore l’optimiseur com- mercial d’IBM, CPLEX [33]. Une fois toutes les contraintes injectées, la maximisation de la fonction objectif donne une surestimation du WCET.

Les contraintes ainsi générées ne suffisent cependant pas pour des programmes avec boucles ; le WCET ainsi obtenu sera toujours infini, correspondant au cas d’exécution où le programme reste dans une boucle à l’infini. Il faut donc rajouter des contraintes correspondant à des bornes de boucles : il s’agit de donner le maximum d’itérations de chaque boucle du programme.

La Figure 2.6 illustre cette méthode en faisant la liste des contraintes de flot de données caractérisant un CFG. v1 v2 v4 v5 v6 v8 v3 v9 v10 v7 v11  ω (a) CFG x→1 = x1 = x1→2 + x1→3 x1→2 = x2 = x2→4 x1→3+ x9→3 = x3 = x3→8 x2→4 = x4 = x4→5 + x4→6 x4→5 = x5 = x5→7 x4→6 = x6 = x6→7 x5→7+ x6→7 = x7 = x7→11 x3→8 = x8 = x8→9 x8→9 = x9 = x9→3 + x9→10 x9→10 = x10 = x10→11 x9→10+ x10→11 = x11 = x11→ω

(b) Contraintes d’arc dérivées de la loi des nœuds

x→1 = x = 1

x11→ω = xω = 1

x9→3 ≤10

(c) Contraintes de flot supplémentaires

WCET = max

x1t1+x2t2+x3t3+x4t4+x5t5

+ x6t6+ x7t7+ x8t8+ x9t9+ x10t10+ x11t11 

(d) Fonction objectif

Figure 2.6 – Exemple de système de contraintes extrait d’un CFG

2.2.3.3 Obtention des bornes de boucles

Il est critique dans le cadre de l’évaluation du WCET de pouvoir borner toutes les boucles d’un programme, sans quoi, le nombre de chemins d’un programme est infini.

Les bornes de boucles peuvent être obtenues de deux manières : manuellement, par annotation d’un expert, ou automatiquement, par détection à partir du code. Diverses techniques efficaces permettent la dérivation de bornes de boucles à partir de code source [19, 66, 88, 69], mais il est difficile de faire la correspondance de manière fiable

avec le code binaire, en particulier en présence d’optimisations du compilateur [62]. D’autres méthodes peuvent obtenir automatiquement des bornes de boucles sur le code binaire, comme par exemple celle de Cullmann et Martin [34]. Cette technique, implémentée dans l’outil aiT [101] et adaptée à de nombreuses architectures, semble donner de bons résultats sur des programmes de taille raisonnable. L’outil SWEET permet également la détection de bornes de boucles sur le code binaire [47], mais s’appuie sur des informations issues du compilateur (et en reste donc dépendant). Enfin, il existe des approches visant à valider des bornes de boucles obtenues sur le source sur du code binaire décompilé [97].