ELE4304 - Projet: Microprocesseur 8-bits

publicité
ELE4304 – Principe des Circuits Intégrés à Très Grande Échelle
Projet: Microprocesseur RISC 32 bits
avec pipeline à quatre étages
Automne 2008
1 Introduction:
Dans ce projet, on vous propose de réaliser l'implémentation complète d'un
microprocesseur simple avec pipeline à quatre étages.
L'implémentation comprend la compréhension d'une architecture simple de
microprocesseur pipeliné, la description/modélisation/simulation VHDL du circuit, la
synthèse et finalement le placement et le routage automatiques.
L'objectif est de vous permettre de vous familiariser avec chacune des étapes
nécessaires à la réalisation d'un circuit VLSI.
Le processeur proposé a une architecture RISC à 32 bit. Il ressemble donc à certains
processeurs communs comme le MIPS, le SPARC ou le NIOS II. Par contre, il diffère
de ceux-ci en ce que l'objectif principal de conception a été la facilité
d'implémentation. Dans cette optique, certaines simplifications de l'architecture ont
été nécessaires.
Figure 1: Exemple de microprocesseur – un MIPS R2000
1
1.1 Objectifs spécifiques:
1. Utiliser le langage VHDL afin de modéliser, décrire et simuler le circuit du
microprocesseur à partir de l'information fournie dans ce document.
2. Créer un banc d'essais pour chaque module du circuit et montrer les
simulations vérifiant toute la fonctionnalité de vos modules.
3. Développer des aptitudes avec les outils de synthèse de Synopsys.
4. Comprendre et réaliser chacune des étapes de placement et de routage
d'une description VHDL.
5. Faire la simulation fonctionnelle et post-synthèse complète du circuit.
1.2 Méthodologie pour la synthèse:
Une fois vos modules et bancs d'essais décrits en VHDL, vous allez procéder à la simulation
fonctionnelle, puis à la synthèse et optimisation de ceux-ci, et finalement à celle de votre circuit
entier (voir Documents de Laboratoire).
Pour la synthèse du projet en vue du placement/routage, vous devez vous référer au Guide
pour le Placement et Routage et non au Chapitre 3 des Documents de Laboratoire. Plusieurs
modifications aux étapes de synthèse sont nécessaires pour le placement/routage.
Faire le placement/routage de votre design dans SoC Encounter. Imprimez le résultat final
après le placement/routage. Pour le routage, veuillez faire un zoom sur le circuit pour montrer
les fils. Importez le design après le « place & route » dans l'éditeur de design de masques de
Cadence. Imprimez le design final. Pensez-vous que le circuit est à ce stade prêt pour la
fabrique? Donnez une brève discussion.
Durant la phase de vérification, vous devez utiliser le même banc d'essais avant et
après synthèse pour ainsi montrer le bon fonctionnement du circuit et la notion de
délai.
Trouvez, à l'aide de Synopsys, la fréquence maximale de l'horloge de votre modèle. Trouvez
par simulation la fréquence maximale du circuit. Expliquez ce qui pourrait différencier les deux
mesures de fréquences.
2
2 Partie 1 : Modules du microprocesseur
Au premier laboratoire, deux modules du microprocesseur ont été réalisés, soit le
compteur de programme et un circuit de décalage de bits. Dans cette partie, les
modules restant seront créés.
2.1 Bloc de registres
La figure 2 montre un aperçu du bloc de registre. Les signaux à gauche sont les
entrées et ceux de droite sont les sorties.
Figure 2: Aperçu du bloc de registre
Le bloc de registre comprend deux ports de lecture et un port d'écriture. Chaque
port de lecture comporte un signal d'entrée (in_addr_a et addr_b) où est placé
l'adresse d'un registre et un signal de sortie (out_data_a et out_data_b) où est
retournée la valeur contenue dans le registre adressé. La lecture d'un registre est
asynchrone; lors d'un changement d'un changement d'adresse, la valeur
correspondante doit être retournée immédiatement, sans attendre un front
d'horloge. Pour ce qui est du port d'écriture, lorsque le signal in_wr est à 1, la valeur
présentée sur in_data_d est écrite dans le registre adressé sur in_addr_d. L'écriture
d'un registre est effectué de manière synchrone (sur front montant).
La valeur du registre 0 est fixé à 0. Ce registre ne peut jamais être modifié.
Votre module comportera deux paramètres génériques. Le premier, nommé
WIDTH_ADDR, correspond au nombre de bits des adresses (par défaut: 5). Bien sûr,
le nombre de registres dépend de ce paramètre. Le second, nommé WIDTH_DATA,
est le nombre de bits de chaque registre (par défaut: 32).
3
Le nom d'entité de votre module sera reg_file. On vous demande de respecter
l'interface décrite à la figure 2 et ci-dessus (mêmes noms des signaux et des
paramètres génériques, tous les signaux présents, aucun ajouté).
2.2 Unité arithmétique et logique
La figure 2 montre un aperçu de l'unité arithmétique et logique. Il n'est pas
demandé que ce module soit générique.
Figure 3: Aperçu de l'unité arithmétique et logique
L'unité arithmétique et logique constitue le coeur du microprocesseur et, comme
son nom l'indique, permet de réaliser diverses opérations arithmétiques et logiques.
Un opérande est présenté sur chacune des deux entrées in_a et in_b et, en fonction
d'un code d'opération donné sur in_op, une opération est réalisée, et le résultat
correspondant est fourni sur out_result de manière purement combinatoire. Les
données ont une largeur de 32 bits et le code d'opération est codé sur 8 bits.
2.2.1 Drapeaux
L'unité arithmétique et logique comporte trois sorties d'un bit chacune nommées
drapeaux (flags). Ces drapeaux fournissent certaines caractéristiques du résultat de
l'opération. Ils sont mis à jour de manière synchrone. Leur description est celle-ci:
●
c – indicateur de retenue (carry flag) : Ceci indique qu'une addition a produit
une retenue. Dans le cas de l'addition de deux opérandes de 32 bits, on peut
le voir comme le 33ème bit du résultat. On pourrait l'implémenter en VHDL de
la manière suivante: sum <= '0' & a + '0' & b; Dans ce cas, sum(32)
représente l'indicateur de retenue et sum(31 downto 0) le résultat de
l'addition.
4
●
s – bit de signe : comme le drapeau précédent, celui-ci s'applique à
l'opération d'addition, ainsi qu'à l'opération de soustraction qui est en fait
réalisée par une addition où l'opérande à soustraire est remplacé par son
complément à deux. Ce drapeau vaut un lorsque le résultat de l'opération est
négatif, en supposant que les opérandes et le résultats utilisent la
représentation en complément à deux. Attention cependant, ce drapeau doit
être valide même en cas de débordement, et il ne suffit donc pas de
seulement prendre le bit le plus significatif du résultat. L'information
concernant la manière correcte de déterminer le signe du résultat est
facilement disponible.
●
z – indicateur de valeur nulle : indique que le résultat de l'opération vaut
zéro.
2.2.2 Liste des instructions de l'unité arithmétique et logique
Le tableau 1 donne un aperçu des instructions implémentées par l'unité
arithmétique et logique.
Instruction
Description
Code
Drapeaux
d'opération (hex) affectés
ADD
Addition
1 (01)
csz
ADDI
Addition avec opérande immédiat
3 (03)
csz
AND
Opération ET binaire
5 (05)
z
FLIP
Inversion de l'ordre des bits
6 (06)
z
NOT
Opération NON binaire
9 (09)
z
OR
Opération OU binaire
10 (0a)
z
SLL
Décalage logique vers la gauche
11 (0b)
z
SRA
Décalage arithmétique vers la droite
12 (0c)
z
SRL
Décalage logique vers la droite
13 (0d)
z
SUB
Soustraction
14 (0e)
csz
SUBI
Soustraction avec opérande immédiat 15 (0f)
csz
XOR
Opération OU exclusif binaire
BCF, BEQ, BNE et BSF Branchements
CALL et RET
16 (10)
z
70 (46) à 73 (49)
-
Appel et retour de fonction
50 (32) et 51 (33)
Tableau 1: Description des instructions
de l'unité arithmétique et logique
-
La dernière colonne montre les drapeaux affectés par chaque instruction. Les
drapeaux doivent conserver leur valeur actuelle lors de l'exécution d'une instruction
qui ne les affecte pas.
5
2.2.3 Instructions de décalage de bits et d'inversion de l'ordre des bits
La figure 4 montre l'assemblage utilisé pour les instructions de décalage de bits et
pour l'instruction d'inversion de l'ordre des bits.
Figure 4: Assemblage pour décalage de bits
Au centre de l'assemblage se trouve le circuit de décalage de bits ( barrel shifter).
Avant et après ce circuit, il est possible d'inverser ou non l'ordre des bits des
données. Si aucune inversion n'est réalisée, le circuit de décalage de bits permet
d'effectuer les décalages arithmétique et logique vers la droite. Lorsque l'entrée et
la sortie sont toutes les deux inversées, l'assemblage décale alors vers la gauche.
Finalement, si l'entrée in_shift_amount est laissée à zéro et que les données ne sont
inversées qu'à l'entrée ou qu'à la sortie, il est possible d'effectuer l'opération
d'inversion de l'ordre des bits. Cet assemblage permet donc l'exécution des
instructions SLL, SRA, SRL et FLIP.
On vous demande de relier l'entrée de l'assemblage à l'entrée in_a de l'unité
arithmétique et logique. De même, in_shift_amount sera reliée aux bits les moins
significatifs de in_b. Les trois autres signaux de contrôle devront être générés à
partir du code d'opération.
6
2.2.4 Opérations arithmétiques
Les opérations arithmétiques sont l'addition et la soustraction. Chacune de ces
opérations existe en une version où les deux opérandes sont des registres (ADD et
SUB) et une autre où l'un des opérandes est une valeur immédiate (ADDI et SUBI).
Vous n'avez pas à vous réoccuper de ceci à l'intérieur de l'unité arithmétique et
logique puisque la sélection de l'opérande est effectuée à l'extérieur. Ceci veux dire
que, par exemple, il n'y a pas de différence entre les instructions ADD et ADDI dans
l'unité arithmétique et logique. Dans les deux cas, le résultat est la somme des
deux opérandes d'entrée.
2.2.5 Opérations binaires
Quatre instructions d'opération binaire sont font partie du jeu d'instructions du
processeur il s'agit de AND (et logique), OR (ou logique), XOR (ou exclusif) et NOT
(non logique). L'instruction NOT est particulière puisqu'elle ne nécessite qu'un seul
opérande. On vous demande d'utiliser dans ce cas l'entrée in_a comme opérande.
2.2.6 Branchements et appels de fonctions
Lors de l'exécution des instructions de branchement (BCF, BEQ, BNE et BSF) et
d'appel ou de retour de fonctions (CALL et RET), l'unité arithmétique et logique est
utilisé pour le calcul de l'adresse de destination. Pour celles-ci, le résultat de l'unité
arithmétique et logique doit donc être le même que dans le cas d'une instruction
d'addition (in_a + in_b). Par contre, ces instructions ne doivent PAS affecter les
drapeaux.
2.2.7 Considérations finales
Si le code d'opération ne correspond pas à l'une des instructions décrites au
tableau 1, le résultat donné par l'unité arithmétique et logique doit être la valeur
inchangée de l'opérande b (entrée in_b).
Le nom d'entité de votre module sera alu. On vous demande de respecter l'interface
décrite à la figure 3 et ci-dessus (mêmes noms des signaux et des paramètres
génériques, tous les signaux présents, aucun ajouté).
7
2.3 Module d'extension de valeur immédiate
Certaines instructions contiennent un opérande immédiat représenté seulement
que sur 19 bits (voir la section 3.1). Il faut donc étendre cet opérande à 32 bits. La
figure 5 montre un aperçu du module d'extension de l'opérande immédiat.
Figure 5: Module d'extension de l'opérande immédiat
L'entrée in_data a une largeur de 19 bits, et peut représenter une donnée
représentée sur 14 ou 19 bits. Le rôle du module est de réaliser l'extension de la
donnée de manière à obtenir en sortie la même valeur codée sur 32 bits. Ce module
est purement combinatoire.
Lorsque in_size est à un, l'entrée in_data contient une donnée représentée sur
19 bits. Lorsque ce signal est à zéro, la donnée est représentée sur les 14 bits les
moins significatifs, et les bits restants doivent donc être ignorée.
Lorsque in_signed est à zéro, la donnée en entrée est non-signée, et l'extension est
donc réalisée en mettant à zéro les bits ajoutés (extension à zéro). Lorsque
in_signed est à un, une extension signée doit être réalisée de manière à préserver
la valeur et le signe.
Le nom d'entité de votre module sera imm_extend. On vous demande de respecter
l'interface décrite à la figure 5 et ci-dessus (mêmes noms des signaux et des
paramètres génériques, tous les signaux présents, aucun ajouté).
8
2.4 Module de forwarding
La figure 6 montre un aperçu du module de forwarding. Ce module permet de
résoudre des problèmes de dépendances de données entre les instructions en allant
chercher des valeurs à des étapes subséquentes du pipeline avant que celles-ci
n'aient été écrites dans les registres. Son utilisation deviendra claire à la partie 2.
Figure 6: Module de forwarding
L'entrée in_addr reçoit l'adresse d'un registre, et in_data_def reçoit la valeur
provenant du registre correspondant du bloc de registres. Cette valeur sera placée
à la sortie out_data, à moins qu'il ne soit possible d'obtenir une valeur plus à jour.
En effet, les deux derniers étages du pipeline peuvent annoncer qu'ils ont une
valeur plus à jour pour un registre en plaçant l'adresse du registre concerné sur
in_addr1 ou in_addr2, et la valeur sur l'entrée associée in_data1 ou in_data2.
Ainsi, si l'une des entrées in_addr1 ou in_addr2 est égale à in_addr et si l'entrée
associée in_en1 ou in_en2 est à un, la valeur correspondante doit être placée sur
out_data (au lieu de in_data_ref). Le port numéro 1 a priorité sur l'autre.
Votre module comportera deux paramètres génériques. Le premier, nommé
WIDTH_ADDR, correspond au nombre de bits des adresses de registres (par
défaut: 5). Le second, nommé WIDTH_DATA, est le nombre de bits des données (par
défaut: 32).
Le nom d'entité de votre module sera forwarding. On vous demande de respecter
l'interface décrite à la figure 6 et ci-dessus (mêmes noms des signaux et des
paramètres génériques, tous les signaux présents, aucun ajouté).
9
3 Partie 2 : Microprocesseur RISC 32 bits
Dans cette partie, vous réaliserez le microprocesseur. Il s'agit d'une version
simplifiée d'un processeur RISC 32 bits pipeliné. Le jeu d'instructions comprend 26
instructions RISC. L'architecture comporte un pipeline à quatre étages, soit:
●
Fetch (FE) : Chargement de l'instruction (ou de la donnée)
●
Decode (DE) :
Décodage de l'instruction et lecture des registres
●
Execute (EX) :
Exécution de l'instruction
●
Write-Back (WB):
Écriture du résultat dans le registre approprié.
La figure 7 montre un aperçu de l'interface externe du microprocesseur.
Figure 7: Interface du microprocesseur
Le processeur a un bus de données de 32 bits (entrée in_data et sortie out_data) et
un bus d'adressage de 24 bits (out_addr) lui permettant d'adresser une mémoire de
16 mégaoctets. Le signal out_wr, lorsqu'il est à un, indique qu'une donnée valide est
présente sur out_data, et qu'elle doit être écrite en mémoire à l'adresse indiquée
par out_addr. Lorsque ce signal est à zéro, une opération de lecture (de donnée ou
d'instruction) est en cours.
Le compteur de programme du microprocesseur a le même nombre de bits que le bus
d'adressage, soit 24. Chaque instruction est représentée sur 32 bits, et le compteur de
programme est incrémenté par 4 à chaque coup d'horloge en fonctionnement normal. L'adresse
initiale du compteur de programme est 0.
10
3.1 Jeu d'instructions :
Le tableau 2 résume le jeu d'instructions du microprocesseur.
Syntaxe
Format Résultat?
Code
Durée
d'opération
d'exécution
(hexadécimal) (en cycles)
ADD
rd ra rb
rrr
oui
1 (01)
1
ADDI
rd ra imm
rri
oui
3 (03)
1
AND
rd ra rb
rrr
oui
5 (05)
1
FLIP
rd ra
rrr
oui
6 (06)
1
NOT
rd ra
rrr
oui
9 (09)
1
OR
rd ra rb
rrr
oui
10 (0a)
1
SLL
rd ra imm
rri
oui
11 (0b)
1
SRA
rd ra imm
rri
oui
12 (0c)
1
SRL
rd ra imm
rri
oui
13 (0d)
1
SUB
rd ra rb
rrr
oui
14 (0e)
1
SUBI
rd ra imm
rri
oui
15 (0f)
1
XOR
rd ra rb
rrr
oui
16 (10)
1
LD
rd ra
rrr
oui
30 (1e)
2
LDI
rd imm
ri
oui
31 (1f)
1
LDIH
rd imm
ri
oui
32 (20)
1
LDIL
rd imm
ri
oui
34 (22)
1
LDIZ
rd imm
ri
oui
35 (23)
1
ST
ra rb
rrr
non
36 (24)
2
BCF
imm
ri
non
70 (46)
1/3
BEQ
imm
ri
non
72 (48)
1/3
BNE
imm
ri
non
73 (49)
1/3
BSF
imm
ri
non
71 (47)
1/3
CALL
rd imm
ri
oui
50 (32)
3
RET
ra
rrr
non
51 (33)
3
rrr
non
0 (00)
1
NOP
Tableau 2: Aperçu du jeu d'instructions du microprocesseur
11
Le jeu d'instructions est constitué de 26 instructions. Les arguments possibles pour
celles-ci sont les suivants:
●
rd: Il s'agit d'un registre de destination. Le résultat de l'opération sera écrit
dans ce registre. Cet argument est représenté dans le mot d'instruction par
l'adresse du registre (5 bits).
●
ra et rb: Il s'agit de registres lus par l'instruction (opérandes). Ces arguments,
lorsque présents, sont représentés dans le mot d'instruction par l'adresse des
registres (5 bits chacun).
●
imm: Il s'agit d'une valeur immédiate, c'est-à-dire une valeur représentée
directement dans le mot d'instruction. Cette représentation est sur 14 ou 19
bits selon le format de l'instruction.
Il existe trois formats possibles pour les instructions. Ils sont ceux-ci:
●
rrr: Les deux opérandes sont deux registres (ra et rb), et le résultat est placé
dans un registre de destination (rd). Le format du mot d'instruction dans ce
cas est le suivant.
●
rri: Un opérande est un registre (ra), et l'autre est une valeur immédiate
(imm) représentée sur 14 bits. Le résultat est placé dans un registre de
destination (rd). Le format du mot d'instruction dans ce cas est le suivant.
●
ri: Il n'y a qu'un seul opérande immédiat (imm) représenté sur 19 bits. Le
résultat est placé dans un registre de destination (rd). Le format du mot
d'instruction dans ce cas est le suivant.
À noter que pour une instruction donnée, certains champs peuvent être ignorés. Par
exemple, l'instruction NOT est au format rrr mais ne requiert qu'un seul opérande,
alors rb est ignoré. De la même manière, ST est au format rrr mais ne produit aucun
résultat, et rd est donc ignoré. Les instructions qui ne produisent aucun résultat,
identifiées comme tel à la troisième colonne du tableau 2, ne doivent pas modifier
le contenu des registres. Les champs inutilisés dans une instruction sont mis à zéro.
12
Le fonctionnement des instructions arithmétiques et logiques a déjà été décrit plus
haut (voir section 2.2). Les instructions restantes sont décrites ci-après.
3.1.1 Chargement et sauvegarde
Les instructions de chargement et de sauvegarde peuvent être divisés en deux
groupes: les instructions d'accès à la mémoire et les instructions de chargement de
valeur immédiate.
Le premier groupe est formé des instructions LD (load) et ST (store). LD permet de
charger un valeur prise de la mémoire (adresse prise dans le registre ra) et de le
stocker dans un registre (rd). ST permet l'inverse, soit de sauvegarder en mémoire
(adresse prise dans le registre ra) la valeur contenue dans un registre (rb).
L'exécution de chacune de ces deux instructions prend deux coups d'horloge au lieu
d'un seul. En effet, ces instructions demandent de prendre le contrôle du bus
pendant un coup d'horloge, et ce bus ne peut alors pas être utilisé pour charger la
prochaine instruction comme c'est normalement fait à chaque coup d'horloge. Ceci
implique que, lors de l'exécution de l'une de ces deux instructions, le signal in_stall
du compteur de programme soit mis à un afin que l'instruction qui aurait dû être
chargée au coup d'horloge actuel soit chargée au coup d'horloge suivant.
Le second groupe est formé des instructions LDI, LDIH, LDIL et LDI. Ces quatre
instructions permettent de prendre l'opérande immédiat décrit dans le mot
d'instruction et de le stocker dans un registre. Par contre, il faut remarquer que cet
opérande a une largeur de 19 bits, alors que les registres ont une largeur de 32 bits.
Une extension de l'opérande est donc nécessaire, et les quatre instructions diffèrent
dans leur manière d'effectuer cette extension:
●
LDI (load immediate) : la valeur immédiate est considérée être signée, et une
extension signée est donc réalisée.
●
LDIZ (load immediate zero-extended) : la valeur immédiate est considérée
être non-signée, et une extension à zéro est donc réalisée.
●
LDIL (load immediate low) : Seuls les 16 bits les moins significatifs de
l'opérande sont considérées. Ceux-ci sont placés dans les 16 bits les moins
significatifs du registre, et les bits restants sont mis à zéro.
●
LDIH (load immediate high) : Seuls les 16 bits les moins significatifs de
l'opérande sont considérées. Ceux-ci sont placés dans les 16 bits les plus
significatifs du registre, et les bits restants sont mis à zéro.
13
3.1.2 Instruction NOP
L'instruction NOP (no operation) ne fait rien du tout. L'état du microprocesseur
après l'exécution d'une instruction NOP doit être identique à ce qu'il aurait été si
aucune instruction n'avait été exécutée, mis à part bien sûr l'incrémentation
normale du compteur de programme.
3.1.3 Branchements
Les instructions de branchement permettent un saut conditionnel. Elles sont les
suivantes:
●
BCF (branch if carry flag set): Le saut est effectué si le drapeau C est à un.
●
BSF (branch if sign flag set): Le saut est effectué si le drapeau S est à un.
●
BEQ (branch if equal): Le saut est effectué si le drapeau Z est à un.
●
BNE (branch if not equal): Le saut est effectué si le drapeau Z est à zéro.
Pour effectuer le saut, il suffit de mettre la nouvelle adresse à l'entrée in_load du
compteur de programme et de mettre à un le signal in_jump. On vous demande
d'implémenter un saut relatif à l'adresse courante. Pour ce faire, vous placerez à
l'entrée in_load du compteur de programme la somme de l'adresse de l'instruction
courante et de l'opérande immédiat signé. L'unité arithmétique et logique sera
utilisée pour ceci (voir section 2.2.4).
On remarque au tableau 2 que les instructions de branchement ont une durée
d'exécution d'un ou trois cycles d'horloge. En fait, lorsque la condition est fausse, et
donc que le saut n'est pas effectué, l'instruction prend un seul coup d'horloge. Par
contre, lorsque le saut est effectué, l'instruction nécessite trois coups d'horloge, ce
qui s'explique par le fait que l'instruction correspondant à la nouvelle adresse
prendra deux coup d'horloge avant de traverser les étages du pipeline jusqu'à
l'étage d'exécution (EX). Au moment de l'exécution d'une instruction de saut
(comme un branchement lorsque la condition est vraie) il est nécessaire de se
débarrasser des deux instructions suivantes qui se trouvent dans les étages FE et
DE du pipeline puisque celles-ci ne sont pas à exécuter. Un mécanisme pour ce faire
sera décrit plus bas. Il permet de transformer les instructions visées en instructions
NOP à l'étage de décodage (DE) de manière à ce qu'elles n'aient aucun effet.
14
3.1.4 Appels de fonctions
Les deux instructions restantes, CALL et RET, permettent respectivement
d'effectuer un appel de fonction et d'en retourner pour reprendre le traitement où
on l'avait laissé. Lors de l'appel de fonction, l'adresse de l'instruction courante (une
instruction CALL) est sauvegardée dans un registre et un saut est effectué. Lors du
retour de la fonction, cette adresse est récupérée du registre et le traitement
reprend à l'instruction suivante.
Dans le cas de l'instruction CALL, la nouvelle adresse est déterminée de la même
manière que dans le cas des branchements, c'est-à-dire qu'il s'agit d'un saut relatif.
Le signal in_jump du compteur de programme doit bien sûr être mis à un.
L'instruction CALL a aussi pour effet de stocker l'adresse de l'instruction actuelle
dans un registre (rd).
L'instruction RET est plus simple. L'adresse placée sur l'entrée in_load du compteur
de programme est prise directement d'un registre (ra). Le saut n'est donc pas
relatif, mais absolu (aucune addition nécessaire). Dans le cas de l'instruction RET
c'est le signal in_ret du compteur de programme qui est mis à un.
Comme pour les branchements, l'exécution des instructions CALL et RET nécessite
trois coups d'horloges. Il est aussi nécessaire dans ce cas de se débarrasser des
instructions présentes aux étages FE et DE du pipeline en les transformant en
instructions NOP.
15
3.2 Description détaillée de l'architecture
Le microprocesseur comporte un pipeline à quatre étages, c'est-à dire que la
logique a été découpée en quatre étages séparées par des registres. Ceci permet
de réduire les délais de propagation registre-à-registre, et donc d'augmenter la
fréquence d'horloge. De plus, comme dans une chaîne d'assemblage, pendant
qu'un étage travaille à exécuter une partie d'une instruction, une autre travaille sur
l'instruction suivante et ainsi de suite pour chacune. Il en résulte une augmentation
du débit d'instructions traitées à peu près proportionnelle à l'augmentation de la
fréquence d'horloge. Les quatre étages du pipeline sont décrites ci-après.
3.2.1 Étage de chargement (FE)
Le premier étage du pipeline est l'étage de chargement. Il permet le chargement
des instructions, et éventuellement des données. La figure 8 en montre un aperçu.
Le rectangle du haut dans cette figure représente l'ensemble de trois registres qui
permet de passer des données à l'étage suivant.
Figure 8: Étage de chargement (FE)
On peut voir le compteur de programme comme faisant partie de l'étage de
chargement. Dans le cas général, celui-ci est incrémenté à chaque coup d'horloge
de manière à charger chaque instruction séquentiellement. Sa sortie est placée sur
le bus d'adressage du processeur de manière à pouvoir lire l'instruction
correspondante dans une mémoire externe. L'instruction ainsi récupérée est placée
dans un registre prévu à cet effet (DE_ireg). Une copie de l'adresse est aussi
conservée (DE_addr).
16
Les signaux d'entrée du compteur de programme sont commandés par l'instruction
se trouvant au troisième étage du pipeline (étage d'exécution). Par exemple, s'il
s'agit d'une instruction de branchement il se peut que le signal pc_jump soit mis à
un, ce qui a pour effet d'effectuer un saut dans le programme.
Au lieu de la sortie du compteur de programme, il est aussi possible de placer sur le
bus d'adressage l'adresse d'une donnée à charger ou à sauvegarder. C'est ce qui se
produit lorsque l'instruction en cours d'exécution dans le troisième étage du
pipeline est un changement ou une sauvegarde. Les signaux pertinents
(EX_do_mem et EX_ra) seront mentionnés à la section traitant de cet étage.
Finalement, on retrouve à la figure 8 un signal nommé invalidate_fe. Ce signal, en
mettant sa valeur dans le registre EX_invalid, permet d'indiquer au deuxième étage
du pipeline que le contenu de DE_ireg ne doit pas être interprété, et doit plutôt être
remplacé par une instruction NOP (no operation). Ceci est nécessaire par exemple
lorsque le contenu de ce registre est une donnée au lieu d'une instruction, ce qui se
produit lors de l'exécution d'une instruction de chargement.
3.2.2 Étage de décodage (DE)
Le deuxième étage du pipeline est l'étage de décodage. Il permet l'interprétation de
l'instruction avant son exécution à l'étage suivant. C'est à cet étage que les
opérandes sont pris des registres s'il y a lieu.
Figure 9: Étage de décodage des instructions (DE)
17
Les valeurs suivantes sont produites à l'étage de décodage:
●
EX_dreg_index: Il s'agit de l'adresse du registre rd extrait directement du mot
d'instruction contenu dans DE_ireg. Consultez la section 3.1 pour connaître
l'emplacement exact de cet argument dans le mot d'instruction.
●
EX_addr: Il s'agit d'une copie directe de DE_addr. Cette valeur correspond à
l'adresse de l'instruction courante.
●
EX_op: Il s'agit du code d'opération pris dans le mot d'instruction. Par contre,
si le bit DE_invalid vaut un, ou encore si invalidate_de vaut un, ce code
d'opération est remplacé par 0, soit le code correspondant à l'instruction
NOP.
●
EX_wr: bit mis à un si le code d'opération correspond à une instruction
produisant un résultat. Référez-vous au tableau 2.
●
EX_do_mem: mis à un si le code d'opération correspond à une instruction ST
ou LD.
●
EX_imm: Valeur immédiate prise du mot d'instruction et traitée par le module
imm_extend. Référez-vous à la description du jeu d'instructions de la
section 3.1 pour déduire le valeurs de in_signed et de in_size en fonction du
code d'opération. Si une instruction donnée ne nécessite pas d'opérande
immédiat, in_signed et in_size peuvent prendre des valeurs arbitraires
puisque EX_imm sera ignoré dans ce cas.
●
EX_areg et EX_breg: Valeurs correspondant respectivement aux arguments ra
et rb du mot d'instruction. Les adresses des registres sont prises dans le mot
d'instruction, les valeurs correspondantes sont obtenues des registres, et ces
valeur peuvent être remplacées par d'autres plus à jour provenant des
étages suivants du pipeline, ce qui est le rôle du module forwarding.
Seuls les ports de lecture du bloc de registres sont montrés à la figure 9 puisque le
port d'écriture est plutôt utilisé au quatrième étage du pipeline (étage de
sauvegarde). Il est important que les données provenant du troisième étage (étage
d'exécution) soient placées sur le port 1 des unités de forwarding (port formé de
in_en1, in_data1 et in_addr1 – voir la description de ce module à la section 2.4).
Ainsi, on s'assure qu'elles aient priorité sur celles provenant du quatrième étage
(étage de sauvegarde).
18
3.2.3 Étage d'exécution
Le troisième étage du pipeline, l'étage d'exécution, constitue le coeur du
processeur. Comme son nom l'indique, c'est là que les instructions sont exécutées.
Le composant principal de cet étage est l'unité arithmétique et logique.
Figure 10: Étage d'exécution (EX)
Vous utiliserez la description du jeu d'instructions de la section 3.1 afin de
déterminer les opérandes devant être sélectionnés à l'entrée de l'unité arithmétique
et logique ainsi que le résultat final devant être placé dans WB_dreg. Certaines
instructions ne produisent pas de résultats (EN_wr à 0). Dans ce cas, la valeur
placée dans WB_dreg importe peu puisqu'elle sera ignorée.
Le signal pc_load est relié à la sortie de l'unité arithmétique et logique,
conformément à ce qui est suggéré à la section 2.2.4. Lors des instructions de
branchement ou de l'instruction CALL, l'entrée in_a de l'unité arithmétique et
logique correspond à l'adresse de l'instruction actuelle (EX_addr) et in_b correspond
à l'opérande immédiat (EX_imm). Ceci permet, d'implémenter le saut relatif
(rappelons que l'unité arithmétique et logique est en mode d'addition à ce
moment). Lors de l'instruction RET, in_a prend EX_rega (valeur de l'adresse de
retour) et in_b prend la valeur immédiate qui vaut toujours zéro pour cette
instruction (champ non utilisé de l'instruction, voir section 3.1). Ceci a pour effet de
placer la valeur de EX_areg sur pc_load (in_a + 0 = in_a).
19
Pour ce qui est des signaux de contrôle:
●
WB_load est mis à un pour l'instruction LD et à zéro pour toutes les autres.
●
pc_jump est mis à un par l'instruction CALL, ainsi que par les instructions de
branchement lorsque la condition correspondante est vraie (branchement
pris).
●
pc_ret est mis à un par l'instruction RET.
●
pc_stall est mis à un pour les instructions ST et LD.
●
out_wr est mis à un par l'instruction ST.
●
invalidate_fe est mis à un par les instructions LD et ST, par les instructions
CALL et RET, ainsi que par les instructions de branchement lorsque la
condition correspondante est vraie (branchement pris).
●
invalidate_de est mis à un par les instructions CALL et RET, ainsi que par les
instructions de branchement lorsque la condition correspondante est vraie
(branchement pris).
3.2.4 Étage de sauvegarde
Le dernier étage du pipeline est l'étage de sauvegarde. C'est à cet étage que le
résultat de l'instruction est écrit dans un registre lorsque approprié.
Figure 11: Étage de sauvegarde (WB)
Le fonctionnement de cet étage est plutôt simple. La particularité est que lorsque
WB_load est à un, ce qui indique qu'une instruction de chargement (LD) vient d'être
exécutée, la valeur à écrire dans le registre est prise non pas de WB_dreg (valeur
produite à l'étage d'exécution) mais plutôt directement dans le registre
d'instruction (DE_ireg). Dans ce cas, ce registre d'instruction ne contient pas une
instruction, mais bien une donnée qui vient d'être chargée de la mémoire.
20
4 Projet et Organisation de la Remise
Le projet consiste à réaliser la modélisation VHDL, la synthèse/optimisation et le
placement/routage du microprocesseur détaillé aux pages précédentes. Afin de
structurer et de simplifier la réalisation du projet, vous devez suivre les étapes
décrites ci-dessous. Assurez-vous d’inclure dans le rapport toutes les informations
demandées aux sections Rapport et Questions et de bien identifier chacune de
vos figures.
Avant de commencer, veuillez télécharger le fichier *.tar.gz pour le projet, situé sur
la page des laboratoires. Il faudra extraire son contenu dans le dossier
« ~/Labs/Lab3 ». Ce fichier contient une structure de répertoires et de fichiers qui
serviront à configurer votre compte pour pouvoir réaliser les étapes de simulation
post-synthèse et de placement/routage.
Il est impératif que vos codes source de description VHDL soient disposés dans le
répertoire de travail « ~/Labs/Lab3/synopsys/ ». Vous trouverez dans ce
répertoire un fichier nommé constants.vhd et contenant des constantes utiles,
notamment les codes d'opération du microprocesseur. Utilisez-le en ajoutant la
ligne suivante en haut de vos fichiers source, juste en-dessous des autres lignes
semblables:
use work.constants.all;
4.1 Format du rapport/remise:
Le rapport rendu devra comporter une introduction, une conclusion et une partie
par module où vous expliquerez comment fonctionne le module que vous avez
conçu, ainsi que le fonctionnement du banc d'essai qui va avec. Vous pouvez
ajouter plus d'information si vous sentez qu’un module a besoin d’une explication
plus détaillée. Il faudra ajouter une table des matières à votre rapport aux pages
numérotées.
Le code source sera en annexe, imprimé deux pages par côté de feuille, sur les
deux côtés de celles-ci (quatre pages de code par feuille). Toutes les images dans
votre rapport devront avoir un titre et un numéro les identifiant.
Pour la remise électronique, elle se fera par courriel. Le fichier à envoyer sera un
fichier
de
type
*.tar.gz
ou
*.zip,
et
celui-ci
aura
pour
nom
« ele4304_proj_XX.tar.gz » ou « ele4304_proj_XX.zip » où « XX » est le numéro
de votre équipe.
21
4.2 Description VHDL:
Vous devez d’abord réaliser la description VHDL de chacun des modules composant
le microprocesseur, et vous assurer de leur bon fonctionnement. Notez qu’il est
impératif que vous respectiez le nom des ports d’entrée/sortie décrits.
Pour simuler le fonctionnement du microprocesseur, vous devez réaliser un banc
d'essai où aura été instanciée une mémoire contenant un programme de test. Une
telle mémoire vous est fournie sous la forme du fichier ram_fibo.vhd dans « ~/Labs/
Lab3/assembler/ ». Elle contient un programme calculant les 40 premières valeurs
de la suite de Fibonacci. Le fichier source à partir duquel elle a été produite se
trouve dans le même répertoire et est nommé fibo.asm.
Le script assembler.tcl se trouvant dans le même répertoire vous permettra quant à
lui de générer une nouvelle mémoire à partir d'un programme que vous aurez vousmême réalisé. Utilisez fibo.asm comme modèle dans ce cas.
4.2.1 Rapport et Questions:
1. Inclure le code-source VHDL de chacun des modules du microprocesseur.
2. Donnez les bancs d’essai pour chacun des modules.
3. Faites la simulation fonctionnelle du microprocesseur pour le programme
décrit ci-haut. Ne donnez que le résultat de cette simulation.
4.3 Synthèse et simulation post-synthèse:
Faites les simulations post-synthèse en utilisant le même banc d’essai que celui
utilisé lors de la simulation fonctionnelle. Avant de procéder à la simulation,
assurez-vous de bien utiliser la structure de répertoires/fichiers tel qu'expliqué au
début de la section 4.
4.3.1 Rapport et Questions:
4. Démontrez les résultats de simulation post-synthèse (représentation
HEXADECIMALE). Vos simulations doivent illustrer d’une part le bon
fonctionnement du circuit après synthèse et, d’autre part, la notion de délai.
5. Trouvez à l’aide de Synopsys Design Vision la fréquence maximale de
l’horloge de votre modèle.
6. Trouvez par simulation la fréquence maximale du circuit. Expliquez ce qui
pourrait différencier les deux mesures de fréquences.
22
4.4 Placement et routage:
Faites le placement et routage automatique de votre circuit final, tel qu’expliqué
dans les documents de référence du laboratoire (sur le site web).
4.4.1 Rapport et Questions:
7. Imprimez le résultat final après le placement/routage de votre design dans
SoC Encounter.
8. Importez le design placé et routé dans Cadence et vérifiez les règles de
dessin (DRC). Imprimez le design final.
9. Pensez-vous que le circuit est, à ce stade, prêt pour la fabrique? Donnez une
brève discussion.
5 Autres Directives :
Nous souhaitons avoir vos commentaires sur les difficultés que vous avez
rencontrées durant la réalisation de ce Projet. Nous sommes particulièrement
intéressés par les lacunes pouvant subsister dans la documentation.
Soignez votre rapport, et Bon Travail !
Philippe Aubertin
23
Téléchargement