Baniere Saphir Control
http://www.saphir-control.fr/

bar


BACK

Tous ces articles en ligne sur Scilab ont été écrits pour LINUX MAGAZINE FRANCE par les développeurs du Scilab Group. Les articles sont sous licence FDL (Free Documentation Licence)

De la compilation à la simulation



Dans l'article paru dans le numéro précédent nous avions vu comment fonctionne l'éditeur graphique de Scicos, dont l'utilisation permet, par de simples clics de souris, la construction de systèmes dynamiques sous forme de schéma-blocs. L'article présenté ici détaille les différentes étapes necéssaires, de la compilation à la simulation des schéma-blocs. Nous verrons dans un prochain article, le lien entre les étapes de la compilation et la génération automatique de code.

1   Introduction

Dans Scicos la modélisation se traduit par la représention sous forme de schéma-blocs de modèles de systèmes dynamiques. Le fonctionnement de ces modèles est obtenu par l'exécution de la simulation. Celle-ci permet, bien sûr, de calculer la solution du système dynamique modélisé, mais aussi d'autres opérations, comme par exemple la visualisation de signaux (bloc Scope ou MScope) ou l'enregistrement de leurs valeurs dans un fichier (bloc Writef). Ces valeurs pouvant ensuite être lues ( bloc Readf) ou ré-utilisées en post-processing dans Scilab. De la modélisation à la simulation il y a une phase importante que l'on appelle la compilation (cf. figure 1). La compilation consiste à coder les informations graphiques, architecturales et paramétriques d'un schéma-bloc et surtout à calculer l'ordre d'appel des blocs (ordonnancement) pendant la simulation. La compilation d'un schéma-bloc s'exécute, la première fois d'une manière complète, en deux étapes par les fonctions Scilab c_pass1 et c_pass2.



Figure 1: De la modélisation à la simulation

Nous verrons par la suite que lorsque des modifications sont apportées à postériori au schéma-bloc, selon le cas, la compilation peut être optimisée.

2   La compilation complète

Lorsqu'un un schéma-bloc est compilé pour la première fois, ce sont les fonctions c_pass1 et c_pass2 qui sont exécutées. Afin d'illustrer leur fonctionnement, nous considérons l'exemple de la figure 2, contenant 7 blocs.



Figure 2: Un système hybride.

2.1   La première étape de compilation

La fonction c_pass1 réalise la première étape de compilation complète, elle se trouve dans le fichier /macros/scicos/c_pass1.sci. Son rôle est d'assurer : La syntaxe de la fonction c_pass1 est : [blklst,cmat,ccmat,cor,corinv,ok]=c_pass1(scs_m,ksup). Ses entrées sont : Le résultat de la compilation est donné par les sorties de la fonction c_pass1 : ce sont la liste blklst, les matrices de connections des ports réguliers cmat et des ports d'activations ccmat, ainsi que les listes cor et corinv. cor est une liste dont la structure est identique à la liste scs_m . Chaque composante contient l'indice du bloc associé dans la liste blklst. La liste cor contient le chemin d'accès à la structure contenue dans scs_m, pour chaque numéro de bloc de la liste blklst. La liste corinv permet l'opération inverse de cor : à partir du numéro d'un bloc, on obtient son indice dans la structure principale scs_m.

2.1.1   La liste blklst

blklst est la liste contenant des données sur chaque bloc, blklst représente une liste de sous-listes. Dans notre schéma de 7 blocs, blklst contient 7 sous-listes. Chaque sous-liste correspond au champ model du bloc associé. A partir des renseignements contenus dans blklst, nous en déduisons la numérotation des blocs dans la figure 2.

2.1.2   La matrice cmat

cmat est la matrice de connections des ports réguliers. La première colonne indique le numéro de bloc dont le port de sortie régulier (numéroté dans la deuxième colonne) est connecté au bloc numéroté dans la troisième colonne, par son port d'entrée régulier (numéroté dans la quatrième colonne). Dans notre exemple nous avons :
cmat=[
Bloc amont Port sortie Bloc aval Port entree
5 1 4 1
5 1 2 1
7 1 6 1
2 1 1 1
]
où la deuxième ligne de la matrice indique que le port de sortie régulier numéro 1 du bloc numéro 5 est relié au port d'entrée régulier numéro 1 du bloc numéro 2.

2.1.3   La matrice ccmat

ccmat est la matrice de connections des ports d'activations, la première colonne indique le numéro de bloc dont le port de sortie d'activations (numéroté dans la deuxième colonne) est connecté au bloc numéroté dans la troisième colonne, par son port d'entrée d'activations (numéroté dans la quatrième colonne). Ce qui donne dans notre exemple :
ccmat=[
Bloc amont Port sortie Bloc aval Port entree
3 1 3 1
3 1 4 1
3 1 1 1
4 2 6 1
6 1 2 1
]
La première ligne, de la matrice indique que le port de sortie d'activation numéro 1 du bloc numéro 3 est relié à lui même. Il s'agit du bloc Clock qui, en réalité, est un super-bloc compilé, constitué d'un bloc Delay bouclé sur lui-même (cf. fig 3). C'est par une activation initialement programmée qui auto-active le bloc Delay dès qu'elle est générée, réalisant ainsi un générateur d'activations.

{short description of image}


Figure 3: Le bloc Clock.

2.2   La deuxième étape de compilation

L'architecture du schéma bloc étant codée, il s'agit maintenant, pour l'exécution de la simulation, de définir un ordonnancement des blocs en fonction de leurs interactions. Cette tâche est réalisée par la fonction c_pass2, dans le fichier /macros/scicos/c_pass2.sci. Pour définir l'ordonnancement c_pass2 exécute principalement quatres actions.

2.2.1   Garantir le traitement des blocs continus

Dans Scicos, l'activation des blocs continus est assurée par un unique bloc fictif générant un signal d'activation permanente. Cependant, comme nous le verrons par la suite (cf. procédure cossim ), dans la simulation l'aspect continu et discret ne sont pas traités de manière parallèle mais séquentielle. Ceci signifie que le bloc fictif génère un signal d'activation qui est toujours actif sauf aux instants d'occurrence des activations discrètes. Autrement dit, aux instants précis d'activations discrètes, pour lesquelles l'on traite la simulation du fonctionnement discret, le fonctionnement continu n'est pas assuré. Ceci pose donc un problème de garantie du fonctionnement des blocs activés en continu, pendant la phase d'activation des blocs discrets. C'est la raison pour laquelle la matrice ccmat doit être modifiée, puisque les blocs continus sont tous activés par chacune des sources d'activations discrètes présentes, ce qui correspond à des connections d'activations supplémentaires (cf. exemple de la figure 4).



Figure 4: Les modifications apportées à la figure 2

Cette étape garantissant le fonctionnement continu pendant les activations discrètes est assurée par la fonction Scilab pak_ersi qui se trouve dans le fichier c_pass2.sci.

2.2.2   Définir l'héritage des activations

Dans Scicos, lorsqu'un bloc ne possède pas de port d'entrée d'activation, il hérite de l'activation des signaux sur ses ports d'entrée régulière. L'héritage des activations est une facilité graphique dans Scicos qui évite de surcharger un schéma en liens d'activations : ils sont implicites. Cependant, pour la compilation, il faut que ces liens soient clairement définis, y compris ceux concernant l'activation du bloc fictif et gérés comme pour les autres blocs. L'héritage des activations est assuré, dans la fonction Scilab pak_ersi, en partie par la procédure tree4, qui détermine le graphe de dépendance des blocs héritants, de manière verticale (pour chaque liaison d'activation existante). Ces graphes de dépendance servent, dans la fonction pak_ersi (dans le fichier c_pass2.sci), à rajouter la liaison d'activation manquante sur chaque bloc héritant. Dans l'exemple de la figure 5, le bloc 4 est activé par héritage, c'est comme si on l'avait relié directement par une connection au bloc 1.

2.2.3   Uniformiser les types de blocs

Dans Scicos il existe quatre types de blocs (Standard, Synchro , Zcross, Memo), différents de par leur fonctionnement. La différence principale dans le conditionnement de ces types de blocs, concerne les blocs de type Synchro, pour lesquels les activations générées sont synchrones avec celles reçues. Un des aspect important de l'ordonnancement est la détermination, pour chaque activation (sur un port de sortie), de la liste des blocs à activer. Afin que la simulation soit performante en temps, cette liste doit être déterminée au moment de la compilation (une séquence fixe de numéro des blocs à activer), plutôt que pendant la phase de simulation une séquence variable de numéro des blocs à activer). Dans l'exemple de la figure 5, les activations sont générées uniquement par le port de sortie du bloc 1, et donne lieu à la séquence de mise à jour des blocs suivants : (bloc 2, bloc 3 et bloc 4).



Figure 5: Un exemple sans bloc Synchro

Pendant la compilation, on ne prend pas en compte la valeur du signal régulier à l'entrée du bloc. Pourtant, la séquence d'activation des blocs Synchro n'est pas fixe puisqu'elle dépend de la valeur du signal régulier de leur entrée. Dans l'exemple de la figure 2, lorsqu'une activation est générée par le bloc 3, les séquences liées à son port de sortie d'activations peuvent être (bloc 5, bloc 7, bloc 4, bloc 1), (bloc 5, bloc 7, bloc 4, bloc 6, bloc 1) ou (bloc 5, bloc 7, bloc 4, bloc 6, bloc 2, bloc 1) . Pour obtenir, pour chaque sortie d'activations, des séquences fixes de blocs à activer, nous devons transformer, pendant la phase de compilation, les blocs Synchro en blocs de type Standard, ceci dans le strict respect du conditionnement d'origine. Les activations en sortie d'un bloc Synchro étant exclusives, la modification est basée sur le principe que, pour un bloc Synchro, l'activation en entrée est équivalente à l'union des activations de sortie. La modification consiste à faire la somme (en guise d'union) des signaux d'activation de tous les ports de sortie du bloc Synchroif then else (cf. fig 6 et fig 7).



Figure 6: Avant modifications





Figure 7: Après modifications

Cette transformation est illustrée, pour notre exemple de la figure 2, par le schéma de la figure 8 où tous les blocs sont de type Standard. On peut constater que pour chaque sortie d'activations il y a une séquence fixe unique :



Figure 8: Les modifications sur les blocs Synchro pour la figure 4

Signalons néanmoins que la transformation des blocs Synchro en blocs Standard ne se résume pas simplement à faire des modifications sur les connections d'activations. En effet, dans le cas où un bloc Synchro est activé par la somme de plusieurs activations d'origine différente (cf. figure 9), il faut dupliquer le bloc pour permettre un nouveau routage des liens d'activations. Sur la figure 10, on peut voir que si l'on se contente de remplacer les connections comme nous l'avons vu précédemment, pour une activation générée via la connection ``B'', le bloc ``FOO'' est activé, contrairement à la configuration de la figure 9 ; le conditionnement qui résulte de cette transformation est différent du conditionnement initial. La solution pour résoudre ce problème consiste à dupliquer le bloc Synchro autant de fois que de connections d'activations (cf. figure 11).



Figure 9: Avant modifications des connections





Figure 10: Après modifications des connections





Figure 11: Après duplication du bloc et modifications des connections

Sans pour autant expliquer plus en détail la réelle complexité de la méthode itérative pour dupliquer les blocs Synchro, nous allons juste en donner un aperçu. Prenons, par exemple, le cas où le bloc ``FOO'' est lui aussi un bloc Synchro ... on voit bien la nécessité de le dupliquer, car il est conditionné par la somme de deux activations. Il faut donc effectuer une recherche dans l'arborescence du conditionnement des blocs Synchro pour déterminer quels sont les blocs à dupliquer ainsi que le routage des liens d'activations que cela implique. Ces étapes de transformation sont assurées par la fonction Scilab paksazi, dans le fichier c_pass2.sci.

2.2.4   Détermination des graphes de dépendance

Il s'agit de déterminer le graphe de dépendance des blocs associés à chaque sortie d'activation. En effet, un schéma bloc constitue un graphe d'ordre total, dans lequel la dépendance de conditionnement s'exprime suivant la nature des blocs, par des graphes d'ordre partiel. Ces graphes d'ordre partiel traduisent des arbres de dépendances et sont obtenus par des procédures (fortran), qui exécutent des algorithmes de calcul pour différents types d'informations : Bien entendu, ces arbres de dépendance prennent en compte (s'il y a lieu) de la dépendance directe de l'entrée des blocs sur leur sortie pour déterminer un ordre dans le conditionnement des blocs, en fonction de chaque sortie d'activation associée.



Figure 12: Un exemple simple de relation d'ordre entre les blocs

L'exemple simple de la figure 12 montre bien que le bloc ``D'' hérite (procédure tree4) de l'activation continue conditionnant le bloc ``A''. Pour une activation générée par le bloc fictif, la relation d'ordre des blocs associés (``A'' et ``D''), impose que le bloc ``A'' soit mis à jour avant (procédure tree2) le bloc ``D''. En revanche, pour une activation générée par le bloc ``H 1'', il n'y a pas de relation d'ordre stricte pour les blocs associés (``B'' et ``C''). La fonction scheduler établie, à l'aide des procédures tree2 et tree3 les tables d'ordonnancement des blocs : ordptr, ordclk, cord, iord, oord, zord (cf. tableau 1), qui définissent la relation d'ordre entre les blocs, associés à chaque sortie d'activation.

Noms Type  
des de Descriptif
tables fonctionnement  
iord activé à matrice à deux colonnes, la première indiquant les blocs
  l'initialisation générant une valeur constante, dépendant de cette constante
    (cf. Note) ou activés par le bloc fictif, la deuxième indiquant,
    par un codage binaire, le port par lequel le bloc est activé
cord continu matrice à deux colonnes, la première indiquant les blocs
    activés en continu par le bloc fictif, la deuxième indiquant,
  par un codage binaire, le port par lequel le bloc est activé
oord continu sous-ensemble de cord, c'est une matrice à deux colonnes :
    la première indiquant les blocs pour lesquels est calculée
    la dérivée de l'état continu, la deuxième indiquant
    par un codage binaire, le port par lequel le bloc est activé
zord continu sous-ensemble de cord, c'est une matrice à deux colonnes :
    la première indiquant les blocs dont la sortie affecte le calcul
    des surfaces traversée par zéro, la deuxième indiquant
    par un codage binaire, le port par lequel le bloc est activé
ordptr par activation vecteur de pointeurs vers la matrice ordclk, indiquant la partie
    de la matrice ordclk correspondant à chaque source d'activation
ordclk par activation matrice à deux colonnes, la première indiquant les blocs à mettre
    à jour, selon l'activation pointée par ordptr, la deuxième indiquant,
    par un codage binaire, le port par lequel le bloc est activé.


Table 1: Les tables d'ordonnancement pour la mise à jour des blocs


Note concernant iord (dans le tableau 1) :
Les blocs qui génèrent une valeur constante sont définis comme n'ayant ni entrée régulière, ni entrée d'activation, ni sortie d'activation, et ne sont pas déclarés activés en continu. On considère que ces blocs sont activés par un seul événement fictif lors de l'initialisation ou au re-démarrage de la phase de simulation. Un statut particulier à été défini pour ces blocs, pour éviter de re-calculer leurs mises à jour inutilement pendant la simulation. Il en va de même pour les blocs qui dépendent de générateur de constante (cf. figure 13) : ce qui met en évidence un certain nombre de blocs à activer et dans un ordre précis.

{short description of image}


Figure 13: Le bloc sin dépend d'une valeur constante.





Figure 14: Un autre système hybride.

Concrètement, avec l'exemple du schéma de la figure 14, les informations contenues dans ces tables indiquent :
iord=[
3 0
4 0
6 2
]
Les blocs 3 et 4 sont activés en permanence (par le bloc fictif). Le port d'entrée numéro 2 du bloc 6 hérite de la sortie du bloc 3. Et pour les mêmes raisons, nous avons :
cord=[
3 0
4 0
6 2
]
oord=[
3 0
4 0
6 2
]
La matrice zord est vide, puisque le schéma bloc ne contient pas de bloc de type ``z''.
ordptr=[
1
7
]
Notre exemple contient deux sources d'activation : le bloc fictif (qui active les blocs continus sinusoid generator et 1/s) et la source d'activation discrète. Le vecteur ordptr est composé de deux valeurs qui pointent la zone affectée par la source d'activation discrète de la matrice ordclk (de la ligne 1 à la ligne 7). Les blocs contenus dans cette zone sont activés par la source d'activation discrète.
ordclk=[
2 1
3 0
4 0
5 1
1 1
6 3
]
La première ligne de ordclk indique que la sortie du bloc 2 est reliée à son entrée. Les deuxième et troisième lignes concernent le synchronisme du bloc fictif avec le bloc 2. Ainsi le bloc 6, héritant des activations de ses entrées, la dernière ligne indique le port 3 (activation des deux entrées du bloc 6) au lieu d'indiquer le port 1 du bloc 6 (activation de l'entrée reliée au bloc 5).

2.2.5   La liste %cpr

La syntaxe de la fonction c_pass2 est la suivante : %cpr=c_pass2(bllst,connectmat,clkconnect,cor,corinv) La liste %cpr est le résultat de compilation d'un schéma-bloc, mais ne contient pas les informations sur la topologie, la couleur, la forme etc... des blocs car non utiles pour la simulation. Ces informations ne sont donc pas prises en compte dans la fonction c_pass2 . %cpr est constitué de quatre structures de paramètres : state, sim, cor et corinv . state est une liste typée (tlist) qui contient l'information sur les états initiaux suivants : Le contenu de state évolue pendant la simulation mais à la sortie de la fonction scicossim on mémorise le contenu final pour permettre l'exploitation du résultat de la simulation, notamment lors d'une éventuelle reprise du cours d'une simulation interrompue. sim contient des informations figées dans le temps, obtenues après compilation par la fonction c_pass2 : La structure de données %cpr est fournie en entrée de la fonction scicossim qui exécute les différentes étapes de la simulation.
Remarque sur l'optimisation de la compilation
Lorsqu'un schéma-bloc a été préalablement compilé, et si par la suite des modifications mineures sont effectuées (changements de paramètres, de la tailles des entrée et sorties ...), sans induire de modifications sur l'ordonnancement, il n'est pas nécessaire d'exécuter une compilation complète. Dans ce cas, on effectue une compilation optimisée, à des degrés différents (cf. figure 15).

{short description of image}


Figure 15: Les étapes de compilation

On utilise le paramètre (booléen) modified, dont la valeur indique si les modifications concernent certaines caractéristiques des blocs : On utilise aussi le paramètre newparameters dont la valeur indique si les modifications concernent des blocs contenus dans un super-bloc (compilé ou non). C'est avec la valeur du paramètre needcompile que l'on détermine si les modifications impliquent une nouvelle compilation et si l'on doit informer l'utilisateur, d'un message pour enregistrer les modifications avant de fermer le fichier contenant le schéma. Le lancement d'une simulation (fonction do_run) passe par une prise en compte d'éventuels changements dans le schéma-bloc (fonction do_update). En fonction de la valeur de needcompile, la compilation est optimisée ou complète. Les paramètres needcompile et modified sont nuls et la liste newparameters est vide. Dans ce cas, il n'y a aucune re-compilation et la fonction scicossim gère les étapes de simulation (cf. par la suite). Signalons dans la fonction do_run, le paramètre alreadyran qui est utilisé pour arrêter et reprendre une simulation en cours. Il existe quatre degrés de compilation :

3   La simulation

Le schéma de la figure 16 montre les différentes étapes de la simulation. Elles sont exécutées par des procédures écrites en Fortran (plus rapide qu'en langage Scilab). Dès que l'utilisateur lance une simulation, les deux procédures intcos et scicos sont appelées successivement. intcos gère l'interface entre les programmes du simulateur (procédure scicos) et la gestion de la mémoire dans Scilab. scicos appelle les 3 procédures : cosini, cossim, cosend pour, respectivement, initialiser, exécuter et clore la simulation.

{short description of image}


Figure 16: La simulation dans Scicos

Pour bien comprendre le fonctionnement de la simulation il faut distinguer les activations conditionnées (générées par les blocs de type Synchro) et les activations originales (générées par les autres types de bloc). Signalons que, même si les blocs Synchro ont été transformés, lors de la compilation, en blocs de type Standard, l'information sur le type de bloc subsiste néanmoins pour la simulation. En effet, c'est précisément pendant la procédure cossim que sont gérées prioritairement, dans l'agenda de programmation des activations, les activations conditionnées.

3.1   La procédure cosini

Cette procédure réalise la phase d'initialisation de la simulation par un appel à tous les blocs avec flag 4 (cf. numéro 19 de Linux Magazine), pour initialiser les entrées et sorties régulières et les registres des temps d'activation de sortie (tvec). Un appel de cosini à tous les blocs avec flag 6 correspond à une ré-initialisation. Signalons que les activations existantes à l'initialisation sont exclusivement originales.

3.2   La procédure cossim

L'essentiel de la simulation est assuré par la procédure cossim, dans laquelle le temps évolue soit en fonction du solveur ODE (temps continu), soit en fonction des événements (activations ponctuelles) programmés dans l'agenda (temps discret).

{short description of image}


Figure 17: La procédure cossim

Le fonctionnement de la procédure cossim est illustrée par le schéma de la figure 17. cossim gère les appels à différentes procédures permettant la mise à jour des blocs, selon que l'activation reçue soit continue ou discrète et en fonction du type de bloc :

3.2.1   Le solveur ODE

Le solveur ODE est un programme d'intégration numérique des équations différentielles du schéma, permettant de faire progresser le temps continu d'un pas et donnant la valeur de l'état à ce nouvel instant. Le pas est calculé de manière interne et variable (suivant les calculs d'intégration) par la procédure lsodar. Cette dernière est aussi utilisée pour les calculs liés à la détection de traversée de zéro.
L'évolution du temps continu
Les calculs liés à l'évolution du temps nécessite de fournir à la procédure lsodar, la dérivée de l'état continu du système à simuler. Cette dérivée est un vecteur fournit par la procédure simblk et composé de la dérivée de chaque bloc concerné. Cette dérivée est en fonction de l'état continu du bloc et de la valeur du signal en entrée du bloc. La procédure simblk permet de réaliser une interface entre le format de la procédure lsodar et celui de la procédure odoit. La procédure odoit est utilisée pour calculer la valeur de l'entrée des blocs ayant un état continu. Cette procédure fait appel à la procédure oodoit, qui assure sa récursivité pour les calculs impliquant des blocs de type Synchro.
La détection de traversée de zéro
Les calculs liés à la détection de traversée de zéro nécessite de fournir à la procédure lsodar , une fonction (y=f(x,t)) qui retourne les valeurs de l'état continu du système à simuler. x est l'état continu, t est le temps continu et y est un vecteur dont le nombre d'éléments est fonction du nombre de blocs de type Zcross à simuler. y est le vecteur des valeurs d'équations de surface qui indique une position par rapport à la dérivée de l'état continu. La détection de traversée de zéro pour l'ensemble des blocs de type Zcross d'un système est considérée comme un ensemble de surfaces. La valeur des éléments de y varie entre trois possibilités : positive au dessus du seuil, négative en dessous et nulle sur le seuil. C'est la procédure grblk qui fournit l'équation y=f(x,t) à la procédure lsodar. Si l'un des élément de la fonction y=f(x,t) change de signe, la procédure lsodar engage une dichotomie du pas de temps avant et après la détection de traversée de zéro, de manière à détecter le bloc concerné et déterminer la date exacte du changement de signe. Il est à noter que dans le cas particulier de détection de traversée de zéro pris à l'instant ``zéro'' même, la procédure lsodar se lance dans des calculs d'intégration particulièrement longs, tant et si bien que la simulation s'en trouve considérablement ralentie. Pour pallier ce problème il est nécessaire de faire avancer le temps d'intégration à l'instant suivant de manière à reprendre les calculs d'intégration, cette fois-ci avec la procédure lsoda. La procédure lsoda est adaptée uniquement aux blocs de type Zcross. Nul besoin est de reprendre plus d'une fois cette tentative de décalage du temps d'intégration, car si elle échoue : il s'agit réellement d'un problème d'intégration plus complexe. Dans ce cas la simulation est arrêtée et un message d'erreur invite l'utilisateur à faire des modifications dans le schéma-bloc. La procédure grblk permet de réaliser une interface entre le format de la procédure lsodar et celui de la procédure zdoit. La procédure zdoit est utilisée pour calculer la valeur de l'entrée des blocs de type Zcross. Cette procédure fait appel à la procédure zzdoit, qui assure sa récursivité pour les calculs impliquant des blocs de type Synchro.

3.2.2   L'agenda

Pendant la simulation, les événements sont programmés dans un agenda définit lors de la phase de compilation. Cet agenda est composé de deux vecteurs. Le premier (evtspt ) est un vecteur d'entiers indiquant le numéro du port générant une activation. Si un événement i est la prochaine activation à programmer, evtspt(i) contient le numéro du port de sortie d'activation correspondant (ou zéro s'il n'y a aucun autre événement programmé). La date d'occurrence de cet événement est stockée dans le second vecteur, tevts(i) (cf. figure 18). La taille des vecteurs evtspt et tevts correspond au nombre de ports de sortie d'activation existants dans le schéma bloc. A la fin de la compilation, le vecteur evtspt contient le numéro de port des blocs devant générer les activations pré-programmées.



Figure 18: L'agenda est composé de deux vecteurs.

Le numéro du port de sortie d'activation du prochain événement à générer est stocké dans la variable pointi. Pendant la simulation, la programmation des activations dans l' agenda dépend de deux procédures : addevs et putevs. Le rôle de addevs est spécifique aux blocs discrets (hormis les blocs Synchro), il consiste à rechercher le bon emplacement dans l'agenda pour programmer l'activation à générer (non synchrone avec l'activation causale). La procédure putevs permet de traiter prioritairement (à l'itération courante) l'activation à générer en sortie des blocs Synchro concernés. L'activation n'est pas programmée dans l'agenda car elle doit être synchrone avec l'activation causale. Il n'existe pas dans l'agenda d'activations conditionnées qui soient programmées.

3.3   La procédure cosend

La procédure cosend permet de mettre à zéro, avec flag 5, le registre des temps d'activations tvec de chaque bloc afin de terminer la simulation. Ceci correspond à une procédure d'arrêt, qui prend toute sa signification par exemple pour les blocs Writef (écriture sur fichier) qu'il est nécessaire de fermer en écriture, pour valider leur contenu. Rachid Djenidi
Scilab Group
scilab@inria.fr
http://www-rocq.inria.fr/scilab/
This document was translated from LATEX by HEVEA.