Architecture 1 TP 5 : fonctionnement d'un processeur - Ensiwiki
Architecture 1 TP 5 : fonctionnement d'un processeur - Ensiwiki
Architecture 1 TP 5 : fonctionnement d'un processeur - Ensiwiki
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
<strong>Architecture</strong> 1<br />
<strong>TP</strong> 5 : <strong>fonctionnement</strong> d’un <strong>processeur</strong><br />
ENSIMAG 1A<br />
Année scolaire 2012–2013<br />
Il est impératif d’avoir effectué le travail préparatoire avant de venir en séance.<br />
Le but de ce <strong>TP</strong> est de comprendre le <strong>fonctionnement</strong> d’un <strong>processeur</strong> (ici le <strong>processeur</strong><br />
MIPS vu en TD12) et plus précisément :<br />
– comment fonctionne sa mécanique interne (PC et PO),<br />
– comment le jeu d’instructions permet de le contrôler,<br />
– comment il s’intégre dans un système.<br />
Ex. 1 : Travail préparatoire<br />
En plus de la mémoire déjà intégrée en TD, l’environnement du <strong>processeur</strong> est enrichi avec<br />
des périphériques (LED, interrupteurs, afficheurs 7 segments. . .) pour nous permettre de communiquer<br />
avec lui. Le <strong>processeur</strong> peut accéder à ses périphériques en utilisant les instructions<br />
d’accès mémoire classique (lw, sw) dans une plage d’adresses dédiée aux périphériques. Ainsi<br />
pour les adresses entre 0x4000 et 0x4FFF, le module périphérique est activé et l’accès à la<br />
mémoire ne sera pas pris en compte. La table d’allocation des périphériques donnée en annexe,<br />
permet de savoir les adresses à utiliser pour communiquer avec un périphérique et le type d’accès<br />
pouvant y être réalisé.<br />
L’environnement du <strong>processeur</strong> utilisé dans ce <strong>TP</strong> est représenté ci-dessous. Il contient un<br />
bloc DCM (Digital Clock Manager) utilisé pour fournir un reset et une horloge à 25MHz 1 au<br />
reste du circuit.<br />
1. Le <strong>processeur</strong> fournit ne peut pas fonctionner à 50MHz
La partie opérative du <strong>processeur</strong> et le jeu d’instruction sont rappelés en annexe.<br />
Question 1 Ecrire en langage d’assemblage un programme recopiant en boucle sur les LED<br />
la valeur présente sur les interrupteurs. Puis, traduire ce programme en langage machine (en<br />
hexadécimal évidemment). Le programme débute à l’adresse 0.<br />
Un timer est un composant matériel donnant au <strong>processeur</strong> des informations sur le temps<br />
écoulé. Le timer fourni s’active à une fréquence d’environ 1,5Hz par une impulsion au niveau<br />
bas dont la durée est fixée au nombre de cycles pris par le <strong>processeur</strong> pour exécuter un lw, un<br />
beq et un j.<br />
Afin de détecter l’activation de ce timer, le <strong>processeur</strong> doit faire une boucle de scrutation. Pour ne<br />
manquer aucune impulsion du timer, il faut que la durée de l’impulsion du timer soit exactement<br />
égale à celle de la boucle de scrutation.<br />
Question 2 Avec les 3 instructions proposées, écrire une boucle de scrutation sautant vers<br />
fonction lorsque le timer s’active. Écrire ensuite la fonction correspondante pour que le programme<br />
fasse clignoter toutes les LED.<br />
Au cours du <strong>TP</strong>, on vous demandera d’exécuter<br />
un programme permettant d’afficher un chenillard<br />
sur les LED de la carte. C’est-à-dire que<br />
les LED allumées se décalent d’une position<br />
à chaque activation du timer. L’algorithme<br />
ci-contre permet de réaliser un chenillard sur<br />
un afficheur à 8 LED :<br />
motif ← 0x03;<br />
while true do<br />
while timer = 1 do<br />
timer ← lire_timer();<br />
end while<br />
afficher(motif);<br />
motif ← motif
Cette commande va mettre à jour le contenu de la mémoire du système simulé, puis va recompiler<br />
le testbench (src/tb_MMIPS_simple.vhd) en prenant en compte les fichiers déjà compilés pour<br />
lesquels nous n’avons pas fourni les sources 2 . Finalement, la commande lance le simulateur de<br />
ISE.<br />
Question 2 Lancez une simulation sur le programme pgcd fourni. Par défaut, le simulateur<br />
ne fournit que les entrées-sorties du module simulé. Quelles informations peut-on obtenir du<br />
chronogramme obtenu ?<br />
Pour obtenir plus d’informations, il faut ajouter des signaux à votre simulation. Pour ça,<br />
il faut sélectionner dans l’onglet « Instances and Processes » le composant contenant le signal<br />
recherché. Tous les signaux de ce composant apparaissent dans l’onglet « Objects ». Il suffit alors<br />
de faire glisser le signal désiré vers le chronogramme.<br />
Pour conserver un chronogramme lisible, pensez à regrouper les signaux par thématique, à<br />
utiliser des séparateurs (clic droit dans le chronogramme et « New Divider ») et à demander la<br />
bonne interprétation des vecteurs de bits (clic droit sur le signal dans le chronogramme, puis<br />
prendre l’interprétation voulue dans le champs Radix).<br />
Question 3 Conservez uniquement les signaux utiles de la simulation initiale. Ajoutez ensuite<br />
les signaux suivants :<br />
– clk25 et rst du composant C_MMIPS_simple, pour avoir les signaux de synchronisation<br />
utilisé par le <strong>processeur</strong> ;<br />
– les signaux du composant C_RAM, pour savoir ce qui se passe au niveau de la mémoire<br />
(attention les 2 bits d’adresses de poids faible ne sont pas utilisés par le module mémoire) ;<br />
– le groupement de signaux cmd du composant C_PROC pour voir les commandes données<br />
par la PC à la PO ;<br />
– le signal d’état de la PC (state_q) et les signaux vous paraissant pertinent dans la PO.<br />
Le banc de registre est appelé rf_q.<br />
Enfin, relancez la simulation.<br />
Question 4 Trouvez dans la simulation l’instant où le <strong>processeur</strong> commence à travailler, puis<br />
vérifier que l’état du registre PC évolue bien comme prévu par les instructions du programme<br />
(en s’aidant des registres PC et IR).<br />
Vérifier que le contenu des registres évolue aussi comme désiré.<br />
Trouvez la première instruction subu et suivre sur les signaux de la PO et de la RAM l’impact<br />
des ordres donnés dans la PC dans l’état avant le fetch, dans l’état fetch, dans l’état decode et<br />
dans l’état d’exécution.<br />
Pour gagner du temps et éviter de refaire ces fichiers de configuration de vos simulations, il<br />
est possible de les sauvegarder. Le répertoire wcfg est là à cet usage. Vous y retrouverez notre<br />
fichier de configuration pour le pgcd. Si vous voulez lancer automatiquement vos simulations<br />
avec vos fichiers de configuration, sauvegardez dans ce répertoire votre fichier de configuration<br />
et remplacer <strong>TP</strong>5 par WCFG dans l’appel à make. Ex :<br />
make run_simu WCFG=pgcd.<br />
Question 5 Ecrire dans un fichier src/copy.mem le programme en hexadécimal trouvé à la<br />
question 1 du travail préparatoire en respectant la syntaxe des fichiers mem, puis lancer une<br />
simulation pour vérifier votre travail :<br />
make run_simu <strong>TP</strong>5=copy<br />
2. Vu que ca sera votre boulot de les écrire dans le module CEP.
Ex. 3 : Exécution du programme sur la carte FPGA<br />
Pour faire les exécutions sur carte, il suffit de taper la commande :<br />
make run_FPGA <strong>TP</strong>5=<br />
Le makefile modifiera alors le contenu du fichier de configuration du FPGA et programmera ce<br />
dernier 3 .<br />
En cas d’erreur, le makefile fourni ne donne aucune indication. Afin d’avoir plus d’informations,<br />
il suffit de mettre dans la ligne de commande la variable VERB à 1 :<br />
make run_FPGA <strong>TP</strong>5= VERB=1<br />
Question 1 Implantez sur la carte le circuit avec les programmes pgcd et copy des questions<br />
précédentes et vérifiez leur bon <strong>fonctionnement</strong>. Pensez à initialiser avec le bouton poussoir<br />
« user reset » le circuit pour charger votre programme.<br />
Comme il est fastidieux de traduire à la main un programme du langage d’assemblage au<br />
langage machine, on vous fournit un assembleur réalisant cette tâche pour vous à condition de<br />
respecter la syntaxe introduite dans le fichier pgcd.s.<br />
Question 2 Recopiez les solutions trouvées durant les questions 2 et 3 de l’exercice préparatoire<br />
dans les fichiers src/cligno.s et src/chenillard.s. Vérifiez directement sur carte leur<br />
<strong>fonctionnement</strong>.<br />
Si ça ne marche pas comme vous l’espériez, vérifiez en simulation que votre programme est correct.<br />
Question 3 Ouvrez le fichier mystere.mem fourni. A votre avis, que fait-il ?<br />
Implantez le sur la carte et vérifiez.<br />
Question 4 Il vous reste du temps. Pourquoi ne pas s’amuser avec vos propres programmes ?<br />
Quelques idées en vrac :<br />
– Coder la multiplication vue au TD10.<br />
– Coder le LFSR vu en <strong>TP</strong>1.<br />
– Ecrire un programme PGCD "interactif". Ce programme peut lire A puis B sur les interrupteurs,<br />
en utilisant un bouton poussoir pour valider une valeur, puis affiche le résultat<br />
soit sur les LED, soit sur l’afficheur 7 segments.<br />
3. à condition qu’il soit correctement branché bien sur ! !
Ex. 4 : Annexes<br />
Table des périphériques :<br />
Périphérique Accès Adresse Action<br />
LEDs écriture 0x4000 Affiche l’octet de poids faible écrit<br />
par le <strong>processeur</strong> sur les LED<br />
afficheurs écriture 0x4004 Affiche en hexa les 2 octets de<br />
7 segments poids faible<br />
interrupteurs lecture 0x4008 récupère la valeur sur les 8<br />
interrupteurs et met des 0 sur les bits de poids forts<br />
boutons poussoir lecture 0x400C récupère la valeur sur les 3 boutons poussoirs<br />
timer lecture 0x4010 récupère la valeur du timer (actif à 0)<br />
Partie Opérative du <strong>processeur</strong> :<br />
Jeux d’instructions :<br />
Le MIPS a un jeu d’instructions à 3 opérandes et ses instructions sont réparties dans 3 formats<br />
différents :<br />
31 2625 2120 1615 1110 65 0<br />
Format R : opcode RS RT RD SH FUNC<br />
Format I : opcode RS RT IMM16<br />
Format J : opcode<br />
IMM26
Dans ce <strong>TP</strong>, nous considérerons les instructions suivantes :<br />
Nmémonic/ For- Opcode/ Opération Nom<br />
syntaxe mat Func Complet<br />
addiu $rt, $rs, imm I 0x9 R[rt]=R[rs]+SignExtImm 1 addition non signée avec<br />
un immédiat<br />
addu $rd, $rs, $rt R 0x0/0x21 R[rd]=R[rs]+R[rt] addition non signée entre registres<br />
and $rd, $rs, $rt R 0x0/0x24 R[rd]=R[rs] & R[rt] ET bit à bit entre registres<br />
andi $rt, $rs, imm I 0xC R[rt]=R[rs] & ZeroExtImm 2 ET bit à bit avec un immédiat<br />
beq $rs, $rt, label I 0x4 if(R[rs]== R[rt]) Branchement si égalité<br />
PC=PC+4+BranchAddr 3<br />
bne $rs, $rt, label I 0x5 if(R[rs] != R[rt]) Branchement si inégalité<br />
PC=PC+4+BranchAddr 3<br />
j label J 0x2 PC = JumpAddr 4 Saut inconditionnel<br />
lui $rt, imm I 0xF R[rt] = IMM16|0 16 Chargement immédiat haut<br />
lw $rt, imm($rs) I 0x23 R[rt] = chargement registre<br />
mem[R[rs]+SignExtImm 1 ]<br />
or $rd, $rs, $rt R 0x0/0x25 R[rd] = R[rs] | R[rt] OU bit à bit registre à registre<br />
ori $rt, $rs, imm I 0xD R[rt] = R[rs] | ZeroExtImm 2 OU bit à bit avec immédiat<br />
slt $rd, $rs, $rt R 0x0/0x2A R[rd] = (R[rs] < R[rt]) ? 1 : 0 Set Less Than registre à registre<br />
slti $rt, $rs, imm I 0xA R[rt] = Set Less Than avec immédiat<br />
(R[rs] < SignExtImm 1 ) ? 1 : 0<br />
sll $rd, $rt, sh R 0x0/0x0 R[rd] = R[rt] « SH décalage à gauche<br />
srl $rd, $rt, sh R 0x0/0x2 R[rd] = R[rt] » SH décalage logique à droite<br />
subu $rd, $rs, $rt R 0x0/0x23 R[rd]=R[rs]-R[rt] soustraction non signée entre<br />
registres<br />
sw $rt, imm($rs) I 0x2B mem[R[rs]+SignExtImm 1 ] stockage registre<br />
= R[rt]<br />
xori $rt, $rs, imm I 0xE R[rt] = R[rs] XOR ZeroExtImm OU exclusif bit à bit avec<br />
un immédiat<br />
1. SignExtImm = IMM16 16<br />
15|IMM16<br />
2. ZeroExtImm = 0 16 |IMM16<br />
3. BranchAddr = IMM16 16<br />
14|IMM16|0 2<br />
4. JumpAddr = (P C + 4) 31···28|IMM26|0 2