← Retour au blogArchitecture de processeur

Le compteur ordinal expliqué : le marque-page du processeur

Découvrez comment le compteur ordinal désigne la prochaine instruction, progresse dans le code séquentiel et est redirigé par les branchements, sauts, exceptions et réinitialisations.

DennyDenny
9 min de lecture
Chalkboard feature illustration for “Le compteur ordinal expliqué : le marque-page du processeur”

En bref : le compteur ordinal, ou PC — également appelé pointeur d’instruction dans certaines architectures — désigne la prochaine instruction à charger. L’exécution séquentielle l’avance de la longueur décodée de l’instruction ; les branchements, sauts, exceptions, interruptions et réinitialisations sélectionnent une autre valeur pour le prochain PC.

Le compteur ordinal est un élément d’état architectural spécialisé, situé au cœur de la lecture des instructions. Dans un processeur pédagogique, il peut s’agir d’un registre littéral qui pilote l’adresse de la mémoire d’instructions. Dans un processeur moderne, prédiction, files d’attente, caches, traduction d’adresses et lecture spéculative rendent l’implémentation plus distribuée, mais l’architecture définit toujours l’adresse de la prochaine instruction.

Cet article explique ce que stocke le PC, comment il s’incrémente, comment les branchements et les sauts le redirigent, puis comment en câbler un à partir d’un registre, d’un additionneur et d’un multiplexeur. Chaque composant renvoie vers un circuit fonctionnel que vous pouvez manipuler dans le modèle Exécuteur séquentiel d’instructions.

Qu’est-ce que le compteur ordinal ?

Le compteur ordinal est un registre consacré à une seule tâche : pointer vers la prochaine instruction en mémoire. Ce n’est pas un registre général que le code utilisateur peut lire et écrire librement. C’est un registre spécialisé piloté par la logique de commande du processeur.

Dans la machine la plus simple, sa largeur et l’unité adressable de la mémoire délimitent l’espace des adresses de code :

  • Un PC de 8 bits peut sélectionner 28=2562^8 = 256 emplacements adressables.
  • Un PC de 16 bits peut sélectionner 216=65,5362^{16} = 65{,}536 emplacements.
  • Un PC de 32 bits possède 2322^{32} motifs de bits possibles.
  • Un PC de 64 bits possède 2642^{64} motifs de bits possibles.

Ces emplacements ne sont des octets que dans une architecture adressée par octets. Les processeurs réels peuvent implémenter moins de bits d’adresse que la largeur nominale du registre, traduire les adresses virtuelles des instructions en mémoire physique et imposer des règles d’alignement ou d’adresses canoniques.

Le composant PROGRAM_COUNTER_8BIT de DigiSim réalise le cas de 8 bits : une taille suffisante pour exécuter de vrais programmes dans le simulateur, tout en restant assez petite pour être inspectée bit par bit.

Le PC se trouve en tête de l’étage de lecture

L’étage de lecture du cycle lecture-décodage-exécution utilise quatre signaux successivement :

  1. Le PC place sa valeur courante sur le bus d’adresses.
  2. La mémoire renvoie le mot d’instruction situé à cette adresse.
  3. Le mot d’instruction est verrouillé dans le registre d’instruction.
  4. Le PC est mis à jour afin que la lecture suivante obtienne l’instruction suivante.

Les étapes 1 à 3 sont traitées dans la présentation générale de la lecture. Le présent article porte sur l’étape 4.

Pourquoi le PC doit-il s’incrémenter automatiquement ?

Si le PC restait immobile, le processeur lirait éternellement la même instruction. Le matériel intègre donc un incrément automatique : par défaut, chaque cycle de lecture est suivi d’un pas en avant.

L’incrément est calculé par un additionneur dédié — généralement un petit additionneur à propagation de retenue semblable à celui détaillé dans Maîtriser l’addition binaire — dont les entrées sont le PC courant et un décalage constant. La sortie de cet additionneur revient vers l’entrée de données du PC, qui la verrouille au front d’horloge suivant.

PC + 1 ou PC + 4 : pourquoi la largeur de l’instruction compte

La constante ajoutée au PC est la largeur d’une instruction exprimée en unités adressables, et pas toujours la valeur littérale 1.

ArchitectureLargeur d’instructionIncrémentRaison
Processeur pédagogique DigiSim de 8 bits1 octet (1 mot)PC + 1Chaque adresse contient une instruction complète
MIPS ; RISC-V sans instructions compressées4 octetsPC + 4La mémoire est adressée par octets ; ces codages occupent 4 octets
ARM (A32)4 octetsPC + 4Même raison
RISC-V avec l’extension C ; Arm Thumb/Thumb-22 ou 4 octetsPC + longueur décodéeTous deux comprennent des codages de 16 bits ; des codages de 32 bits peuvent aussi apparaître
x861 à 15 octetsPC + longueur décodéeInstructions de longueur variable ; le décodeur indique la longueur

Le principe architectural reste identique : l’adresse séquentielle suivante dépend du codage de l’instruction courante. Une ISA à largeur fixe peut employer un incrément constant. Une ISA à largeur variable doit déterminer la longueur de l’instruction courante, même si un frontal hautes performances prédit et lit au-delà de cette frontière avant la fin du décodage.

Description booléenne

Pour une architecture dont la largeur fixe d’instruction est WW, la valeur suivante du PC par défaut est :

PCn+1=PCn+W\text{PC}_{n+1} = \text{PC}_{n} + W

Dans le cas DigiSim de 8 bits, W=1W = 1 ; l’incrément est donc un simple additionneur +1.

Comment les branchements et les sauts remplacent-ils le PC ?

L’exécution séquentielle est le cas sans surprise. Un vrai programme a besoin de boucles, de conditions, d’appels de fonction et de retours : autant d’opérations qui imposent au PC de sauter ailleurs qu’à l’adresse séquentielle suivante.

Deux catégories courantes de transfert de contrôle illustrent ce changement :

  • Saut inconditionnel : remplacer le PC par une adresse cible sans tenir compte d’une condition.
  • Branchement conditionnel : sélectionner une cible uniquement si la condition définie par l’ISA est vraie ; sinon, choisir l’adresse séquentielle. Certaines ISA testent des indicateurs d’état tels que zéro, retenue, signe ou débordement. D’autres, dont le RISC-V de base, comparent directement des registres et ne possèdent aucun registre de codes conditionnels arithmétiques. Le guide des indicateurs du processeur explique l’organisation fondée sur ces indicateurs.

Dans les deux cas, l’opération revient à écrire une valeur non séquentielle dans le PC.

D’où vient l’adresse cible ?

La cible est codée de l’une des trois manières suivantes :

  1. Immédiate, relative au PC : le mot d’instruction contient un décalage. Le prochain PC vaut PC + offset. Les instructions BEQ de RISC-V, B d’ARM et les sauts courts de x86 emploient cette forme. Elle favorise le code indépendant de sa position.
  2. Directe ou relative à une région : l’instruction fournit certains bits de la cible, éventuellement combinés avec une base fixe ou les bits de poids fort du PC courant. L’instruction J du MIPS classique en est un exemple familier. Une adresse absolue complète tient rarement dans une instruction ordinaire de largeur fixe.
  3. Indirecte par registre : la cible se trouve dans un registre général ou dans la sortie de l’ALU. JALR de RISC-V, BX d’ARM et JMP rax de x86 en sont des exemples. Cette forme prend en charge les pointeurs de fonction, la répartition virtuelle et les goto calculés.

Dans un petit chemin de données monocycle, ces candidats peuvent alimenter un multiplexeur. Les implémentations plus avancées peuvent calculer, prédire et mettre en file les cibles dans plusieurs unités avant la validation du chemin architectural choisi.

Réalisation : registre + incrément + multiplexeur

La structure matérielle du PC est l’un des chemins de données les plus limpides d’un processeur :

                        ┌──────────────┐
       PC current ─────▶│  Adder (+W)  │──── PC + W ──┐
                        └──────────────┘              │
                                                      ▼
                                              ┌───────────────┐
                                              │ MUX (2:1)     │
                target_addr ─────────────────▶│  sel = take?  │──── next_PC
                                              └───────────────┘
                                                      │
                                                      ▼
                                              ┌───────────────┐
                  clock ─────────────────────▶│   PC register │──── current_PC
                                              └───────────────┘

Trois éléments :

  1. Un registre qui conserve l’adresse courante. Dans le chemin de données pédagogique, il s’agit d’un registre de 8 bits, construit à partir d’un stockage déclenché sur front et élargi à la taille du bus d’adresses.
  2. Un additionneur dont une entrée reçoit le PC et l’autre la largeur constante WW.
  3. Un multiplexeur 2:1 dont une entrée vient de l’additionneur — chemin séquentiel par défaut — et l’autre de la cible de branchement — chemin du branchement pris. La ligne de sélection est pilotée par l’unité de commande et activée lorsque l’instruction courante est un saut ou un branchement dont la condition est vraie. Les multiplexeurs sont étudiés dans Le contrôleur du trafic de données.

À chaque front d’horloge, le PC verrouille la valeur que le multiplexeur sélectionne à cet instant. Cet unique verrouillage constitue tout le mécanisme qui distingue « avancer » de « brancher ».

Entrées facultatives du multiplexeur

Les conceptions réelles ajoutent d’autres sources au même multiplexeur :

SourceMoment de la sélection
PC + WPar défaut — exécution séquentielle
PC + décalage (relatif au PC)Branchements conditionnels, sauts courts
Cible directe / vecteurSauts directs, réinitialisation ou transferts de contrôle définis par l’architecture
Registre / sortie d’ALUSauts indirects, retours de fonction, répartition de switch
Vecteur de réinitialisation / démarrageAprès la mise sous tension ou une réinitialisation externe
Vecteur d’exception / interruptionAprès une trappe

La ligne de sélection passe de 1 à 3 bits, mais l’idée structurelle reste la même.

Comportement à la réinitialisation : où commence le PC ?

À la mise sous tension ou lors d’une réinitialisation, le PC doit contenir une adresse connue ; sinon, l’exécution commence au hasard.

Deux conventions sont courantes :

  • PC = 0 : l’exécution commence à l’adresse 0x0000…0. Le processeur pédagogique de DigiSim suit cette convention simple, avec la première instruction à l’emplacement zéro.
  • Vecteur de démarrage : une adresse fixe non nulle. À froid, x86 se réinitialise à l’adresse physique 0xFFFFFFF0, en haut de l’espace de 4 Go, près de la ROM du BIOS. Les cœurs ARM Cortex-M lisent le PC initial depuis un vecteur de réinitialisation stocké à l’adresse 0x00000004. Certaines puces de la famille 6502 lisent ce vecteur à 0xFFFC/0xFFFD.

Dans le matériel, « reset » est un fil relié à l’entrée d’effacement asynchrone — ou de chargement synchrone — du PC. Lorsqu’il est actif, le PC est forcé à la valeur de démarrage sans tenir compte du multiplexeur.

Exemple détaillé : une boucle de cinq instructions

Considérons le pseudo-programme suivant pour un processeur de 8 bits où W=1W = 1 :

0x00: LDI R0, 5      ; load 5 into R0
0x01: LDI R1, 0      ; load 0 into R1
0x02: ADD R1, R0     ; R1 = R1 + R0
0x03: DEC R0         ; R0 = R0 - 1, sets Z flag if R0 hits 0
0x04: BNZ 0x02       ; if Z == 0, branch back to 0x02
0x05: HLT

Suivons les valeurs du PC :

CyclePC à la lectureInstructionAprès la lectureBranchement pris ?PC suivant
10x00LDI R0, 5PC + 1 = 0x01sans objet0x01
20x01LDI R1, 0PC + 1 = 0x02sans objet0x02
30x02ADD R1, R0PC + 1 = 0x03sans objet0x03
40x03DEC R0 (R0=4, Z=0)PC + 1 = 0x04sans objet0x04
50x04BNZ 0x02PC + 1 = 0x05; target = 0x02oui (Z=0)0x02
60x02ADD R1, R0………

Au cycle 5, le chemin de données pédagogique sélectionne la cible de branchement (0x02) à la place de l’adresse séquentielle suivante (0x05), car l’indicateur Z est effacé. La machinerie du flux de contrôle réel est plus élaborée, mais le résultat architectural reste le choix entre le chemin de poursuite et une cible de transfert de contrôle.

Pièges courants

  • Erreur d’une unité dans PC + W. Un bogue de simulateur fréquent consiste à employer PC + 1 pour une architecture dont les instructions occupent 4 octets. Le processeur lira le deuxième octet de chaque instruction comme le début de la suivante et se comportera comme si tout programme était constitué de données aléatoires.
  • Mettre à jour le PC avant que la lecture de mémoire ne soit terminée. Le PC doit conserver l’adresse courante pendant la lecture de la mémoire. Mettez-le à jour au front d’horloge, pas de manière combinatoire.
  • Oublier la réinitialisation. Sans fil de reset, un PC démarre avec la valeur aléatoire prise par les bascules à la mise sous tension. Reliez toujours la réinitialisation.
  • Brancher vers un alignement invalide. L’alignement requis des instructions dépend de l’ISA et de ses extensions. Une machine qui n’accepte que des instructions alignées sur 32 bits rejette une cible telle que 0x1003 ; une ISA dotée de codages de 16 bits peut autoriser davantage de cibles. Appliquez la règle propre à l’architecture au lieu de figer une hypothèse universelle.

Construisez-le dans DigiSim

Ouvrez le modèle Exécuteur séquentiel d’instructions. Vous y verrez :

  • Un bloc PROGRAM_COUNTER_8BIT en haut du chemin de lecture.
  • Un additionneur câblé pour ajouter systématiquement 1 à chaque cycle d’horloge.
  • Un multiplexeur qui choisit entre PC + 1 et une adresse cible fournie par l’unité de commande.
  • Un interrupteur de réinitialisation qui force le PC à 0x00.

Faites avancer manuellement l’horloge et observez la progression du PC. Chargez ensuite un programme contenant une instruction de branchement et repérez l’instant où le multiplexeur passe de « séquentiel » à « cible » : ce seul bit est le flux de contrôle dans sa forme la plus pure.

La place du PC dans l’ensemble

Le compteur ordinal est un nœud du flux de données plus vaste du processeur. L’instruction qu’il désigne est capturée pour le traitement par le registre d’instruction et le décodeur. Les résultats arithmétiques peuvent mettre à jour les indicateurs du processeur, qu’une conception de branchement fondée sur des indicateurs consulte ensuite.

Lisez l’étude de cas du cycle lecture-décodage-exécution pour suivre la boucle complète, puis chargez le modèle Exécuteur séquentiel d’instructions et avancez pas à pas jusqu’à une instruction de branchement. La première fois que vous voyez le PC effectuer un saut non séquentiel, l’abstraction cesse d’être un schéma pour devenir un circuit.

Transformez l’idée en un circuit fonctionnel.