Votre smartphone a l’air d’être une boîte magique qui répond à vos mouvements de doigts par de la sorcellerie ? Vous vous demandez quels lutins cachés transforment le code informatique en logiciel qui tourne ? Partons à l’aventure pour comprendre le fonctionnement d’un microprocesseur.

Crédit : David Latorre Romero // Unsplash

Nos appareils numériques se veulent intuitifs et naturels à l’utilisation. Mais pour créer cette surface familière aux humains, les smartphones et ordinateurs doivent s’activer en coulisses à grand renfort d’opérations mathématiques. Comment peut-on donc, avec simplement des uns et des zéros, faire émerger tous ces univers numériques ?

Il n’y a pas besoin de grand-chose pour faire un ordinateur. Il faut un périphérique d’entrée pour pouvoir lui parler, comme un écran tactile ou un clavier. Il faut un périphérique de sortie pour qu’il puisse nous répondre, comme un écran tout court ou des haut-parleurs. Entre les deux, il faut une mémoire et un processeur qui lui servent de cerveau, et c’est cela qui va nous intéresser dans cet article.

Et en parlant de cerveau, on vous préviens : il va falloir faire travailler le vôtre pour tout comprendre au sujet abordé ici !

Dans l’atelier du CPU

Le CPU (Central Processing Unit) est le cœur du processeur. Si le processeur est multicœurs, il contient plusieurs CPU. Mais à part cela, les deux termes sont souvent interchangeables dans la langue parlée. Aujourd’hui, tous les processeurs sont des microprocesseurs, c’est-à-dire que leurs composants sont tous présents sur le même circuit intégré.

Le CPU est doté de trois éléments principaux : l’ALU (Arithmetic Logic Unit), l’unité de contrôle, et les registres. On peut imaginer un CPU comme un atelier où l’ALU serait la travailleuse, où l’unité de contrôle serait sa cheffe, et où les registres seraient des étagères. Le travail de cet endroit est d’exécuter des instructions, qui sont écrites des livres appelés programmes. Les programmes sont entreposés hors de l’atelier, dans un grand hangar qui s’appelle la mémoire.

Le cycle d’instruction

Presque tous les CPU fonctionnent sur un cycle d’instruction composé de ces trois ou quatre étapes : récupérer l’instruction, la décoder, l’exécuter (et écrire le résultat). La durée de ce cycle est déterminée par la fréquence d’horloge, ou cadence. L’« horloge » d’un CPU est un cristal oscillateur qui envoie des impulsions à intervalle régulier, comme le tic-tac d’une vraie horloge.

À chaque cycle d’horloge, l’instruction passe à l’unité suivante du processeur. Un CPU cadencé à 2 GHz a deux milliards d’impulsions par seconde. C’est un indicateur approximatif de la vraie vitesse d’un processeur, et en conditions réelles, il est plus fiable de se baser sur des benchmarks.

Êtes-vous prêt à plonger dans le tourbillon du cycle d’instruction ? Car la partie qui suit est dense, trèèèès dense ! Alors bouclez votre ceinture, faites chauffer les méninges et c’est parti !

Recherche de l’instruction (fetch)

D’abord, l’unité de contrôle doit aller dans la mémoire pour chercher l’instruction, localisée à une adresse mémoire calculée par l’AGU (Address Generation Unit). Il faut pour cela demander son chemin à la MMU (Memory Management Unit). Ce bout de hardware dispose d’un grande carte de la mémoire virtuelle de l’ordinateur, celle que le CPU comprend, listant les adresses physiques correspondantes. C’est à la MMU qu’incombe de limiter l’accès du CPU à la mémoire, pour éviter qu’un programme ne prenne trop de place.

Plutôt que de faire des aller-retour vers le hangar en ne prenant qu’une instruction à la fois — ce serait très lent — on préférera prendre le livre entier du programme et le feuilleter à l’atelier, dans le cache, un petit morceau de mémoire situé directement dans le processeur. Un des registres du CPU contient un compteur de programme, une sorte de marque-page qui indique à quelle instruction on en est dans le livre en notant son adresse mémoire.

À chaque fois, les informations sont découpées en mots, et un CPU 32 bits aura des mots de 32 chiffres de long. La plupart des registres font une taille d’un mot, et c’est la quantité maximum de bits qui pourra être manipulée en une seule action.

Je vous avais prévenu qu’il fallait s’accrocher et j’ai le regret de vous annoncer que ce n’est pas fini. Allez, encore un effort !

Décodage (decode), exécution (execute) et écriture (writeback)

L’instruction est déposée sur l’étagère appelée MBR (Memory Buffer Register). Mais l’ALU ne peut pas la lire comme ça. En effet, elle n’est capable que d’effectuer des actions très basiques, comme des additions ou des multiplications. On peut comparer cela à empiler des briques de Lego. C’est au décodeur d’instruction de dire à l’ALU quelles briques utiliser, en piochant dans un stock de briques disponibles appelées le jeu d’instructions. Certaines sont communes à tous les processeurs, mais d’autres dépendent du fabricant voire du modèle.

On peut comparer cela à empiler des briques de Lego

Une architecture x86, comme dans un processeur Intel, n’utilisera pas les mêmes briques de Lego qu’un processeur Qualcomm d’architecture ARM. Cela signifie aussi qu’un système d’exploitation conçu pour une architecture donnée ne tournera pas sur un autre processeur : en regardant l’instruction, le décodeur verra des briques dont il n’a jamais entendu parler.

L’ALU exécute enfin l’instruction en lisant ou écrivant au besoin dans les registres. Elle dispose pour cela de circuits logiques spécialisés chacun dans une opération mathématique. Le résultat peut être soit gardé dans les registres pour être accédé plus facilement, soit mis dans la mémoire (vive ou morte) où il y a plus de place.

Interruptions et parallélisme

Félicitations, vous connaissez maintenant le cycle de travail quotidien d’un CPU ! Prenez le temps de souffler un peu, parce que l’on va bientôt repartir pour quelques détails pratiques. Le CPU est un endroit très occupé, et il lui faut utiliser quelques astuces pour être le plus performant possible et ne pas faire patienter les programmes.

Imaginez qu’un logiciel ou un périphérique ont une tâche urgente à faire, par exemple quand l’utilisateur a appuyé sur un bouton. Le CPU ne peut pas dire « désolé, je travaille sur un autre programme, attendez votre tour ». Sinon, on ne s’en sortait jamais. Le périphérique va donc envoyer un interrupt au CPU pour lui dire d’interrompre temporairement ce qu’il est en train de faire. Le compteur de programme note l’endroit où le CPU a arrêté son programme précédent, pour qu’il puisse le reprendre une fois l’interruption gérée.

Crédits image : Skitterphoto // Pexels

Les processeurs modernes appliquent le principe du pipelining, c’est-à-dire du « travail à la chaîne » : quand le décodeur termine de donner une instruction à l’ALU, il attaque tout de suite l’instruction suivante sans attendre la fin du cycle. Si l’instruction n°2 a absolument besoin de connaître le résultat de l’instruction n°1, une bulle est rajoutée dans le pipeline pour le faire patienter un peu. Dans les processeurs multiscalaires, chaque unité travaille sur plusieurs instructions en même temps.

Beaucoup de processeurs modernes sont multicœurs, c’est-à-dire formés de plusieurs CPU distincts ou « cœurs ». Mais comment les faire travailler en même temps sur le même programme ? Grâce au multithreading. Les processus sont découpés en threads, suites d’instructions dépendantes les unes des autres, qui ont chacun tendance à se mettre sur des cœurs différents. Attention à ce que les threads ne s’emmêlent pas : un bug de compétition se produit s’ils essaient de modifier les mêmes données en même temps.

Ceci n’est qu’un bref aperçu du fonctionnement d’un CPU. En pratique, il y a beaucoup d’autres raffinements au niveau de chaque étape. Croyez-le ou non, nous n’avons fait qu’effleurer la surface dans cet article. Ce sont justement toutes ces complexités qui font les merveilles de l’informatique, et nous espérons que les cœurs de nos appareils vous seront devenus moins insondables.