Changes between Initial Version and Version 1 of SoclibCourseTp2


Ignore:
Timestamp:
Sep 1, 2009, 7:14:50 PM (16 years ago)
Author:
alain
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • SoclibCourseTp2

    v1 v1  
     1{{{
     2#!html
     3<h1>TP2: Protocole de communication VCI</h1>
     4}}}
     5[[PageOutline]]
     6
     7= 1. Objectif =
     8
     9L'objectif de ce second TP est d'introduire la modélisation du protocole de communication VCI.
     10Pour des raisons d'inter-opérabilité, tous les composants matériels de la plate-forme de prototypage SoCLib
     11respectent le protocole de communication VCI, qui a été présenté en cours. On va donc modifier les deux
     12composants matériels du TP1, pour qu'ils utilisent des ports de communication VCI.
     13Ceci va permettre d'interconnecter plusieurs composants ''initiateurs'' et plusieurs composants ''cibles''
     14à travers un micro-réseau à commutation de paquets intégré sur puce.
     15
     16= 2. Architecture matérielle =
     17
     18L'architecture matérielle instancie deux composants matériels: Le premier
     19composant est un coprocesseur cablé (c'est à dire non programmable)
     20qui calcule le PGCD (plus grand commun diviseur) de deux nombres entiers positifs A et B, codés sur 32 bits.
     21Le second composant est chargé de transmettre les valeurs des opérandes A et B au coprocesseur, et de récupérer
     22le résultat. Ces deux composants matériels fonctionnent en parallèle, et communiquent entre eux par des canaux de communication de type FIFO.
     23
     24[[Image(soclib_tp1_fig1_archi.png)]]
     25
     26Conformément aux principes CFSM, ces deux composants sont donc modélisés par deux automates synchrones (c'est à dire cadencés par la même horloge CK). L'écriture dans les tous les registres du système se fait sur le front montant de CK. Ils sont initialisés par le même signal  RESETN, actif à l'état bas.
     27
     28== 2.1 Canal de communication FIFO ==
     29
     30Le canal de communication FIFO implante un protocole de communication très simple supportant le contrôle de flux.
     31
     32[[Image(soclib_tp1_fig2_fifo.png)]]
     33
     34Chacune des deux entités communicantes considère que son interlocuteur est une simple FIFO. Une FIFO est une mémoire double accès de type First-In-First-Out sans adressage explicite. Le producteur peut écrire dans la FIFO en activant le signal W. L'écriture est effective lorsque la FIFO n'est pas pleine (WOK peut être considéré comme un signal d'état signifiant FIFO non pleine). Le producteur peut lire une donnée dans la FIFO en activant le signal R. La lecture est effective lorsque la FIFO n'est pas vide
     35(ROK peut être considéré comme un signal d'état signifiant FIFO non vide).
     36
     37Attention : Il n'y a donc pas de mécanisme de ''handshacking'' : le producteur n'a pas besoin de consulter la consommateur
     38pour envoyer un ordre d'écriture (c'est à dire W = true). De même, le consommateur n'a pas besoin de consulter le producteur pour envoyer un ordre de lecture (c'est à dire R = true). Simplement, une donnée est effectivement transmise à chaque cycle où les deux  signaux WOK et ROK ont simultanément la valeur true.
     39Ce protocole supporte un débit maximal d'une donnée par cycle, et permet à chacun des interlocuteurs d'interrompre la transmission quand il n'est pas prêt.
     40
     41Un des avantages de ce protocole est que les deux composants communicants se comportent tous les deux comme des automates de Moore :
     42Il n'y a évidemment qu'un seul émetteur par signal, et la valeur des signaux échangés ne dépend que de l'état interne de l'émetteur.
     43
     44== 2.2 Composant ''fifo_lcd_coprocessor'' ==
     45
     46L'algorithme de calcul du PGCD implanté par cet automate cablé peut être décrit par le code C suivant :
     47{{{
     48uint32_t lcd( uint32_t opa, uint32_t opb)
     49{
     50    while (opa != opb )
     51        {
     52        if ( opa > opb ) opa = opa - opb; 
     53        if ( opa < opb ) opb = opb - opa
     54        }
     55    return( opa );
     56}
     57}}}
     58Le chemin de donnée permettant de réaliser ce calcul doit donc comporter deux registres r_opa et r_opb pour stocker
     59les valeurs opa et opb qui évoluent au cours du calcul, ainsi qu'un comparateur et un soustracteur sur 32 bits.
     60
     61Par ailleurs l'automate cablé reçoit les deux valeurs des opérandes OPA et OPB sur son port FIFO d'entrée, et renvoie le résultat sur son port FIFO de sortie.
     62
     63Finalement, l'automate qui contrôle le composant `fifo_lcd_coprocesseur` exécute un boucle infinie, dans laquelle il effectue successivement les 4 opérations suivantes:
     64
     65 1. lecture de l'opérande A sur son port FIFO d'entrée
     66 1. lecture de l'opérande B sur son port FIFO d'entrée
     67 1. calcul effectif du PGCD
     68 1. écriture du résultat sur son port FIFO de sortie
     69
     70Ces quatres opérations ont des durées d'exécution variables, puisque le nombre de cycles pour effectuer le calcul
     71(étape 3) dépend de la valeur des opérandes, et que les opérations de communications (étapes 1, 2 ou 4) ont des durées
     72qui dépendent de la disponibilité du composant fifo_lcd_master.
     73
     74[[Image(soclib_tp1_fig3_coprocessor.png)]]
     75
     76Outre le registre d'état de l'automate ''r_fsm'', cet automate contrôle donc deux autres registres ''r_opa'' et ''r_opb''
     77utilisés pour le calcul :
     78 * Dans l'état '''READ_OPA''' (resp. '''READ_OPB'''), on écrit dans le registre ''r_opa'' (resp ''r_opb'') la valeur de l'opérande OPA (resp. OPB) lue sur le port FIFO d'entrée (champs ''p_in.data''). On ne sort de cet état que si la donnée est valide (condition ''p_in.rok'' = true).
     79 * Dans l'état '''WRITE_RES''', on écrit le contenu du registre ''r_opa'' sur le port FIFO de sortie ''p_out.data''. On ne sort de cet état que si la donnée est acceptée (condition ''p_out.wok'' = true).
     80 * Dans l'état '''COMPARE''', on effectue la comparaison entre les contenus des registres ''r_opa'' et ''r_opb''. On n'écrit pas dans les registres ''r_opa'' et ''r_opb'', mais les conditions de sortie dépendent du résultat de la comparaison.
     81 * Dans l'état '''DECR_A''' (resp. '''DECR_B'''), on écrit le dans le registre ''r_opa'' (resp. ''r_opb''). On ne reste qu'un cycle dans ces états, puisque la décrémentation ne dépend d'aucune condition extérieure.
     82
     83 == 2.3 Composant ''fifo_lcd_master'' ==
     84
     85Ce composant matériel effectue le travail normalement effectué par un processeur programmable, consistant à générer les valeurs des deux opérandes, à transmettre ces valeurs d'entrée au coprocesseur, à récupérer le résultat calculé par le coprocesseur, et à afficher ce résultat sur un terminal. L'utilisation de processeurs programmables suppose qu'on est capable de déployer le code binaire exécutable par le processeur programmable sur l'architecture matérielle simulée.
     86Ce problème sera traité dans la suite de ce cours, mais dans ce premier TP, on se contente d'utiliser un ''processeur cablé'', qui exécute en boucle le programme suivant:
     87 1. génération  (pseudo-aléatoire) de deux valeurs OPA et OPB.
     88 1. écriture de l'opérande OPA sur son port FIFO de sortie.
     89 1. écriture de l'opérande OPB sur son port FIFO de sortie
     90 1. lecture du du résultat sur son port FIFO d'entrée.
     91 1. affichage des valers sur le terminal.
     92Pour modéliser la génération aléatoire, on utilise la fonction ''rand()'' fournie par la `libc` de la station de travail
     93qui exécute la simulation. On génère évidemment des valeurs aléatoires différentes à chaque itération de la boucle,
     94mais pour faciliter le deboguage, on garantit un fonctionnement reproductible, en contrôlant la valeur initiale du générateur aléatoire grace à la fonction ''srand()'' utilisée dans le constructeur du modèle.
     95
     96Le composant ''fifo_lcd_master'' est donc un composant matériel paramètrable (un paramètre permettant de contrôler
     97la séquence de valeurs aléatoires), modélisé comme un automate à 5 états :
     98
     99[[Image(soclib_tp1_fig4_master.png)]]
     100
     101Outre le registre d'état de l'automate ''r_fsm'', cet automate contrôle 5 autres registres : les registres ''r_opa'', ''r_opb'', et ''r_res'' permettent de stocker respectivement  les deux opérandes et le résultat du calcul. Le registre
     102''r_cyclecount'' est incrémenté à chaque cycle, et contient donc la date (en nombre de cycles) depuis l'initialisation
     103du système. Le registre ''r_iterationcount'' est incrémenté à chaque itération, et contient donc le numéro de l'itération courante.
     104 * dans l'état '''RANDOM''' on écrit les valeurs pseudo-aléatoires OPA et OPB dans les registres ''r_opa'' et ''r_opb''. On ne reste qu'un cycle dans cet état.
     105 * dans l'état '''WRITE_OPA''' (resp. '''WRITE_OPB''') on écrit le contenu du registre ''r_opa'' (resp ''r_opb'') sur le port FIFO de sortie (champs ''p_out.data''). On ne sort de ces états que si la donnée est acceptée (condition ''p_out.wok'' = true).
     106 * dans l'état '''READ_RES''', on écrit dans le registre ''r_res'' la valeur lue sur le port FIFO d'entrée (champs ''p_in.data''). On ne sort de cet état que si la donnée lue est valide (condition ''p_in.rok'' = true).
     107 * Dans l'état '''DISPLAY''', on ne modifie pas le contenu des registres ''r_opa'', ''r_opb'', et ''r_res'', mais on affiche la date
     108courante ainsi que les valeurs des opérandes et du résultat sur le terminal standard de la station de travail qui exécute la simulation. On ne reste qu'un cycle dans cet état.
     109
     110= 3. Travail à réaliser =
     111
     112L'archive attachement:soclib_tp1.tgz contient différents fichiers dont vous aurez besoin pour ce premier TP.
     113Créez un répertoire de travail spécifique TP1 pour ce TP, recopier l'archive dans ce répertoire TP1, et décompressez-la:
     114{{{
     115$ tar xzvf soclib_tp1.tgz
     116}}}
     117
     118Cette archive contient les fichiers suivants :
     119 * ''fifo_signals.h'' : fichier définissant l'objet C++ '''!FifoSignal''' représentant les signaux d'un canal FIFO. Ce fichier est complet et ne doit pas être modifié.
     120 * ''fifo_ports.h'' : fichier définissant les objets C++ '''!FifoInput''' et '''!FifoOutput''' représentant les ports d'accès à un canal FIFO. Ce fichier est complet et ne doit pas être modifié.
     121 * ''fifo_lcd_master.h'' : fichier définissant l'objet C++ '''!FifoLcdMaster''' représentant  le modèle du  master. Ce fichier est complet et ne doit pas être modifié.
     122 * ''fifo_lcd_master.cpp'' : fichier contenant l'implémentation C++ des méthodes utilisées par le composant master. Ce fichier est complet et ne doit pas être modifié.
     123 * ''fifo_lcd_coprocessor.h'' : fichier définissant l'objet C++ '''!FifoLcdCoprocessor''' représentant  le modèle du coprocesseur. Ce fichier ne contient qu'une carcasse vide et devra être complété.
     124 * ''fifo_lcd_master.cpp'' : fichier contenant l'implémentation C++ des méthodes utilisées par le composant master. Ce fichier ne contient qu'une carcasse vide et devra être complété.
     125 * ''tp1_top.cpp'' : fichier C++  décrivant l'architecture matérielle du système, dont la compilation générera le simulateur proprement dit. Ce fichier est partiellement incomplet, et devra être complété.
     126
     127== 3.1 Ecriture du modèle CABA du coprocesseur ==
     128
     129Pour une présentation détaillée des règles d'écriture des modèles de simulation au niveau CABA, vous pouvez consulter la documention disponible en ligne sur le site sur le site WEB du projet SoCLib : [https://www.soclib.fr/trac/dev/wiki/WritingRules/Caba].
     130
     131Le modèle de simulation d'un composant matériel (appelé ''module'' en SystemC) nécessite la définition d'une classe C++ dont le nom correspond au nom du module matériel modélisé.
     132En vous inspirant du code fourni pour le composant '''master''', complêter les deux fichiers ''fifo_lcd_coprocessor.h'' et
     133''fifo_lcd_coprocessor.cpp''.
     134
     135Comme pour tout modèle CABA SoCLib, les variables membres de la classe `FifoLcdCoprocessor` sont de trois types :
     136 * '''ports''' : les variables membres représentant les ports d'entrée sortie sont de type ''sc_core::sc_in'' ou ''sc_core::sc_out'', ou des objets plus complexe (possédant éventuellement un paramètre template) représentant des regroupements de plusieurs ports élémentaires : c'est la cas des types `soclib::caba::FifoOutput<typename>` et `soclib::caba::FifoInput<typename>` utilisés pour accéder à un cana FIFO. Pour des raisons de lisibilité, il est recommandé que les noms de registre soient préfixé par '''p_'''. On définira 2 ports simples (''p_ck'', ''p_resetn''), et deux ports FIFO (''p_in'' et ''p_out''). Ce sont évidemment des variables publiques.
     137* '''registres''' : les variables membres représentant les registres sont de type ''sc_core::sc_signal''. Pour des raisons de lisibilité, il est recommandé que les noms de registre soient préfixé par '''r_'''. On définira trois registres ''r_fsm'', ''r_opa'' et ''r_opb''. Ce sont des variables privées.
     138 * '''constantes''' : ces variables membres sont en fait des constantes permettant de stocker les valeurs des paramètres définis comme arguments du constructeur pour les composants matériels génériques. Ces variables membres sont initialisées dans le constructeur, et leur valeur reste constante au cours de la simulation.  Pour des raisons de lisibilité, il est recommandé que les noms de constantes soient préfixé par '''m_'''. Ces variables sont toujours privées.  Le coprocesseur n'étant pas paramètrable, on ne définira aucune variable de ce type.
     139
     140Le constructeur du coprocesseur LCD ne possède qu'un seul argument, qui est le nom d'instance (on a besoin d'un nom d'instance, car il est possible d'avoir plusieurs instances du même coprocesseur dans une architecture).  Ce nom d'instance est de type ''sc_core::sc_module_name'', et il est stoké dans une variable membre de la classe ''sc_module'', qui est une classe générique dont héritent tous les modèles de composant SoCLib.
     141
     142Enfin, comme tous les modèles CABA de SoCLib, le coprocesseur LCD possède des fonctions membres définissant
     143le comportement du composant, qui sont de trois types :
     144 * la fonction ''transition()'' est sensible au front montant du port d'etrée CK, et permet de calculer la valeur future des
     145registres en fonction de la valeur courante des registres et des valeurs présentes sur les autres ports d'entrée.
     146 * la fonction ''genMoore()'' est sensible au front descendant du port d'entrée CK, et permet de calculer la valeur des ports de sortie qui ne dépendent que des valeurs stockées dans les registres.
     147 * les fonctions ''genMealy()'' (une ou plusieurs fonction). Chacune de ces fonction est  sensible au front descendant du port CK, et à un ensemble particulier de port d'entrée. Elle permettent de calculer la valeur des ports de sorties qui dépendent de façon combinatoire des ports d'entrée.
     148Les noms de fonction ne sont pas imposés, mais il est recommandé de respecter les noms proposés ci-dessus.
     149Le coprocesseur LCD se comportant globalement comme un automate de Moore, on n'a pas besoin de définir de fonctions de type ''genMealy()''.
     150
     151Les architectures matérielles modélisées avec SoCLib peuvent comporter plusieurs dizaines de modèles différents.
     152Pour réduire les temps de compilation la plate-forme de modélisation SoCLib exploite le principe de la compilation séparée: Chaque modèle de composant matériel est compilé séparément.
     153
     154A titre d'exemple, compilez le modèle du composant `FifoLcdMaster`, en utilisant le compilateur g++.
     155Il faut lancer la commande suivante dans votre répertoire de travail TP1 :
     156{{{
     157$ g++ -Wno-deprecated -I. -I/users/outils/dsx/cctools/include -c -o fifo_lcd_master.o fifo_lcd_master.cpp
     158}}}
     159Cette commande doit créer fichier objet ''fifo_lcd_master.o dans le répertoire TP1.
     160
     161Vous pouvez utiliser la même commande (en changeant les noms des fichiers) pour compiler... et déboguer le modèle
     162du composant `FifoLcdCoprocessor`.
     163
     164== 3.2 Ecriture du modèle CABA de la ''top-cell'' ==
     165
     166On appelle généralement ''top-cell'' la description structurelle decrivant l'interconnexion des différents composants
     167matériels constituant l'architecture matérielle qu'on souhaite simuler.
     168Editez le fichier ''tp1_top.cpp'', qui décrit l'architecture, ainsi que les directives de simulation. Ce fichier est volontairement incomplet pour vous obliger à analyser en détail les différentes sections :
     169
     170 * '''arguments''' : On définit dans cette section les arguments  qui pourront être passés en lgne de commande lors du lancement de la simulation.  On prévoit ici de passer en premier argument le nombre de cycles à simuler, et comme deuxième argument la valeur d'initialisation du générateur aléatoire utilisé dans le composant master. cette section n'a pas besoin d'être modifiée. 
     171
     172 * '''Signals''' : On définit dans cette section les différents signaux qui seront utilisés pour connecter entre eux les ports d'entrée sortie des différents composants. On a besoin de 4 signaux : les deux signaux ''signal_ck'' et ''signal_resetn''
     173devront être connectés aux ports correspondants des deux composants matériels.  Les deux signaux ''signal_fifo_m2c'' et ''signal_fifo_c2m'' sont des signaux composites représentant les deux canaux de communication entre les deux composants. On utilise un type générique, en ce sens que le type de la donnée transférée à chaque cycle doit être défini par un paramètre template : dans le cas présent, on transfère un entier 32 bits ''uint32-t''. Le signal ''signal_clk'' est également un objet complexe de type ''sc_core::sc_clock'', dont on peut définir la période (sc_time(1,SC_NS) signifie 1 ns),
     174ainsi que le rapport cyclique. Vous devez ajouter le signal manquant dans cette section.
     175
     176 * '''Components''' : Dans cette section on appelle les constructeurs des différents composants instanciés, en définissant les paramètres. Le nom d'instance est un paramètre obligatoire. Le composant master possède un second paramètre qui est la valeur d'initialisation du générateur aléatoire. Vous devez aouter l'appel au constructeur du composant coprocesseur.
     177
     178 * '''Net-List''' : On décrit dans cette section les connexions entre les composants. La syntaxe utilisée pour connecter un signal s au port p d'un composant c est : ''c.p(s)''. Vous devez ajouter les connexions concernant les ports du coprocesseur.
     179
     180 * '''Simulation''' : Cette section décrit les directives de simulation. Le mécanisme de RESET étant synchrone, On commence par exécuter un cycle en forçant  ''signal_resetn'' à l'état bas (actif), pour initialiser les registres internes de tous les composants, puis on exécute le nombre de cycles spécifié en forçant ''signal_resetn'' à l'état haut (inactif).
     181
     182Vous pouvez compiler ce fichier ''tp1_top.cpp'' pour générer le fichier objet correspondant en utilisant la commande:
     183{{{
     184$ g++ -Wno-deprecated -I. -I/users/outils/dsx/cctools/include -c -o  tp1_top.o  tp1_top.cpp
     185}}}
     186Cette commande doit créer fichier objet ''tp1_top.o'' dans le répertoire TP1.
     187
     188== 2.3 génération et lancement du simulateur ==
     189
     190Vous pouvez maintenant créer le programme exécutable ''simulator.x'' en effectuant l'édition de liens entre les trois fichiers objet précédemment créés :
     191{{{
     192$ g++ -Wno-deprecated -L. -L/users/outils/dsx/cctools/lib-linux -o simulator.x fifo_lcd_master.o fifo_lcd_coprocessor.o tp1_top.o -lsystemc 2>&1 | c++filt
     193}}}
     194Cette commande doit créer fichier objet ''simulator.x'' dans le répertoire TP1.
     195
     196On lance l'exécution du simulateur pour 10000 cycles avec la commande :
     197{{{
     198$ ./simulator.x 10000
     199}}}
     200Quelle est la duréee moyenne d'une itération?
     201
     202Regroupez toutes les commandes de compilation dans un fichier ''Makefile'', en explicitant les dépendances entre les fichiers.
     203
     204== 2.4 Simulation avec SystemCASS ==
     205
     206Comme cela a été expliqué en cours, le style d'écriture des modèles de simulation CABA utilisé dans SoCLib permet une simulation rapide - même en utilisant le moteur de simulation SystemC2.0 fourni par le consortium OSCI -
     207puisque dans le cas où tous les composants matériels se comportent comme des automates de Moore, les deux fonctions ''transition'' et ''genMoore'' de chaque composant ne sont exécutées qu'une seule fois par cycle.
     208
     209Le moteur de simulation SystemC2.0 utilise une technique d'ordonnancement dynamique (avec gestion d'un échéancier),
     210qui a le mérite d'être très générale, et de s'adapter à à peuprès n'importe quel style d'écriture des modèles SystemC.
     211Mais il est possible de gagner un facteur 10 sur la vitesse de simulation en  utilisant le moteur de simulation SystemCASS (développé par le laboratoire LIP6), qui utilise une technique d'ordonnancement statique (sans échéancier) pour exploiter
     212les caractéristiques particulières des modèles SoCLib.
     213
     214Pour utiliser SystemCASS, il n'est pas nécessaire de modifier le code SystemC des composants instanciés, ni le code SystemC décrivant la top_cell, mais il faut recompiler l'ensemble des fichiers sources, en modifiant les chemins d'accès aux fichiers
     215d'include et aux bibliothèques de SystemC.
     216
     217La génération des fichiers objets utilise la commande suivante :
     218{{{
     219$ g++ -Wno-deprecated -I. -I/users/outils/dsx/systemcass/include -c -o filename.o filename.cpp
     220}}}
     221La génération de l'exécutable utilise la commande suivante :
     222{{{
     223$ g++ -Wno-deprecated -L. -L/users/outils/dsx/systemcass/lib -o  fast_simulator.x fifo_lcd_master.o fifo_lcd_coprocessor.o tp1_top.o -lsystemc 2>&1 | c++filt
     224}}}
     225Modifiez le fichier Makefile de la question précédente pour générer un exécutable fast_simulator.x et comparez les vitesses des deux simulateurs.
     226
     227
     228= 4. Compte-rendu =
     229
     230Il ne vous est pas demandé de compte-rendu pour ce TP, mais on vous demandera une démonstration de votre simulateur
     231au début du TP de la semaine suivante...