• Aucun résultat trouvé

4.3 Génération de composants intergiciel adaptés

5.1.2 Méta-modèle du processus

Pour mettre en place le processus de raffinement incrémental, nous définissons un méta-modèle de chaîne de raffinement en partie représenté par la figure 5.2. Nous décrivons celui-ci dans les paragraphes suivants.

La définition d’une chaîne de raffinement commence par la création d’un objet de type Work- flow. Le point d’entrée du processus est déterminé par l’utilisateur : validation préliminaire du

5.1. PROCESSUS D’ANALYSE ET DE TRANSFORMATION 55

FIGURE5.2 – Vue d’ensemble du méta-modèle de chaîne de raffinement

modèle initial, transformation... Dans ce cas, le méta-modèle définit le type générique Workflow- Element qui représente une étape du processus au sens général. Le point d’entrée est alors un élément de type WorkflowElement qui se décline en sous-types Transformation, AbstractAnalysis, Serializationpour la production d’une version textuelle du modèle raffiné, ou Generation pour la génération de code exécutable final. Nous citerons également le type Loop qui modélise de façon plus compacte l’utilisation de stratégies de transformations alternatives à une étape du raffinement donnée. Nous décrivons chacune de ces étapes dans les paragraphes suivants.

Transformation Afin de répondre à l’objectif no1, le raffinement du modèle est réalisé lors d’é-

tapes de type Transformation. Chacune produit un modèle raffiné dans le même formalisme que le modèle source. Nous nous sommes inspirés du travail réalisé dans [59] pour obtenir des modèles d’implémentation proches du code généré. Pour répondre à l’objectif no2, chaque étape de trans-

formation spécifie les modules qui la composent, ceux-ci facilitant l’adaptation et la réutilisation de transformations. Pour chaque module, l’utilisateur renseigne le chemin vers celui-ci (attribut path). Par exemple, si deux stratégies alternatives de raffinement partagent une certaine logique, alors on l’isole dans un premier module common, et l’on définit les spécificités de chaque alternative dans les modules strategy1 et strategy2. Ainsi, selon la stratégie choisie, l’étape de transformation sera constituée des modules (common, strategy1) ou (common, strategy2). Pour faciliter l’identification des modules à utiliser, ceux-ci sont répartis par catégorie en fonction de l’objectif du raffinement et de la dépendance (ou non) à une plate-forme donnée. Par ailleurs, l’objectif no4 est la capacité

à modifier la stratégie du processus de raffinement. Dans un tel cas, le processus ignore le dernier modèle raffiné (qui a été invalidé) pour appliquer un raffinement alternatif à un modèle antérieur.

Pour retrouver le modèle antérieur, chaque modèle raffiné issu d’une transformation est associé à un identifiant outputModelIdentifier. Chaque transformation spécifie alors un attribut inputMod- elIdentifierpour déterminer le modèle à raffiner. Si aucune des stratégies de raffinement n’a été validée pour un élément particulier de l’architecture, cela signifie soit que le processus est dans l’incapacité à produire un code qui respecte les contraintes du système, soit que la combinaison des choix de raffinements précédents ont conduit à une violation des contraintes. L’utilisateur va spécifier soit une étape de type ErrorState stoppant le processus en indiquant la cause, soit une autre chaîne de raffinement sur des éléments précédemment raffinés. Le processus conserve ainsi une trace des modèles produits pour modifier la stratégie courante en repartant d’un modèle inter- médiaire. Une autre solution serait de conserver les différences entre chaque modèle intermédiaire et le modèle final afin d’économiser de la mémoire. Nous n’avons actuellement pas expérimenté cette solution. Par conséquent nous conservons l’intégralité de chaque modèle intermédiaire.

AbstractAnalysis Pour répondre à l’objectif no3, à chaque transformation va éventuellement

succéder une analyse évaluant l’impact du raffinement sur les performances du système. Le type AbstractAnalysis modélise une étape d’analyse générique. Celle-ci se décline en Analysis pour une unique analyse associée à une transformation ou en AnalysisSequence pour une succession d’analyses : on distingue les sous-types Conjunction et Disjunction qui indiquent que l’ensem- ble des analyses doit être validé, ou au contraire qu’une unique analyse de la séquence doit être validée, pour que la transformation soit considérée valide. On connecte l’attribut element d’un objet Transformation à un objet héritant de AbstractAnalysis. Par exemple, après un raffinement de la spécification métier d’une tâche et une réévaluation de son WCET, on réalise une analyse d’ordonnancement pour évaluer l’impact de cette nouvelle estimation. Une étape d’analyse spé- cifie alors l’identifiant de l’outil de validation que l’on souhaite utiliser (attribut method). L’outil doit être préalablement enregistré dans le processus avec un identifiant unique. Il peut s’agir d’un outil externe existant (e.g. Cheddar, AADLInspector, Bound-T) ou interne au processus (analyse de WCET à partir de modèles). Chaque analyse fournit des résultats normalisés selon le méta- modèle illustré par la figure 5.3 dans le but d’assurer une intégration et une compatibilité au sein du processus.

FIGURE5.3 – Méta-modèle de chaîne de raffinement : normalisation des résultats d’analyse

L’ensemble des résultats d’une analyse sont modélisés par des objets de type AnalysisResult re- groupés dans un objet de type AnalysisArtifact. On distingue deux types de résultat : qualitatif ou quantitatif. Dans le premier cas, il s’agit d’une réponse binaire à un test (le test a t-il réussi ?). Dans le second cas, le résultat indique une marge par rapport à une propriété particulière : par exemple, la marge entre l’échéance d’une tâche et son pire temps de réponse. Dans la première situation,

5.1. PROCESSUS D’ANALYSE ET DE TRANSFORMATION 57

le résultat d’analyse suffit pour déterminer si le raffinement actuel est approprié. Dans la seconde, l’utilisateur va potentiellement décider si le raffinement est approprié en se basant sur les marges affichées. On spécifie alors pour chaque analyse, le mode d’exécution (automatique ou manuel) qui détermine si l’utilisateur doit intervenir dans le processus décisionnel. Afin de retracer chaque analyse, les résultats s’accompagnent d’un objet de type AnalysisSource qui indique notamment les éléments du modèle qui ont été analysés, avec quel outil/méthode (attribut method). Chaque analyse doit influencer le déroulement du processus afin de répondre à l’objectif no4. Pour cela,

après chaque étape AbstractAnalysis, le processus se divise en deux branches. La branche sélec- tionnée dépend du résultat d’analyse (selon si l’analyse réussie ou échoue). Ces deux branches correspondent aux attributs validOption et invalidOption de l’objet AbstractAnalysis. Ainsi, dans le cas où l’analyse échoue, on modélise un changement de stratégie en reliant l’attribut invalidOp- tionà une nouvelle étape de transformation. Dans le cas où l’analyse réussie, l’objet connecté à l’attribut validOption correspond alors à la prochaine étape du processus.

FIGURE5.4 – Modélisation partielle de deux processus : l’un définit deux raffinements successifs,

le second définit deux raffinements alternatifs

La modélisation de raffinements successifs ou alternatifs est déterminée par l’enchaînement d’étapes de type Analysis et Transformation. Cela est illustré par la figure 5.4. Celle-ci donne un exemple de deux processus. Celui du haut définit deux raffinements successifs. L’attribut input- ModelIdentifierdu second raffinement correspond à l’attribut outputModelIdentifier du premier. Cela signifie que le second raffinement s’applique sur le modèle raffiné issu du premier. Le pro- cessus du bas défini deux raffinements alternatifs. Après le premier raffinement, une analyse est effectuée. Si l’analyse échoue (branche invalidOption), un raffinement alternatif est réalisé. Dans ce cas, l’identifiant inputModelIdentifier des deux raffinements a la même valeur. Cela signifie que le modèle d’entrée des deux raffinements est le même (le premier modèle raffiné n’est pas pris en compte).

Loop En chaînant les étapes Transformation et Analysis on modélise ainsi le choix d’une stratégie parmi un ensemble de stratégies alternatives. Cependant, cette modélisation complexifie consid- érablement la modélisation du processus lorsque que celui-ci réalise des choix stratégiques sur

des éléments différents de l’architecture (e.g. communication entre tâches, communication entre noeuds, synchronisation). Pour améliorer la lisibilité du modèle, nous définissons le type Loop qui est équivalent à une chaîne d’étapes de raffinements alternatifs. Un objet de type Loop est asso- cié à une liste de stratégies alternatives de raffinement (chacune étant modélisée par une liste de modules) qui sont évaluées les unes après les autres jusqu’à obtenir une stratégie valide. Toutes les stratégies associées à l’objet Loop sont validées par la même analyse associée à cet objet. La branche validOption de cette analyse correspond au cas où l’une des stratégies a été validée. Cet attribut indique la prochaine étape du processus dans ce cas. La branche invalidOption correspond au cas où aucune des stratégies alternatives n’a été validée : cela signifie qu’aucun raffinement n’est valide pour un élément de l’architecture. Cette branche est alors soit associée à un objet de type ErrorState soit à toute autre étape annulant un ensemble de raffinements précédents (en repartant d’un modèle intermédiaire).

Serialization La sérialisation est la sauvegarde d’un modèle raffiné en le traduisant en version textuelle. L’ensemble du modèle raffiné est sauvegardé afin d’éventuellement le réutiliser et l’- analyser dans un autre processus, notamment pour la certification (objectif no5). L’étape de Se-

rialization indique alors l’identifiant du modèle à sauvegarder (attribut outputModelIdentifier). L’utilisateur spécifie à quels moments du processus le modèle raffiné doit être sauvegardé. La séri- alisation est explicitée par l’utilisateur. Ainsi, une étape Serialization succède à une étape de type Transformationou Analysis.

Generation La génération de code est l’étape finale du processus et consiste à traduire le modèle raffiné en code exécutable (objectif no6). Le générateur est sélectionné en fonction de la plate-

forme d’exécution ciblée spécifiée à la configuration. Celui-ci traduit le modèle raffiné en langage cible et n’introduit aucune ressource supplémentaire non modélisée de manière à garantir la co- hérence du processus. Chaque générateur agit de façon similaire à un pretty-printer et cela a déjà été expérimenté dans [59]. Dans notre cas, nous fournissons des générateurs de code pour des plates-formes ARINC653, POSIX, OSEK et Ada Ravenscar.

Nous avons introduit le méta-modèle qui modélise des processus de raffinement incrémental. En particulier, chaque étape de type Transformation, modélisant un raffinement, est définie à par- tir d’une liste de modules de transformations afin de réaliser l’adaptation de la transformation en répondant ainsi à la problématique de l’adaptabilité du processus de génération (abordée en section 5.2). Nous nous appuyons pour cela sur la technique existante de superimposition qui est introduite dans la section suivante.