these
Author Kola Djigande - prepared by P. Bakowski
Contents: introduction, processeur etudie, developpement des modeles de simulation, synthese VHDL, novelles versions, conclusion
Dans cette phase de l'étude, nous présentons une méthode de modélisation d'un processeur de traitement du signal (DSP pour Digital Signal Processor). Cette méthode de modélisation comporte trois niveaux: le niveau algorithmique, le niveau transfert de registres sans pipeline et le niveau transfert de registres avec pipeline. Ces trois modèles écrits en VHDL sont simulés en utilisant différents simulateurs [Bakowski93]. La description VHDL du modèle le plus complet est synthétisée avec l'outil de synthèse Compass (click here)
Finalement, une évaluation des performances du processeur de base (bus de données 16 bits) est faite pour montrer la faisabilité et l'intérêt de la méthode.
D'autres versions du processeurs obtenues en faisant varier la taille du bus de données (8, 12, 24 et 32 bits) ont été synthétisées dans la même optique. 1.
La méthode de conception traditionnelle de composants consistait tout d'abord à transformer un cahier des charges définissant les fonctionnalités du système en spécifications. Ces spécifications sont alors utilisées pour générer l'architecture du système en terme d'interconnexions de blocs fonctionnels. Chaque bloc est alors défini au niveau portes logiques. Le schéma ainsi obtenu sert de document pour la maintenance du système.
Avec l'apparition récente des outils de synthèse et des langages de description du matériel la méthodologie de conception a dû évoluer. Le système est décrit à un niveau d'abstraction de plus en plus élevé à l'aide des langages de description du matériel. Les outils de synthèse sont utilisés pour générer les portes logiques et finalement les transistors. Cette description sert aussi de documentation pour le système.
La modélisation (qui est l'action de décrire le comportement d'un système dans son ensemble) modifie en profondeur les méthodes de conception.
Parmi les langages de description du matériel disponibles, VHDL est celui qui supporte le plus haut niveau d'abstraction dans la description d'un système, tout en acceptant les descriptions de bas niveau.
La modélisation de circuits aussi complexes qu'un processeur est un véritable défi pour les concepteurs de modèles VHDL. Dans certains cas, l'étape de modélisation peut être suivie de la synthèse des spécifications fonctionnelles en vue de reproduire le circuit original en utilisant de nouveaux outils de synthèse associés à une technologie plus récente.
Dans notre cas, nous avons développé une série de modèles VHDL traduisant de manière plus ou moins complète et à différents niveaux d'abstraction le comportement d'un processeur de traitement du signal de base (TMS320C10).
Pour la simulation, les trois modèles développés correspondent à trois niveaux de modélisation: niveau algorithmique, niveau transfert de registres sans pipeline et niveau transfert de registres avec pipeline. Ces modèles implémentés en VHDL ont été simulés sur une station de travail RISC (IBM RS6000) en utilisant le simulateur ModelTech. Le dernier modèle de simulation qui est aussi le plus complet a été transformé en un modèle synthétisable par l'outil de synthèse Compass.
L'objectif de cette étude est double.
On souhaite montrer, d'une part qu'il est possible d'utiliser un langage unique de description (VHDL), pour couvrir le cycle entier de la conception, de la spécification fonctionnelle avec ses raffinements successifs à la description structurelle bas niveau et donc à la synthèse.On peut ainsi mettre en évidence les avantages et surtout les limites des outils de synthèse actuels.
D'autre part, le modèle de synthèse finalement obtenu nous permet d'évaluer les performances de plusieurs algorithmes de traitement du signal implémentés sous forme de codes assembleur chargés dans la mémoire programme du processeur (solution de type logiciel/matériel) et de les comparer aux performances de circuits spécifiques, synthétisés sous forme d'ASIC. Il faut noter que cette comparaison est effectuée en utilisant exactement la même méthode de description, le même outil de synthèse et la même technologie. Dans le sous-titre 2 nous présentons le processeur étudié, nous décrivons son architecture interne, son jeu d'instruction et la manière dont se déroule l'exécution d'un programme. Dans le sous-titre 3, nous présentons les différents modèles de simulation développés. Les résultats de la synthèse VHDL du processeur sont présentés dans le sous-titre 4. Nous présentons le générateur du code machine à charger dans la mémoire programme ainsi que les résultats de la synthèse des nouvelles versions du processeur avant de conclure dans la dernière section.
Le processeur de traitement de signal étudié en guise d'exemple pour l'application de la méthode, est le TMS320C10. C'est le processeur de base de la série TMS320 de Texas Instruments qui ne cesse d'évoluer. Nous présentons ici l'architecture et le jeu d'instructions avant de détailler le déroulement de l'exécution des instructions par le processeur.
Le microprocesseur pris comme exemple est un processeur 16 bits de traitement du signal très répandu. D'autres processeurs plus récents et plus puissants de la même famille sont disponibles mais leur architecture reste très semblable à celle du TMS320C10. Il contient un chemin de données optimisé pour le traitement de signal en virgule fixe (figure ci-dessous).
L'architecture est du type Harvard optimisée pour des raisons de vitesse et de flexibilité. Dans une stricte architecture Harvard, les mémoires programme et données se trouvent dans deux endroits séparés permettant un chevauchement temporel des opérations de recherche et d'exécution des instructions. La modification de l'architecture Harvard dans le processeur permet le transfert entre les espaces programme et données, et l'augmentation de la flexibilité. Cette modification architecturale autorise le transfert des coefficients constants chargés dans la mémoire programme vers la mémoire de données interne, ce qui permet d'éviter d'utiliser une mémoire de type ROM pour les stocker. La puissance de traitement est maximisée en maintenant les deux bus séparés (programme et données) permettant une exécution rapide. Le processeur implémente matériellement un certains nombre de fonctions complexes que la plus part des autres processeurs implémentent en microcode. C'est ainsi qu'il contient un composant multiplieur qui effectue la multiplication de deux vecteurs signés 16 bits avec un résultat sur 32 bits en un cycle d'horloge (200 ns) et un décaleur pour le décalage et le reformatage des données signées. Il contient également une mémoire de données de 144 mots de 16 bits, une unité arithmétique et logique de 32 bits, un contrôleur qui génère et reçoit les signaux de contrôle pour permettre la communication avec les périphériques, deux registres auxiliaires contenant les adresses dans le cas d'un adressage indirect, un accumulateur, un registre T stockant la première opérande de l'opération de multiplication, un registre P mémorisant le résultat de la multiplication, une pile contenant 4 mots et un compteur programme de 12 bits. Il est relié à une mémoire programme externe de 4096 mots de 16 bits. Ce processeur est construit en utilisant une technologie 2 microns, il dissipe une puissance typique de 100 mW et fonctionne avec un cycle d'instruction de 200 ns. figure 3-1 Architecture interne du processeur
Le jeu d'instructions du processeur contient des instructions que l'on retrouve généralement dans tout processeur, à savoir des instructions arithmétiques et logiques, de transfert de données, de contrôle de programme, de communication avec les périphériques et autres. Deux modes d'adressage, direct et indirect sont offerts.
Ce sont, les opérations d'addition, de soustraction, de multiplication, de chargement de l'accumulateur et des opérations logiques.
Ce sont, les opérations d'écriture du contenu de l'accumulateur ou des registres auxiliaires dans la mémoire de données, de transfert d'une donnée de la mémoire vers un registre (T, AR1, AR2, ACCU etc), de transfert du contenu d'une case mémoire vers une autre ou de transfert d'une constante de la mémoire programme vers la mémoire de données. Le codage des instructions a été particulièrement optimisé pour accélerer les recherches d'instructions. La plupart des instructions sont codées au moyen d'un seul mot de 16 bits. Les instructions de transfert de données et certaines instructions arithmétiques et logiques nécessitent une lecture et/ou une écriture mémoire. Dans ce cas, le code opération de l'instruction est contenu pour certaines instructions dans les 8 bits de poids forts tandis que pour d'autres, seuls les 4 bits de poids forts constituent le code opération alors que les 4 autres bits indiquent le nombre de décalages à gauche à faire subir à la donnée juste après lecture ou juste avant son écriture dans la RAM. Les 7 bits de poids faibles constituent les 7 bits de poids faibles de l'adresse de lecture et/ou d'écriture dans le cas d'un adressage direct, le bit de poids fort est alors détenu par un signal interne (DataP): le pointeur de la page mémoire. Quelques instructions permettent de mettre ce pointeur à `0' ou à `1'. Le bit de rang 7 ne servant pas de poids fort pour l'adresse, il indique le mode d'adressage. S'il est à `0' il s'agit d'un adressage direct, sinon c'est un adressage indirect et dans ce cas, les 8 bits de poids faibles de l'un des deux registres sélectionné par le pointeur de registre auxiliaire, constitue l'adresse de lecture et/ou d'écriture.
Elles sont de deux groupes: les longues (nécessitant plus d'un cycle d'instruction pour leur exécution) et les courtes. 1. Les longues: deux cycles de recherche d'instruction sont nécessaires. Le premier cycle produit le code de l'instruction de branchement et nous renseigne sur la condition à vérifier pour assurer le branchement. Le deuxième cycle fournit l'adresse de branchement au cas où la condition serait vérifiée. Ce sont, les instructions de branchement (inconditionnel ou conditionnel au contenu de l'accumulateur ou d'un des registres auxiliaires, ou à un signal de contrôle d'interface) et d'appel de sous-programme. 2. Les courtes: seul le code de l'instruction est lu en un cycle d'instruction. L'adresse de branchement est contenue dans un registre qui peut être soit l'accumulateur ou le sommet de la pile dans le cas d'un retour de sous-programme.
Elles sont au nombre de deux: l'instruction IN qui permet de lire la donnée présente sur un port externe spécifique et de charger le résultat de la lecture dans la mémoire de données et l'instruction OUT qui place sur un port spécifique une donnée issue de la mémoire de données.
D'autres instructions permettent de positionner le pointeur de registre auxiliaire, le numéro de la page de mémoire, de charger et de décharger les registres auxiliaires.
Un mot d'instruction contient toujours un code opération de longueur variable, éventuellement une destination, une opérande, une adresse et autres.
L'exécution d'un programme commence par l'initialisation du compteur programme à l'adresse de la première instruction. Le programme est ensuite exécuté séquentiellement à moins que des instructions de branchement ne le déroutent. Au deuxième front descendant de l'horloge interne du processeur (figure 3-2), le compteur programme est chargé avec l'adresse de l'instruction (LOAD PC2) à pré-chercher pendant que l'instruction courante (EXECUTE 1) est décodée et que son exécution a commencé.
La prochaine instruction est ensuite ``pré-cherchée'' (FETCH 2) pendant que continue l'exécution de l'instruction courante (EXECUTE 1). Au troisième front descendant de l'horloge, apparait une autre recherche anticipée (FETCH 3), pendant que continue l'exécution de l' instruction courante (EXECUTE 2) et celle de la précédente (EXECUTE 1). Ceci est rendu possible par la présence d'un pipeline.
Nous décrivons ici la méthode de modélisation utilisée pour construire les différents modèles de simulation VHDL du processeur et présentons les résultats.
L'idée est d'utiliser une méthode basée sur une suite de raffinements itératifs à partir d'une description d'un niveau d'abstraction élevé jusqu'au niveau plan de masques, en développant systématiquement une nouvelle hiérarchie de modèle VHDL. Chacun des modèles développés a un but spécifique, en d'autres termes, il facilite certaines tâches existantes dans le processus de conception. Ici nous utilisons seulement trois niveaux de modélisation: niveau spécification, niveau transfert de registres sans pipeline et niveau transfert de registres avec pipeline. Le but est de réduire le temps de développement et de faciliter la correction des erreurs dans le comportement du circuit. Le dernier modèle de simulation (plus bas niveau) est synthétisable par les outils commerciaux. Pour simuler les modèles VHDL, les composants périphériques du processeur sont également modélisés en fonction du protocole de communication retenu pour le processeur.
Ainsi, la figure ci-dessus présente le schéma du processeur dans son environnement, réduit au strict minimum. Tous les modèles de simulation développés ont été simulés avec les simulateurs Intermetrics, Viewlogic et ModelTech chronologiquement
Dans le modèle algorithmique, nous modélisons seulement la fonctionnalité du circuit. Dans le cas du processeur, il s'agit d'implémenter correctement l'ensemble du jeu d'instructions. Le jeu d'instructions du processeur est la seule information prise en compte pour le développement de ce premier modèle, les détails architecturaux tels que le nombre d'étages de pipeline, l'utilisation d'un multiplieur matériel ont peu d'importance. Le but principal d'un modèle de niveau algorithmique est de fournir une documentation haut niveau du système, qui facilite le développement de nouvelles versions du circuit. Par simulation de plusieurs programmes d'applications tournant sur le modèle algorithmique, on peut détecter des instructions qui ne soient pas fréquemment utilisées. Si le matériel nécessaire à l'implémentation de ces instructions est très coûteux, on peut les retirer du jeu d'instructions. C'est le cas de l'instruction TBLW par exemple qui permet de lire une donnée contenue dans la RAM interne du processeur et de la charger dans une mémoire externe. De la même façon, on peut avoir besoin de rajouter d'autres instructions en fonction des résultats de la simulation. C'est le cas par exemple de l'instruction LTP qui lit une donnée en mémoire pour la charger dans le registre T, et charge l'accumulateur avec le contenu du registre P. Dans le modèle algorithmique, la spécification initiale est constituée du jeu d'instructions incluant un ensemble d'instructions d'entrée/sortie qui autorisent la communication entre le processeur et ses périphériques (mémoire programme, ports et éventuellement autres). Le modèle algorithmique est constitué de deux processus: Fetch et decode_execute. Le processus Fetch positionne les signaux nécessaires pour l'obtention d'un nouvelle instruction. Le processus decode_execute modélise la plus grande partie du comportement du processeur: les opérations arithmétiques et logiques, les opérations de lecture-écriture mémoire, les communications avec les périphériques et autres. Naturellement, on peut n'utiliser qu'un seul processus car la spécification initiale est constituée d'un jeu d'instructions homogène, sans aucune notion de partitionnement. Ces deux processus s'exécutent l'un après l'autre. Ainsi, c'est le processus Fetch qui après recherche de l'instruction courante active le processus decode_execute et attend la fin de ce dernier se traduisant par l'émission d'un signal fin_execution avant la recherche d'une nouvelle instruction. Afin de modéliser des comportements concurrents, le processus decode_execute contient plusieurs procédures qui, bien qu'écrites séquentiellement s'exécutent en même temps selon la sémantique du langage VHDL. L'entité processeur est constituée de signaux (nMEN, data_lines, address_lines, ACK) nécessaires à la communication avec la mémoire externe et les ports d'entrée/sortie. La modélisation des temps d'accès dans la communication entre le processeur et son environnement a nécessité l'association de délais aux affectations de signaux.
Le schéma du protocole de communication adopté est représenté sur la figure ci-dessus et une partie du code VHDL correspondant à la communication entre le bloc Fetch du processeur et le bloc mémoire programme se trouve sur le programme ci-dessous.
Code VHDL implémentant la communication Fetch-mémoire programme
Ici, en plus du jeu d'instructions du processeur, l'architecture interne est prise en compte. Dans ce modèle, le système est décrit comme un ensemble de blocs fonctionnels tels que l'ALU, le multiplieur ou la mémoire de données communiquant au moyen de signaux et de bus. Chaque bloc fonctionnel constitue un process au sens VHDL. Dans le modèle précédent, lors d'une communication avec les périphériques, le processeur devait activer un signal de demande d'accès, attendre un signal de réponse de la part du périphérique avant de transmettre ou de récupérer le message. Ici, on utilise trois signaux de contrôle pour la communication: nMEN, nWE et nDEN. Au front descendant de nMEN, la mémoire programme doit fournir l'instruction courante, au front descendant de nDEN, un port externe spécifié par le contenu du bus d'adresse doit fournir une information tandis qu'au front descendant de nWE, il doit recevoir une information. L'exécution d'une instruction est décomposée en plusieurs opérations de transfert de registres effectuées en fonction de l'instruction à exécuter. Ce changement de protocole de communication entraîne une nouvelle modélisation des périphériques du processeur. L'analyse du code des instructions montre que des instructions de même type (comme une addition et une soustraction) ont un code qui commence par la même séquence et que seuls les derniers bits du code opération permettent de les différencier. De la même façon, les opérations à effectuer dans ce cas sont de la même nature (dans le cas de l'addition et de la soustraction, on effectue d'abord la lecture des opérandes, ensuite un décalage sur les opérandes si nécessaire puis enfin, on positionne les bits de contrôle de l'ALU qui différencient les deux opérations). Dans ce modèle, on effectue donc une multitude d'étapes de décodage tenant compte de la structure du code de l'instruction. A chaque étape de décodage, on effectue les opérations communes aux instructions dont le code commence par la même séquence.
Protocole de communication et diagramme de bloc du modèle RTL1
Dans cette étape, afin d'améliorer les performances du processeur, les blocs fonctionnels définis sous forme de process VHDL pour implémenter l'ALU, la mémoire de données ou le multiplieur ont été remplacés par des composants obtenus en compilant des descriptions VHDL traduisant leur comportement. Afin d'augmenter la vitesse d'exécution du processeur, trois étages de pipeline ont été introduits tout en maintenant la même structure de blocs fonctionnels introduite dans le modèle précédent. Ceci est rendu possible par la séparation du bus de données et du bus d'adresses. Une horloge est également introduite à ce niveau pour synchroniser les comportements des blocs fonctionnels. Le bloc de décodage d'instructions constitue le premier étage du pipeline. Les blocs de lecture des opérandes en mémoire et exécution (positionnement des signaux d'entrée de l'ALU, du multiplieur, du décaleur, etc) constituent le deuxième étage du pipeline. Le dernier étage est constitué du bloc d'écriture en mémoire du contenu d'un registre représentant un résultat (figure 3-6). Bien qu'il convienne parfaitement pour la description d'architectures matérielles, le langage VHDL n'a pas de structures syntaxiques conçues pour décrire un pipeline. Il faut donc créer un process pour représenter chaque étage. Les trois étages de pipeline décrits précédemment correspondent chacun à un process qui s'active à chaque front descendant de l'horloge interne du système plutôt que par une transaction sur un signal d'entrée. Effectivement, ces process s'exécutent en parallèle dans le modèle niveau transfert de registres avec pipeline et non séquentiellement comme c'était le cas dans le modèle niveau transfert de registres sans pipeline. Grâce au style de modélisation du pipeline, le code VHDL du modèle avec pipeline est très semblable à celui du modèle sans pipeline. La différence essentielle vient du mode d'activation des principaux process. D'autre différences incluent l'addition de deux registres d'instruction qui sont IR1et IR2 et une modification de l'entité contrôle de sorte que les signaux de contrôle soient générés en fonction des données issues du registre d'instruction approprié. Notons, enfin, que l'utilisation de ce pipeline nécessite une fréquence d'horloge trois fois plus grande que dans le modèle RTL1.
Organisation du pipeline interne
Afin de vérifier le comportement du processeur, il est également nécessaire de modéliser ses composants périphériques (la mémoire programme et les ports). Nous décrivons ici ces composants et les différentes parties du processeur .
3.1.4.1 La mémoire programme
La mémoire programme contient les instructions. Elle est modélisée par une mémoire de type ROM. Sa description VHDL de simulation se compose de deux processus. Un processus activé par un signal de chargement et un autre activé par un signal de lecture. Lors de l'apparition d'une transaction sur le signal de chargement, le premier process effectue la lecture d'un fichier d'entrée pour charger la donnée lue dans la mémoire programme qui est ici modélisée par un signal de type tableau de vecteurs de bits (array(1 to N) of bit_vector). Ce signal (implémentant la mémoire) doit être initialisé une seule fois et cela avant le démarrage de l'exécution du programme. Chaque ligne de ce fichier constitue le code d'une instruction du programme que l'on souhaite exécuter. La première ligne du fichier constitue le code machine de la première instruction tandis que la dernière ligne constitue celui de la dernière instruction. Nous avons écrit un générateur (explicité au niveau du sous-titre 5) qui lit un fichier contenant la description de l'algorithme écrite en assembleur humainement compréhensible (utilisant des instructions comme ADD, SUB, MULT et autres), le traduit en code machine pour le charger dans le fichier que va lire le premier process. A chaque front descendant du signal de lecture, le deuxième processus convertit en entier la donnée se trouvant sur le bus d'adresse, se suspend (à l'aide de l'instruction: WAIT FOR temps_acces) pendant le temps d'accès de la mémoire programme (choisi arbitrairement pour la simulation) avant de mettre sur le bus de données, la donnée chargée à l'adresse correspondante, pendant l'exécution du premier process.
3.1.4.2 Les Ports d'entrée/sortie
Un port d'entrée/sortie ne contient qu'un seul processus. Ce processus est activé par les signaux de contrôle (nDEN et nWE) qui sont des signaux de sortie du processeur contrôlant les opérations sur les ports externes. Si le signal nDEN est à l'état bas, le processus lit une ligne d'un fichier d'entrée spécifié par son nom, se bloque pendant le temps d'accès du port avant de mettre la donnée sur le bus de données. Si par contre c'est le signal nWE qui est à l'état bas, le processus récupère la donnée mise sur le bus de données par le processeur et l'écrit dans un fichier d'écriture spécifié également par son nom. On peut noter que trois entités peuvent écrire sur le bus de données externe du processeur: le processeur, pour envoyer un résultat à un port; le port, pour envoyer une donnée au processeur et enfin la mémoire programme, pour fournir le code de l'instruction. Deux des trois signaux de contrôle: nMEN (lecture mémoire programme), nDEN et nWE ne seront pas actifs en même temps permettant ainsi de résoudre ce conflit.
3.1.4.3 La Recherche d'instruction
Cette entité ne comporte qu'un seul processus. Dans le dernier modèle RTL2 du processeur, ce processus est activé par le front descendant de l'horloge interne pour maintenir les trois niveaux de pipeline. Dans les autres modèles de simulation, il est activé par un signal fetch (après l'exécution de l'instruction précédente). A la fin de la recherche on active l'opération de décodage-exécution. Lorsque le processus de recherche d'instruction est actif, on teste si l'instruction précédente est une instruction de branchement. Si oui et que la condition de branchement est satisfaite, l'adresse de branchement est lue et transférée sur le compteur programme lié au bus d'adresse.
Dans le cas contraire:
3.1.4.4 La partie contrôle
Ce bloc est similaire au bloc de recherche d'instruction. Il est activé par un front descendant de l'horloge interne dans le dernier modèle et par un signal émis par le bloc de recherche d'instruction dans les autres modèles de simulation. L'entité contrôle effectue deux principales opérations: le décodage des instructions et le contrôle des flots de données. Le décodage des instructions est modélisé en utilisant une instruction CASE testant le code opération. Comme nous l'avions dit, à partir du modèle RTL1, le décodage d'une instruction s'effectue en plusieurs étapes. Les premiers bits (quatre généralement) sont testés pour trouver le groupe de l'instruction, ensuite un certain nombre de bits suivants déterminent son sous-groupe et ainsi de suite jusqu'à l'identification complète de l'instruction. La partie contrôle positionne également les signaux de contrôle nécessaires à une lecture ou une écriture en RAM, au contrôle de l'ALU et des opérations sur les ports externes. Elle positionne également les opérandes de l'ALU, du multiplieur et autres composants d'exécution.
3.1.4.5 Gestion RAM
Cette entité comporte un processus activé par les signaux (issus de la partie contrôle) qui contrôlent les opérations de lecture/écriture. La mémoire de données est de type simple port et peut contenir 144 mots de 16 bits. Elle est modélisée par un signal de type tableau de 144 vecteurs de 16 bits. Si le signal de lecture est actif, l'information binaire contenue sur le signal d'adresse est convertie en un entier. Le processus est suspendu pendant le temps d'accès à la RAM (choisi arbitrairement) puis l'information correspondant à l'adresse est transmise sur le registre approprié. Dans le cas d'une écriture, l'information contenue sur le signal d'adresse est toujours traduite en entier, le processus se suspend pendant le temps d'accès de la RAM (par l'instruction WAIT FOR temps_acces) ensuite le contenu du registre à décharger est mis dans la case mémoire spécifiée par l'adresse.
3.1.4.6 L'ALU
L'entité ALU est décrite par un processus combinatoire activé par ses opérandes et un signal (ALU_op) spécifiant l'opération à effectuer. Lorsque ce process est activé, l'opération courante est sélectionnée en utilisant une instruction CASE sur la valeur du signal ALU_op. L'ALU effectue six opérations: addition, soustraction, chargement, ET logique, OU logique et OU Exclusif logique. Le résultat de l'opération est chargé dans le registre accumulateur après le temps de calcul arbitrairement choisi pour effectuer les opérations en utilisant l'instruction (AFTER delai_ALU). L'opération de chargement effectue le transfert du contenu de la deuxième opérande dans l'accumulateur après un temps égal à delai_ALU. Vu l'architecture interne du processeur, la première opérande est égale à la valeur courante de l'accumulateur.
3.1.4.7 Le multiplieur
L'entité multiplieur effectue la multiplication de ses deux données d'entrée dont l'une est égale au contenu du registre T, attend un délai choisi pour modéliser la durée d'une multiplication avant de positionner le résultat en sortie (registre P).
3.1.4.8 Génération du reset
L'entité qui génère le ``reset'' global est activée par le signal externe (RS) de demande du ``reset'' et l'horloge externe du processeur. Lorsque le signal RS est actif pendant une durée au moins égale à cinq cycles de cette horloge externe, l'entité active le signal interne RESET qui initialise le système.
Pour démontrer l'efficacité de la technique de modélisation utilisée, nous avons simulé les modèles du processeur sur une station IBM RS6000 en utilisant le simulateur Modeltech. Nous avons noté les temps de simulation du système en exécutant plusieurs algorithmes de traitement de signal aussi différents les uns des autres (filtre FIR, égalisation, FFT, oscillateur, etc).
La performance du système est mesurée par le temps d'exécution des programmes. Deux idées de base peuvent être vérifiées au moyen de cette expérience. La première est la validation de la stratégie de modélisation suivie. Il faut vérifier, en effet, que les temps de simulation et de conception des modèles ne sont pas excessivement longs. La deuxième est la démonstration de l'utilité de la méthode par la facilité avec la quelle on passe d'un modèle au suivant. Les résultats expérimentaux montrent que les trois modèles peuvent être décrits relativement facilement et simulés pour la vérification et même synthétisés en utilisant un seul langage de description du matériel tel que VHDL.
Comme nous l'avons vu, chaque modèle a son importance et facilite la construction du modèle suivant qui est plus complet et plus structuré. Le tableau 3-1 résume les résultats de la comparaison entre les temps de simulation des trois modèles ALG, RTL1 et RTL2.
L'algorithme exécuté pour cette simulation est un algorithme d'adaptation des coefficients d'un filtre adaptatif décrit en annexe. Nous avons fait exécuter 4000 cycles, chaque cycle comportant 250 instructions. On peut noter que le temps de simulation du modèle RTL1 est moins long que celui du modèle ALG; ceci est dû principalement à la multitude d'étapes de décodage introduites qui réduit aussi bien le nombre de signaux utilisés que la taille du code VHDL. Le modèle RTL2 bien que plus complet, plus grand et comportant plus de signaux que le modèle RTL1 offre un temps de simulation plus faible. Il faut noter que les trois étages de pipeline introduits permettent au modèle RTL2 d'exécuter en moyenne trois instructions pendant que les autres en exécutent une. Ainsi, si on doit effectuer 3 million d'itérations d'une nano seconde chacune pour les modèles ALG et RTL1, 1 million d'itérations suffisent pour le modèle RTL2. Quand on réduit le nombre de cycles à 40, le modèle RTL1 offre alors un temps de simulation plus court que le modèle RTL2, ceci étant dû au temps de chargement des modèles avant le démarrage de l'exécution proprement dite qui est à l'avantage du modèle RTL1 (moins complet). Il faut noter également que la taille des codes VHDL et le nombre de signaux restent pratiquement inchangés pour tous les modèles, même si les modèles sont de plus en plus complets au fil de leur développement. Ceci est principalement dû au degré d'organisation qui est rendu possible par l'introduction de nouvelles informations dans l'élaboration d'un nouveau modèle.
Dans beaucoup de cas, le but d'une modélisation de composant est de synthétiser un circuit. De plus en plus, les outils de synthèse intègrent des spécifications faites à l'aide d'un langage de description du matériel pour couvrir le cycle entier de la conception d'ASIC, de la modélisation à un haut niveau d'abstraction à la génération des masques. Le point de départ du développement d'un modèle synthétisable a été le modèle RTL2. Ce modèle est le plus complet car non seulement il implémente le jeu d'instructions mais tient aussi compte de l'architecture matérielle du composant.
Les outils de synthèse VHDL existants imposent beaucoup de contraintes à la description VHDL. C'est ainsi, qu'un circuit aussi complexe qu'un processeur 32 bits par exemple ne peut à présent être synthétisé à partir d'une description VHDL si on impose de grandes performances (vu les résultats obtenus avec un processeur 16 bits). L'outil de synthèse utilisé est celui précédemment évoqué. Ces contraintes sont évoquées dans le chapitre 2, quelques unes sont rappelées ici. · Un process ne peut être que de deux sortes: combinatoire ou séquentiel. · La génération d'un composant effectuant la multiplication de deux vecteurs binaires signés de taille assez grande (supérieur à 16 bits) est très laborieuse pour le synthétiseur qui y passe des heures. Même si ce composant était obtenu, sa performance resterait dégradée. Il est plus préférable de choisir un composant déjà optimisé résidant dans une des bibliothèques offertes par le synthétiseur. · L'usage des types composés (enregistrement, pointeur, tableaux multi-dimensionnels etc) n'est pas autorisé en général. Les nouvelles versions du synthétiseur (à partir de la version v8r4) autorisent la déclaration d'un signal de type tableau de vecteur de bits pour implémenter une RAM (array(1 to N) of bit_vector). Ce signal de type tableau doit être utilisé dans un process séquentiel pour lire ou écrire une donnée de ce tableau. La taille de ce tableau doit être très réduite (inférieure à 10 mots de 16 bits) si on souhaite obtenir des résultats dans un délai raisonnable. Un tableau de taille 144 mots de 16 bits est tout simplement impossible à synthétiser. Il faut là encore recourir à un composant optimisé disponible dans une bibliothèque. · Un process ne peut plus être suspendu en utilisant l'instruction WAIT FOR ou WAIT UNTIL ou WAIT ON. Des délais fictifs ne peuvent pas alors être attribués aux opérations, ce qui était fait dans les modèles de simulation.
Les composants déjà optimisés, importés de la bibliothèque de Compass ont leurs propres contraintes temporelles. Le code VHDL du composant qui les instancie doit dans certains cas être réécrit pour pouvoir les intégrer. Comme exemple, la figure 3-7 montre les contraintes temporelles imposées par le composant RAM pris dans la bibliothèque quand on souhaite effectuer une opération de lecture (pour une écriture il suffit d'inverser le signal de contrôle WEB). Il faut donc que les signaux de contrôle WEB et OEB, et l'adresse (plus la donnée dans le cas d'une écriture) soient valides au moins 5 ns avant le front descendant de l'horloge CEB de la RAM pour qu'une opération de lecture/écriture soit correcte. figure 3-7 Contraintes temporelles de la RAM importée
Une première solution d'intégration de la RAM a consisté à mettre en série des inverseurs afin de créer les 5 ns de retard nécessaires. Lorsqu'on souhaite effectuer une opération d'accès à la RAM, l'adresse et la donnée sont positionnées au même moment (ou presque) qu'un signal intermédiaire CEB1. Ce signal intermédiaire se propage à travers la série d'inverseurs pour donner naissance au signal CEB (figure ci-dessous). Le comportement temporel que l'on souhaite obtenir est reporté sur la figure 3-8.
Chronogramme souhaité pour utiliser la RAM
La spécification schématique et la description VHDL correspondant au comportement souhaité sont données respectivement sur la figure 3-9 et le programme 3-2.
figure 3-9 Une spécification schématique pour un usage correct de la RAM
Une description VHDL permettant un usage correct de la RAM Cette première solution bien qu'intéressante fournit des résultats non satisfaisants lors de la simulation. En effet, l'outil de synthèse annule l'effet de retard (qui devrait être introduit par les inverseurs mis en série) pendant la phase d'optimisation, de telle sorte que l'on ne peut plus garantir les 5 ns de retard.
Pour maintenir nos trois étages de pipeline, on doit pouvoir effectuer une opération de lecture et une opération d'écriture durant chaque cycle d'instruction. Cependant, le composant de type RAM fourni par le synthétiseur est du type simple port et nécessite l'apparition d'un front descendant de sa "pseudo'' horloge pour la prise en compte d'une opération de lecture ou d'écriture. Une solution fiable et simple pour l'intégration de ce composant consiste à le piloter par une "vraie" horloge de fréquence double de l'horloge interne du processeur. Ainsi, pendant chaque période de l'horloge interne du processeur, apparaissent les deux fronts descendants de l'horloge de la RAM nécessaires pour effectuer les deux opérations désirées sur la mémoire. Un diviseur de fréquence étant moins coûteux qu'un multiplieur de fréquence, nous avons ainsi été amenés à utiliser l'horloge externe du processeur pour piloter la RAM et effectuer une division de fréquence pour générer l'horloge interne (H) du système dont la période représente un cycle d'instruction
Ainsi, il suffit de choisir une horloge externe ayant une demi-période supérieure au temps de positionnement des signaux de contrôle (WEB, OEB, adresse, donnée) plus les 5 ns. figure 3-10 Spécification temporelle de la solution retenue Une fois le code VHDL correctement écrit, l'outil de synthèse peut être utilisé pour générer les portes logiques, les ``pads'', les mémoires et autres qui peuvent être alors convertis en plan de masques.
Tant que les modèles sont développés pour effectuer seulement une simulation fonctionnelle, le concepteur peut attribuer n'importe quel délai à une opération. Ainsi, le modèle RTL2 peut être écrit de manière à obtenir exactement le même comportement temporel que n'importe quel processeur existant aussi performant soit-il. Lors de la transition vers un modèle synthétisable, il faut omettre la spécification de ces délais dans la description. Un modèle de synthèse ne contient donc pas de délais explicites. Après la synthèse, les délais réels seront ceux des portes logiques et des blocs qui auront été générés. Ces délais deviennent alors exploitables en simulation. Afin d'évaluer les performances du processeur, il est nécessaire de trouver la fréquence maximale de l'horloge utilisable. Pour cela il faut connaitre les opérations les plus contraignantes. L'ALU et le multiplieur effectue chacun au plus une opération pendant chaque cycle d'instruction. Au front montant de l'horloge H (au début de la deuxième demi-période), on positionne les entrées de ces composants en fonction de l'instruction courante. Après synthèse, quelle que soit l'instruction, les entrées de l'ALU et du multiplieur sont valides respectivement 28,76 ns et 27, 89 ns après le front montant de l'horloge H. Par ailleurs, le temps de propagation dans l'ALU est de 42,63 ns alors que celui dans le multiplieur est de 57,5 ns. L'ALU impose une période d'horloge d'au moins 71,39 ns (42,63 ns+28,76 ns) tandis que le multiplieur impose 85,39 ns. Tout comme la RAM, la ROM programme est aussi importée de la bibliothèque et est pilotée par une horloge. Cependant, puisqu'il suffit d'obtenir une nouvelle instruction pendant chaque cycle de l'horloge interne, cette ROM est pilotée par l'horloge interne H du processeur. Pendant la première demi-période de H, on positionne l'adresse et le signal de lecture et cela 5 ns avant l'autre demi-période (front descendant de H) et pendant la deuxième demi-période, l'opération de lecture doit être terminée (temps d'accès de la ROM inférieur à une demi-période).
Après synthèse, il résulte que les signaux de contrôle de la mémoire programme et l'adresse de l'instruction sont disponibles 27,89 ns à partir du début de la première demi-période de H. A cela, il faut ajouter les 5 ns supplémentaires (27,89+5=32,89ns). Le temps d'accès de la ROM programme n'est que de 17 ns. La mémoire programme impose donc une demi-période de H supérieure ou égale à 32,89 ns. Par ailleurs, à chaque front descendant de l'horloge clk de la RAM (horloge qui produit l'horloge interne H du système par division de fréquence), une opération de lecture ou d'écriture peut être sollicitée. Pour cela, comme souligné plus tôt, l'adresse, la donnée (dans le cas d'une écriture) et les signaux de contrôle (WEB, OEB) doivent avoir été positionnés au moins 5 ns auparavant. Pour qu'une opération de lecture se déroule correctement if faut que (tH + tRd + tm) ne soit pas inférieur à la demi-période de l'horloge clk qui pilote la RAM, où tH est le délai entre le front montant de clk et celui descendant de H; tRd est le délai entre le front descendant de H (à partir du quel on commence le décodage de l'instruction afin de voir si une opération sur la RAM est nécessaire) et le positionnement de l'adresse, la donnée et des signaux de contrôle de la RAM et tm est égal aux 5 ns de marge avant le front descendant de clk à partir duquel commence la lecture.
Après synthèse, on trouve tH=8,51 ns et tRd=22,75 ns; d'où la contrainte demi-période de clk supérieure ou égale à 36,26 ns donc une période de H supérieure ou égale à 145,04 ns. A noter que le temps d'accès de notre RAM n'est que de 18 ns, on pourrait donc choisir une RAM ayant un temps d'accès beaucoup plus long mais inférieur à 36,26 ns. Finalement, de toutes ces contraintes, une seule est capitale et englobe en quelque sorte les autres; il s'agit de celle liée aux signaux à positionner afin d'effectuer une opération de lecture ou d'écriture sur la mémoire de données. Cette contrainte impose une période de l'horloge d'entrée clk supérieure ou égale à 72,52 ns.
Dans la phase de synthèse, c'est d'abord le modèle RTL2 qui est modifié pour satisfaire les contraintes du synthétiseur puis compilé. On obtient ainsi une netlist que nous appelons modèle SYNT1. Ce modèle qui, comme nous venons de le voir impose une période de l'horloge externe clk (qui est aussi l'horloge de la RAM) égale au moins à 36,26 ns a été optimisé en effectuant manuellement une réduction des équations au niveau de la partie contrôle. La partie du code optimisé est présentée sur le programme
Optimisation d'une partie du code VHDL
Cette optimisation a permis d'obtenir un temps tRd égal à 19,05 ns, d'où une demi-période de clk minimale égale à 32,56 ns (période de H supérieure ou égale à 130,24 ns). Ceci montre l'influence du style d'écriture d'une description pour la synthèse. C'est ce modèle optimisé que nous avons appelé SYNT2. Des opérations de placement et routage sont alors effectuées sur ce modèle optimisé afin d'extraire le plan de masques du circuit final. Ce plan de masques est appelé modèle SYNT3. Puisqu'il prend en compte la géométrie du circuit, la longueur des lignes, les temps de propagation dans les différents pads, les performances de ce dernier modèle en terme de durée minimale du cycle d'horloge sont moindres. Une demi-période de 37,2 ns est nécessaire pour l'horloge clk. Le schéma et les caractéristiques du dessin des masques du processeur se trouvent sur la figure 3-11 tandis que les vitesses de fonctionnement des différents modèles sont indiquées sur le tableau 3-2. tableau 3-2
Performances des différents modèles de synthèse modèles
version
SYNT1 (netlist)
SYNT2 (optimisé)
SYNT3 (layout)
cycle d'instruction
145,04 ns
130,24 ns
148,8 ns
technologie: (CMOS) (l=0.6 um) taille: 6.034 X 5.752 mm nombre de transistors: 39840
Caractéristiques et schéma du plan de masques
Afin de valider le processeur, il faut lui faire exécuter des algorithmes de traitement de signal aussi diverses que possible. Pour cela, il sera connecté à un port d'entrée-sortie et une mémoire programme. Au niveau du modèle de synthèse, la mémoire programme est un composant pré-défini, optimisé de type ROM importée de la bibliothèque du synthétiseur. Dans la ROM sera chargé le code machine correspondant à l'algorithme que l'on souhaite exécuter. Nous avons ainsi développé un générateur du code machine. Sa tâche principale est de fournir l'adresse et le codage correctes de chaque instruction. Il doit aussi, dans le cas d'une instruction de branchement fournir l'adresse exacte de l'instruction vers laquelle s'effectue le branchement. Pour cela, une mémorisation de l'adresse correspondant à chaque étiquette de branchement est obligatoire. La forme d'une étiquette et celle d'une instruction de branchement sont explicitées dans le chapitre 5.
Le programme 3-4 montre un exemple de code machine issu du générateur à partir de la description assembleur contenue dans le même programme. programme 3-4
Un exemple de code machine issu du générateur
Dans ce qui précède, nous avons explicité la démarche adoptée pour modéliser et finalement synthétiser un processeur de traitement du signal. Ce processeur est du type 16 bits (taille du bus de données), il possède un code d'instruction, un bus de données et des registres internes de taille 16 bits. Seuls les registres accumulateur (sortie de l'ALU) et produit (sortie du multiplieur 16x16) sont de taille 32 bits. Un des intérêts d'une description VHDL en vue de la synthèse est sa flexibilité. Ainsi, nous avons modifié la description du processeur 16 bits afin de synthétiser des versions 8, 12, 24 et 32 bits du processeur. Pour ces nouvelles versions du processeur de traitement du signal 16 bits, la taille du bus de données, de la mémoire de données, des différents registres internes, des opérandes du multiplieur et donc des différents modules matériels (ALU, multiplieur etc) est égale à celle du bus de données (8 pour la version 8 bits, 12 pour la version 12 bit, etc) alors que la taille des opérandes de l'ALU et de sa sortie, celle de la sortie du multiplieur sont égales au double de la taille du bus de données (16 pour la version 8 bits, 24 pour la version 12 bits, etc). Seul la taille du code d'instruction reste égal à 16 bits pour toutes les versions afin de maintenir un jeu d'instructions unique. Pour la synthèse de ces nouvelles versions du processeur, une (nouvelle) version (v8r4.6) du synthétiseur a été utilisée. Afin de maintenir une homogénéité, les résultats de la synthèse de la version 16 bits du processeur (originale) indiqués dans le tableau 3-3 correspondent à ceux obtenues avec ce nouveau synthétiseur. Les résultats de la synthèse des différentes versions sont fournis dans le tableau 3-3 et sur les trois figures suivantes. Dans ce tableau, cycle d'instruction désigne la durée maximale du cycle d'instruction autorisée en nano secondes (c'est le double de la période de l'horloge externe), taille correspond au nombre de portes Nand à 2 entrées équivalentes, puissance désigne la puissance moyenne consommée lorsqu'on impose la fréquence maximale de fonctionnement et 60% du circuit en activité pendant chaque cycle d'instruction.
tableau 3-3 Comparaison des différentes versions du processeur
Variation de la durée du cycle d'instruction en fonction de la version du processeur figure 3-13 Variation de la taille du circuit en fonction de la version du processeur figure 3-14 Variation de la puissance consommée en fonction de la version du processeur Pour valider les nouvelles versions synthétisées, les algorithmes de traitement du signal décrits en annexe ont été exécutés sur chacune d'elles. Il faut noter que la quantité (élévée) de puissance consommée par la version 8 bits du processeur est due à la fréquence élévée de l'horloge. A une même fréquence de fonctionnement que la version 12 bits (correspondant à un cycle d'horloge de 146,88 ns) on obtient une puissance de 426 mW (contre 475 pour la version 12 bits).
Nous avons présenté trois niveaux de modélisation pour la simulation du processeur de traitement du signal étudié. Le dernier modèle est quasiment synthétisable hormis quelques légères modifications dues aux limitations du synthétiseur. Certaines de ces limites ont été compensées par l'usage de composants optimisés disponibles dans la bibliothèque du synthétiseur, d'autres ont conduit à une réécriture du code VHDL. Les performances obtenues à l'issue de la synthèse sont satisfaisantes quand on les compare à celles du TMS320C10. Nous pensons également que cette méthode de modélisation descendante réduit considérablement le temps de conception si la complexité du circuit est grande. Des améliorations ou modifications peuvent être facilement intégrées dans chacun des modèles permettant ainsi de concevoir un autre processeur ou tout au moins d'adapter la précision du processeur sans grand effort. C'est ainsi que des versions 8, 12, 24 et 32 bits du processeur ont été synthétisées. Par ailleurs, nous pouvons noter que la conception d'ASIC à partir d'un langage de description du matériel comme VHDL est très souple et très rapide, et probablement efficace pour les circuits simples. Il ne faudra cependant pas espérer synthétiser n'importe quel ASIC si on lui impose de grandes performances, tant que les synthétiseurs n'utiliseront que des composants de base (portes logiques, bascules et autres).