Explorer les Livres électroniques
Catégories
Explorer les Livres audio
Catégories
Explorer les Magazines
Catégories
Explorer les Documents
Catégories
Microprocesseur
Master I
Dr A. M. CHANA LEMALE
Tables des Matières
I. Généralités
Le système le plus couramment utilisé est le système décimal qui utilise les chiffres de 0
à 9, c'est le système de référence. Le nombre de chiffres utilisés dans un système
s'appelle sa base. Les machines digitales ou numériques fonctionnent en binaire, c'est-à-
dire selon le système de base 2.
En particulier on a :
0 et 1 : base 2
0à7: base 8
0 à 9 et de A à F : base 16
Si B est la base, alors un nombre entier N en base B s'exprime sous la forme :
𝑁 = 𝑎𝑛 𝑏 𝑛 + 𝑎𝑛−1 𝑏 𝑛−1 … . 𝑎1 𝑏1 + 𝑎0
Ou
𝑁 = 𝑎𝑛 𝑎𝑛−1 … . 𝑎1 𝑎0 en notation de position. La position d'un chiffre rappelle la
puissance de la base qui multiplie ce chiffre. Dans le cas des ai c'est Bi.
En base 10
152 = 1 x 102 + 5 x 101+ 2 x 100 ce qui s'écrit encore :
a2a1a0 = a2102 + a1101+a0100
Un nombre fractionnaire P, c'est-à-dire compris entre 0 et 1 s'exprime sous la forme
suivante dans la base B:
𝑃 = 𝑎−1 𝑏 −1 + 𝑎−2 𝑏 −2 + ⋯ + 𝑎−𝑛 𝑏 −𝑛
Ou
𝑃 = 0. 𝑎−1 𝑎−2 … . 𝑎−𝑛 en notation de position.
On fait précéder le premier chiffre non nul de "0." pour signifier que c'est un nombre
décimal. La puissance de la base qui correspond à un rang donné s'appelle le poids de ce
nombre. Pour éviter des confusions, du fait que les mêmes chiffres sont communs à
plusieurs bases, on spécifie la base de la manière suivante :
13 (13)10 (1101)2 (15)8 (D)16
Ou
13 1310 11012 158 D16
1. Partie entière
On a N = (anan-1…a1a0)𝛼 on veut avoir N =(cmcm-1…c1c0)𝛽
Il y a deux méthodes :
i. On connait la table de conversion de chiffre entre les deux bases, on connait la table de
multiplication dans la base 𝛽. On connait la table de l’addition dans la base 𝛽. On écrit N
dans sa base polynômiale qui est :
c11
On a donc (111011000101)2
En base 8 on a
3781 8
472 8 5
59 8 0 qui donne (7305)8
7 8 3
7 8 7
0
En base 16 on a
3781 16 5
236 16 C d’où (EC5)16
16 E
0
𝑦 = ∑ 𝑐𝑘 𝛽 −𝑘 = (0. 𝑐1 𝑐2 … 𝑐𝑚 )𝛽
𝑘=1
𝑦𝛽 = 0. 𝑐1 𝑐2 𝑐3 … 𝑐𝑚
Chaque ci obtenu est la partie entière du produit yi*β. On recommence le processus avec
la partie fractionnaire de ce même produit jusqu’à ce que celle-ci devienne 0 ou qu’on
obtienne une séquence de répétions.
Soit x le nombre, on définit par E(x) la partie entière de x et F(x) la partie fractionnaire
de x avec 0 ≤ 𝑥 < 1. La conversion de x en base 𝛽 se fait de la manière suivante :
On définit d0= x et d1 = F(𝛽d0), c1=E(𝛽d0) ; d2=F(𝛽d1), c2=E(𝛽d1) jusqu’à
dm=F(𝛽dn-1), cm=E(𝛽dm-1). Obtient ainsi la représentation de x=(0.c1c2…cm)
Exemple : x=(0,825)10 convertir en binaire
0.825
× 2
d0= c0=1
1.650
0.650 0.600
× 2 × 2
d1= c1=1 d 3= c3=1
1.300 1.200
0.300 0.200
× 2 × 2
d2= c2=0 d 4= c4=0
0.600 0.400
0.400 0.800
× 2 × 2
d5= c5=0 d6= c6=1
0.800 1.600
n = m / logb
Ainsi par exemple, si m = 3(exemple précédent), on aura respectivement n = 10 en
binaire, 4 en octal et 3 en hexa.
a. Conversion 2 8 16
(i) 2 8
On suppose que n+1 est un multiple de 3 sinon on adjoint des zéros au début pour en
faire. On constate alors que les puissances de 2 dans la nouvelle expression peuvent se
mettre sous forme d’une puissance de 8. Les coefficients de chacune de ces puissances
sont des chiffres de la base 8. Chacun étant constitué de 3 chiffres binaires, on retrouve
la subdivision précédente
F(𝑥) = 2−3 (4𝑏1 + 2𝑏2 + 𝑏3 ) + 2−6 (4𝑏4 + 2𝑏5 + 𝑏6 ) + ⋯ + 2−𝑚 (4𝑏𝑚−2 + 2𝑏𝑚−1 + 𝑏𝑚 )
(ii) 2↔ 𝟏𝟔
a) Addition
𝑥 𝑦 𝑥+𝑦 𝑟
0 0 0 0
0 1 1 0
1 0 1 0
1 1 0 1
b) Multiplication
𝑥 𝑦 𝑥∗𝑦
0 0 0
0 1 0
1 0 0
1 1 1
c) Division
𝑥 𝑦 𝑥/𝑦
0 0 !
0 1 0
1 0 !
1 1 1
0 0 0 0
0 1 1 1
1 0 1 0
1 1 0 0
1. Nombre en complément
La représentation des nombres en complément facilite l’opération de soustraction dans les
ordinateurs. Ainsi, au lieu de soustraire, on ajoute le complément.
Exemple : 𝑥 − 𝑦 ⟺ 𝑥 + (𝑐𝑜𝑚𝑝𝑙𝑒𝑚𝑒𝑛𝑡 𝑑𝑒 𝑦).
Pour chaque base𝛽, il existe 2 types de complément d’un nombre.
- Le complément à 𝛽
- Le complément à 𝛽 − 1
Exemple : base 10 : complément à 10, à 9
Base 2 : complément à 2, à 1
i) complément à 𝛽 − 1
ii) complément à 𝛽
Soit un nombre x représenté avec n bits. x se mettant sous la forme : (𝛼𝑛−1 𝛼𝑛−2 … . . 𝛼0 )𝛽.
Le complément à 𝛽 𝑑𝑒 𝑥 est égal à : 𝛽 𝑛 − 𝑥 = (𝛽 𝑛 − 1) − 𝑥 + 1
Le complément à 𝛽 d’un nombre x est défini comme 𝛽 𝑛 − 𝑥 en l’exprimant sous la
forme(𝛽 𝑛 − 1) − 𝑥 + 1. On en déduit que le complément à 𝛽 est égal au complément à
(𝛽 − 1) + 1.
Pour trouver le complément d’un nombre à 𝛽on parcoure le nombre de la droite vers la
gauche en copiant tous les 1ers zéros rencontrés avant la premier chiffre non nul qui
sera remplacé par son complément à 𝛽 et le reste des chiffres par leur complément à 𝛽 −
1.
2. Soustraction en complément
L’inconvénient avec cette approche (nombre sans signe) c’est qu’il faut comparer M et N
pour savoir ce qu’il faut faire du résultat. On contourne cette difficulté en représentant
les nombres avec signe.
Le premier bit représente le signe, le reste c.-à-d. n-1 la valeur absolue du nombre
Exemple : n=8 représentation de 5 et -5
00000101 et 10000101 respectivement
ii) complément à 1 avec le signe
On représente la valeur absolue du nombre sur les n bits et on le remplace par son
complément à r y compris le 1er bit (s’il est négatif on le remplace par son complément à r)
Remarque :
• Nous avons un débordement si la somme de deux nombres positifs donne un
nombre négatif.
• Ou la somme de deux nombres négatifs donne un Nombre positif
• Il n’y a jamais un débordement si les deux nombres sont de signes différents.
Exemple : n=4
-(23-1) [-7,7] complément à 1 et signe + | |
[-8,7] complément à 2
1. Virgule fixe
Dans cette représentation la partie entière est représentée sur n bits et la partie
fractionnelle sur p bits, en plus un bit est utilisé pour le signe.
Exemple : si n=3 et p=2 on va avoir les valeurs suivantes
0 000 00 + 0,0
0 000 01 + 0,25
0 000 10 + 0,5
0 000 11 + 0,75
0 001 .00 + 1,0
. . . .
. . . .
2. Virgule Flottante
En interne, les nombres réels sont représentés à l’aide d’une notation spéciale appelée
virgule flottante. La représentation se fait à l’aide d’un mot en précision simple et de
plusieurs mots en grande précision.
Pour un mot de n bits, la représentation se décompose de la façon suivante :
1 n1 n2
Signe de la
mantisse
Mantisse
Exposant
sur n2 bits
sur n1 bits
n=1+n1+n2 (nombre de chiffres qu’il faut pour la représentation)
Pour 𝛼1 𝑜𝑛 𝑎 1 ≤ 𝛼𝑖 ≤ 𝛽 − 1
Si 𝛼𝑖 est égal à zéro alors 𝑓 = 0
- L’exposant t est un entier relatif, il peut être représenté sous la forme à complément ou
sous la forme signe + | | ou sous une forme spéciale dite biaisée.
1 0 1 0 0 1 1 0 1 0 0 0 0
Remarque : si la mantisse est sur k bits et si elle est représentée dans la machine sur
k’ bits tel que k> k’, alors la mantisse sera tronquée : on va prendre uniquement k’ bits
perdre dans la précision.
Forme biaisée
En complément à 2, l’intervalle des valeurs qu’on peut représenter sur p bits :
-2 (p -1) ≤ N ≤ 2 (p -1) -1
Si on rajoute la valeur 2 (p -1) à tous les termes de cette inégalité :
- 2 (p -1) + 2 (p -1) ≤ N + 2 (p -1) ≤ 2 (p -1) - 1 + 2 (p -1)
0 ≤ N + 2 (p -1) ≤ 2p - 1
Exemple :
On veut représenter les nombres (0,015)8 et -(15, 01)8 en virgule flottante dans une
machine ayant le format suivant :
Signe mantisse Exposant biaisé Mantisse normalisée
Un nombre flottant simple précision est stocké dans un mot de 32 bit : 1 bit de signe, 8
bits pour l'exposant et 23 pour la mantisse.
L'exposant est décalé de 28 − 1 − 1 = 127 dans ce cas. L'exposant va donc de -126 à +127.
Un exposant de -127 serait décalé vers la valeur 0, mais celle-ci est réservée pour 0 et les
nombres dé-normalisés. Un exposant de 128 serait décalé vers 255, qui est réservé pour
coder les infinis, et les NaNs (Not a Numbers). Il y a trois cas particuliers :
si l'exposant et la mantisse sont tous deux nuls, le nombre est ±0 (selon le bit de
signe)
si l'exposant est égal à 2e – 1 (1 sur tous les bits de l’exposant), et si la
mantisse est nulle, le nombre est ±infini (selon le bit de signe)
si l'exposant est égal à 2e − 1, mais que la mantisse n'est pas nulle, le nombre est
NaN (not a number : pas un nombre)
Remarque :
La version 1985 de la norme IEEE 754 définit 4 formats pour représenter des nombres à
virgule flottante :
simple précision (32 bits : 1 bit de signe, 8 bits d'exposant (-126 à 127), 23 bits de
mantisse, avec bit 1 implicite),
simple précision étendue (≥ 43 bits, obsolète, implémenté en pratique par la double
précision),
double précision (64 bits : 1 bit de signe, 11 bits d'exposant (-1022 à 1023), 52 bits de
mantisse, avec bit 1 implicite),
double précision étendue (≥ 79 bits, souvent implémenté avec 80 bits : 1 bit de signe,
15 bits d'exposant (-16382 à 16383), 64 bits de mantisse, sans bit 1 implicite).
I. Introduction
Un microprocesseur est un circuit intégré complexe caractérisé par une très grande
intégration et doté des facultés d'interprétation et d'exécution des instructions d'un
programme.
Il est chargé d’organiser les tâches précisées par le programme et d’assurer leur
exécution. Il doit aussi prendre en compte les informations extérieures au système et
assurer leur traitement. C’est le cerveau du système.
A l’heure actuelle, un microprocesseur regroupe sur quelques millimètres carrés des
fonctionnalités toujours plus complexes. Leur puissance continue de s’accroître et leur
encombrement diminue régulièrement, on parlera d'ici peu de "nanoprocesseur".
Les applications des systèmes à microprocesseurs sont multiples et variées :
Ordinateur, PDA
console de jeux
calculatrice
télévision
téléphone portable
distributeur automatique d’argent
robotique
lecteur carte à puce, code barre
automobile
instrumentation
etc…
Remarque :
Il existe deux types de registres :
les registres d'usage général permettent à l'unité de traitement de manipuler des
données à vitesse élevée. Ils sont connectés au bus de données interne au
microprocesseur.
les registres d'adresses (pointeurs) connectés sur le bus adresses.
A. L’unité de commande
B. L’unité de traitement
C’est le cœur du microprocesseur. Elle regroupe les circuits qui assurent les
traitements nécessaires à l'exécution des instructions :
L’Unité Arithmétique et Logique (UAL) est un circuit complexe qui assure les
fonctions logiques (ET, OU, Comparaison, Décalage, etc…) ou arithmétique
(Addition, soustraction).
Le registre d'état est généralement composé de 8 bits à considérer individuellement.
Chacun de ces bits est un indicateur dont l'état dépend du résultat de la dernière
opération effectuée par l’UAL. On les appelle indicateur d’état ou flag ou drapeaux.
Dans un programme le résultat du test de leur état conditionne souvent le
déroulement de la suite du programme. On peut citer par exemple les indicateurs de :
- retenue (carry : C)
- retenue intermédiaire (Auxiliary-Carry : AC)
- signe (Sign : S)
- débordement (overflow : OV ou V)
- zéro (Z)
- parité (Parity : P)
Les accumulateurs sont des registres de travail qui servent à stocker un opérande au
début d'une opération arithmétique et le résultat à la fin de l'opération
𝐅𝐇
𝐌𝐈𝐏𝐒 = avec FH en MHz
𝐂𝐏𝐈
A. Définition
B. Type d’instruction
Les instructions que l’on trouve dans chaque microprocesseur peuvent être
classées en quatre groupes :
i) Transfert de données : Pour charger ou sauvegarder en mémoire, effectuer des
transferts de registre à registre, …
ii) Opérations arithmétiques : Addition, soustraction, division et multiplication.
C. Codage
Spécificateur Champ
Opération
d’adresse 1 d’adresse
Généralement, le type d’un opérande (par exemple, entier, flottant simple précision,
caractère) donne sa taille. Les types courants d’opérandes comprennent le caractère (un
octet), le demi-mot (16 bits), le mot (32 bits), flottant simple précision (un mot) et flottant
double précision (deux mots). Les caractères sont presque toujours représentés en ASCII et
les entiers sont presque universellement représentées comme des binaires en compléments à
deux.
A. L’architecture CISC
Pourquoi
Par le passé la conception de machines CISC était la seule envisageable. En effet, vue que la
mémoire travaillait très lentement par rapport au processeur, on pensait qu’il était plus
intéressant de soumettre au microprocesseur des instructions complexes. Ainsi, plutôt que de
coder une opération complexe par plusieurs instructions plus petites (qui demanderaient autant
d’accès mémoire très lent), il semblait préférable d’ajouter au jeu d’instructions du
microprocesseur une instruction complexe qui se chargerait de réaliser cette opération. De plus,
le développement des langages de haut niveau posa de nombreux problèmes quant à la
conception de compilateurs. On a donc eu tendance à incorporer au niveau processeur des
instructions plus proches de la structure de ces langages.
Comment
C’est donc une architecture avec un grand nombre d’instructions où le microprocesseur doit
exécuter des tâches complexes par instruction unique. Pour une tâche donnée, une machine
CISC exécute ainsi un petit nombre d’instructions mais chacune nécessite un plus grand nombre
de cycles d’horloge. Le code machine de ces instructions varie d’une instruction à l’autre et
nécessite donc un décodeur complexe (micro-code)
B. L’architecture RISC
Pourquoi
Des études statistiques menées au cours des années 70 ont clairement montré que les
programmes générés par les compilateurs se contentaient le plus souvent d'affectations,
d'additions et de multiplications par des constantes. Ainsi, 80% des traitements des langages de
haut niveau faisaient appel à seulement 20% des instructions du microprocesseur. D’où l’idée
de réduire le jeu d’instructions à celles le plus couramment utilisées et d’en améliorer la vitesse
de traitement.
C’est donc une architecture dans laquelle les instructions sont en nombre réduit (chargement,
branchement, appel sous-programme). Les architectures RISC peuvent donc être réalisées à
partir de séquenceur câblé. Leur réalisation libère de la surface permettant d’augmenter le
nombre de registres ou d’unités de traitement par exemple. Chacune de ces instructions
s’exécutent ainsi en un cycle d’horloge. Bien souvent, ces instructions ne disposent que d’un
seul mode d’adressage. Les accès à la mémoire s’effectuent seulement à partir de deux
instructions (Load et Store). Par contre, les instructions complexes doivent être réalisées à partir
de séquences basées sur les instructions élémentaires, ce qui nécessite un compilateur très
évolué dans le cas de programmation en langage de haut niveau.
C. Comparaison
Le choix dépendra des applications visées. En effet, si on diminue le nombre d'instructions, on
crée des instructions complexes (CISC) qui nécessitent plus de cycles pour être décodées et si on
diminue le nombre de cycles par instruction, on crée des instructions simples (RISC) mais on
Augmente alors le nombre d'instructions nécessaires pour réaliser le même traitement.
D. Processeurs spéciaux
Le microcontrôleur
Ce sont des systèmes minimum sur une seule puce. Ils contiennent un CPU, de la RAM, de la
ROM et des ports d’Entrée/Sorties (parallèles, séries, I2C, etc..). Ils comportent aussi des
fonctions spécifiques comme des compteurs programmables pour effectuer des mesures de
durées, des CAN voir des CNA pour s’insérer au sein de chaînes d’acquisition, des interfaces
pour réseaux de terrain, etc ...
Le processeur de signal
Le processeur de signal est beaucoup plus spécialisé. Alors qu'un microprocesseur n'est pas
conçu pour une application spécifique, le processeur DSP (Digital Signal Processor) est optimisé
pour effectuer du traitement numérique du signal (calcul de FFT, convolution, filtrage
numérique, etc...).
Les domaines d’application des D.S.P étaient à l’origine les télécommunications et le secteur
militaire. Aujourd’hui, les applications se sont diversifiées vers le multimédia (lecteur CD, MP3,
etc..) l’électronique grand public (télévision numérique, téléphone portable, etc…),
l’automatique, l’instrumentation, l’électronique automobile, etc…
I. Introduction
Nous présentons divers aspects de l'architecture des processeurs. Nous abordons les
notions de base nécessaires au lecteur voulant comprendre le fonctionnement d'un
microprocesseur. Notamment la notion de pipeline d'instruction et les traitements
qu'elle implique. Le fonctionnement des processeurs superscalaires, EPIC et VLIW sont
décrits afin d'illustrer l'utilisation des techniques matérielles d'accélération des calculs.
Une première opération fondamentale dans la mise en œuvre consiste à les uniformiser
en se positionnant dans le pire des cas. Le temps de cycle du pipeline sera défini par:
Pour chaque instruction et pour chaque phase, le timing d’exécution sera aligné sur Tcyc
permettant de garantir que dans tous les cas la phase i de l’instruction Ij puisse avoir le
temps de s’exécuter.
Donc lorsque le nombre n d’instructions à exécuter est grand par rapport à k, on peut admettre
qu’on divise le temps d’exécution par k.
Remarque :
Le temps de traitement dans chaque unité doit être à peu près égal sinon les unités rapides
doivent attendre les unités lentes.
Exemples :
L’Athlon d’AMD comprend un pipeline de 11 étages.
Les Pentium 2, 3 et 4 d’Intel comprennent respectivement un pipeline de 12, 10 et 20 étages.
L’organisation matérielle
L'utilisation des ressources dans le pipeline est représentée par des tables de réservation.
Par construction, dans notre première version simple du pipeline, toutes les instructions
ont exactement la même table de réservation.
D. Le pipeline instruction
A la différence du fonctionnement classique en mode séquentiel, le pipeline n’attend pas
la fin complète d’une instruction avant de démarrer la suivante: une nouvelle
instruction est lancée à chaque cycle. Exemple de code:
1 LDR #2, R3
2 MUL R5, R6, R7
3 LDI 8(R9), R12
4 LDR #4, R10
5 ADD R13, R14, R15
NOTE: Attention, la séquence ci-dessus a été choisie avec soin: ni dépendances de
données, ni dépendances de contrôle !! Les 5 instructions ci-dessus sont rigoureusement
indépendantes!!
Au début de chaque cycle, les instructions « entrent » dans l’étage suivant puis
effectuent le traitement correspondant et enfin se « synchronisent » pour passer à l’étage
suivant.
Il n’y a pas de conflit d’accès à la ressource suivante car par construction en un cycle,
chaque instruction dispose d’un temps suffisant pour effectuer le traitement requis (cf.
choix du temps de cycle).
Les étages fonctionnent en parallèle mais les instructions entrent séquentiellement dans
le pipeline conformément à l’ordre d’exécution de référence. Plus précisément, cet ordre
de référence va être conservé pour TOUTES les phases, ainsi les instructions finiront
(phase WB) dans le même ordre. Cette propriété de conservation de l’ordre est due au
fait que toutes les instructions ont la même table de réservation!!
La performance en mode pipeline ci-dessus ne peut être attends que s'il n'existe pas de
dépendances entre les instructions. Ces dépendances peuvent être de plusieurs ordres
I1 lit X; I1 écrit X;
I2 lit X I2 lit X
WAR: Write After Read WAW: Write After Write
I1 lit X; I1 écrit X;
I2 écrit X I2 écrit X
RAR (Consommateur/Consommateur)
RAW (Producteur/Consommateur)
I1 exécutée avant I3
I1 et I3 utilisent le même registre R7: I1 en écriture et I3 en lecture
WAR (Consommateur/Producteur)
I1 exécutée avant I3
I1 et I3 utilisent le même registre R4: I1 en lecture et I3 en écriture
WAW (Producteur/Producteur)
I1 exécutée avant I3
I1 et I3 utilisent toutes les deux le même registre R7 et en écriture
Le code précédent est idiot (n’a aucune raison d’être généré par un compilateur décent):
aucune instruction n’utilise la valeur produite par I1 dans R7!!
Les exemples précédents mettaient en jeu des registres mais le même type de
dépendance existe avec la mémoire. Le calcul des dépendances peut être effectué au
niveau matériel ou logiciel.
Il est à remarquer que la notion de dépendances de données est aussi utilisée pour les
programmes
Le résultat en sortie de l'ALU peut être intercepté avant l'écriture dans le fichier de
registres:
La cible et la direction d'un branchement sont connues très tard dans le pipeline. Au
plus tôt :
la prédiction de branchement
le délai de branchement
Une solution simple pour résoudre le problème est d'appliquer la technique du blocage
du pipeline jusqu'à ce que l'opérande source du branchement soit disponible. Cela
nécessite donc de bloquer le pipeline durant cinq cycles, avant de pouvoir débloquer
l'instruction de branchement. Cette solution est difficilement envisageable compte tenu
du nombre d'instructions de branchement conditionnel présent dans les programmes
classiques (environ une instruction sur cinq).
L'une des solutions possibles consiste à laisser le pipeline lire les instructions qui suivent
le branchement et à les annuler s'il le faut. Dans le cas ci-dessus, on constate qu'entre le
moment où le branchement entre dans le pipeline et le moment où l'on est capable de
savoir comment exécuter ce branchement, 5 instructions ont été lues par le processeur.
Au cycle 5, le registre R1 est produit, ce qui permet, au cycle 6 de connaître le
comportement du branchement. A partir de là, deux cas de figures peuvent se présenter:
La solution technique mise en œuvre pour annuler les instructions est une invalidation
des écritures des opérandes destinations. Le fait de rendre l'écriture dans les registres
résultats inactifs, transforme toutes ces instructions en instructions de type Nop. Cette
solution, bien que donnant un fonctionnement correct, n'est pas satisfaisante car elle
Le cycle suivant, le processeur va donc faire entrer dans son pipeline des instructions
dont il suppose l'exécution. On qualifie ces instructions de prédites, puisque l'on prédit
leur exécution sans pour autant être sur qu'elles sont à exécuter. Lorsque l'instruction
Sub termine son exécution, alors le processeur peut vérifier l'hypothèse qu'il avait faite.
Deux situations peuvent alors se produire :
Plusieurs prédicteurs ont été développés. Les plus anciens prédicteurs étaient simples et
peu coûteux à implémenter, mais ils ont rapidement été remplacés par des prédicteurs
plus complexes offrant de bien meilleures performances (on appelle performance d'un
prédicteur de branchement le taux de bonnes prédictions de celui-ci). Il est relativement
aisé d'observer que le nombre de cycles perdus en cas de mauvaise prédiction dépend
de la longueur du pipeline. Cette observation n'empêche pas pour autant les
constructeurs à allonger le pipeline de leurs processeurs. Il leur faut donc compenser
l'augmentation du nombre de cycles perdus lors d'une mauvaise prédiction par un taux
Les sections suivantes vont détailler les différentes techniques que l'on peut globalement
classer en deux catégories qui sont les techniques statiques et dynamiques.
Ces techniques sont dites statiques parce qu'elles proposent une méthode globale à tous
les branchements pour calculer l'hypothèse.
Des études sur le comportement des branchements ont montré que le comportement
moyen de ceux-ci dépendait beaucoup de leur sens. La notion de sens des branchements
permet de distinguer les branchements arrières et les branchements avants :
Il a été montré que les branchements arrières ont plutôt tendance à être pris par le
processeur. En effet, les branchements conditionnels arrières résultent très souvent de la
compilation de boucles. Or la caractéristique principale d'une boucle est évidemment
que les instructions situées dans la boucle vont être exécuté plusieurs fois. On donne ci-
dessous le code de haut niveau d'une boucle exécutant N fois un calcul élémentaire.
Program LI R0, @U
LI R1, @V
LI R2, @X
LI R3, N
Boucle
LI R4, (R0)
LI R5, (R1)
ADD R6, R5, R4
LI (R2), R6
ADD R0, R0, 1
ADD R1, R1, 1
ADD R2, R2, 1
SUB R3, R3, 1
BRNZ R3, Boucle
End EXIT
Pour ce qui concerne les branchements avants, ils sont typiquement issus de la
compilation d'un code ayant une structure si, alors, sinon telle que présentée dans le code
ci-dessous. Or, il a été montré, même si c'est moins évident, qu'ils ont plutôt tendance à
être non pris.
if (condition) else {
Instructions;
} else {
instructions ;
}
La question qui se pose alors est de savoir comment on conserve cet historique. La
première solution développée a consisté à attribuer un bit d'historique par branchement.
Une seconde solution a ensuite été développée accordant 2 bits pour le stockage du
comportement de chaque branchement.
Une table pour le stockage de cet historique des branchements est alors mise en place
dans le processeur. Comme sa taille est forcement limitée et que tous les historiques de
tous les branchements ne peuvent pas être conservés, alors le fonctionnement de cette
table d'historique est assimilable à un cache. Ne sont conservés que les historiques des
branchements les plus récemment exécutés. Cette table est ensuite utilisée par le
processeur afin de calculer l'hypothèse (la prédiction) et elle est mise à jour lorsque le
branchement s'exécute (vérification hypothèse). La figure ci-dessous montre dans quels
étages cette table est utilisée pour permettre une cohérence dans le processeur.
La prédiction de branchement dynamique à 1 bit met en œuvre un seul bit pour stocker
le comportement de chaque branchement. Ce bit mémorise alors un historique peu
ancien indiquant simplement comment le branchement s'est comporté lors de
l'exécution précédente.
Les performances plutôt décevantes du prédicteur dynamique à 1 bit, ont amené les
concepteurs à proposer un prédicteur conservant un historique plus important. Une
solution mettant en œuvre 2 bits pour stocker l'historique des branchements a alors été
proposée. Les 2 bits de stockage de l'historique sont à nouveau utilisés pour calculer
Lors de l'exécution effective du branchement, le processeur vient faire une mise à jour
de la machine d'états. Les mises à jour sont symbolisées par les changements d'états
(flèches d'état à état sur la figure ci-dessus).
Nous avons donné dans les sections précédentes, les solutions qui peuvent être mises en
œuvre dans le cas où le processeur doit exécuter des instructions de branchements
conditionnels. Les constructeurs ont déployé des efforts importants pour fournir des
prédicteurs de branchements efficaces. Il n'en reste pas moins que le problème est de
plus en plus critique lorsque le pipeline du processeur s'allonge.
Il existe une autre voie pour limiter les risques de pertes de cycles dans les contrôleurs
pipelines des processeurs dans le cas d'un branchement. Il s'agit tout simplement
d'essayer de supprimer les instructions de branchements conditionnels. Cette solution
qui peut sembler, a priori, utopique est toutefois réalisable par le biais du
conditionnement de toutes les instructions du processeur. Considérons le code suivant :
if (condition) then {
...
BR condition, @then
else
instruction3 ;
instruction4 ;
BRA @suite
then
instruction1 ;
instruction2 ;
suite
...
...
Les instructions suivantes (partie the et else) sont ensuite alignées les unes à la suite des
autres sans faire de saut. Les instructions circuleront donc dans le pipeline du
processeur, mais seules deux de ces instructions auront s'exécuteront normalement, les
deux autres auront le comportement d'instruction Nop. Les instructions qui
s'exécuteront normalement sont celles dont le registre pi est vrai.
Le processeur Pentium IV est basé sur l’architecture NetBurst se distingue par une
profondeur de pipeline jamais atteinte à ce jour par un processeur x86, puisqu´elle est de
20 niveaux, contre 10 par exemple pour une architecture de type P6. A titre de rappel,
un pipeline est un ensemble d´unités effectuant un travail à la chaîne, dans le but final
de traiter les instructions. Lorsque l´on augmente la profondeur du pipeline, on
augmente le nombre d´unités, et on réduit donc le travail que chacune doit effectuer.
Cela à des avantages, mais aussi des inconvénients.
Il est à noter que l´architecture NetBurst est également capable d´exécuter les
instructions dans le désordre (out of order execution). Ainsi, si par exemple la première
ALU traite le calcul A = 5 x 6 et que le calcul suivant est B = A + 2; la seconde ALU ne
peut rien faire dans le cas d´une exécution in order (dans l´ordre), si ce n´est attendre le
résultat du calcul A. Avec un le système out of order, la deuxième ALU peut sauter ce
calcul pour passer à un suivant, tous les résultats étant bien sur remis dans l´ordre à la
fin.
Le « in-order front end » charge les instructions et les décode. Elle nécessite 5
étages du pipeline (1 à 5).
Le « out-of-order (OOO) execution logic » réordonne les instructions et les
répartit vers les unités de calcul. Il occupe 7 étapes du pipeline (6 à 12).
La phase d'exécution fait intervenir les unités de calcul proprement dites : 5
étapes (13 à 17).
La phase de « retirement » réordonne les résultats du calcul de façon cohérente : 3
étapes (18 à 20).
Afin d'accélérer cette phase de décodage, les processeurs modernes multiplient les
unités de décodage. Ainsi le Pentium III et l'Athlon sont capables de décoder jusqu'à
trois instructions IA-32 par cycle. Le Pentium 4 quant à lui utilise une technique
différente : il n'est capable de décoder qu'une seule instruction IA-32 par cycle, mais en
revanche il dispose d'une mémoire tampon permettant de stocker le résultat des
décodages; il s'agit du Trace Cache.
A la différence d'un cache code classique qui contient des instructions non décodées, le
Trace Cache est inséré dans les premières étapes du pipeline, il contient donc des µops
directement utilisables par les étapes suivantes du pipeline.
Réduire les cycles de pénalités en cas d'échec de branchement. En effet, dans une
telle situation, le pipeline doit être vidé puis remplit à nouveau avec les bonnes
instructions, qui avec un peu de chance sont contenues dans le cache code. Un
cache code classique contient des instructions IA-32 qui doivent alors être à
nouveau décodées pour être utilisables par le pipeline. Le Trace Cache, contenant
des µops déjà décodées, permet d'éviter cette phase de décodage.
Par rapport à un cache code classique, le Trace Cache se situe après l'unité de
prédiction de branchement (BPU) ; cela implique que les µops contenues dans le
Trace Cache sont celles prévues par la prédiction de branchement, alors qu'un
Cependant le Trace Cache présente quelques désagréments, liés au fait qu'il est une
mémoire insérée dans le pipeline. En effet, rechercher une information dans une
mémoire n'est pas immédiat, et la latence engendrée dépend directement de sa taille et
de son organisation. Afin de ne pas insérer trop de latences au sein même du pipeline, le
Trace Cache se doit d'avoir une taille limitée. Et plus la taille est faible, moins les
chances d'y trouver l'information sont grandes, c'est là l'éternel dilemme des mémoires
caches.
L'autre désavantage est lié à l'architecture physique de la mémoire qui occupe une
surface assez importante dans la puce. Le fonctionnement optimal du pipeline nécessite
que les unités impliquées dans les étapes successives soient le plus rapprochées possible
d'un point de vue physique, afin de réduire la distance de parcourt des signaux. A ce
titre, le Trace Cache représente une importante quantité de transistors, et propager une
donnée jusqu'à l'étape suivante du pipeline peut s'avérer problématique en terme de
distance. Le résultat est que le pipeline possède une étape dédiée à la propagation du
signal depuis le Trace Cache vers l'étape suivante, justement nommée étape Drive. Le
pipeline du Pentium 4 possède en tout deux étapes Drive dédiées à la propagation du
signal.
I. Introduction
Plus une mémoire est grande, plus son temps d’accès est long
banc de registres
o peu d’entrées, temps d’accès court (< 1 cycle), plusieurs ports
mémoire dynamique (DRAM)
o mémorisation d’une charge sur une capacité,
o 1 transistor par bit grande densité d’intégration (16-64 Mbits)
o temps d’accès long: 50-100 ns
o utilisé comme mémoire principale
mémoire statique (SRAM)
o mémorisation par bouclage de 2 portes: 1-4 Mbits
o cher
o temps d’accès court: 5-10 ns
La latence mémoire n’est pas seulement constituée par le temps d’accès DRAM, il faut
aussi ajouter:
la translation d’adresse
la traverser les broches du processeur et le bus externe
le multiplexage si plusieurs bancs mémoires
Latence de la mémoire principale: 100-200 ns à 1 GHz, ça fait 100 à 200 cycles CPU
Les registres: accessibles immédiatement par le processeur, ils sont caractérisés par
une grande vitesse et servent principalement au stockage des opérandes et des
résultats intermédiaires.
La figure suivante montre une comparaison des différentes catégories de mémoires dans un
ordinateur, plus on s’éloigne du CPU vers les mémoires auxiliaires, on constate que le
temps d’accès et la capacité des mémoires augmentent, mais que le coût par bit diminue.
La localité spatiale est exploitée lors des transferts entre niveaux: au lieu d'effectuer des
transferts mot à mot, les transferts seront faits par blocs d'adresses contiguës
Localité spatiale
Un programme exhibe de la localité spatiale lorsque des données ou des instructions qui
sont à des adresses proches ont tendance à être accédées dans des temps rapprochés. Sur
un défaut de cache, on ne chargera pas une seule donnée ou une seule instruction, mais
un bloc de plusieurs instructions ou données.
Impact sur les performances de la localité spatiale
La localité spatiale influence les performances des codes.
do i=1,rep do i=1,rep
do j = 1,n do j = 1,n
y(i) = y(i) + x(j) y(i) = y(i) +x(pas*j)
enddo enddo
enddo enddo
end end
Localité temporelle
Chaque fois qu'une adresse virtuelle est référencée, le mapping (ou topographie)
convertit cette adresse en une adresse physique qui est l'emplacement du début de bloc
en mémoire principale. Bien entendu, ceci suppose que le bloc a préalablement été
chargé en mémoire principale. Si ce n'est pas le cas, un processus d'interruption permet
de rechercher le bloc en mémoire secondaire, de le charger en mémoire principale (il
possède alors une adresse physique) et d'effectuer la correspondance adresse virtuelle
vers adresse physique.
B. Pagination
Les pages sont des blocs de taille fixe et l'adresse virtuelle est de la forme (p,d) où p est
le numéro de page en mémoire virtuelle. Un élément de la table des pages sera de la
forme (r, s, D, p') où r est le bit de résidence (0 si la page est en mémoire secondaire, 1 si
la page est chargée en mémoire principale), s est l'adresse en mémoire secondaire (si
r=0), p' est le numéro de page en mémoire principale (si r=1) ; D correspond aux droits
d'accès de la page (lecture, écriture, exécution).
On peut distinguer trois types de mapping :
mapping "direct-associatif" : on
essaie d'abord de trouver p'
avec la table associative, sinon
on utilise la table générale.
C. Segmentation
Un segment est un bloc de taille variable ; une adresse virtuelle est de la forme (s,d) où s
est le numéro de segment. Le mécanisme de mapping est assez similaire à celui de la
pagination. Un élément de la table des segments sera de la forme (r, s, l, D, s') où r , s, D,
s' ont la même signification que précédemment (en remplaçant page par segment), l
désigne la longueur du segment.
On essaie d'abord la recherche avec la table associative, sinon on utilise les tables
segment-pages.
LRU
La stratégie LRU (Least Recently Use) consiste à remplacer la page la moins récemment
utilisée. C'est donc ici l'utilisation et non le chargement qui guide la politique de
remplacement. Bien entendu, il faut estampiller chaque page avec une date chaque fois
qu'elle est utilisée. Le problème que l'on rencontre dans cette stratégie est celui des
traitements faisant intervenir des boucles de programme.
F IF O
Chaque page qui vient d'être chargée est affectée d'une date (de chargement). En se
basant sur cette date, il est possible d'éliminer les pages les plus anciennes. Telle est la
stratégie FIFO (First In First Out).