05.06.2015 Views

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

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!