{{{ #!html

TP1: Modélisation CABA (Cycle Accurate Bit Accurate)

}}} [[PageOutline]] = 1. Objectif = L'objectif de ce premier TP est d'illustrer -sur un exemple très simple ne comportant que deux composants matériels - les principes de la modélisation SystemC au niveau d'abstraction CABA (Cycle Accurate, Bit Accurate).La modélisation CABA est l'un des deux niveaux d'abstraction utilisés pour modéliser les composants de la bibliothèque SoCLib. Ce type de modélisation s'appuie sur la théorie des automates d'états synchrones communicants (CFSM), et permet d'utiliser des technique d'ordonnancement statique permettant d'accélérer la simulation. = 2. Architecture matérielle = L'architecture matérielle à modéliser réalise Elle ne comporte que deux composants matériels: Le premier composant est un coprocesseur cablé (c'est à dire non programmable) qui calcule le PGCD (plus grand commun diviseur) de deux nombres entiers positifs A et B, codés sur 32 bits. Le second composant est chargé de transmettre les valeurs des opérandes A et B au coprocesseur, et de récupérer le résultat. Ces deux composants matériels fonctionnent en parallèle, et communiquent entre eux par des canaux de communication de type FIFO. [[Image( )]] Conformé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 NRESET, actif à l'état bas. == 2.1 Canal de communication FIFO == == 2.2 Composant ''fifo_lcd_coprocessor'' == L'algorithme de calcul du PGCD implanté par cet automate cablé peut être décrit par le code C suivant : {{{ uint32_t lcd( uint32_t opa, uint32_t opb) { while (opa != opb ) { if ( opa > opb ) opa = opa - opb; if ( opa < opb ) opb = opb - opa } return( opa ); } }}} Le chemin de donnée permettant de réaliser ce calcul doit donc comporter deux registres r_opa et r_opb pour stocker les valeurs opa et opb qui évoluent au cours du calcul, ainsi qu'un comparateur et un soustracteur sur 32 bits. Par 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 d'entrée. Finalement, 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: 1. lecture de l'opérande A sur son port FIFO d'entrée 1. lecture de l'opérande B sur son port FIFO d'entrée 1. calcul effectif du PGCD 1. écriture du résultat sur son port FIFO de sortie Ces quatres opérations ont des durées d'exécution variables, puisque le nombre de cycles pour effectuer le calcul (é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 qui dépendent de la disponibilité du composant fifo_lcd_master. [[Image( )]] Outre le registre d'état de l'automate ''r_fsm'', cet automate contrôle donc deux autres registres ''r_opa" et ''r_opb'' utilisés pour le calcul : * 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). * 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). * 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. * 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. == 2.3 Composant ''fifo_lcd_master'' == Ce 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. Ce 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: 1. génération (pseudo-aléatoire) de deux valeurs OPA et OPB. 1. écriture de l'opérande OPA sur son port FIFO de sortie. 1. écriture de l'opérande OPB sur son port FIFO de sortie 1. lecture du du résultat sur son port FIFO d'entrée. 1. affichage des valers sur le terminal. Pour modéliser la génération aléatoire, on utilise la fonction ''rand()'' fournie par la LibC de la station de travail qui exécute la simulation. On génère évidemment des valeurs aléatoires différentes à chaque itération de la boucle, mais 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. Le composant ''fifo_lcd_master''est donc un composant matériel paramètrable (un paramètre permettant de contrôler la séquence de valeurs aléatoires), modélisé comme un automate à 5 états : [[Image( )]] Outre le registre d'état de l'automate ''r_fsm'', cet automate contrôle quatre 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 ''r_cyclecount'' est incrémenté à chaque cycle, e permet de gérer une date (en nombre de cycles) depuis l'initialisation du système. * 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 q'un cycle dans cet état. * 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). * 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). * Dans l'état '''DISPLAY''', on ne modifie pas le contenu des registres ''r_opa'', ''r_opb'', et ''r_res'', mais on affiche la date courante 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. = 3. Travail à réaliser = L'archive attachement:soclib_tp1.tgz contient différents fichiers dont vous aurez besoin pour ce premier TP. Créez un répertoire de travail spécifique TP1 pour ce TP, recopier l'archive dans ce répertoire TP1, et décompressez-la: {{{ $ tar xjvf soclib_tp1.tgz }}} Cette archive contient en principe les fichiers suivants : * ''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é. * ''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é. Ce fichier est complet et ne doit pas être modifié. * ''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é. * ''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é. * ''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é. * ''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é. * ''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é. == 3.1 Ecriture du modèle CABA du coprocesseur == Pour 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]. Le 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é. En vous inspirant du code fourni pour le composant '''master''', complêter les deux fichiers ''fifo_lcd_coprocessor.h'' et ''fifo_lcd_coprocessor.cpp''. == 3.2 Ecriture du modèle CABA de la ''top-cell'' == == 2.3 Compilation et génération du simulateur == == 2.4 Simulation avec le moteur de simulation OSCI == == 2.5 Simulation avec le moteur de simulation SystemCass ==