Un microprocesseur moderne est une entité extrêmement compliquée, et il a fallu des décennies de travail à des milliers de personnes pour en arriver là où il est aujourd'hui. Il est presque impossible de couvrir toutes les bases ici, mais je vais faire une tentative. Préparez un seau de popcorn, car cela va être long.
Tout système moderne fonctionne sur la base de bonnes abstractions, c'est-à-dire de modules plus simples sur lesquels sont construites des choses plus complexes. À mon avis, le processeur moderne peut être décomposé en couches très larges suivantes :
- Dispositifs (transistors)
- Circuits
- Portes logiques
- Blocs logiques simples
- Processeur
- Logiciels
Partons d'un "terrain intermédiaire", qui n'est ni trop compliqué à comprendre ni trop éloigné d'un processeur réel : la porte logique. Une porte logique prend un certain nombre d'entrées, toutes égales à 0 ou 1, et produit un bit qui est à nouveau égal à 0 ou 1 selon une règle donnée. Par exemple, une porte ET ne sortira 1 que si toutes ses entrées sont 1.
Vous pourriez maintenant commencer à me questionner "Mais qu'entendez-vous par 0 et 1 ? Qu'est-ce que cela signifie en termes d'électricité ?". La réponse est fantastiquement compliquée. Cela peut signifier un niveau de tension (0 est 0V, 1 est 1V), une impulsion électrique (0 est aucune impulsion, 1 est une impulsion de 1V pendant 1 nanoseconde, un milliardième de seconde), un photon (0 est aucun photon, 1 est 1000 photons), et ainsi de suite, tout cela en fonction de la façon dont le circuit a été conçu. C'est la puissance des abstractions. Vous n'avez pas besoin de savoir ce que le 0 et le 1 signifiaient pour concevoir des choses plus haut (mais vous prendrez de mauvaises décisions plus haut si vous ne le savez pas, donc peut-être que l'abstraction n'est pas parfaite).
Maintenant, réfléchissons à la façon dont nous pouvons faire quelque chose avec ces portes très simples. Imaginons que vous êtes sur le point de lancer votre propre entreprise de processeurs et que vous voulez faire un bloc simple qui ajoute deux nombres en utilisant uniquement ces portes.
"Mais attendez", dites-vous, "qu'est-ce qu'un nombre en termes de 0 et 1 ? Je ne connais que des nombres comme 57 et 42, qui sont composés de chiffres de 0 à 9, et pas seulement de 0 et 1". C'est vrai, mais tu vois, 57 n'est qu'une "représentation" du nombre en dessous, qui est en réalité 5*10+7. Tu peux aussi représenter 57 comme 1*2^5+1*2^4+1*2^3+0*2^2+0*2^1+1*2^0. Voilà, vous l'avez, 57 est le même que 111001 dans ce nouveau système. Vous pouvez vous convaincre que tout nombre peut être représenté sous cette forme.
Maintenant, réfléchissons à la façon dont nous allons construire un additionneur. Tout d'abord, essayons de construire un "demi-additionneur", celui qui prend deux bits et les additionne pour sortir deux bits. Ainsi, si les deux bits sont tous deux à 0, il produira 00, si un seul d'entre eux est à 1, il produira 01, et si les deux sont à 1, il produira 10. Réfléchissons un bit à la fois et prenons d'abord le premier bit. Au bout d'un certain temps, nous nous rendons compte que "Oh ! ce bit n'est 1 que si les deux bits d'entrée sont 1". Donc, nous pouvons obtenir par une porte ET. Génial !". Maintenant, nous avons fait la moitié de notre travail. Il ne reste qu'un seul bit.
Maintenant, nous nous asseyons pour réfléchir à nouveau. Hmm, cet autre bit semble plus difficile. Il est presque comme une porte OU, mais ne sort pas 1 si les deux entrées sont 1. Ok, ne réfléchissons pas davantage et décidons simplement de l'appeler un nouveau type de porte, une porte OU exclusive.
"Don't worry", dis-je, "nous allons engager des ingénieurs en circuits super géniaux qui peuvent concevoir une telle porte dans leur sommeil." Maintenant, nous dessinons une image de notre nouveau circuit étonnant : un demi additionneur.
Mais, maintenant vous dites, "nous ne pouvons ajouter que des nombres de 1 bit. Notre entreprise concurrente peut ajouter des nombres de plus de 1 milliard. Comment pouvons-nous faire cela ? La réponse est, surprise surprise, les abstractions. Vous voyez, notre conception actuelle ne peut ajouter que deux nombres d'un bit, et la sortie est une somme et une "retenue", qui doit maintenant être ajoutée au bit supérieur suivant. Cela nécessite l'addition de trois bits, ce que notre petit gars ne peut'pas faire.
Alors, après une autre journée complète à nous creuser la tête à ce sujet, nous nous rendons compte que ce sera un bon circuit pour faire cela et nous l'appelons un additionneur "complet".
Maintenant, nous avons toute la puissance d'addition du monde dans nos mains. Vous voyez, maintenant nous pouvons simplement enchaîner 32 de ces petits gars ensemble comme le suivant et nous avons dans nos mains un monstre qui peut ajouter des nombres plus de 1 milliard, en un clin d'œil.
Et voici la merveilleuse nouvelle : vous pouvez simplement continuer à faire des portes de mieux en mieux, et votre circuit deviendra de mieux en mieux. C'est le pouvoir de l'abstraction.
Bien sûr, il s'avère que notre façon d'ajouter des choses n'est pas vraiment si géniale. Vous pouvez faire mieux... beaucoup mieux. Mais, grâce à notre ami l'abstraction, cela peut être fait indépendamment des portes. Si votre nouveau circuit est 2x meilleur que l'ancien, ET que vous avez des portes 2x plus rapides, vous avez un circuit 4x meilleur ! !! C'est l'une des principales contributions à la façon dont nous sommes devenus des milliers de fois meilleurs en quelques décennies. Nous avons construit des portes plus petites, plus rapides, moins consommatrices d'énergie. Et nous avons trouvé de meilleures façons de faire le même calcul. Et nous les avons ensuite réunies. Cela a fonctionné comme par magie !
Nous nous échinons maintenant pendant un an dans notre garage et construisons des circuits qui peuvent multiplier, ajouter, soustraire, diviser, comparer et faire toutes sortes d'arithmétique, le tout en 1 nanoseconde. Nous fabriquons même un minuscule circuit qui peut "stocker" une valeur, c'est-à-dire que sa sortie dépendra de la valeur qui lui a été écrite auparavant (quelqu'un suggère de l'appeler une bascule. C'est un drôle de nom, nous le gardons ^_^ ). Mais, vous voyez, une chose que tous nos circuits ont en commun, c'est qu'ils prennent simplement des entrées et font la même opération sur elles pour donner la sortie. Et si je voulais parfois faire une multiplication, et d'autres fois une addition ?
Maintenant, nous avons une idée de génie ! !! Nous disons, ne considérons pas les bits comme de simples nombres. Essayons de représenter les "actions" elles-mêmes en bits. Disons que 0 signifie "ajouter", 1 signifie "multiplier". Maintenant, construisons un minuscule circuit qui voit un bit comme une "commande", et sélectionne entre deux entrées, I0 et I1, et sort I0 si la commande est 0, et I1 si elle est 1. C'est un multiplexeur.
"Wow ! !!", dites-vous, "maintenant nous avons juste besoin d'un multiplexeur pour choisir entre les sorties d'un additionneur et d'un multiplicateur, et nous avons notre solution ! !!". En fait, pourquoi ne pas avoir beaucoup de ces multiplexeurs pour choisir entre tant de sorties, et nous avons obtenu une machine étonnante. Elle peut faire tant d'opérations arithmétiques en fonction de ce que vous lui donnez comme "commande"".
Maintenant nous avons une autre idée AWESOME ! !! Vous vous souvenez de ces drôles de petites bascules que nous avons construites plus tôt ? Nous pensons, et si nous branchions un multiplexeur 1024-1 à la sortie de 1024 flip-flops ? Maintenant nous avons ce qu'on appelle une mémoire de 1 Kilobit ! !! Nous pouvons lui donner une "adresse", et il nous renverra un bit, qui était le bit stocké à cet emplacement numéroté. C'est cool, non ? Quoi's plus, ces bits peuvent maintenant être soit des "nombres" (données), soit des "commandes" (instruction).
Asseyons-nous et pensons à ce que nous avons jusqu'à présent : nous avons tant de fonctions arithmétiques, nous avons un multiplexeur cool sélectionnant quelle sortie choisir, et nous avons une mémoire, qui peut nous donner n'importe quel bit si nous lui donnons une "adresse".
Voici la chose incroyable maintenant. Nous avons TOUT ce dont nous avons besoin pour construire un processeur. Voyons comment :
- Premièrement, nous avons un tableau de mémoire MEM contenant toutes les "commandes" (instructions) et les "nombres" (données).
- Deuxièmement, nous avons un nombre appelé le "compteur de programme", un que nous utilisons pour sélectionner quelle instruction exécuter à partir de MEM. Il ne fait normalement qu'augmenter de 1 à chaque étape.
- Troisièmement, nous avons un bloc arithmétique avec des multiplexeurs.
- Quatrièmement, nous générons les deux entrées de notre bloc arithmétique à partir de MEM.
- Enfin, il y a deux types d'instructions : les instructions de données et les instructions de contrôle. Chaque instruction de données contient quatre choses : deux adresses spécifiant les deux nombres à prendre dans MEM, une commande disant quelle opération effectuer, et un autre emplacement disant où remettre le résultat. Les instructions de contrôle remettent simplement une autre adresse dans le "compteur de programme".
Cette chose que vous venez de construire s'appelle une machine de Von-Neumann (ouais, des fous comme lui ont compris tous ces trucs en 1945, je ne'sais pas comment). Les gens commencent aujourd'hui à se demander si c'est la meilleure façon de construire les choses, mais c'est la façon standard dont tout processeur de nos jours est construit.
Bien, quand j'ai dit plus tôt que c'est ainsi que tous les processeurs sont construits, je voulais dire "théoriquement", et par "théoriquement", je veux dire "considérons qu'une vache est une sphère" théoriquement. Vous voyez, le CPU de votre concurrent peut faire tourner en rond votre CPU Von-Neumann de base. Vous n'avez que 1000 Kilobits de mémoire, votre concurrent peut gérer jusqu'à des milliards (Gb) ou des trillions (Tb) de bits de mémoire. Mais vous dites maintenant qu'il n'y a aucune chance que ces gars-là puissent créer un multiplexeur à un milliard de bits et obtenir ses données en une nanoseconde. C'est vrai. Leur sauce secrète est quelque chose appelé localité.
Ce que cela signifie, c'est que votre programme n'utilise normalement que quelques emplacements de la mémoire de données et d'instructions à la fois. Donc ce que vous faites, c'est que vous avez une grande mémoire constituée de GB's de données, puis vous en amenez une petite partie - celle qui est utilisée actuellement, dans un tableau beaucoup plus petit (peut-être 1 Mo) appelé le cache. Bien sûr, maintenant vous pouvez avoir un cache encore plus petit en dessous de ce cache, et ainsi de suite, jusqu'à ce que vous arriviez à quelque chose que vous pouvez lire ou écrire dans à peu près le même temps que vous pouvez faire un calcul arithmétique.
Une autre idée puissante que vous pouvez faire est appelée traitement hors ordre. Le concept derrière cela peut être illustré par le programme suivant qui calcule X = (A+B)*(C+D)
- Ajouter A et B et le stocker dans U
- Ajouter C et D et le stocker dans V
- Multiplier U et V et le stocker dans X
Dans la manière normale, vous allez juste le faire séquentiellement, en allant une instruction après l'autre et en terminant l'exécution en 3 étapes. Mais, si vous avez deux additionneurs dans votre système, vous pouvez exécuter les instructions 1 et 2 en parallèle, et ainsi avoir terminé en 2 étapes. Ainsi, vous exécutez autant que possible chaque étape et vous terminez votre exécution plus rapidement.
Maintenant, repensez à l'époque où tout ce que vous connaissiez était une simple porte ET. Cette chose que vous avez construite semble tellement étrangère à cela. Mais il ne s'agit en réalité que de couches sur couches de blocs, et de la réutilisation d'un bloc plus simple pour construire un bloc plus complexe. C'est l'idée clé ici. Une unité centrale n'est construite qu'en assemblant des pièces, qui sont construites en assemblant des pièces plus petites. À la fin cependant, si vous regardez simplement la chose, elle ressemble à ceci:
- Adder (électronique)
- Architecture Von Neumann
- Cache du processeur
- Exécution hors ordre
- ARK | Processeur Intel® Core™ i7-3960X Extreme Edition (15M Cache, jusqu'à 3,90 GHz)
Edit : Il y a beaucoup de détails que j'ai omis dans la réponse originale. Cette réponse équivaudra à répondre à "Comment fonctionne une voiture de F1 ?" par "Elle a des roues, et une direction qui guide les roues, et un moteur pour faire fonctionner les roues". En réalité, la conception et la construction d'une unité centrale de traitement est l'un des miracles de la technologie moderne qui fait appel à un grand nombre de disciplines d'ingénierie (y compris, par exemple, la physique quantique, la métallurgie, la photonique, etc.) Je vais essayer d'aborder d'autres questions ci-dessous.
Fabrication
L'un des exploits étonnants de la technologie a été la capacité de créer et de connecter des milliards de transistors minuscules, chacun de moins de 100 nm (oui c'est nano, ce qui signifie un milliardième de mètre) de large, dans un modèle précis défini par les concepteurs de circuits et les architectes de CPU, tout en le rendant incroyablement bon marché. Il est clair que créer et connecter un tel nombre de transistors un par un est impossible à la main ou même par toute forme de mécanique.
La méthode pour fabriquer une puce est appelée photolithographie, et c'est la raison derrière le prix extrêmement bas des processeurs par rapport à leur complexité. L'idée est similaire à la façon dont une photo analogique était "développée" (si quelqu'un s'en souvient). Je vais d'abord décrire comment créer un motif d'oxyde de silicium sur du silicium (utilisé dans les portes des transistors). Tout d'abord, une couche d'oxyde de silicium est déposée sur le silicium. Ensuite, une couche de matériau photorésistant est appliquée par-dessus. Ce matériau est sensible à la lumière, mais résiste à la "gravure". L'inverse du motif à créer est également réalisé sous la forme d'un "masque" à travers lequel une lumière UV est projetée sur la résine photosensible. Cependant, cela pose alors la question de savoir comment le masque a été créé en premier lieu.
Voici la magie de la photolithographie : le masque est en fait beaucoup plus grand que la taille du motif à graver. La lumière projetée à travers le masque est simplement focalisée par une lentille pour avoir la bonne taille lorsqu'elle tombe sur le silicium. Une fois que la lumière modifie la résine photosensible, celle-ci est gravée par un souffle de plasma, ne laissant que le motif souhaité sur l'oxyde de silicium.
Pour créer une couche de métal, en revanche, on suit une procédure similaire. Cependant, maintenant, l'inverse du motif est gravé sur le SiO2, puis le métal est déposé sur les "sillons" créés par le SiO2.
La raison pour laquelle cette méthode est si économique est qu'une fois que vous avez le "masque", vous pouvez créer un très grand nombre de puces à partir de celui-ci. Ainsi, bien qu'un masque soit assez cher (quelques millions de $), son coût est divisé en de nombreuses puces, ce qui rend chaque puce très bon marché (jeu de mots non prévu).
Types de mémoires
Comme je l'ai dit précédemment, vous pouvez construire une mémoire en connectant des flip-flops à des multiplexeurs. Cependant, ce n'est pas une façon particulièrement efficace de faire les choses. Une bascule consomme environ 15 à 20 transistors. En pratique, il existe deux types de structures de mémoire : la RAM statique (ou SRAM en abrégé), qui utilise 6 transistors par bit, et la RAM dynamique (ou DRAM en abrégé), qui n'utilise qu'un transistor et un condensateur par bit. Une RAM statique est essentiellement constituée de deux portes NOT connectées en boucle comme ceci.
Il y a clairement deux états possibles pour A et B, soit A = 1, B = 0, soit A = 0, B = 1. L'idée est d'appliquer une certaine tension externe pour pousser la boucle dans l'un ou l'autre état, qui est alors le bit "stocké", puis de simplement lire la tension en A ou B pour "lire" le bit.
D'autre part, la RAM dynamique ou DRAM, est encore plus simpliste et se présente à peu près comme ceci.
Dans cette conception, le transistor agit simplement comme un interrupteur pour stocker la charge dans le condensateur, auquel cas il est lu comme un 1, sinon un 0. Cependant, la charge dans le condensateur fuit le transistor de temps en temps. Elle doit donc être lue et réécrite à intervalles fixes, et c'est pour cela qu'on l'appelle RAM dynamique.
Les caches d'une puce sont généralement des SRAM, car elles sont plus rapides. Cependant, les mémoires principales d'un ordinateur sont généralement des DRAM, car elles sont beaucoup plus petites en taille, et donc une plus grande quantité de mémoire peut tenir dans une seule puce.
- Photolithographie
- Mémoire vive statique
- Mémoire vive dynamique
P.S. J'ai commencé un blog sur les idées de base de l'architecture des processeurs à Architecture des processeurs. Au cas où cette réponse vous intéresse, vous pouvez y jeter un coup d'œil.
.