Architecture matériel

Des problèmes de calcul à la machine à calculer programmable

De la complexité des calculs nécessaires à la résolution de problèmes mathématiques et physiques et des progrès techniques sont nées les premières machines à calculer1.

Dans les années 1830, face au nombre important d’accidents de navigation en raison d’importantes erreurs dans les tables nautiques (dues à des erreurs de calculs), Charles Babbage imagina une machine à calculer automatique (programmable) avec des engrenages, utilisant d’abord des cylindres, puis des cartes perforées inspirées des métiers à tisser Jacquard. Mais, la technologie de l’époque ne permit pas sa réalisation. Dans le même temps, une jeune femme, Ada Lovelace, qui entretenait une correspondance avec Babbage, publia le premier algorithme destiné à être exécuter sur une machine.

Il faudra attendre les années 1940 pour voir la première construction des premières machines programmables.

De la machine à calculer programmable à l’ordinateur actuel

La machine de Turing (1936)

En 1936, à la question “qu’est ce qui est calculable ?”, Alan Turing2 conceptualise pour la première fois, de manière abstraite, l’ordinateur3: la machine de Turing.

La machine de Turing

Plus en détails,

La machine de Turing (source: https://en.wikipedia.org/wiki/Turing_machine_gallery)

ou la vidéo présente ici ou encore cette autre vidéo portant sur son rôle sur l'Enigma.

Il expliqua toutefois que sa machine n’est pas désirable concrètement en raison de plusieurs contraintes:

  • le temps pour adapter l’outil par un opérateur humain afin de pouvoir soumettre un problème à la machine;

  • les limites de la machine: le ruban est sensé être de longueur infinie et la machine est figée avec une machine par procédure (que Turin a partiellement corrigé par l’introduction de la machine universelle).

Architecture de von Neumann (1945)

En 1945, von Neumann et ses collaborateurs Mauchly et Eckert élaborent un nouveau modèle: architecture de von Neumann. De nos jours, les ordinateurs se reposent encore sur ce modèle (vieux de plus de 74 ans !).

Schéma de l'architecture de von Neumann (source:https://en.wikipedia.org/wiki/Von_Neumann_architecture)

Ce modèle est constitué …

  • d’une Memory Unit/Unité Mémoire adressable. Dans ce modèle, une fonction est une donnée comme une autre. L’organisation de la mémoire dépend de l'OS/operating system/système d’exploitation présent sur la machine.

  • d’une UAL/Unité Arithmétique et Logique (unité de calcul) et d’une UC/Unité de Contrôle. Ces deux unités forment le CPU/processeur refroidi par un dissipateur.

  • d’une horloge pour synchroniser le fonctionnement de la machine

Exemple: la fiche technique d’un processeur indique qu’il peut atteindre une fréquence de \(4.6\) GHz, autrement dit \(4,600,000,000\) cycles d’horloge par seconde.

Comparaison des deux modèles:

Machine de Turing Architecture de von Neumann
Défauts Modèle théorique, modèle figé Le progamme peut se modifier lui-même: non prévisibilité, présence possible de bugs
Avantages Programme non modifiable: prévisibilité Possibilité d’écrire de nouveaux programmes, des mises à jour (corriger les bugs)

Fonctionnement de l’UAL et de la mémoire

Éléments physiques d’un UAL

L'Unité Arithmétique et Logique ou UAL est constitué d’une multitude de circuits électroniques eux-mêmes constitués de transitors. La très grande majorité des porcesseurs actuels possèdent de multiples UAL regroupés dans des cores/coeurs.

Schéma d'une UAL à deux entrées A et B pour une fonction F ayant pour résultat R et de drapeau D (source: https://fr.wikipedia.org/wiki/Unit%C3%A9_arithm%C3%A9tique_et_logique)

Les différents circuits présents permettent de représenter et calculer avec des nombres en binaire. Les portes logiques/fonctions binaires vues dans le 2.1 sont représentées graphiquement par:

Opérateur Représentation
NOT NOT
AND AND
OR OR
XOR XOR
NAND NAND
NOR NOR
XNOR XNOR

Pour les exemples qui suivent, j’utilise l’excellent4 simulateur de circuit simcirjs. Il permet de concevoir un circuit et d’observer son fonctionnement.

Exemple: circuit AND.

La valeur 1 signifie la présence d'une tension électrique
0 pour l'absence de tension.

{ "width":400, "height":200, "showToolbox":true, "toolbox":[ {"type":"In"}, {"type":"Out"}, {"type":"Joint"}, {"type":"DC"}, {"type":"LED", "color":"#00FF00"}, {"type":"PushOff"}, {"type":"PushOn"}, {"type":"Toggle"}, {"type":"BUF"}, {"type":"NOT"}, {"type":"AND"}, {"type":"NAND"}, {"type":"OR"}, {"type":"NOR"}, {"type":"XOR"}, {"type":"XNOR"}, {"type":"OSC"}, {"type":"7seg"}, {"type":"16seg"}, {"type":"4bit7seg"}, {"type":"RotaryEncoder"}, {"type":"BusIn"}, {"type":"BusOut"}, {"type":"RS-FF"}, {"type":"JK-FF"}, {"type":"T-FF"}, {"type":"D-FF"}, {"type":"8bitCounter"}, {"type":"HalfAdder"}, {"type":"FullAdder"}, {"type":"4bitAdder"}, {"type":"2to4BinaryDecoder"}, {"type":"3to8BinaryDecoder"}, {"type":"4to16BinaryDecoder"}, {"type":"AltFullAdder"}, {"type":"Transmitter"}, {"type":"Delay"}, {"type":"NumSrc"}, {"type":"NumDsp"}, {"type":"DSO"} ], "devices":[ {"type":"AND","id":"dev0","x":126,"y":80,"label":"AND"}, {"type":"NumDsp","id":"dev1","x":202,"y":88,"label":"NumDsp","state":{"direction":2}}, {"type":"NumSrc","id":"dev2","x":54,"y":64,"label":"NumSrc","state":{"direction":0,"on":false}}, {"type":"NumSrc","id":"dev3","x":54,"y":120,"label":"NumSrc","state":{"direction":0,"on":true}} ], "connectors":[ {"from":"dev0.in0","to":"dev2.out0"}, {"from":"dev0.in1","to":"dev3.out0"}, {"from":"dev1.in0","to":"dev0.out0"} ] }

DC: générateur de courant continu
Toggle: bouton.

{ "width":400, "height":200, "showToolbox":true, "toolbox":[ {"type":"In"}, {"type":"Out"}, {"type":"Joint"}, {"type":"DC"}, {"type":"LED","color":"#00FF00"}, {"type":"PushOff"}, {"type":"PushOn"}, {"type":"Toggle"}, {"type":"BUF"}, {"type":"NOT"}, {"type":"AND"}, {"type":"NAND"}, {"type":"OR"}, {"type":"NOR"}, {"type":"XOR"}, {"type":"XNOR"}, {"type":"OSC"}, {"type":"7seg"}, {"type":"16seg"}, {"type":"4bit7seg"}, {"type":"RotaryEncoder"}, {"type":"BusIn"}, {"type":"BusOut"}, {"type":"RS-FF"}, {"type":"JK-FF"}, {"type":"T-FF"}, {"type":"D-FF"}, {"type":"8bitCounter"}, {"type":"HalfAdder"}, {"type":"FullAdder"}, {"type":"4bitAdder"}, {"type":"2to4BinaryDecoder"}, {"type":"3to8BinaryDecoder"}, {"type":"4to16BinaryDecoder"}, {"type":"AltFullAdder"}, {"type":"Transmitter"}, {"type":"Delay"}, {"type":"NumSrc"}, {"type":"NumDsp"}, {"type":"DSO"} ], "devices":[ {"type":"LED","color":"#00FF00","id":"dev0","x":248,"y":75,"label":"LED"}, {"type":"DC","id":"dev1","x":24,"y":125,"label":"DC"}, {"type":"Toggle","id":"dev2","x":96,"y":125,"label":"Toggle","state":{"on":true}}, {"type":"AND","id":"dev3","x":176,"y":75,"label":"AND"}, {"type":"Toggle","id":"dev4","x":96,"y":25,"label":"Toggle","state":{"on":false}}, {"type":"DC","id":"dev5","x":24,"y":25,"label":"DC"} ], "connectors":[ {"from":"dev0.in0","to":"dev3.out0"}, {"from":"dev2.in0","to":"dev1.out0"}, {"from":"dev3.in0","to":"dev4.out0"}, {"from":"dev3.in1","to":"dev2.out0"}, {"from":"dev4.in0","to":"dev5.out0"} ] }

Cliquer sur les valeurs en entrée (premier circuit) pour les modifier ou sur les boutons (second circuit) pour les actionner et ainsi voir comment ce circuit fonctionne.

Vérifier la valeur en sortie à l’aide d’une table de vérité.

\(a\) \(b\) \(a \text{ AND } b\)
\(0\) \(0\)
\(1\) \(0\)
\(0\) \(1\)
\(1\) \(1\)

Intéractions entre un processeur et l’unité mémoire

Pour simplifier, un processeur est constitué:

  • de registres: mémoire interne en nombre fixe (nombre variable suivant le processeur) afin de stocker des opérandes, des résultats intermédaires en sortie de l’UAL et l’adresse mémoire de l’instruction en cours d’usage (noté PC);

  • d’un jeu d’instructions: un dictionnaire de mots (spécifiques à chaque processeur) qui permet d’intéragir avec les données présentes dans la mémoire. Ces instructions sont présentes sous la forme de codes (en binaire) qui forment un langage dit de bas niveau5.

Étant fastidieux de programmer directement en binaire, on a recours à un programme, l'assembleur avec l’usage d’un langage dit d’assemblage.

À titre d’exemple, add $R1 $R2 $R0 désigne l’instruction qui consiste à additionner les valeurs contenues dans les registres $R1 et $R2 et de placer le résultat dans le registre R0.

Notes de bas de page:

  1. “calculer” vient du mot latin computare. Celui-ci a donné le mot anglais “computer”. ↩︎

  2. Mathématicien. Il travailla avant la Seconde guerre mondiale notamment sur la calculabilité, puis pendant celle-ci sur Enigma, enfin sur l’Intelligence Artificielle après celle-ci. ↩︎

  3. le terme “ordinateur” a été proposé qu’en 1955 par le professeur de philologue français Jacques Perret comme traduction de “computer”. “ordinateur” vient du latin “ordinator” (celui qui met de l’ordre, ordonnateur). ↩︎

  4. avis personnel. Merci à l’auteur de ce projet Kazuhiko Arase. Les détails d’emploi sont à trouver ici↩︎

  5. langage machine en opposition aux langages de haut niveau comme Python: langages proches du langage humain↩︎