Microprocesseur

Structures ordinateurs et réseaux

RISC/CISC

CISC

Pourquoi?

C’était le seul envisageable à l’époque car la mémoire travaillait lentement par rapport au processeur. Au lieu de coder une opération complexe par plusieurs instructions plus petites (beaucoup d’accès mémoire =>lent), on donnait une instruction complexe qui se chargeait de réaliser cette opération.
A cause du développement des langages de haut niveau, il y avait des problèmes au niveau de la conception de compilateur.
Donc on a eu tendance à incorporer des instructions plus proches de la structure de ces langages.

Comment?

C’est une architecture où le microprocesseur doit exécuter des tâches complexes par instruction unique. Donc pas beaucoup d’instructions mais chacune demande un plus grand nombre de cycles d’horloge. Le code machine de ces instructions varie d’une à l’autre et nécessite un décodeur complexe.

RISC

Pourquoi?

Des études statistiques faites dans les années 70 montrent que les programmes (générés par les compilateurs) se contentent le plus souvent d’affectations, d’additions et de multiplications par des constantes. 80% des traitements de langages de haut niveau ne font appel qu’à 20% des instructions du micro-processeur.
D’où l’idée de réduire le jeu d’instruction à celles le plus couramment utilisées et d’en améliorer la vitesse de traitement.

Comment?

C’est une architecture avec peu d’instructions. La réalisation d’une architecture RISC libère de la surface, on peut augmenter le nombre de registres ou d’unités de traitement par exemple. Chaque instruction prend 1 cycle d’horloge.
Souvent, les instructions n’ont qu’un seul mode d’adressage. Les accès à la mémoire s’effectuent à partir de 2 instructions, Load et Store. Si on veut faire une instruction complexe avec un RISC, on a besoin d’un compilateur évolué (dans le cas de programmation en langages de haut niveau).

Comparaison

RISC CISC
-Instruction simple ne prenant qu'un seul cycle -Instruction complexe prenant plusieurs cycles
-Instruction au format fixe -Instruction au format variable
-Décodeur simple(câblé) -Décodeur complexe
-Beaucoup de registres -Peu de registres
-Seules les instructions LOAD et STORE ont accès à la mémoire -Toutes les instructions sont susceptibles d'accéder à la mémoire
-Compilateur complexe -Compilateur simple

Pipeline

Un pipeline, dans la microarchitecture d’un processeur, est l’élément dans lequel l’exécution des instructions est découpée en étages. Le processeur peut donc exécuter une nouvelle instruction sans attendre que la précédente soit terminée. Chaque étape est réalisée dans un circuit séparé des autres, ce circuit qui permet d’effectuer une étape s’appelle, un étage de pipeline. Le nombre total d’étages s’appelle la profondeur du pipeline.

Photo de modèle classique

Photo de modèle pipeline

En supposant que chaque étape met 1 cycle pour s’exécuter, il faut normalement 5 cycles pour exécuter une instruction. En utilisant la technique du pipeline, notre processeur peut alors contenir plusieurs instructions, chacune à une étape différente. Il termine une instruction à partir de la cinquième étape. Au 5ème cycle, tous les étages sont en cours d’exécution.

Classic RISC pipeline

Créer par David Patterson, inventeur des processeurs RISC et du concept pipeline. Avec ce pipeline, 5 étapes sont nécessaire pour accomplir une instruction :
- IF (Instruction Fetch), charge l’instruction à exécuter dans le pipeline
- ID (Instruction Decode), décode l’instruction et l’adresse des registres
- EX (Execute), exécute l’instruction (par la/les unités arithmétiques et logiques)
- MEM (Memory), dénote un transfert depuis un registre vers la mémoire dans le cas d’une instruction de type STORE (accès en écriture) et de la mémoire vers un registre dans le cas d’une instruction de type LOAD (accès en lecture).
- WB (Write Back), stocke le résultat dans un registre. La source peut être la mémoire ou bien un registre.

Autres pipelines

Ce pipeline n’est pas la seule organisation possible.
Exemples :
- On pourrait faire des pipelines à seulement 2 étapes :
1) étape Fetch, charge et décode une instruction et met à jour le Program Counter*.
2) étape Exec, qui effectue l’opération proprement dite (avec les accès à la mémoire et/ou aux registres)
- celui de l’IBM Stretch project composé des 3 étapes suivantes :
1) Fetch, charge l’instruction et met à jour le Program Counter*.
2) Decode, décodage de l’instruction
3) Exec, exécute l’instruction avec éventuellement des accès mémoires
* registre avec l’adresse mémoire de l’instruction.
Bref, de nombreuses variations sont possibles.

Certaines fonctionnalités de la microarchitecture d’un processeur ont besoin d’étages supplémentaires (ex : étape en plus si il faut renommer les registres). Les processeurs les plus performants utilisent des pipelines extrêmement longs (une vingtaine d’étages) pour augmenter les performances et la fréquence de l’horloge (moins de travail par étage).
Aujourd’hui tous les microprocesseurs sont pipelinés :
- Intel Pentium 4 Prescott, 31 étages
- Intel Pentium 4, 20 étages
- IBM PowerPC 970, 16 étages
- Intel Core 2 Duo, 14 étages
- Etc.
Certaines architectures ont largement augmenté leur nombre d’étages (ex :Intel Pentium 4 Prescott), une telle architecture est appelée superpipelinée.

Implémentation

Pour que les données passent d’un étage à l’autre, il existe 3 grands types d’implémentation :
- Pipelines synchrones (la technique la plus utilisée)
Les étages sont séparés par des registres tampons, tous reliés au signal d’horloge du processeur. A chaque cycle d’horloge, les registres deviennent accessibles en écritures et les données passent donc à l’étage suivant.
Photo de pipeline synchrone
- Pipelines asynchrones
Les étages sont séparés par des registres tampons, les transferts entre registres sont décidés par un protocole asynchrone.
Photo de pipeline asynchrone
- Pipelines à vagues
Il n’y a pas de registres entre les étages: en contrôlant leur vitesse de propagation, les données envoyées une par une dans le pipeline sont récupérées dans l’ordre à l’autre bout sans nécessiter de mémorisation temporaire.

Problèmes

Les pipelines provoquent de nouveaux problèmes, en particulier d’interdépendance.

Dépendances structurelles:


Dans certain cas bien précis, il arrive que plusieurs étages aient besoin d’accéder à la même ressource matérielle(le même registre, mémoire,…). Si celle-ci n’est pas conçue pour cela, les 2 instructions entre en concurrence et l’un passe devant pendant que l’autre attend. Il peut être nécessaire de bloquer tous les étages qui précédent l’instruction bloquée.

Ce genre de dépendance se règle souvent en dupliquant la ressource, mais ce n’est pas toujours possible, notamment pour les accès mémoires.

Dépendances de données:


Deux instructions ont une dépendance de données s’ils veulent lire ou écrire dans le même registre, ou dans la même adresse mémoire.

Différent cas sont possibles. Mais l’ordre d’exécution des lectures et écritures ne doit pas changer, sous peine de se retrouver avec des résultats erronés.

Diverses optimisations peuvent rendre la situation plus supportable. Certaines dépendances peuvent être éliminées via renommage de registres ou autre mécanisme,…

Dépendances de contrôle:


L’adresse d’un branchement n’est connue que quelques cycles plus tard, vers la fin de l’étage. Entretemps, le processeur aura continué de charger des instructions dans son pipeline. En clair, des instructions sont chargées par erreur dans notre pipeline.

Pour réduire ce genre de problèmes, nos processeurs peuvent fournir diverses fonctionnalités, des mécanismes de prédiction de branchement,…