fonctionnement d`un processeur

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