12. TP CPU¶
Le processeur, aussi appelé CPU (Central processing Unit) ou unité de traitement central, lit des instructions dans la mémoire programme et les exécute.
Tout ce que le processeur fait peut être décrit en 3 lignes:
chercher une instruction dans la mémoire de programme (Fetch)
exécuter cette instruction (Execute)
incrémenter le pointeur vers la prochaine instruction (Increment)
Dans cette section nous allons étudier comment encoder des instructions en code binaire, et comment ensuite exécuter ce code dans le CPU. Nous allons nous inspirer du premier microprocesseur, la puce Intel 4004, sortie en 1971.
12.1. Intel 4004¶
Le premier CPU sur un seul circuit intégré fut le 4004 commercialisé par Intel en 1971. Il contenait les éléments suivants:
une ALU (unité arithmétique et logique)
16 registres de travail
un accumulateur (accumulator)
un bus de données (data bus)
un bus d’adresses (adress bus)
des fanions (flags)
un registre d’instruction (instruction register)
un compteur de programme (program counter)
un pointeur de pile (stack pointer)
une pile (stack)
une unité de contrôle (control unit)
Voici le schéma de l’architecture du 4004.
12.2. Langage assembleur¶
Nous allons commencer tout de suite avec un exemple de programme pour le 4004, en langage assembleur. Voici un bout de programme qui additionne deux nombres 4 bits.
ADD2
; add two 4bit numbers on the Intel 4004
;
FIM P0, $A2 ; initialize: R0=2 R1=A
LDR R0 ; load R0 into accumulator
ADD R1 ; add R1 into accumulator
XCH R1 ; and store in R1
Le point-virgule (;
) sert comme symbole de commentaire. C’est l’équivalent du #
en Python.
Un programme en assembleur est typiquement structuré en 4 colonnes :
Une étiquette pour désigner une adresse de programme (
ADD2
)Une mnémonique de l’opération (
FIM
,LDR
,ADD
,XCH
)Des données (P0, $A2, R0, R1)
Des commentaires en fin de ligne
12.3. Le langage machine¶
Le langage machine, ou code machine, est la suite de bits qui est interprétée par le processeur d’un ordinateur exécutant un programme informatique. C’est le langage natif d’un processeur, c’est-à-dire le seul qu’il puisse traiter. Il est composé d’instructions et de données à traiter codées en binaire.
1000RRRR
additionne (ADD) le registreRRRR
à l’accumulateur1001RRRR
soustrait (SUB) le registreRRRR
de l’accumulateur1101DDDD
charge (LDM = load) le nombreDDDD
vers l’accumulateur
Le code machine est composée de :
la partie instruction ou opcode, tel que
1000=ADD
,1001=SUB
la partie donnée ou data, qui indique un registre
RRRR
où un nombreDDDD
Par exemple l’instruction en assembleur ADD R3
se traduit en code machine comme 10000011
.
Trouvez les deux autres codes machine.
12.4. Mémoire de programme¶
Le CPU 4004 traite des données de 4 bits. Les données que ce processeur peut traiter avec une seule instruction sont limitées à une plage de 0 à 15 (de 0000
à 1111
). On dit que c’est un processeur 4 bits ou une architecture 4 bits.
Chaque instruction par contre est encodée sur 8 bits. Ce processeur pourrait donc avoir au maximum 256 instructions différentes. En réalité il a 46 instructions.
Le vrai CPU 4004 peut adresser un espace mémoire de programme avec une adresse 12 bits. Ceci lui permet d’adresser un maximum de \(2^{12}\) instructions différentes dans sa mémoire programme. Ici nous simplifions beaucoup et utilisons des adresses de 4 bits. Notre mémoire programme a une taille de 16 x 8 bits. Notre programme peut avoir un maximum de 16 instructions.
Beaucoup d’instructions sont composées d’une partie
instruction (4 bits), appelée opcode
données (4 bits), appelé data
Dans le circuit ci-dessous, ajoutez :
une broche 4 bits
une sortie 4 bits
un affichage 4 bits (en hexadécimal)
une étiquette opcode
Mettez les instructions
ADD R3
,SUB R15
etLDM 13
dans les 3 premiers octets de la mémoire programme.
12.5. Le jeu d’instructions¶
On appelle jeu d’instruction (instruction set) la totalité des instructions qu’un processeur peut exécuter. Ces instructions sont représentées par une abréviation à 3 lettres (mnémonique). Les premières 14 instructions sont composées d’une partie:
instruction (4 bits), appelée opcode, de
0000
à1101
données (4 bits), appelé data
La partie `data’ peu représenter 3 types de données :
AAAA
une adresse dans la mémoire programmeRRRR
un registre dans la banque des registresDDDD
une donnée immédiate (un nombre de 0 à 15)
NOP 00000000 No Operation
JCN 0001AAAA Jump Conditional
FIM 0010RRR0 DDDDDDDD Fetch Immediate
FIN 0011RRR0 Fetch Indirect
JUN 0100AAAA Jump Unconditional
JMS 0101AAAA Jump to Subroutine
INC 0110RRRR Increment
ISZ 0111RRRR AAAAAAAA Increment and Skip
ADD 1000RRRR Add register
SUB 1001RRRR Subtract register
LDR 1010RRRR Load register
XCH 1011RRRR Exchange register
BBL 1100DDDD Branch Back and Load
LDM 1101DDDD Load Immediate data
12.6. Décoder une instruction¶
Pour décoder les 14 instructions, nous pouvons utiliser un démultiplexeur. Pour compléter le circuit de décodage d’instruction :
Ajoutez un deuxième démultiplexeur
Ajoutez les 11 sorties manquantes
Ajoutez les étiquettes (
FIN
àLDM
)Remplissez la mémoire programme avec les 14 instructions (
NOP
àLDM
)Vérifiez que chaque instruction est décodée correctement
Par exemple à l’adresse 0100
(4) se trouve l’instruction 00010001
(JCN 1
) et le décodeur active correctement la sortie JCN
.
12.7. Bus 4 bits¶
Une ALU doit acheminer différents signaux sur une même ligne de transfert des données. On appelle un tel chemin un bus de données. Pour y connecter plusieurs sources, nous devons utiliser un multiplexeur.
Ajoutez une deuxième entrée 4 bits
Liez le multiplexeur et le démultiplexeur à travers une broche 4 bits
Ajoutez les 2 entrées de sélection
Ajoutez 4 affichages 4 bits pour montrer tous les signaux
12.8. Charger imméd. (LDM)¶
La commande LDM
(Load immediate) va charger une valeur directe (0-15), contenue dans le code de l’instruction, dans l’accumulateur.
1101DDDD
La partie 1101
est l’opcode (LDM
) et la partie DDDD
représente les 4 bits des données à charger dans l’accumulateur.
Liez les bits b0-b3 avec l’accumulateur
Utilisez la porte ET pour charger cette valeur dans l’accumulateur seulement si le signal execute est activé ET l’instruction
LDM
est décodéePlacez un affichage à la sorte de l’accumulateur et à la sortie de l’ALU
Mettez une valeur dans les bits b0-b3 et exécutez l’instruction avec execute
12.9. Charger depuis reg (LDR)¶
L’instruction LDR
(load from register) charge l’accumulateur avec le contenu d’un des 16 registres.
1010RRRR
La parte 1010
est l’opcode (LD) et la parte RRRR
représente un des 16 registres
Ajoutez la RAM avec les 16 registres
Créez le circuit de décodage pour charger registre
RRRR
dans l’accumulateurPlacez un affichage à la sortie de l’accumulateur et à la sortie de l’ALU
Mettez une valeur dans
R5
Mettez l’instruction
LDR R5
et exécutez l’instruction avec execute
12.10. Choix entre LDR/LDM¶
Avec les deux opcode différents, le circuit de décodage du CPU choisit un registre ou une donnée immédiate comme valeur à charger dans l’accumulateur.
Ajoutez la RAM avec les 16 registres
Ajoutez un multiplexeur 8x4
Créez le circuit de décodage pour choisir entre un registre
RRRR
ou une donnée immédiateDDDD
Placez un affichage à la sortie de l’accumulateur et à la sortie de l’ALU
Mettez une valeur dans
R5
Mettez l’instruction
LDR R5
et exécutez l’instruction avec executeMettez l’instruction
LDM 13
et exécutez l’instruction avec execute
12.11. Choix entre ADD/SUB¶
L’addition et la soustraction se distinguent dans l’opcode d’un seul bit.
1000RRRR
ADD additionner registreRRRR
à l’accumulateur1001RRRR
SUB soustraire registreRRRR
de l’accumulateur
Créez le circuit pour décoder et exécuter ces deux instructions.
Ajoutez la RAM avec les 16 registres
Créez le circuit de décodage pour choisir entre
ADD
etSUB
Placez un affichage à la sortie de l’accumulateur et nommez le acc (y mettre 9)
Placez un affichage à la sortie de la RAM et nommez le reg
Placez un affichage à la sortie de l’ALU et nommez le result
Mettez la valeur 3 dans
R5
Mettez l’instruction
ADD R5
et vous devriez avoir result = 12 (9 + 3)Mettez l’instruction
SUB R5
et vous devriez avoir result = 6 (9 - 3)
12.12. Program counter (PC)¶
Le pointeur de programme, PC (program counter), pointe toujours à la prochaine instruction dans la mémoire de programme. Le contenu à l’adresse pointé par le PC est celui qui est chargé dans le registre d’instruction (IR) et exécuté au prochain pas.
Liez la sortie du PC avec l’entrée A du l’ALU pour incrémenter de 1 à chaque pas
Placez un affichage à la sortie du registre et nommez le PC
Liez le PC avec l’entrée adresse de la mémoire de programme
Liez l’entrée clock avec l’horloge de l’ALU et l’horloge des deux registres IR
Faites avancer le PC et chargez des instructions successives dans le registre IR
12.13. Le saut (jump)¶
Le saut est une instruction qui permet de changer l’avancement linéaire du compteur de programme. L’instruction de saut a la forme :
Jump Uncoditional JUN 0100AAAA
Pour l’exécuter, le CPU doit d’abord détecter l’opcode 0100
. Ceci peut être fait avec une porte ET à 4 entrées et des inverseurs.
Ensuite la valeur actuelle du compteur de programme doit être remplacée par la nouvelle adresse de destination du saut AAAA
. Pour ceci nous utilisons un multiplexeur 8 vers 4.
Utilisez des portes NON et ET pour décoder l’opcode 0100
et l’utiliser pour sélectionner entre incrémentation normale et destination de saut.
A l’adresse 14 se trouve l’instruction 01000011
(JUN 3
). Si le décodeur fonctionne correctement le programme va faire une boucle entre les addresses 3 et 14.
12.14. La pile (stack)¶
La pile est un espace de sauvegarde temporaire. Elle est utilisée pour sauvegarder les adresses de retour lors d’un saut vers une sous-routine.
Ici nous créons une pile de 16 mots à 4 bits. D’habitude on commence la pile en bas de l’espace mémoire (adresse 15) et on empile les valeurs.
Le pointeur de pile (stack pointer) est un registre 4 bit, qui utilise une ALU pour être incrémenté ou décrémenté.
Si l’entrée Op = 0
il incrémente. Si l’entrée Op = 1
il décrémente.
Ajoutez les circuits de contrôle.
Le signal clear efface la pile et met le pointeur de pile à
1111
(tout en bas)Le signal push choisit la décrémentation (sp–) et envoie un coup d’horloge vers le registre du pointeur et la pile
Le signal pop choisit l’incrémentation (sp++) et envoie un coup d’horloge vers le registre du pointeur et la pile
Mettez dans la pile 3141592
(les 7 premiers chiffres du nombre pi) avec l’instruction push.
Ensuite, lisez ces chiffres dans l’ordre inverse avec l’instruction pop
12.15. Projet final¶
Ouvrez l’éditer logique dans une page entière du navigateur et choisissez un des projets suivants:
Complétez l’architecture du CPU 4004 pour en faire un processeur fonctionnel.
Voici le jeu d’instructions complet.Créez une calculatrice avec les touches 0 à 10, les opérations + et -, et un affichage à 7 segments avec 4 chiffres ou plus. Le point décimal est optionnel.
Créez une horloge avec un affichage à 7 segments du style
HH:MM:SS
, avec des boutons up/down pour mettre le temps.Créez un minuteur avec un affichage à 7 segments du style
MM:SS
qui décompte, avec des boutons up/down pour mettre le temps, et des boutons start/stop/clear.Créez un chronomètre avec un affichage à 7 segments du style
MM:SS.S
qui affiche des dixièmes de seconde. Ajoutez des boutons start/stop/clear.
12.16. Nand Game¶
Dans le jeu Nand Game vous allez construire un ordinateur à partir de composants de base.
Le jeu se compose d’une série de niveaux. Dans chaque niveau, vous êtes chargé de construire un composant qui se comporte selon une spécification. Ce composant peut ensuite être utilisé comme bloc de construction dans le niveau suivant.
Le jeu ne nécessite aucune connaissance préalable de l’architecture informatique ou des logiciels, et ne nécessite aucune compétence en mathématiques au-delà de l’addition et de la soustraction. (Cela demande un peu de patience - certaines tâches peuvent prendre un certain temps à résoudre !)
Votre première tâche est de créer un composant nand (Non-Et).
Bonne chance!