Aller au contenu

Fonctionnement d'un ordinateur/L'architecture de base d'un ordinateur

Un livre de Wikilivres.

Dans les chapitres précédents, nous avons vu comment représenter de l'information, la traiter et la mémoriser avec des circuits. Mais un ordinateur n'est pas qu'un amoncellement de circuits et est organisé d'une manière bien précise. Il est structuré autour de trois circuits principaux :

  • un processeur, qui manipule l'information et donne un résultat ;
  • une mémoire qui mémorise les données à manipuler ;
  • les entrées/sorties, qui permettent à l'ordinateur de communiquer avec l'extérieur.
Architecture d'un système à mémoire.

Pour faire simple, le processeur est un circuit qui s'occupe de faire des calculs. Rien d'étonnant à cela. Je rappelle que tout est codé par des nombres dans un ordinateur, ce qui fait que manipuler des nombres revient simplement à faire des calculs. Un ordinateur n'est donc qu'une grosse calculatrice améliorée, et le processeur est le composant qui fait les calculs.

La mémoire s'occupe purement de la mémorisation des données, des nombres sur lesquelles faire des calculs. Pour être plus précis, il y a deux mémoires : une pour les données proprement dites, une autre pour le programme à exécuter. La première est la mémoire RAM, la seconde est la mémoire ROM. Nous détaillerons ce que sont ces deux mémoires dans la suite du chapitre, mais sachez que nous avions déjà rencontré ces deux types de mémoires dans les chapitres sur les registres et les mémoires adressables.

Les entrées-sorties permettent au processeur et à la mémoire de communiquer avec l'extérieur et d'échanger des informations avec des périphériques. Les périphériques regroupent, pour rappel, tout ce est branché sur un ordinateur, mais n'est pas à l'intérieur de celui-ci.

Le processeur, les mémoires et les entrées-sorties communiquent ensemble via un réseau d'interconnexions. Le terme est assez barbare, mais rien de compliqué sur le principe. C'est juste un ensemble de fils électriques qui relie les différents éléments d'un ordinateur. Les interconnexions sont souvent appelées le bus de communication, mais le terme est un abus de langage, comme on le verra plus bas.

Afin de simplifier les explications, on va supposer que le réseau d'interconnexion est le suivant. Tout est connecté au processeur. Il y a des interconnexions entre le processeur et la mémoire RAM, d'autres interconnexions entre processeur et mémoire ROM, et d'autres entre le processeur et les entrées-sorties. Nous verrons que d'autres réseaux d'interconnexions fusionnent certaines interconnexions, pour les partager entre la ROM et la RAM, par exemple. Mais pour le moment, gardez le schéma ci-dessous en tête.

Réseau d'interconnexion avec un processeur au centre

Les mémoires RAM et ROM

[modifier | modifier le wikicode]

La mémoire est le composant qui mémorise des informations, des données. Dans la majorité des cas, la mémoire est composée de plusieurs cases mémoire, chacune mémorisant plusieurs bits, le nombre de bits étant identique pour toutes les cases mémoire. Dans le cas le plus simple, une case mémoire mémorise un octet, un groupe de 8 bits. Mais les mémoires modernes mémorisent plusieurs octets par case mémoire : elles ont des cases mémoires de 16, 32 ou 64 bits, soit respectivement 2/4/8 octets. De rares mémoires assez anciennes utilisaient des cases mémoires contenant 1, 2, 3, 4, 5, 6 7, 13, 17, 23, 36 ou 48 bits. Mais ce n'était pas des mémoires électroniques, aussi nous allons les passer sous silence.

Tout ce qu'il faut savoir est que la quasi-totalité des mémoires électronique a un ou plusieurs octets par case mémoire. Pour simplifier, vous pouvez imaginer qu'une mémoire RAM est un regroupement de registre, chacun étant une case mémoire. C'est une description pas trop mauvaise pour décrire les mémoires RAM, qu'on abordera dans ce qui suit.

Contenu d'une mémoire, case mémoire de 16 bits (deux octets)
Case mémoire N°1 0001 0110 1111 1110
Case mémoire N°2 1111 1110 0110 1111
Case mémoire N°3 0001 0000 0110 0001
Case mémoire N°4 1000 0110 0001 0000
Case mémoire N°5 1100 1010 0110 0001
... ...
Case mémoire N°1023 0001 0110 0001 0110
Case mémoire N°1024 0001 0110 0001 0110

Dans ce cours, il nous arrivera de partir du principe qu'il y a un octet par case mémoire, par souci de simplification. Mais ce ne sera pas systématique. De plus, il nous arrivera d'utiliser le terme adresse pour parler en réalité de la case mémoire associée, par métonymie.

La capacité mémoire

[modifier | modifier le wikicode]

Bien évidemment, une mémoire ne peut stocker qu'une quantité finie de données. Et à ce petit jeu, certaines mémoires s'en sortent mieux que d'autres et peuvent stocker beaucoup plus de données que les autres. La capacité d'une mémoire correspond à la quantité d'informations que celle-ci peut mémoriser. Plus précisément, il s'agit du nombre maximal de bits qu'une mémoire peut contenir. Elle est le produit entre le nombre de cases mémoire, et la taille en bit d'une case mémoire.

Toutes les mémoires actuelles utilisant des cases mémoire d'un ou plusieurs octets, ce qui nous arrange pour compter la capacité d'une mémoire. Au lieu de compter cette capacité en bits, on préfère mesurer la capacité d'une mémoire avec le nombre d'octets qu'elle contient. Mais les mémoires des PC font plusieurs millions ou milliards d'octets. Pour se faciliter la tâche, on utilise des préfixes pour désigner les différentes capacités mémoires. Vous connaissez sûrement ces préfixes : kibioctets, mébioctets et gibioctets, notés respectivement Kio, Mio et Gio.

Préfixe Capacité mémoire en octets Puissance de deux
Kio 1024 210 octets
Mio 1 048 576 220 octets
Gio 1 073 741 824 230 octets

On peut se demander pourquoi utiliser des puissances de 1024, et ne pas utiliser des puissances un peu plus communes ? Dans la majorité des situations, les électroniciens préfèrent manipuler des puissances de deux pour se faciliter la vie. Par convention, on utilise souvent des puissances de 1024, qui est la puissance de deux la plus proche de 1000. Or, dans le langage courant, kilo, méga et giga sont des multiples de 1000. Quand vous vous pesez sur votre balance et que celle-ci vous indique 58 kilogrammes, cela veut dire que vous pesez 58 000 grammes. De même, un kilomètre est égal à 1000 mètres, et non 1024 mètres.

Autrefois, on utilisait les termes kilo, méga et giga à la place de nos kibi, mebi et gibi, par abus de langage. Mais peu de personnes sont au courant de l'existence de ces nouvelles unités, et celles-ci sont rarement utilisées. Et cette confusion permet aux fabricants de disques durs de nous « arnaquer » : Ceux-ci donnent la capacité des disques durs qu'ils vendent en kilo, méga ou giga octets : l’acheteur croit implicitement avoir une capacité exprimée en kibi, mébi ou gibi octets, et se retrouve avec un disque dur qui contient moins de mémoire que prévu.

Lecture et écriture : mémoires ROM et RWM

[modifier | modifier le wikicode]

Pour simplifier grandement, on peut grossièrement classer les mémoires en deux types : les Read Only Memory et les Read Write Memory, aussi appelées mémoires ROM et mémoires RWM. Pour les mémoires ROM, on ne peut pas modifier leur contenu. On peut y récupérer une donnée ou une instruction : on dit qu'on y accède en lecture. Mais on ne peut pas modifier les données qu'elles contiennent. Quant aux mémoires RWM, on peut y accéder en lecture (récupérer une donnée stockée en mémoire), mais aussi en écriture : on peut stocker une donnée dans la mémoire, ou modifier une donnée existante.

Tout ordinateur contient au minimum une ROM et une RWM (souvent une mémoire RAM), les deux n'ont pas exactement le même rôle. Pour simplifier, la mémoire ROM mémorise le programme à exécuter, la mémoire RWM stocke des données. Il a existé des ordinateurs où la mémoire RWM était une mémoire magnétique, voire acoustique, mais ce n'est plus le cas de nos jours. Pour les ordinateurs modernes, la mémoire RWM est une mémoire électronique. Pour faire la différence avec ces anciennes mémoires RWM, elle est appelée la mémoire RAM. Il s'agit d'une mémoire qui stocke temporairement des données que le processeur doit manipuler (on dit qu'elle est volatile). Elle s'efface complètement quand on coupe l'alimentation de l'ordinateur.

Outre le programme à exécuter, la mémoire ROM peut mémoriser des constantes, des données qui ne changent pas. Elles ne sont jamais modifiées et gardent la même valeur quoi qu'il se passe lors de l'exécution du programme. En conséquence, elles ne sont jamais accédées en écriture durant l'exécution du programme, ce qui fait que leur place est dans une mémoire ROM. La mémoire RWM est alors destinée aux données temporaires, qui changent ou sont modifiées lors de l'exécution du programme, et qui sont donc manipulées aussi bien en lecture et en écriture. La mémoire RWM mémorise alors les variables du programme à exécuter, qui sont des données que le programme va manipuler. Pour les systèmes les plus simples, la mémoire RWM ne sert à rien de plus.

Espaces d'adressage sur une archi harvard modifiée

Pour donner un exemple de données stockées en ROM, on peut prendre l'exemple des anciennes consoles de jeu 8 et 16 bits. Les jeux vidéos sur ces consoles étaient placés dans des cartouches de jeu, précisément dans une mémoire ROM à l'intérieur de la cartouche de jeu. La ROM mémorisait non seulement le code du jeu, le programme du jeu vidéo, mais aussi les niveaux et les sprites et autres données graphiques.

Une conséquence est que les consoles 8/16 bits n'avaient pas besoin de beaucoup de RAM, comparé aux ordinateurs de l'époque, vu qu'une grande partie des données utiles étaient dans une ROM directement accessible par le processeur. À l'opposé, les micro-ordinateurs devaient copier les données d'un jeu depuis une disquette dans la mémoire RAM, ce qui demandait d'avoir plus de RAM. Le passage au support CD sur les consoles 32 bits a eu la même conséquence. Le processeur ne pouvant pas lire directement le CD à sa guise, il fallait copier les données du CD en RAM. D'où l'apparition de temps de chargement assez longs, inexistants sur support cartouche.

L'adressage mémoire

[modifier | modifier le wikicode]

Sur une mémoire RAM ou ROM, on ne peut lire ou écrire qu'une case mémoire, qu'un registre à la fois : une lecture ou écriture ne peut lire ou modifier qu'une seule case mémoire. Techniquement, le processeur doit préciser à quel case mémoire il veut accéder à chaque lecture/écriture. Pour cela, chaque case mémoire se voit attribuer un nombre binaire unique, l'adresse, qui va permettre de le sélectionner et de l'identifier celle-ci parmi toutes les autres. En fait, on peut comparer une adresse à un numéro de téléphone (ou à une adresse d'appartement) : chacun de vos correspondants a un numéro de téléphone et vous savez que pour appeler telle personne, vous devez composer tel numéro. Les adresses mémoires en sont l'équivalent pour les cases mémoire.

Exemple : on demande à la mémoire de sélectionner la case mémoire d'adresse 1002 et on récupère son contenu (ici, 17).

L'adresse mémoire est générée par le processeur. Le processeur peut parfaitement calculer des adresses, en extraire du programme qu'il exécute, et bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. Mais pour le moment, nous avons juste besoin de savoir que c'est le processeur qui envoie des adresses aux mémoires RAM et ROM.

Les adresses générées par le processeur sont alors envoyées à la RAM ou la ROM via une connexion dédiée, un ensemble de fils qui connecte le processeur à la mémoire : le bus d'adresse mémoire. L'adresse sélectionne une case mémoire, le processeur peut alors récupérer la donnée dedans pour une lecture, écrire une donnée pour l'écriture. Pour cela, un second ensemble de fil connecte le processeur à la RAM/ROM, mais cette fois-ci pour échanger des données. Il s'agit du bus de données mémoire. Les deux sont souvent regroupés sous le terme de bus mémoire.

Un ordinateur contient toujours une RAM et une ROM, ce qui demande aux bus mémoire de s'adapter à la présence de deux mémoires. Il y a alors deux solutions, illustrées dans les deux schémas ci-dessous. Avec la première, il y a un seul bus mémoire partagé entre la RAM et la ROM, comme illustré ci-dessous. Une autre solution utilise deux bus séparés : un pour la RAM et un autre pour la ROM. Nous verrons les différences pratiques entre les deux à la fin du chapitre. Pour le moment, nous allons partir du principe qu'il y a un bus pour la mémoire ROM, et un autre bus pour la RAM.

Architecture avec une ROM et une RAM.
Réseau d'interconnexion avec un processeur au centre

L'alignement mémoire : introduction

[modifier | modifier le wikicode]

Plus haut, nous avions dit qu'il y a une adresse par case mémoire, chaque case mémoire contenant un ou plusieurs octets. Mais les processeurs modernes partent du principe que la mémoire a un octet par adresse, pas plus. Et ce même si la mémoire reliée au processeur utilise des cases mémoires de 2, 3, 4 octets ou plus. D'ailleurs, la majorité des mémoires RAM actuelle a des cases mémoires de 64 bits, soit 8 octets par case mémoire. Les raisons à cela sont multiple, mais nous les verrons en détail dans le chapitre sur l'alignement mémoire. Toujours est-il qu'il faut distinguer les adresses mémoire et les adresses d'octet gérées par le processeur.

Le processeur génère des adresses d'octet, qui permettent de sélectionner un octet bien précis. L'adresse d'octet permet de sélectionner un octet parmi tous les autres. Mais la mémoire ne comprend pas directement cette adresse d'octet. Heureusement, l'octet en question est dans une case mémoire bien précise, qui a elle-même une adresse mémoire bien précise. L'adresse d'octet est alors convertie en une adresse mémoire, qui sélectionne la case mémoire adéquate, celle qui contient l'octet voulu. La case mémoire entière est lue, puis le processeur ne récupère que les données adéquates. Pour cela, des circuits d'alignement mémoire se chargent de faire la conversion entre adresses du processeur et adresse mémoire. Nous verrons cela dans le détail dans le chapitre sur l'alignement mémoire.

Il existe des mémoires qui n'utilisent pas d'adresses mémoire, mais passons : ce sera pour la suite du cours.

Dans les ordinateurs, l'unité de traitement porte le nom de processeur, ou encore de Central Processing Unit, abrévié en CPU. Le rôle principal du processeur est de faire des calculs. La plupart des processeurs actuels supportent au minimum l'addition, la soustraction et la multiplication. Quelques processeurs ne gèrent pas la division, qui est une opération très gourmande en circuit, peu utilisée, très lente. Il arrive que des processeurs très peu performants ne gèrent pas la multiplication, mais c'est assez rare.

Un processeur ne fait pas que des calculs. Tout processeur est conçu pour effectuer un nombre limité d'opérations bien précises, comme des calculs, des échanges de données avec la mémoire, etc. Ces opérations sont appelées des instructions. Les plus intuitives sont les instructions arithmétiques, qui font des calculs, comme l'addition, la soustraction, la multiplication, la division. Mais il y a aussi des instructions d'accès mémoire, qui échangent des données entre la mémoire RAM et le processeur. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, tout deviendra plus clair dans les chapitres sur le processeur.

Le processeur exécute un programme, une suite d'instructions

[modifier | modifier le wikicode]

Tout processeur est conçu pour exécuter une suite d'instructions dans l'ordre demandé, cette suite s'appelant un programme. Ce que fait le processeur est défini par la suite d'instructions qu'il exécute, par le programme qu'on lui demande de faire. Les instructions sont exécutées dans un ordre bien précis, les unes après les autres. L'ordre en question est décidé par le programmeur. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres.

Le programme à exécuter est stockée dans la mémoire de l'ordinateur. C'est ainsi que l'ordinateur est rendu programmable : modifier le contenu de la mémoire permet de changer le programme exécuté. Mine de rien, cette idée de stocker le programme en mémoire est ce qui a fait que l’informatique est ce qu'elle est aujourd’hui. C'est la définition même d'ordinateur : appareil programmable qui stocke son programme dans une mémoire modifiable.

Une instruction est codée comme les données : sous la forme de suites de bits. Telle suite de bit indique qu'il faut faire une addition, telle autre demande de faire une soustraction, etc. Pour simplifier, nous allons supposer qu'il y a une instruction par adresse mémoire. Sur la grosse majorité des ordinateurs, les instructions sont placées les unes à la suite des autres dans l'ordre où elles doivent être exécutées. Un programme informatique n'est donc qu'une vulgaire suite d'instructions stockée quelque part dans la mémoire de l'ordinateur.

Exemple de programme informatique
Adresse Instruction
0 Copier le contenu de l'adresse 0F05 dans le registre numéro 5
1 Charger le contenu de l'adresse 0555 dans le registre numéro 4
2 Additionner ces deux nombres
3 Charger le contenu de l'adresse 0555
4 Faire en XOR avec le résultat antérieur
... ...
5464 Instruction d'arrêt

Pour exécuter une suite d'instructions dans le bon ordre, le processeur détermine à chaque cycle quelle est la prochaine instruction à exécuter. Pour cela, le processeur mémorise l'adresse de l'instruction en cours dans un registre : le Program Counter. Je rappelle que des instructions consécutives sont dans des adresses consécutives. Pour passer à la prochaine instruction, il suffit donc d'incrémenter le program counter.

Si une instruction prend plusieurs octets, plusieurs adresses, il suffit de l'incrémenter du nombre d'octets/adresses.

D'autres processeurs font autrement : chaque instruction précise l'adresse de la suivante, directement dans la suite de bit représentant l'instruction en mémoire. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur des processeurs aussi bizarres, pas besoin de stocker les instructions en mémoire dans l'ordre dans lesquelles elles sont censées être exécutées. Mais ces processeurs sont très très rares et peuvent être considérés comme des exceptions à la règle.

Nous venons de voir qu'un processeur contient un registre appelé le program counter. Mais il n'est pas le seul. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement, qui sont mémorisées dans des registres de contrôle. La plupart ont des noms assez barbares (registre d'état, program counter) et nous ne pouvons pas en parler à ce moment du cours. Nous les verrons en temps voulu, mais il est important de préciser qu'ils existent.

L'intérieur d'un processeur

[modifier | modifier le wikicode]

Fort de ce que nous savons, nous pouvons expliquer ce qu'il y a à l'intérieur d'un processeur. Le premier point est qu'un processeur fait des calculs, ce qui implique qu'il contient des circuits de calcul. Ils sont regroupés dans une ou plusieurs unités de calcul. Nous avons déjà vu comment fabriquer une unité de calcul simple, dans un chapitre dédié, et c'est la même qui est présente dans un processeur. Du moins dans les grandes lignes, les circuits des processeurs modernes étant particulièrement optimisés. Il en est de même pour les autres circuits de calcul comme ceux pour les multiplications/division/autres.

Si le processeur fait des calculs, qu'en est-il des opérandes ? Et où sont mémorisés les résultats des opérations ? Pour cela, le processeur incorpore des registres généraux. Les registres généraux servent à mémoriser les opérandes et résultats des instructions. Ils mémorisent des données, contrairement aux registres de contrôle mentionnés plus haut. Le nombre de registres généraux dépend grandement du processeur. Les tout premiers processeurs se débrouillaient avec un seul registre, mais les processeurs actuels utilisent plusieurs registres, pour mémoriser plusieurs opérandes/résultats. Mais la présence de registres est source de pas mal de petites complications. Par exemple, il faut échanger les données entre la RAM et les registres, il faut gérer l'adressage des registres, etc. Il s'agit là de détails que nous expliquerons dans les chapitres sur le processeur.

Le processeur contient enfin un circuit pour interpréter les instructions, appelé l'unité de contrôle. Elle lit les instructions depuis la mémoire, interprète la suite de bit associée, et commande le reste du processeur pour qu'il exécute l'instruction. Ses fonctions sont assez variées, mais nous allons simplifier en disant qu'elle configure l'unité de calcul et les registres pour faire le bon calcul. Son rôle est d'analyser la suite de bit qui constitue l'instruction, et d'en déduire quelle opération effectuer. Elle gère aussi l'accès à la mémoire RAM, et notamment ce qui est envoyé sur son bus d'adresse.

Dans ce qui suit, on suppose que le program counter fait partie de l'unité de contrôle.

Pour résumer, un processeur contient une unité de calcul, des registres et une interface avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L’ensemble forme le chemin de données, nom qui trahit le fait que c'est là que les données se déplacent et sont traitées. Il faut aussi ajouter l'unité de contrôle pour commander le tout. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.

Microarchitecture d'un processeur

Un processeur parait donc assez simple expliqué comme ça, mais il y a de nombreuses subtilités. L'une d'entre elle est liée aux registres, et notamment à la manière dont on les utilise. Pour expliquer ces subtilités, nous allons voir comment les premiers processeurs fonctionnaient, avant de passer aux processeurs un peu plus modernes. Les tout premiers processeurs n'utilisaient qu'un seul registre, ce qui fait que l'utilisation des registres était très simple. Le passage à plusieurs registres a complexifié le tout.

D'où viennent les adresses ?

[modifier | modifier le wikicode]

Il est maintenant temps de répondre à une question qui s'était posée dans la section sur l'adressage : d'où viennent les adresses envoyées à la mémoire ? Pour ce qui est des adresses des instructions, on connait déjà la réponse : c'est le program counter qui gère tout. Mais pour les données, il y a deux possibilités, qui correspondent à deux types de données : les données statiques et les données dynamiques.

Les données statiques sont les plus simples : elles existent durant toute la durée de vie du programme. Tant que celui-ci s'exécute, il aura besoin de ces données. En conséquence, il leur réserve une place en mémoire, qui est toujours la même. La donnée se situe donc à une adresse bien précise, qui ne change jamais. Attention cependant : les données peuvent être modifiées, changer de valeur. Le programme écrit dans les donnée statiques, c'est même assez fréquent. Ce sont ne sont pas forcément des données constantes !

Pour les données statiques, elles sont toujours placées à la même adresse mémoire. Pour le dire autrement, l'adresse mémoire est une constante, qui ne change pas. L'adresse est connue avant d’exécuter le programme, le programme a été codé pour utiliser cette adresse pour telle donnée, on a réservé une adresse pour la donnée voulue. Et même si vous quittez le programme et vous le relancez plusieurs jours après, l'adresse mémoire sera la même avant et après.

Et cela permet d'utiliser l'adressage direct. L'idée est que les instructions précisent donc l'adresse à lire ou écrire. Pour cela, l'adresse est intégrée dans l’instruction elle-même. Pour rappel, l'instruction est codée par une suite de bit en mémoire RAM/ROM, dont certains précisent l'opération à faire, les autres servant à autre chose. L'idée est que certains bits précisent l'adresse mémoire de la donnée à lire. Les instructions sont donc du genre :

  • LOAD 56 - lit l'adresse numéro 56 et copie son contenu dans un registre;
  • STORE R5 , adress 99, copie le registre R5 dans l'adresse 99 ;
  • ADD R5 , adress 209 : additionne le registre R5 avec le contenu de l'adresse 209.

S'il existe des données statiques, c'est signe qu'il existe des données dynamiques. Ces dernières sont des données qui sont créées ou détruites selon les besoins. Pour comprendre d'où viennent ces données dynamiques, prenons le cas d'une personne qui écrit du texte sur un ordinateur. Le texte qu'il écrit est mémorisé dans la RAM de l’ordinateur, puis est sauvegardé sur le disque dur quand il sauvegarde son document. Au fur et à mesure qu'il écrit du texte, la RAM utilisée par ce texte augmente. Donc, ce texte est une donnée dynamique, dont la taille varie dans le temps.

Pour gérer des données dynamiques, la plupart des systèmes d'exploitation incorporent des fonctionnalités d'allocation mémoire. Derrière ce nom barbare, se cache quelque chose de simple : les programmes peuvent réclamer de la mémoire au système d'exploitation, pour y placer les données qu'ils souhaitent. Les langages de programmation bas niveau supportent des fonctions comme malloc(), qui permettent de demander un bloc de mémoire de N octets à l'OS, qui doit alors accommoder la demande. De même, un programme peut libérer de la mémoire qu'il n'utilise plus avec des fonctions comme free().

Avec l'allocation mémoire, les données n'ont pas de place fixe en mémoire. Leur adresse mémoire peut varier d'une exécution du programme à l'autre. Pire que ça : les données peuvent être déplacées dans la mémoire RAM, si besoin. En clair : l'adresse est déterminée lors de l'exécution du programme. L'adresse est alors soit calculée, soit lue depuis la mémoire RAM, soit déterminée autrement. Toujours est-il qu'elle se retrouve dans un registre général. Pour gérer ces adresse variables, les processeurs utilisent l'adressage indirect. L'adressage indirect permet d'utiliser une adresse qui est dans un registre de données. L'adresse en question peut être envoyée à la mémoire RAM sans problème, le processeur peut automatiquement connecter le registre adéquat sur le bus d'adresse.

Au tout début de l'informatique, les processeurs ne supportaient que l'adressage direct, pas plus. L'adressage indirect n'était tout simplement pas possible. Avec l'adressage direct, l'adresse à lire est extraite directement des instructions, par l'unité de contrôle. Le bus d'adresse de la RAM est alors relié directement à l'unité de contrôle, le bus de données est relié aux registres.

Architecture Harvard avec adressage direct uniquement

Mais dès les années 70, l'adressage indirect est apparu, rendant la programmation bien plus simple. Mais cela a demandé quelques adaptation au niveau du processeur. Avec l'adressage indirect, le bus d'adresse est connecté aux registres. Il a donc fallu rajouter un multiplexeur pour que le processeur décide de relier le bus d'adresse soit aux registres, soit à l'unité de contrôle.

Un ordinateur peut avoir plusieurs processeurs

[modifier | modifier le wikicode]

La plupart des ordinateurs n'ont qu'un seul processeur, ce qui fait qu'on désigne avec le terme d'ordinateurs mono-processeur. Mais il a existé (et existe encore) des ordinateurs multi-processeurs, avec plusieurs processeurs sur la même carte mère. L'idée était de gagner en performance : deux processeurs permettent de faire deux fois plus de calcul qu'un seul, quatre permettent d'en faire quatre fois plus, etc. C'est très courant sur les supercalculateurs, des ordinateurs très puissants conçus pour du calcul industriel ou scientifique, mais aussi sur les serveurs ! Dans le cas le plus courant, ils utilisent plusieurs processeurs identiques : on utilise deux processeurs Core i3 de même modèle, ou quatre Pentium 3, etc.

Pour utiliser plusieurs processeurs, les programmes doivent être adaptés. Pour cela, il y a plusieurs possibilités :

  • Une première possibilité, assez intuitive, est d’exécuter des programmes différents sur des processeurs différents. Par exemple, on exécute le navigateur web sur un processeur, le lecteur vidéo sur un autre, etc.
  • La seconde option est de créer des programmes spéciaux, qui utilisent plusieurs processeurs. Ils répartissent les calculs à faire sur les différents processeurs. Un exemple est la lecture d'une vidéo sur le web : un processeur peut télécharger la vidéo pendant le visionnage et bufferiser celle-ci, un autre processeur peut décoder la vidéo, un autre décoder l'audio. De tels programmes restent des suites d'instructions, mais ils sont plus complexes que les programmes normaux, aussi nous les passons sous silence.
  • La troisième option est d’exécuter le même programme sur les différents processeurs, mais chaque processeur traite son propre ensemble de données. Par exemple, pour un programme de rendu 3D, quatre processeurs peuvent s'occuper chacun d'une portion de l'image.
Architecture de Von Neumann Princeton multi processeurs

De nos jours, les ordinateurs grand public les plus utilisés sont dans un cas intermédiaire, ils ne sont ni mono-, ni multi-processeur. Ils n'ont qu'un seul processeur, dans le sens où si on ouvre l'ordinateur et qu'on regarde la carte mère, il n'y a qu'un seul processeur. Mais ce processeur est en réalité assez similaire à un regroupement de plusieurs processeurs dans le même boitier. Il s'agit de processeurs multicœurs, qui contiennent plusieurs cœurs, chaque cœur pouvant exécuter un programme tout seul.

La différence entre cœur et processeur est assez difficile à saisir, mais pour simplifier : un cœur est l'ensemble des circuits nécessaires pour exécuter un programme. Chaque cœur dispose de toute la machinerie électronique pour exécuter un programme, à savoir des circuits aux noms barbares comme : un séquenceur d'instruction, des registres, une unité de calcul. Par contre, certains circuits d'un processeur ne sont présents qu'en un seul exemplaire dans un processeur multicœur, comme les circuits de communication avec la mémoire ou les circuits d’interfaçage avec la carte mère.

Suivant le nombre de cœurs présents dans notre processeur, celui-ci sera appelé un processeur double-cœur (deux cœurs), quadruple-cœur (4 cœurs), octuple-cœur (8 cœurs), etc. Un processeur double-cœur est équivalent à avoir deux processeurs dans l'ordinateur, un processeur quadruple-cœur est équivalent à avoir quatre processeurs dans l'ordinateur, etc. Ces processeurs sont devenus la norme dans les ordinateurs grand public et les logiciels et systèmes d'exploitation se sont adaptés.

Les coprocesseurs

[modifier | modifier le wikicode]

Quelques ordinateurs assez anciens disposaient de coprocesseurs, des processeurs qui complémentaient un processeur principal. Les ordinateurs de ce type avaient un processeur principal, le CPU, qui était secondé par un ou plusieurs coprocesseurs. Sauf exception, le CPU et le coprocesseur exécutent des programmes différents, ils travaillent en parallèle.

Les coprocesseurs les plus connus sont les coprocesseurs pour le rendu 2D/3D et les coprocesseurs sonores. Ils ont eu leur heure de gloire sur les anciennes consoles de jeux vidéo, comme La Nintendo 64, la Playstation et autres consoles de cette génération ou antérieure. Ils s'occupaient respectivement de calculer les graphismes des jeux vidéos, et de calculer tout ce qui a trait au son. Pour donner un exemple, on peut citer la console Neo-géo, qui disposait de deux processeurs travaillant en parallèle : un processeur principal, et un co-processeur sonore. Le processeur principal était un Motorola 68000, alors que le co-processeur sonore était un processeur Z80.

L'accès aux périphériques est quelque chose sur lequel nous passerons plusieurs chapitres dans ce cours. Mais sachez que l'accès aux périphériques peut demander pas mal de puissance de calculs. Le CPU principal peut faire ce genre de calculs par lui-même, mais il n'est pas rare qu'un coprocesseur d'IO soit dédié à l'accès aux périphériques. Un exemple assez récent est celui de la console de jeu Nintendo 3DS. Elle disposait d'un processeur principal de type ARM9, d'un coprocesseur pour les divisions qu'on abordera plus bas, et d'un second processeur ARM7. L'ARM 7 était utilisé comme coprocesseur d'I/O, ainsi que pour l'émulation de la console GBA.

Co-processeur pour l'accès aux entrées-sorties.

Les coprocesseurs arithmétiques sont un peu à part des autres. Ils sont spécialisés dans les calculs en virgule flottante. Ils étaient utilisés à une époque où les CPU ne géraient que des calculs entiers (en binaire ou en BCD). Un exemple est le coprocesseur flottant x87, complémentaire des premiers processeurs Intel x86. Il y a eu la même chose sur les processeurs Motorola 68000, avec deux coprocesseurs flottants appelés les Motorola 68881 et les Motorola 68882.

Un exemple récent de coprocesseur est celui utilisé sur la console de jeu Nintendo DS. La console utilisait deux processeurs, un ARM9 et un ARM7, qui ne pouvaient pas faire de division entière. Il s'agit pourtant d'opérations importantes dans le cas du rendu 3D, ce qui fait que les concepteurs de la console ont rajouté un coprocesseur spécialisé dans les divisions entières et les racines carrées. Le coprocesseur était adressable directement par le processeur, comme peuvent l'être la RAM ou les périphériques.

Les entrées-sorties

[modifier | modifier le wikicode]

Tous les circuits vus précédemment traitent des données codées en binaire. Ceci dit, les données ne sortent pas de n'importe où : l'ordinateur contient des composants électroniques qui traduisent des informations venant de l’extérieur en nombres. Ces composants sont ce qu'on appelle des entrées. Par exemple, le clavier est une entrée : l'électronique du clavier attribue un nombre entier (scancode) à une touche, nombre qui sera communiqué à l’ordinateur lors de l'appui d'une touche. Pareil pour la souris : quand vous bougez la souris, celle-ci envoie des informations sur la position ou le mouvement du curseur, informations qui sont codées sous la forme de nombres. La carte son évoquée il y a quelques chapitres est bien sûr une entrée : elle est capable d'enregistrer un son, et de le restituer sous la forme de nombres.

S’il y a des entrées, on trouve aussi des sorties, des composants électroniques qui transforment des nombres présents dans l'ordinateur en quelque chose d'utile. Ces sorties effectuent la traduction inverse de celle faite par les entrées : si les entrées convertissent une information en nombre, les sorties font l'inverse : là où les entrées encodent, les sorties décodent. Par exemple, un écran LCD est un circuit de sortie : il reçoit des informations, et les transforme en image affichée à l'écran. Même chose pour une imprimante : elle reçoit des documents texte encodés sous forme de nombres, et permet de les imprimer sur du papier. Et la carte son est aussi une sortie, vu qu'elle transforme les sons d'un fichier audio en tensions destinées à un haut-parleur : c'est à la fois une entrée, et une sortie.

Les entrées-sorties incluent toutes les entrées et sorties, et même certains composants qui sont les deux à la fois. Il s'agit d'un terme générique, qui regroupe des composants forts différents. Dans ce qui va suivre, nous allons parfois parler de périphériques au lieu d'entrées-sorties, mais les deux termes ne sont pas équivalents. Dans le détail, les entrées-sorties regroupent :

  • Les périphériques sont les composants connectés sur l'unité centrale. Exemple : les claviers, souris, webcam, imprimantes, écrans, clés USB, disques durs externes, la Box internet, etc.
  • Les cartes d'extension, qui se connectent sur la carte mère via un connecteur, comme les cartes son ou les cartes graphiques.
  • D'autres composants sont soudés à la carte mère mais sont techniquement des entrées-sorties : les cartes sons soudées sur les cartes mères actuelles, par exemple.

L'interface avec le reste de l'ordinateur

[modifier | modifier le wikicode]

Les entrées-sorties sont très diverses, fonctionnent très différemment les unes des autres. Mais du point de vue du reste de l'ordinateur, les choses sont relativement standardisées. Du point de vue du processeur, les entrées-sorties sont juste des paquets de registres ! Tous les périphériques, toutes les entrées-sorties contiennent des registres d’interfaçage, qui permettent de faire l'intermédiaire entre l'entrée/sortie et le reste de l'ordinateur. L'entrée/sortie est conçu pour réagir automatiquement quand on écrit dans ces registres.

Registres d'interfaçage.

Les registres d’interfaçage sont assez variés. Les plus évidents sont les registres de données, qui permettent l'échange de données entre le processeur et les périphériques. Pour échanger des données avec l'entrée/sortie, le processeur a juste à lire ou écrire dans ces registres de données. On trouve généralement un registre de lecture et un registre d'écriture, mais il se peut que les deux soient fusionnés en un seul registre d’interfaçage de données. Si le processeur veut envoyer une donnée à une entrée/sortie, il a juste à écrire dans ces registres. Inversement, s'il veut lire une donnée, il a juste à lire le registre adéquat.

Mais le processeur ne fait pas que transmettre des données à l'entrée/sortie. Le processeur lui envoie aussi des « commandes », des valeurs numériques auxquelles l'entrée/sortie répond en effectuant un ensemble d'actions préprogrammées. En clair, ce sont l'équivalent des instructions du processeur, mais pour l'entrée/sortie. Par exemple, les commandes envoyées à une carte graphique peuvent être : affiche l'image présente à cette adresse mémoire, calcule le rendu 3D à partir des données présentes dans ta mémoire, etc. Pour recevoir les commandes, l'entrée/sortie contient des registres de commande qui mémorisent les commandes envoyées par le processeur. Quand le processeur veut envoyer une commande à l'entrée/sortie, il écrit la commande en question dans ce ou ces registres.

Enfin, beaucoup d'entrée/sortie ont un registre d'état, lisible par le processeur, qui contient des informations sur l'état de l'entrée/sortie. Ils servent notamment à indiquer au processeur que l'entrée/sortie est disponible, qu'il est en train d’exécuter une commande, qu'il est occupé, qu'il y a un problème, qu'il y a une erreur de configuration, etc.

Les adresses des registres d’interfaçage

[modifier | modifier le wikicode]

Les registres des périphériques sont identifiés par des adresses mémoires. Et les adresses sont conçues de façon à ce que les adresses des différentes entrées/sorties ne se marchent pas sur les pieds. Chaque entrée/sortie, chaque registre, chaque contrôleur a sa propre adresse. D'ordinaire, certains bits de l'adresse indiquent quel est le destinataire. Certains indiquent quel est l'entrée/sortie voulue, les restants indiquant le registre de destination.

Il existe deux organisations possibles pour les adresses des registres d’interfaçages. La première possibilité est de séparer les adresses pour les registres d’interfaçage et les adresses pour la mémoire. Le processeur doit avoir des instructions séparées pour gérer les périphériques et adresser la mémoire. Il a des instructions de lecture/écriture pour lire/écrire en mémoire, et d'autres pour lire/écrire les registres d’interfaçage. Sans cela, le processeur ne saurait pas si une adresse est destinée à un périphérique ou à la mémoire.

Espaces d'adressages séparés entre mémoire et périphérique

L'autre méthode mélange les adresses mémoire et des entrées-sorties. Si on prend par exemple un processeur de 16 bits, où les adresses font 16 bits, alors les 65536 adresses possibles seront découpées en deux portions : une partie ira adresser la RAM/ROM, l'autre les périphériques. On parle alors d'entrées-sorties mappées en mémoire. L'avantage est que le processeur n'a pas besoin d'avoir des instructions séparées pour les deux.

IO mappées en mémoire

Pour résumer, communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires. Il suffit de lire ou écrire dans des registres d’interfaçage, qui ont chacun une adresse mémoire. Le problème est que le système d'exploitation ne connaît pas toujours le fonctionnement d'une entrée/sortie : il faut installer un programme qui va s'exécuter quand on souhaite communiquer avec l'entrée/sortie, et qui s'occupera de tout ce qui est nécessaire pour le transfert des données, l'adressage du périphérique, etc. Ce petit programme est appelé un driver ou pilote de périphérique. La « programmation » périphérique est très simple : il suffit de savoir quoi mettre dans les registres, et c'est le pilote qui s'en charge.

Les architectures Harvard et Von Neumann

[modifier | modifier le wikicode]

Après avoir vu le processeur, les mémoires et les entrées-sorties, voyons voir comment le tout est interconnecté. Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Mais pour comprendre pourquoi, nous devons regarder qui communique avec qui, dans un ordinateur. Pour rappel, les données sont placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. Le processeur lit des instructions dans la mémoire ROM, il lit et écrit dans la mémoire RAM, et accède aux registres d’interfaçage des entrées-sorties. Il y a donc besoins de trois interconnexions : CPU-ROM, CPU-RAM et CPU-IO.

Réseau d'interconnexion avec un processeur au centre

Il parait intéressant d'utiliser trois interconnexions, au minimum CPU-ROM, CPU-RAM et CPU-IO. Néanmoins, faire ainsi a de nombreux désavantages. Déjà, il faut pouvoir brancher tout ça sur le processeur. Et celui-ci n'a pas forcément assez de broches pour. Aussi, il est parfois préférable de mutualiser des bus, à savoir de connecter plusieurs composants sur un même bus. Par exemple, on peut mutualiser le bus pour la mémoire RAM et pour la mémoire ROM. Il faut dire que les deux bus sont des bus mémoire, avec un bus d'adresse, un bus de données, et surtout : des bus de commande similaires. Les mutualiser est alors très simple, et permet d'économiser pas mal de broches.

Réseau d'interconnexion avec un processeur au centre et une architecture Harvard

Cette mutualisation nous amène naturellement à parler de la distinction entre les architectures Harvard d'un côté et les architectures Von Neumann de l'autre. Elle est très liée au fait d'utiliser soit un bus mémoire unique, soit des bus séparés pour la ROM et la RAM. Voyons cela en détail.

Les architectures Harvard et Von Neumann : des bus séparés ou unifiés

[modifier | modifier le wikicode]

Avec l'architecture Harvard, la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. Il y a un bus RAM pour la mémoire RAM, un bus ROM pour la mémoire ROM. L'avantage de cette architecture est qu'elle permet de charger une instruction et une donnée simultanément : une instruction chargée sur le bus relié à la mémoire programme, et une donnée chargée sur le bus relié à la mémoire de données. Et cela simplifie fortement la conception du processeur.

Architecture Harvard, avec une ROM et une RAM séparées.

Avec l'architecture Von Neumann, mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Le bus unique qui relie processeur, RAM et ROM, s'appelle le bus mémoire. Un défaut de ces architecture est qu'elles ne peuvent pas charger une instruction et une donnée en même temps. Et cela pose quelques problèmes pour la conception du processeur. Par contre, nous verrons dans ce qui suit qu'utiliser un bus mémoire partagé est bien plus flexible et permet des choses que les architectures Harvard ne peuvent pas faire.

Architecture Von Neumann, avec deux bus séparés.

Les architectures Harvard et Von Neumann : des espaces d'adressage séparés ou unifiés

[modifier | modifier le wikicode]

La distinction précédente se base sur les connexions entre RAM, ROM et processeur. Mais il existe une autre distinction, très liée, qui est souvent utilisée comme seconde définition des architectures Harvard/Von Neumann. Elle est liée aux adresses mémoire que le processeur peut gérer. Prenons un processeur 16 bits, par exemple, qui gère naturellement des adresses de 16 bits. Il peut gérer 2^16 adresses, soit 64 kibioctets de mémoire. L'ensemble de ces adresses est appelé un espace d'adressage. Mais comment cet espace d'adressage est utilisé pour adresser une RAM et une ROM ?

Sur les architectures Harvard, le processeur voit deux mémoires séparées avec leur lot d'adresses distinctes. Une même adresse peut donc correspondre soit à la mémoire ROM, soit à la mémoire RAM, suivant le bus utilisé. L'espace d'adressage est donc doublé, dupliqué, avec un pour la ROM, un autre pour la RAM. Rien d'étonnant à cela : il y a deux bus d'adresses, chacun correspondant à un espace d'adressage.

Vision de la mémoire par un processeur sur une architecture Harvard.

Avec l'architecture Von Neumann, la RAM et la ROM doivent se partager les adresses mémoires disponibles. Il n'y a qu'un seul espace d'adressage qui est coupé en deux, avec une partie pour la ROM et une autre pour la RAM. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux. Typiquement, la mémoire ROM occupe une partie des adresses, la mémoire RAM utilise le reste. La répartition des adresses est réalisée par les circuits de décodage d'adresse mentionnés plus haut.

Vision de la mémoire par un processeur sur une architecture Von Neumann.

Les architectures Harvard modifiées sont des intermédiaires entre architectures Harvard et architectures Von Neumann, bien qu'elles penchent bien plus du côté des architectures Harvard. Précisons que la terminologie n'est pas claire, beaucoup d'auteurs mettent des définitions différentes derrière ces deux termes. Mais dans ce cours, nous utiliserons une définition très stricte de ce qu'est une architecture Harvard modifiée.

Une architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Nous avions vu plus haut que les mémoires ROM peuvent mémoriser, en plus d'un programme exécutable, des données constantes, qui ne varient pas. Les architectures Harvard pures ne permettent pas de lire des données de ce genre depuis la mémoire ROM, alors que les architectures Harvard modifiées le permettent.

Une architecture Harvard modifiée dispose d'une instruction pour lire les données en mémoire RWM, et d'une instruction pour lire des données en mémoire ROM. Il y a donc deux versions de l'instruction LOAD, qui copient la donnée dans un registre général, mais dont la source de la donnée est différente. Une autre possibilité, plus rare, est que une instruction de copie, qui copie une constante depuis la mémoire ROM vers la mémoire RAM. Le cas le plus commun est l'utilisation de deux instructions LOAD séparées.

Espaces d'adressage sur une archi harvard modifiée

Ceci étant dit, revenons à la distinction entre architecture Harvard et Von Neumann. Il faut noter que la RAM et la ROM n'ont pas forcément la même taille. Et ce que ce soit sur une architecture Harvard que sur une architecture Von Neumann, mais c'est plus facile à expliquer sur une architecture Harvard.

On peut par exemple imaginer une architecture Harvard qui utilise des adresses de 16 bits pour la ROM, et seulement 8 bits pour la RAM. Le résultat est qu'il peut adresser 64 kibioctets de ROM, mais seulement 256 octets de RAM. Les deux bus d'adresse sont alors de taille différente, l'un faisant 8 bits, l'autre 16. Quelques processeurs 8 bits étaient dans ce cas, comme on le verra dans le chapitre sur les CPU 8bits. Mais d'autres processeurs utilisent des valeurs différentes, avec par exemple des adresses de 16 bits pour la RAM, mais de 20 bits pour la ROM, ou inversement.

Sur une architecture Von Neumann, tout dépend de comment les adresses sont réparties. La solution la plus simple découpe l'espace d'adressage en deux parties égales, avec la RAM qui est dans la moitié basse (qui part de l'adresse 0 jusqu'à l'adresse au milieu), alors que la ROM est dans la moitié haute (entre l'adresse du milieu et l'adresse maximale). Mais ce n'est pas la seule possibilité, la limite entre RAM et ROM peut être mise n'importe où. Prenons par exemple un processeur 32 bits, capable de gérer 4 milliards d'adresse. Il est parfaitement possible de réserver 128 mébioctets de poids fort à la mémoire ROM, et de laisser le reste à la mémoire RAM.

Le décodage d'adresse sur les architectures Von Neumann

[modifier | modifier le wikicode]

Pour résumer, les architectures Harvard et Von Neumann se distinguent sur deux points :

  • L'accès à la RAM et à la ROM se font par des bus séparés sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
  • Les adresses pour la mémoire ROM et la mémoire RAM sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.

Les architectures Von Neumann utilisent donc un seul bus pour connecter la RAM et la ROM au processeur. Mais cela ne parait pas intuitif : comment deux composants peuvent se connecter aux mêmes fils ? Parce que c'est ce qu'implique le fait de partager un bus. Si je prends une mémoire RAM et une mémoire ROM, toutes deux de 8 bits, elles seront connectées à un bus mémoire de 8 bits. Intuitivement, on se dit qu'il y aura des conflits, du genre : la RAM et la ROM vont accéder au bus en même temps, comment savoir si une adresse est destinée à la RAM ou la ROM, etc ?

Tous ces problèmes sont résolus avec une solution très simple : à chaque instant, seule une mémoire est connectée au bus. L'idée est que les mémoires sont connectées ou déconnectées du bus selon les besoins. Si le processeur veut envoyer lire une donnée en mémoire RAM, il déconnecte la mémoire ROM du bus. Et inversement, s'il veut lire une instruction, il déconnecte la RAM et connecte la ROM.

Pour cela, les mémoires RAM et ROM possèdent une entrée Chip Select ou Output Enable, qui agit comme une sorte de bouton ON/OFF. Lorsqu'on met un 1 sur cette entrée, la mémoire se connectera au bus. Ses entrées et sorties fonctionneront normalement, elle pourra recevoir des adresses, envoyer ou recevoir des données, tout sera normal. Par contre, si on met un 0 sur cette entrée, la mémoire se "désactive", ses entrée-sorties ne répondent plus aux sollicitations extérieures. Pire que ça : elles sont électriquement déconnectées.

Au total, tout cela demande de gérer deux bit Chip Select/Output Enable : un pour la RAM, un pour la ROM. Et ces deux bits sont configurés pour chaque accès mémoire, pour chaque lecture ou écriture. Pour cela, un circuit de décodage d'adresse prend en entrée l'adresse mémoire à lire/écrire, et active/désactive les mémoires RAM/ROM selon les besoins. Il prend l'adresse et configure les bits Chip Select/Output Enable.

Décodage d'adresse sur une architecture Von Neumann.

L'implémentation la plus simple réserve la moitié des adresses pour la RAM, l'autre moitié pour la ROM. Typiquement, la ROM prend la moitié basse, la RAM la moitié haute. Dans ce cas, activer/désactiver la RAM et la ROM se fait avec seulement le bit de poids fort de l'adresse. Si le bit de poids fort est à 1, alors on accède à la RAM et la ROM doit être désactivée. Mais si ce bit est à 0, alors on accède à la moitié basse et il faut désactiver la RAM.

Une remarque intéressante : le fait de séparer la mémoire en deux parts égales permet de simuler une architecture Harvard à partir d'une architecture Von Neumann. Par exemple, le tout premier processeur d'Intel, le 4004, était l'un de ceux là. La RAM et la ROM sont reliés au même bus, et il y a donc un unique espace d'adressage, qui est séparé en deux parties égales. Le truc est que le processeur traite les deux parties égales comme deux espaces d'adressage séparés. Le processeur se débrouille pour cacher le fait qu'il y a un espace d'adressage unique coupé en deux, ce qui fait que les programmeurs voient bien deux espaces d'adressages distincts.

Décodage d'adresse sur une architecture Von Neumann basique.

Pour résumer, quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre et se connecter au bus. Le décodage d'adresse garantit que seule la mémoire adéquate réponde à un accès mémoire. Le décodage d'adresse est réalisé par la carte mère, par un composant dédié.

Le mécanisme peut être utilisé pour combiner plusieurs RAM en une seule, idem avec les ROM. Pour comprendre l'idée, je vais prendre l'exemple de l'IBM PC, un des tout premier PC existant. Nous étudierons ce PC dans une section dédiée, à la fin du chapitre, aussi je vais passer rapidement dessus. Tout ce que je vais faire est vous présenter la carte mère du PC, et vous demander de faire est de compter les mémoires ROM et mémoires RAM sur la carte mère :

Carte mère de l'IBM 5150, un modèle de l'IBM PC.

Si vous remarquerez qu'il y a 5 mémoires ROM et 8 à 32 mémoires RAM. Le fait est que le processeur voit les différentes mémoires ROM comme une seule mémoire ROM. Idem avec les mémoires RAM : elle font chacune 2 kibioctets, et l'ensemble est vu par le processeur comme une seule RAM de 16 à 64 kibioctets. Et cela grâce aux circuits de décodage d'adresse, qui sont situés en haut à droite de la carte mère.

Pour comprendre l'idée, prenons l'exemple d'un processeur 16 bits, capable de gérer 64 kibioctets de mémoire. L'espace d'adressage est découpé en quatre portions, de 16 kibioctets chacune. Une portion est réservée à une ROM de 16 kibioctet, les autres sont chacune réservée à une RAM de 16 kibioctet. Le décodage d'adresse sélectionne alors la mémoire adéquate en utilisant les deux bits de poids fort de l'adresse.

  • S'ils valent 00, alors c'est la mémoire ROM qui est activée, connectée au bus.
  • S'ils valent 01, alors c'est la première mémoire RAM qui est connectée au bus.
  • S'ils valent 10, alors c'est la seconde mémoire RAM qui est connectée au bus.
  • S'ils valent 11, alors c'est la troisième mémoire RAM qui est connectée au bus.
Décodage d'adresse sur une architecture Von Neumann, utilisant plusieurs RAM et une ROM

L'impact sur la conception du processeur

[modifier | modifier le wikicode]

Plus haut, j'ai parlé d'un des avantages des architectures Harvard : elles peuvent lire une instruction en même temps qu'elles accèdent à une donnée. La donnée est lue/écrite en RAM, alors que l'instruction est lue en ROM. Et cela permet de simplifier l'intérieur du processeur. Pas de beaucoup, mais c'est déjà ça de pris. Voyons maintenant comment cela impacte l'intérieur du processeur. Tout ce dont vous avez à vous rappeler est la séparation entre chemin de données et unité de contrôle, et que les registres généraux sont dans le premier, le program counter dans la seconde.

Avec une architecture Harvard, les instructions et les données passent par des bus différent : bus ROM pour les instructions, bus RAM pour les données. L'intuition nous dit que le bus pour la mémoire ROM est connecté à l'unité de contrôle, alors que le bus pour la RAM est connecté au chemin de données. Et dans les grandes lignes, c'est vrai. La logique est imparable pour ce qui est des bus de données. Mais il y a une petite subtilité pour les bus d'adresse.

Pour comprendre comment le processeur exploite ces deux bus, voyons ce qui transite dessus. Pour la mémoire ROM, elle reçoit l'adresse de l'instruction à lire, elle renvoie l'instruction adéquate. Pour cela, le program counter est envoyé sur le bus d'adresse, l'instruction sur le bus de données. Pour la mémoire RAM, elle échange des données avec les registres généraux, les registres pour les données. Les adresses utilisées pour la RAM viennent elles soit du chemin de données, soit de l'unité de contrôle, tout dépend du mode d'adressage. Mais le program counter n'est pas impliqué.

Architecture Harvard - échanges de données

Les architectures Harvard modifiées doivent cependant rajouter une connexion entre le bus ROM et les registres généraux. C'est nécessaire pour charger une donnée constante depuis la mémoire ROM. Rappelons que la donnée constante est copiée dans un registre général, donc dans le chemin de données.

Architecture Harvard modifiée - implémentation du processeur

Avec les architectures Von Neumann, il y a un seul bus qui est relié à la fois au chemin de données et à l'unité de contrôle. Si le processeur lit une instruction, le bus doit être relié à l'unité de contrôle. Par contre, s'il accède à une donnée, il doit être relié au chemin de données (le bus d'adresse peut éventuellement être connecté au séquenceur, si celui-ci fournit l'adresse à lire). Il faut donc utiliser un paquet de multiplexeurs et de démultiplexeurs pour faire la connexion au bon endroit.

Architecture Von Neumann - implémentation du processeur

Une instruction se fait en deux temps : on charge l'instruction depuis la mémoire ROM, puis on l'exécute. Avec une architecture Harvard, tout cela se fait en un seul cycle d'horloge, vu que charger la ROM et accéder aux données peut se faire en même temps. Pas avec les architectures Von Neumann, qui doivent libérer le bus mémoire après avoir chargé une instruction. Elles n'ont pas le choix : elles chargent l'instruction lors d'un premier cycle d'horloge, puis l'exécutent lors du second.

Pour cela, ils incorporent un registre appelé le registre d'instruction, qui mémorise l'instruction chargée. L'instruction est copiée dans ce registre lors du premier cycle, puis est utilisée lors du second cycle. Le registre permet de ne pas oublier l’instruction entre les deux cycles. Le registre d'instruction est obligatoire sur les architectures Von Neumann. En comparaison, il est facultatif sur les architectures Harvard. Elles peuvent en avoir un, pour des raisons techniques, mais ce n'est pas obligatoire.

Registre d'instruction.

Les architectures Von Neumann sont plus flexibles

[modifier | modifier le wikicode]

Sur les architectures Harvard, le processeur sait faire la distinction entre programme et données. Les données sont stockées dans la mémoire RAM, le programme est stocké dans la mémoire ROM. Les deux sont séparés, accédés par le processeur sur des bus séparés, et c'est ce qui permet de faire la différence entre les deux. Il est impossible que le processeur exécute des données ou modifie le programme. Du moins, tant que la mémoire qui stocke le programme est bien une ROM.

Par contre, sur les architectures Von Neumann, il est impossible de distinguer programme et données, sauf en ajoutant des techniques de protection mémoire avancées. La raison est qu'il est impossible de faire la différence entre donnée et instruction, vu que rien ne ressemble plus à une suite de bits qu'une autre suite de bits. Et c'est à l'origine d'un des avantages majeur de l'architecture Von Neumann : il est possible que des programmes soient copiés dans la mémoire RWM et exécutés dans celle-ci.

Un cas d'utilisation familier est celui de votre ordinateur personnel. Le système d'exploitation et les autres logiciels sont copiés en mémoire RAM à chaque fois que vous les lancez. Mais cet exemple implique un disque dur, ce qui rend les choses plus compliquées que prévu. Un autre exemple serait la compilation de code à la volée, mais il ne sera pas très parlant.

Un exemple plus adapté serait celui où la ROM mémorise un programme compressée dans la mémoire ROM, qui est décompressé pour être exécuté en mémoire RAM. Le programme de décompression est stocké en mémoire ROM et est exécuté au lancement de l’ordinateur. Cette méthode permet d'utiliser une mémoire ROM très petite et très lente, tout en ayant un programme rapide (si la mémoire RWM est rapide).

Il est aussi possible de créer des programmes qui modifient leurs propres instructions : cela s'appelle du code auto-modifiant. Ce genre de choses servait autrefois sur des ordinateurs rudimentaires, au tout début de l'informatique. A l'époque, les adresses à lire/écrire devaient être écrites en dur dans le programme, dans les instructions exécutées. Pour gérer certaines fonctionnalités des langages de programmation qui ont besoin d'adresses modifiables, comme les tableaux, on devait corriger les adresses au besoin avec du code auto-modifiant. De nos jours, le code automodifiant est utilisée occasionnellement pour rendre un programme indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés).

L'impossibilité de séparer données et instructions est à l'origine de problèmes assez fâcheux. Il est parfaitement possible que le processeur charge et exécute des données, qu'il prend par erreur pour des instructions. C'est le cas quand des pirates informatiques arrivent à exploiter des bugs. Il arrive que des pirates informatiques vous fournissent des données corrompues, qui contiennent un virus ou un programme malveillant est caché dans les données. Les bugs en question permettent d'exécuter ces données, donc virus. Pour éviter cela, le système d'exploitation peut marquer certaines zones de la mémoire comme non-exécutable, c’est-à-dire que le système d'exploitation interdit d’exécution de quoi que ce soit qui est dans cette zone. Mais ce n'est pas parfait.

Toujours est-il que tout cela est impossible sur les architectures Harvard. Et ce serait très limitant. Imaginez : pas possible de lancer un programme depuis le disque dur ou une clé USB, le programme doit impérativement être dans une mémoire ROM, pas de compilation à la volée, etc. Que des techniques très utilisées dans l'informatique moderne. Malgré ses défauts, les architectures Von Neumann ne sont pas les plus utilisées pour rien. Les architectures Harvard sont concrètement utilisées uniquement dans l'informatique embarquée, sur des microcontrôleurs très spécifiques.

Le bus de communication avec les entrées-sorties

[modifier | modifier le wikicode]

Le processeur, la mémoire et les entrées-sorties sont connectées par un ou plusieurs bus de communication. Ce bus n'est rien d'autre qu'un ensemble de fils électriques sur lesquels on envoie des zéros ou des uns. Pour communiquer avec la mémoire, il y a trois prérequis qu'un bus doit respecter : pouvoir sélectionner la case mémoire (ou l'entrée-sortie) dont on a besoin, préciser à la mémoire s'il s'agit d'une lecture ou d'une écriture, et enfin pouvoir transférer la donnée. Pour cela, on doit donc avoir trois bus spécialisés, bien distincts, qu'on nommera le bus de commande, le bus d'adresse, et le bus de donnée.

  • Le bus de données, sur lequel s'échangent les données entre les composants.
  • Le bus de commande pour configurer la mémoire et les entrées-sorties.
  • Le bus d'adresse, facultatif, permet de préciser quelle adresse mémoire il faut lire/écrire.

Chaque composant possède des entrées séparées pour le bus d'adresse, le bus de commande et le bus de données. Par exemple, une mémoire RAM possédera des entrées sur lesquelles brancher le bus d'adresse, d'autres sur lesquelles brancher le bus de commande, et des broches d'entrée-sortie pour le bus de données. Précisons cependant que le bus de commande n'est pas exactement le même entre des mémoires RAM/ROM et des entrées-sorties.

Contenu d'un bus, généralités.

Le réseau d'interconnexion : généralités

[modifier | modifier le wikicode]

Reprenons où nous nous étions arrêté. Avant de voir les architectures Harvard et Von Neumann, nous avions dit que le processeur, les mémoires et les entrées-sorties sont reliées entre eux par un réseau d'interconnexion. Nous venons de voir qu'il est possible de mutualiser certains bus, notamment celui de la mémoire RAM et celui de la mémoire ROM. Mais il est possible de faire la même chose pour les entrées-sorties. Là encore, il est possible de regrouper le bus mémoire avec les bus pour les entrées-sorties. Voyons ce que cela implique.

Réseau d'interconnexion avec une architecture Harvard.
Interconnexions d'une architecture Von Neumann.

Avant de poursuivre, nous devons préciser quelque chose d'important. Sur les ordinateurs modernes, les entrées-sorties peuvent accéder à la mémoire RAM. Les ordinateurs modernes intègrent des techniques de Direct Memory Access (DMA) qui permettent aux entrées-sorties de lire ou d'écrire en mémoire RAM. Les transferts DMA se font sans intervention du processeur. Ils permettent de copier un bloc de plusieurs octets, dans deux sens : de la mémoire RAM vers une entrée-sortie, ou inversement. Le DMA demande d'ajouter un circuit dédié sur la carte mère : le contrôleur DMA. Il effectue la copie d'un paquet d'octets de la RAM vers l'entrée-sortie ou dans l'autre sens.

Réseau d'interconnexion avec un processeur au centre, et direct memory access

Les bus systèmes

[modifier | modifier le wikicode]

La première solution utilise un bus unique, celui-ci est appelé le bus système, aussi appelé backplane bus. Le bus système est connecté à la mémoire RAM, la mémoire ROM, au processeur, et aux entrées-sorties. Tous les composants présents dans l'ordinateur sont connectés à ce bus, sans exception. De tels bus avaient pour avantage la simplicité. Le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches et économise des fils. La mutualisation des bus est totale, le câblage est plus simple, la fabrication aussi.

Architecture minimale d'un ordinateur.

Un bus système contient un bus d'adresse, de données et de commande. Un bus système se marie bien avec des entrées-sorties mappées en mémoire. La conséquence est que le bus d'adresse ne sert pas que pour l'accès à la mémoire RAM/ROM, mais aussi pour l'accès aux entrées-sorties. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.

Architecture Von Neumann avec les bus.

Un bus système n'a pas de limitations quant aux échanges de données. Le processeur peut communiquer directement avec les mémoires et les entrées-sorties, les entrées-sorties peuvent communiquer avec la mémoire RAM, etc. Notamment, un bus système peut implémenter le Direct Memory Access. Il suffit juste de connecter un contrôleur DMA sur le bus système. Le contrôleur DMA est considéré comme une entrée-sortie, ses registres sont mappés en mémoire et sont donc accessibles directement par le processeur.

Bus système avec contrôleur DMA.

Si on suit la définition à la lettre, un bus système est systématiquement une architecture Von Neumann, vu que la mémoire ROM et la mémoire RAM sont reliées sur le bus système. La conséquence est que les circuits de décodage d'adresse sont présents. Ils sont toujours sur la carte mère, et sont plus ou moins à côté du bus système. Cependant, le décodage d'adresse est parfois étendu pour tenir compte des entrées-sorties.

Les entrées-sorties soudées sur la carte mère ont elles aussi des entrées Chip Select ou quelque chose de similaire. Le décodage d'adresse peut alors les activer ou les désactiver suivant l'adresse envoyée sur le bus d'adresse. C'est ce qui arrive quand le processeur écrit dans un registre d’interfaçage : il envoie l'adresse de ce registre sur le bus d'adresse, le circuit de décodage d'adresse active seulement l'entrée-sortie associée.

Il faut noter que ce n'est pas systématique, il existe des techniques pour se passer de décodage d'adresse. Mais nous en reparlerons dans le chapitre sur les bus de communication.

Exemple détaillé.

Les bus systèmes sont certes très simples, mais ils ont aussi des désavantages. Par exemple, il faut éviter que le processeur et les entrées-sorties se marchent sur les pieds, ils ne peuvent pas utiliser le bus en même temps. De tels conflits d'accès au bus système sont fréquents et ils réduisent la performance, comme on le verra dans le chapitre sur les bus. De plus, un bus système a le fâcheux désavantage de relier des composants allant à des vitesses très différentes : il arrivait fréquemment qu'un composant rapide doive attendre qu'un composant lent libère le bus. Le processeur était le composant le plus touché par ces temps d'attente.

Elle était utilisée sur les tout premiers ordinateurs, pour sa simplicité. Elle était parfaitement adaptée aux anciens composants, qui allaient tous à la même vitesse. De nos jours, les ordinateurs à haute performance ne l'utilisent plus trop, mais elle est encore utilisée sur certains systèmes embarqués, en informatique industrielle dans des systèmes très peu puissants.

Les bus d'entrées-sorties

[modifier | modifier le wikicode]

Les bus systèmes ont de nombreux problèmes, ce qui fait que d'anciens ordinateurs faisaient autrement. A la place d'un bus système unique, ils utilisent un bus séparé pour les mémoires, et un autre séparé pour les entrées-sorties. Le bus spécialisé pour la mémoire est appelé le bus mémoire, l'autre bus est appelé le bus d'entrées-sorties. Le bus mémoire est généralement relié à la fois à la mémoire RAM et à la mémoire ROM, les exceptions ne sont pas rares, cependant.

Bus mémoire séparé du bus pour les IO

Les bus d'entrée-sorties peuvent être spécialisés et simplifiés. Par exemple, ils peuvent avoir un bus de commande différent de celui de la mémoire, qui utilise nettement moins de fils. Le bus d'adresse peut aussi être réduit, et utiliser des adresses plus courtes que celles du bus mémoire. Les bus de données peuvent aussi être de taille différentes. Il est ainsi possible d'avoir un bus mémoire capable de lire/écrire 64 bits à la fois, alors que la communication avec les entrées-sorties se fait octet par octet ! En général, les bus d'entrée-sortie sont assez petits, ils ont une taille de 8 ou 16 bits, même si le bus mémoire est plus grand. Cela permet de ne pas gaspiller trop de broches. Ajouter un bus d'entrée-sortie n'est donc pas très gourmand en broches et en fils.

Il est en théorie possible d'avoir une fréquence différente pour les deux bus, avec un bus mémoire ultra-rapide et un bus pour les entrées-sorties est un bus moins rapide. Mais il faut que le processeur soit prévu pour, et c'est très rare.

Niveau performances, le processeur peut théoriquement accéder à la mémoire en attendant qu'une entrée/sortie réponde, mais il faut que le processeur soit prévu pour, et ce n'est pas de la tarte. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. En clair : pas d'entrée-sortie mappée en mémoire ! Un autre problème est que les entrées-sorties ne peuvent pas communiquer avec la mémoire directement, elles doivent passer par l'intermédiaire du processeur. En clair : pas de Direct Memory Access ! Les deux sont des défauts rédhibitoires pour les programmeurs système, notamment pour ceux qui codent les pilotes de périphériques.

Pour résumer, les défauts sont assez problématiques : pas d'entrées-sorties mappées en mémoire, pas de Direct Memory Access, économie de broches limitée. Les deux premiers sont des défauts majeurs, qui font que de tels bus ne sont pas utilisés dans les ordinateurs modernes. A la place, ils utilisent une troisième solution, distincte des bus systèmes et des bus d'entrée-sorties.

Les bus avec répartiteur

[modifier | modifier le wikicode]

Il existe une méthode intermédiaire, qui garde deux bus séparés pour la mémoire et les entrées-sorties, mais élimine les problèmes de brochage sur le processeur. L'idée est d'intercaler, entre le processeur et les deux bus, un circuit répartiteur. Il récupère tous les accès et distribue ceux-ci soit sur le bus mémoire, soit sur le bus des périphériques. Le ou les répartiteurs s'appellent aussi le chipset de la carte mère.

C'était ce qui était fait à l'époque des premiers Pentium. À l'époque, la puce de gestion du bus PCI faisait office de répartiteur. Elle mémorisait des plages mémoires entières, certaines étant attribuées à la RAM, les autres aux périphériques mappés en mémoire. Elles utilisaient ces plages pour faire la répartition.

IO mappées en mémoire avec séparation des bus

Niveau adresses des registres d'interfacage, il est possible d'avoir soit des adresses unifiées avec les adresses mémoire, soit des adresses séparées.

L'usage d'un répartiteur ne pose pas de problèmes particuliers pour implémenter le DMA. La seule contrainte est que le contrôleur DMA soit intégré dans le répartiteur. Les échanges entre IO et mémoire passent par le répartiteur, qui fait le pont entre bus mémoire et bus des IO.

Implémentation du DMA avec un répartiteur

Les microcontrôleurs et system on chip

[modifier | modifier le wikicode]

Parfois, on décide de regrouper la mémoire, les bus, le CPU et les ports d'entrée-sortie dans un seul circuit intégré, un seul boitier. L'ensemble forme alors ce qu'on appelle un System on Chip (système sur une puce), abrévié en SoC. Le nom est assez explicite : un SoC comprend un système informatique complet sur une seule puce de silicium, microprocesseurs, mémoires et périphériques inclus. Ils incorporent aussi des timers, des compteurs, et autres circuits très utiles.

SoC basé sur un processeur ARM, avec des entrées-sorties typiques de celles d'un µ-contrôleur. Le support du bus CAN, d'Ethernet, du bus SPI, d'un circuit de PWM (génération de signaux spécifiques), de convertisseurs analogique-digital et inverse, sont typiques des µ-contrôleurs.

Le terme SoC regroupe des circuits imprimés assez variés, aux usages foncièrement différents et à la conception distincte. Les plus simples d’entre eux sont des microcontrôleurs, qui sont utilisés pour des applications à base performance. Les plus complexes sont utilisés pour des applications qui demandent plus de puissance, nous les appellerons SoC haute performance.

La relation entre SoC et microcontrôleurs est assez compliquée à expliquer, la terminologie n'est pas clairement établie. Il existe quelques cours/livres qui séparent les deux, d'autres qui pensent que les deux sont très liés. Dans ce cours, nous allons partir du principe que tous les systèmes qui regroupent processeur, mémoire et quelques périphériques/entrées-sorties sont des SoC. Les microcontrôleurs sont donc un cas particulier de SoC, en suivant cette définition.

Les microcontrôleurs

[modifier | modifier le wikicode]

Les microcontrôleurs sont des composants utilisés dans l'embarqué ou d'informatique industrielle. Leur nom trahit leur rôle. Ils sont utilisés pour contrôler de l'électroménager, des chaines de fabrication dans une usine, des applications robotiques, les alarmes domestiques, les voitures. De manière générale, on les trouve dans tous les systèmes dits embarqués et/ou temps réel. Ils ont besoin de s'interconnecter à un grand nombre de composants et intègrent pour cela un grand nombre d'entrée-sorties. Les microcontrôleurs sont généralement peu puissants, et doivent consommer peu d'énergie/électricité.

Microcontrôleur Intel 8051.

Un microcontrôleur tend à intégrer des entrées-sorties assez spécifiques, qu'on ne retrouve pas dans les SoC destinés au grand public. Un microcontrôleur est typiquement relié à un paquet de senseurs et son rôle est de commander des moteurs ou d'autres composants. Et les entrées-sorties intégrées sont adaptées à cette tâche. Par exemple, ils tendent à intégrer de nombreux convertisseurs numériques-analogiques pour gérer des senseurs. Ils intègrent aussi des circuits de génération de signaux PWM spécialisés pour commander des moteurs, le processeur peut gérer des calculs trigonométriques (utiles pour commander la rotation d'un moteur), etc.

Fait amusant, on en trouve dans certains périphériques informatiques. Par exemple, les anciens disques durs intégraient un microcontrôleur qui contrôlait plusieurs moteurs/ Les moteurs pour faire tourner les plateaux magnétiques et les moteurs pour déplacer les têtes de lecture/écriture étaient commandés par ce microcontrôleur. Comme autre exemple, les claviers d'ordinateurs intègrent un microcontrôleur connecté aux touches, qui détecte quand les touches sont appuyées et qui communique avec l'ordinateur. Nous détaillerons ces deux exemples dans les chapitres dédiés aux périphériques et aux disques durs, tout deviendra plus clair à ce moment là. La majorité des périphériques ou des composants internes à un ordinateur contiennent des microcontrôleurs.

Les SoC haute performance

[modifier | modifier le wikicode]

Les SoC les plus performants sont actuellement utilisés dans les téléphones mobiles, tablettes, Netbook, smartphones, ou tout appareil informatique grand public qui ne doit pas prendre beaucoup de place. La petite taille de ces appareils fait qu'ils gagnent à regrouper toute leur électronique dans un circuit imprimé unique. Mais les contraintes font qu'ils doivent être assez puissants. Ils incorporent des processeurs assez puissants, surtout ceux des smartphones. C'est absolument nécessaire pour faire tourner le système d'exploitation du téléphone et les applications installées dessus.

Niveau entrées-sorties, ils incorporent souvent des interfaces WIFI et cellulaires (4G/5G), des ports USB, des ports audio, et même des cartes graphiques pour les plus puissants d'entre eux. Les SoC incorporent des cartes graphiques pour gérer tout ce qui a trait à l'écran LCD/OLED, mais aussi pour gérer la caméra, voire le visionnage de vidéo (avec des décodeurs/encodeurs matériel). Par exemple, les SoC Tegra de NVIDIA incorporent une carte graphique, avec des interfaces HDMI et VGA, avec des décodeurs vidéo matériel H.264 & VC-1 gérant le 720p. Pour résumer, les périphériques sont adaptés à leur utilisation et sont donc foncièrement différents de ceux des microcontrôleurs.

Hardware d'un téléphone. On voit qu'il est centré autour d'un SoC, complété par de la RAM, un disque dur de faible capacité, de quoi gérer les entrées utilisateurs (l'écran tactile, les boutons), et un modem pour les émissions téléphoniques/2G/3G/4G/5G.

Un point important est que les processeurs d'un SoC haute performance sont... performants. Ils sont le plus souvent des processeurs de marque ARM, qui sont différents de ceux utilisés dans les PC fixe/portables grand public qui sont eux de type x86. Nous verrons dans quelques chapitres en quoi consistent ces différences, quand nous parlerons des jeux d'instruction du processeur. Autrefois réservé au monde des PCs, les processeurs multicœurs deviennent de plus en plus fréquents pour les SoC de haute performance. Il n'est pas rare qu'un SoC incorpore plusieurs cœurs. Il arrive même qu'ils soient foncièrement différents, avec plusieurs cœurs d'architecture différente.

La frontière entre SoC haute performance et microcontrôleur est de plus en plus floue. De nombreux appareils du quotidien intègrent des SoC haute performance, d'autres des microcontrôleurs. Par exemple, les lecteurs CD/DVD/BR et certains trackers GPS intègrent un SoC ou des processeurs dont la performance est assez pêchue. À l'opposé, les systèmes domotiques intègrent souvent des microcontrôleurs simples. Malgré tout, les deux cas d'utilisation font que le SoC/microcontrôleur est connecté à un grand nombre d'entrées-sorties très divers, comme des capteurs, des écrans, des LEDs, etc.

Hardware d'un tracker GPS.

Étude de quelques exemples d'architectures

[modifier | modifier le wikicode]

Après avoir vu la théorie, nous allons voir des exemples réels d'ordinateurs. Dans ce qui suit, nous allons voir des ordinateurs assez anciens, pour une raison simple : ils collent assez bien à l'architecture de base vue plus haut, avec un CPU, une RAM et une ROM, quelques entrées-sorties. Tous les ordinateurs modernes, mais aussi dans les smartphones, les consoles de jeu et autres, utilisent une architecture grandement modifiée et améliorée, avec un grand nombre de périphériques, disques durs/SSD, un grand nombre de mémoires différentes, etc.

Il pourrait sembler pertinent d’étudier des microcontrôleurs ou des System On Chip, en premier lieu. Mais nous éviterons soigneusement de tels systèmes pour le moment. La raison est qu'ils ont un grand nombre d'entrées-sorties, qui sont peu familières. Attendez-vous à avoir près d'une vingtaine ou centaine d'entrée-sorties différentes pour de tels systèmes. Le tout est très complexe, bien trop pour un premier exemple. A la place, nous allons voir précisément des exemples plus simples : les premiers PC, et des consoles de jeu 8 et 16 bits.

Bien que ce soit des systèmes très simples, ils sont cependant plus complexes que l'architecture de base. Et leur avantages/désavantages sont un peu inverse l'un de l'autre. Si on devait résumer les différences, on aurait ceci :

  • Les PC ont plus d'entrées-sorties que les consoles, bien que nettement moins que pour les microcontrôleurs/SoC.
  • Les PC utilisent des disques durs, les consoles font avec soit des cartouches de jeu, soit des CD/DVD.
  • Les PC utilisent des cartes électroniques séparées pour le son et l'écran, les consoles utilisent des circuits soudés sur la carte mère, qui sont souvent des co-processeurs.
  • Les PC ont une mémoire ROM soudées sur la carte mère, les consoles 8 bits font sans.

Les PC et micro-ordinateurs ont plus d'entrées-sorties que les consoles. Même si on mets de côté les périphériques, ils ont aussi beaucoup de composants soudées sur la carte mère. En comparaison, les consoles de jeu 8/16 bits se débrouillent avec : une cartouche de jeu et une manette en entrée, une sortie vidéo et une sortie son.

Un autre point important est l'absence de disque dur ou de lecteur CD. La présence d'un disque dur ou d'un lecteur CD/DVD complexifie tout de suite l'architecture des PC. Il faut leur réserver un bus dédié ou les connecter à un bus système, cela demande d'ajouter des circuits sur la carte mère, etc. Et surtout, il faut expliquer comment l'ordinateur exécute des programmes, ce qui demande de parler de l'interaction avec le disque dur et la ROM du BIOS. Rien de tout cela sur les consoles de jeu 8 et 16 bits. Elles utilisent à la place des cartouches de jeu, qui intègrent une mémoire ROM, pour mémoriser les données du jeu, voire son code. Pas besoin de parler des mémoires de stockage, on est beaucoup plus proche de l'architecture de base avec une ROM unique.

Par contre, n'allez pas croire que tout est rose avec les consoles 8/16 bits. Il y a quelques différences qui font qu'elles sont plus complexes qu'un PC sur certains points.

Les PC utilisent des cartes électroniques à brancher sur la carte mère pour alimenter l'écran et les hauts-parleurs/casques, alors que les consoles de jeu utilisent des souvent co-processeurs dédiés pour le son et les graphismes. La différence parait mineure, mais elle avantage les consoles. Nous avons déjà expliqué ce que sont les co-processeurs plus haut, aussi les co-processeurs des consoles nous paraitrons familiers. On n'a pas à s’embêter à expliquer ce que sont les cartes d'extension, les bus associés et tout ce qui va avec, cela peut être retardé pour la section sur l'architecture des PC.

La gestion de la cartouche de jeu est aussi un peu subtile à comprendre, bien que ce soit bien plus simple à comprendre qu'un système avec un disque dur. Les cartouches de jeu intègrent une mémoire ROM, pour mémoriser les données du jeu, voire son code. Et le processeur doit exécuter le code depuis cette mémoire ROM. La conséquence est que les consoles 8/16 bits utilisent une architecture Harvard, avec un bus relié à la cartouche pour lire les instructions. Mais si ce n'était que ça... Les cartouches mémorisent aussi les données pour les graphismes, ce qui fait que le co-processeur vidéo doit lui aussi lire la cartouche pour récupérer ces données...

L'architecture de la TurboGraphX-16

[modifier | modifier le wikicode]

La console PC Engine, aussi appelée TurboGraphX, est une ancienne console 8 bits. Elle contient un processeur 65C02, 8 kibioctets de RAM, un port manettes, une carte son et une carte vidéo. La carte son est le composant qui s'occupe de commander les haut-parleurs et de gérer tout ce qui a rapport au son. La carte graphique est le composant qui est en charge de calculer les graphismes, tout ce qui s'affiche à l'écran. Sur cette console, les cartes son et graphique ne sont PAS des co-processeurs, ce sont des circuits électroniques dits fixes. C'est totalement différent de ce qu'on a sur les consoles modernes, aussi le préciser est important.

Bien que la carte graphique ne soit pas un processeur, elle a 64 kibioctets de RAM rien que pour elle. La RAM en question est séparée de la RAM normale, c'est un circuit intégré séparé. Et c'est un cas très fréquent, qui reviendra par la suite. La majeure partie des cartes graphiques dispose de leur propre mémoire vidéo, totalement réservée à la carte graphique. La RAM vidéo est connectée à la carte graphique via un bus séparé. Le processeur est souvent connecté à ce bus, afin de pouvoir écrire des données dedans, mais ce n'est pas le cas ici.

Architecture de la PC Engine, aussi appelée TurboGrafx-16

L'architecture de la console était particulièrement simple. Le processeur était le centre de l'architecture, tout était connecté dessus. Il y a un bus pour la cartouche de jeu, un autre pour la RAM, un autre pour les manettes, un autre pour carte son, et un dernier pour la carte graphique. Le fait d'avoir un bus par composant est assez rare et ce n'est le cas ici que parce des conditions particulières sont remplies. Déjà, il y a peu d'entrée-sorties. Ensuite, les bus font tous 8 bits, vu que le processeur est un CPU 8 bits. Avec 5 connexions de 8 bits, le tout utilise 40 broches, ce qui est beaucoup, mais totalement gérable. Par contre, les choses changerons pour les autres consoles.

Au final, l'organisation des bus peut s'expliquer avec ce qu'on a vu dans la section sur les bus de communication. La console utilise une architecture Harvard, car la ROM et la RAM utilisent des bus différents. De plus, il y a des bus dédiés aux entrées-sorties, séparés des bus mémoire. Enfin, la carte graphique a droit à ses propres bus pour lire dans la cartouche et dans sa RAM vidéo dédiée.

L'architecture de la console de jeu NES

[modifier | modifier le wikicode]

Maintenant, nous allons voir la console de Jeu Famicom, aussi appelée la NES en occident. Elle a une architecture centrée sur un processeur Ricoh 2A03, similaire au processeur 6502, un ancien processeur autrefois très utilisé et très populaire. Le processeur est associé à 2 KB de mémoire RAM.

Sur certaines cartouches, on trouve une RAM utilisée pour les sauvegardes, qui est adressée par le processeur directement. Première variation par rapport à l'architecture de la console précédente : l'ajout de la RAM pour les sauvegardes dans les cartouches.

Niveau carte graphique, une différence importante est que la carte graphique est connectée à la cartouche de jeu via un autre bus, afin de pouvoir lire les sprites et textures du jeu dans la cartouche.

Architecture de la NES

La différence avec l'architecture précédente est que des bus ont été fusionnés. Comme dit plus haut, le système utilise une architecture Harvard, vu que la ROM est dans la cartouche, alors que la RAM est soudée à la carte mère. Par contre, la Famicon utilise un bus dédié aux entrées-sorties. Il est utilisé pour la carte son et la carte graphique, seules les manettes sont sur un bus à part. Ce qui fait qu'on devrait plutôt parler de bus de sorties, mais passons... L'essentiel est qu'on n'est plus tout à fait dans le cas de la console précédente, avec un bus par composant.

L'architecture de la SNES

[modifier | modifier le wikicode]

L'architecture de la SNES est illustrée ci-dessous. Les changements pour le processeur et la RAM sont mineurs.La RAM a augmenté en taille et passe à 128 KB. Pareil pour la RAM de la carte vidéo, qui passe à 64 KB. Par contre, on remarque un changement complet au niveau des bus, de la carte graphique et de la carte son.

Architecture de la SNES

La console utilise un bus système unique, sur lequel tout est connecté : ROM, RAM, entrées-sorties, etc. La seule exception est pour les manettes, qui sont encore connectées directement sur le processeur, via un bus séparé. La transition vers un bus système s'explique par le fait que la console est maintenant de 16 bits, ce qui fait que les bus doivent être plus larges. Le processeur adresse des mémoires RAM et ROM plus grandes, ce qui double la taille de leurs bus. De plus, les entrées-sorties aussi ont besoin d'un bus plus large. Le processeur n'ayant pas un nombre illimité de broches, la seule solution est de fusionner les bus en un seul bus système.

Un autre changement est que la carte graphique est maintenant composée de deux circuits séparés. Encore une fois, il ne s'agit pas de coprocesseurs, mais de circuits non-programmables. Par contre, la carte son est remplacée par deux coprocesseurs audio ! De plus, les deux processeurs sont connectés à une mémoire RAM dédiée de 64 KB, comme pour la carte graphique. L'un est un processeur 8 bits (le DSP), l'autre est un processeur 16 bits.

Un point très intéressant : certains jeux intégraient des coprocesseurs dans leurs cartouches de jeu ! Par exemple, les cartouches de Starfox et de Super Mario 2 contenait un coprocesseur Super FX, qui gérait des calculs de rendu 2D/3D. Le Cx4 faisait plus ou moins la même chose, il était spécialisé dans les calculs trigonométriques, et diverses opérations de rendu 2D/3D. En tout, il y a environ 16 coprocesseurs d'utiliser et on en trouve facilement la liste sur le net. La console était conçue pour, des pins sur les ports cartouches étaient prévues pour des fonctionnalités de cartouche annexes, dont ces coprocesseurs. Ces pins connectaient le coprocesseur au bus des entrées-sorties. Les coprocesseurs des cartouches de NES avaient souvent de la mémoire rien que pour eux, qui était intégrée dans la cartouche.

L'architecture de la Megadrive et de la néo-géo

[modifier | modifier le wikicode]

Passons maintenant à la console de jeu Megadrive, une console 16 bits. Elle a une architecture similaire à celle de la néo-géo, une autre console bien plus puissante, sorti à peu près en même temps. Elles intègrent deux processeurs : un Motorola 68000 qui sert de processeur principal, un Z80 qui sert de processeur dédié à l'audio. Le Z80 et le Motorola 68000 étaient deux processeurs très populaires à l'époque. Le Z80 est une sorte de version améliorée de l'Intel 8088 utilisé sur les anciens PC et de nombreuses consoles utilisaient des Z80 comme processeur principal. Il était familier pour les programmeurs de l'époque, pour son cout réduit, sa bonne disponibilité, et bien d'autres avantages liés à sa production de masse.

Le Z80 est utilisé comme co-processeur audio. Il commande un synthétiseur sonore, et est relié à sa propre mémoire, distincte de la mémoire principale. Le MC68000 est le processeur principal et a une relation maitre-esclave avec le Z80 : le MC68000 envoie des commandes au Z80, mais la communication ne va pas dans l'autre sens.

Le Motorola 68000 était un processeur 16 bits, alors que le Z80 est un processeur 8 bits. Et cette différence fait que l'on ne peut pas connecter directement les deux sur le même bus, ou du moins pas facilement. La solution retenue est d'utiliser deux bus séparés : un bus de 16 bits connecté au 68000, un bus de 8 bits connecté au Z80. Le premier bus est un bus système sur lequel est connecté le 68000, 64 kibioctets de RAM, la cartouche de jeu, et la carte graphique. Le second bus est un bus de 8 bits, plus court, relié au Z80, à un synthétiseur sonore, et 8 kibioctets de RAM

Les deux bus sont connectés à un chipset, un circuit répartiteur, qui fait le pont entre les deux bus. Les manettes sont connectées sur le chipset. Il contient un registre de 8 bits, dans lequel le MC68000 peut écrire dedans à sa guise, le registre étant adressable par le processeur. Lorsque le MC68000 écrit une valeur dedans, cela déclenche l’exécution automatique d'un programme pré-déterminé sur le Z80.

Pour ceux qui savent ce qu'est une interruption, les valeurs écrites dans ce registre sont des numéros d'interruption, qui indiquent quelle routine d'interruption exécuter.
Architecture de la Megadrive et de la Néogeo

Cet exemple nous montre que les bus systèmes sont certes très simples, mais aussi inflexibles. Ils fonctionnent bien quand les composants branchés dessus sont tous des composants 8 bits, ou sont tous de 16 bits, ou tous 32 bits. Mais dès qu'on mélange composants 8, 16, 32 ou 64 bits, les choses deviennent plus compliquées. Il est alors préférable d'utiliser des bus séparés, avec des répartiteurs pour faire le pont entre les différents bus. Et nous verrons que le problème s'est posé lui aussi sur les PC.

L'architecture des anciennes consoles Playstation : beaucoup de co-processeurs

[modifier | modifier le wikicode]

Les consoles que nous venons d'aborder étaient des consoles 8 ou 16 bits. A partir des consoles 32 bits, leur architecture s'est rapprochée de celle des PC, avec un usage plus complexes de répartiteurs. La XBOX était très semblable à un PC : le processeur était un Pentium 3 modifié, la carte graphique était une Geforce 3 modifiée, les 64 mébioctets de RAM était la même mémoire DDR que celle des PC, le répartiteur secondaire était un chipset nForce de NVIDIA, etc. Mais les Playstation 1, 2 et 3 se distinguent de leur contemporains. Elles disposent de très nombreux co-processeurs, qui sont en plus très variés.

La Playstation 1 a été une des premières console à utiliser les CD-ROM comme support de stockage, en remplacement des cartouches. La conséquence est que la console contient une mémoire ROM, soudée à la carte mère, de 512 kibioctets. Elle contient aussi 2 mébioctets de RAM, une carte graphique avec 1 mébioctet de mémoire vidéo, un processeur, et de quoi gérer les périphériques. Il y a un co-processeur audio spécialisé, avec 512 kibioctets de RAM, ce qui nous est familier. Par contre, les autres co-processeurs ne le sont pas.

Déjà, le lecteur de CD-ROM est associé à des circuits sur la carte mère, il y a tout un sous-système dédié au lecteur de CD. Il y a un contrôleur qui sert d'interface avec le lecteur proprement dit, mais aussi deux co-processeurs audio et 32 kibioctets de RAM. Les co-processeurs audio servent à lire des CD sans trop utiliser le second co-processeur audio, ils lui servent de complément.

Ensuite, le processeur incorpore plusieurs cœurs, avec un cœur principal et plusieurs co-processeurs. Le premier est un co-processeur système, qui est utilisé pour gérer la mémoire cache intégrée au processeur, pour des fonctionnalités appelées interruptions et exceptions, ainsi que pour configurer le processeur. Le second est un co-processeur arithmétique spécialisé dans les calculs en virgule flottante, très importants pour le rendu 3D. Enfin, il y a un décodeur vidéo, qui n'est pas un co-processeur, mais un circuit non-programmable, spécialisé dans le décodage vidéo. De nos jours, ce circuit aurait été intégré dans la carte graphique, mais il était intégré dans le processeur sur la Playstation 2.

Pour le reste, le processeur est la figure centrale de la console. Il est connecté à 4 bus : un pour la RAM, un pour la carte graphique, un pour les manettes, un autre pour le reste. Le dernier bus est connecté au système audio et au système pour le lecteur CD. Ce serait un bus d'entrée-sortie, s'il n'était pas connecté à la mémoire ROM. Vous avez bien lu : la mémoire ROM est reliée au bus d'entrée-sortie.

Architecture de la Playstation

La Playstation 2 est composé d'un processeur, couplé à 32 Mébioctets de RAM, et d'un paquet de co-processeurs. Plus de co-processeurs que la PS1. Le processeur principal n'est pas la même que celui de la PS1, mais il a une architecture similaire. Il intègre un décodeur vidéo sur le même circuit intégré, ainsi que deux co-processeur. Les co-processeurs ne sont cependant pas les mêmes.

Le co-processeur système disparait et est remplacé par un second co-processeur arithmétique. Les deux co-processeurs arithmétiques sont spécialisés dans les nombres flottants, avec quelques différences entre les deux. Par exemple, le second co-processeur gérait des calculs trigonométriques, des exponentielles, des logarithmes, et d'autres fonctions complexes du genre ; mais pas le premier co-processeur. Ils sont reliés à 4 kibioctets de RAM pour le premier, 16 kibioctets de RAM pour le second ; qui sont intégrées dans le processeur et non-représentés dans le diagramme ci-dessous.

La PS2 intègre aussi un co-processeur d'entrées-sorties. Pour information, il s'agit du processeur principal de la Playstation 1, qui est ici utilisé différemment, suivant que l'on place un jeu PS1 ou PS1 dans la console. Si on met un jeu PS1, il est utilisé pour émuler la Playstation 1, afin de faire tourner le jeu PS1 sur la PS2. Si on met un jeu PS2, il est utilisé comme co-processeur d'entrée-sortie et fait l'interface entre CPU et entrées-sorties. Il est relié à 2 mébioctets de RAM, soit exactement la même quantité de mémoire que la Playstation 1.

Tous les périphériques sont connectés au co-processeur d'entrées-sortie. Pour cela, le co-processeur d'entrées-sortie est relié à deux bus dédiés aux périphériques. Le premier bus est relié aux manettes, aux ports USB et aux ports pour cartes mémoires. Le second bus est relié à la carte son, la carte réseau, le lecteur DVD, et un port PCMIA. Notons que la carte son intègre un co-processeur audio, qui n'est pas représenté dans le diagramme ci-dessous.

Playstation 2 architecture

L'architecture des PC et son évolution

[modifier | modifier le wikicode]

Après avoir vu les consoles, nous allons maintenant voir les anciens PC, des années 80 ou 90. Le tout premier PC était techniquement l'IBM PC. Par la suite, de nombreux ordinateurs ont tenté de reproduire l'IBM PC originel, avec parfois quelques modifications mineures. De tels ordinateurs IBM PC compatibles, ont été très nombreux, pour des raisons diverses. Le fait d'utiliser des composants banalisés, facilement disponibles, ainsi qu'une bonne documentation de l'IBM PC originel, a grandement aidé. Les IBM PC compatibles ont progressivement évolué pour donner les PC actuels. L'IBM PC compatible a donné naissance à de nombreux standards divers.

L'IBM PC originel et l'IBM PC XT

[modifier | modifier le wikicode]
IBM PC XT.

Nous allons commencer par voir l'IBM PC originel, et son successeur : l'IBM Personal Computer XT. Nous les appelerons tous deux l'IBM PC. L'IBM PC utilisait un processeur Intel 8088, qui était un processeur 8 bits. Ils utilisaient un bus système unique, appelé le bus XT. Le bus système allait à 4.77 MHz, soit la même fréquence que le processeur. C'était un bus de 8 bits, ce qui collait parfaitement avec les processeurs 8 bits commercialisés par Intel à l'époque.

L'IBM PC comprenait une mémoire ROM avec de quoi faire fonctionner le PC. La ROM en question contenait un programme minimal, appelé le BIOS, sans lequel le PC ne fonctionnait pas du tout. Il servait de base pour le système d'exploitation et MS-DOS ne fonctionnait pas sans elle. De nos jours, son rôle est plus limité : sans elle, le PC ne démarre pas. Mais nous détaillerons cela dans le prochain chapitre.

En plus de la ROM pour le BIOS, l'IBM PC avait quatre mémoires ROM dédiée au langage de programmation BASIC. Lorsque le PC démarrait, il ne bootait pas un système d'exploitation, mais lançait l'interpréteur pour le langage BASIC. De nos jours, ce serait l'équivalent d'un ordinateur qui boote directement sur du Python, à savoir la console Python que vous avez peut-être déjà utilisé si vous avez testé Python. Ceux qui ont déjà touché à un ordinateur de l'époque savent ce que ca veut dire, mais c'est malheureusement très difficile à expliquer sans ce genre d'expérience. Toujours est-il que c'était une sorte de norme à l'époque

les ordinateurs bootaient généralement sur un interpréteur BASIC.
Connecteur du bus XT.

Les PC étaient conçus pour qu'on branche des cartes d'extension, à savoir des cartes électroniques qu'on branchait sur la carte mère, à l'intérieur du PC. Les cartes d'extension de l'époque étaient surtout des cartes son ou des cartes graphiques, mais aussi des cartes pour brancher des péripéhriques. par exemple, on pouvait ajouter deux cartes graphiques dans l'IBM PC originel : l'IBM Monochrome Display Adapter et/ou la IBM Color Graphics Adapter. De nos jours, les cartes son sont intégrées à la carte mère, mais les cartes graphiques sont restées des cartes d'extension.

Les cartes d'extension étaient branchées sur un connecteur XT, qui était directement relié au bus XT. Le connecteur XT est illustré ci-contre, mais ne vous en souciez pas trop pour le moment. La carte mère de l'IBM PC avait 5 connecteurs de ce type, qu'on pouvait peupler avec autant de cartes d'extension. L'IBM Personal Computer XT est passé à 8 connecteurs XT, soit trois de plus.

Pour ce qui est des périphériques, l'IBM PC avait plusieurs connecteurs : un port série, un port parallèle, un port pour le clavier, et un port pour un lecteur cassette. Le clavier et le lecteur cassette étaient connectés directement sur la carte mère, qui contenait quelques circuits pour gérer le clavier. Par contre, les deux premiers n'étaient pas connectés à la carte mère. Le port série était en réalité une carte d'extension, branchée sur un connecteur XT. Et il en est de même pour le port parallèle.

Pour ce qui est des supports de stockage, l'IBM PC originel n'avait pas de disque dur et n'avait que des lecteurs de disquette. De plus, le lecteur de disquette n'était pas connecté directement sur la carte mère, mais était connecté à une carte d'extension, branchée sur un connecteur XT. La carte d'extension avait deux connecteurs, un par lecteur de disquette, ce qui fait que les deux lecteurs de disquettes pouvaient être branchés sur une seule carte d'extension. L'IBM Personal Computer XT a ajouté un disque dur, sauf sur quelques sous-modèles spécifiques.

Le PC avait aussi un petit haut-parleur capable de faire des bips.

Pour résumer, l'IBM PC originel se reposait beaucoup sur les cartes d'extension, sa carte mère contenait peu de choses. Enfin, peu de choses... Il y avait un processeur Intel 8088, éventuellement un coprocesseur flottant 8087, de la RAM, de la ROM, et des circuits intégrés assez divers. En voici la liste, certains vous seront familiers, d'autres vous seront inconnus à ce stade du cours :

  • les circuits de décodage d'adresse ;
  • un contrôleur DMA intel 8273 ;
  • un contrôleur d'interruption 8259 ;
  • un contrôleur de bus Intel 8288 pour gérer le bus XT ;
  • un générateur d'horloge Intel 8284 et un diviseur de fréquence ;
  • un timer Intel 8253, le même que celui étudié dans le chapitre sur les timers ;
  • un contrôleur parallèle 8255.

Les multiplexeurs, registres et portes logiques, sont des circuits de décodage d'adresse, qui permettent de combiner plusieurs RAM en une seule, idem avec la mémoire ROM. Si vous verrez qu'il y a 5 mémoires ROM : une ROM pour le BIOS, et quatre autres ROM pour le BASIC. Les 4 ROM du BASIC sont combinées en une seule mémoire ROM. Pour les RAM, il y en a 8 à 32, qui sont combinées en une seule RAM de 16 à 64 kibioctets.

Carte mère de l'IBM 5150, un modèle de l'IBM PC.

L'architecture d'un IBM PC compatible 16 bits

[modifier | modifier le wikicode]

Les PC suivants sont passés à des processeurs 16 bits, mais c'était toujours des processeurs x86 d'Intel, à savoir des Intel 286 et 386. La RAM a grossi, quelques entrées-sorties ont été ajoutées, mais l'architecture globale est plus moins resté le même. C'est surtout au niveau du bus et des périphériques que les changements majeurs ont eu lieu.

Connecteur ISA.

Les PC 16 bits utilisaient un bus système unique, sur lequel tout était connecté : le processeur, la RAM, la ROM, les cartes d'extension et tout le reste. Le bus en question s'appelait le bus AT, mais il a rapidement été renommé en bus ISA (Industry Standard Architecture). Le bus ISA était prévu pour avoir une compatibilité avec le bus 8 bits de l'IBM PC originel. D'ailleurs, cela se ressent jusque dans le connecteur utilisé : le connecteur ISA est un connecteur XT qu'on a fusionné avec un second connecteur pour l'étendre de 8 à 16 bits.

Les PC 16 bits avaient toujours un port série, un port parallèle, un clavier, un lecteur de disquette et des cartes d'extension. Des disques durs pouvaient être ajoutés, aussi. Mais pour ces périphériques, un changement majeur a eu lieu comparé à l'IBM PC originel. L'IBM PC originel utilisait des cartes d'extension pour tout, sauf le clavier. Mais maintenant, les périphériques ne sont plus connectés à une carte d'extension. A la place, les circuits de la carte d'extension sont déplacés sur la carte mère. Mais n'allez pas croire qu'ils étaient connectés directement au bus ISA, il y avait des intermédiaires.

Le clavier était relié à un contrôleur de clavier, qui faisait l'interface entre le connecteur du clavier et le bus ISA. Le contrôleur de clavier était appelé le Keyboard Controler, abrévié en KB. Il recevait ce qui est tapé au clavier et traduisait cela en quelque chose de compréhensible par l'ordinateur.

Les autres périphériques étaient connectés à un circuit intégré dédié : l'Intel 82091AA. Il était connecté au lecteur de disquette, au port série et au port parallèle. Il servait d'intermédiaire entre ces périphériques et le bus ISA. Vous pouvez le voir comme une sorte de répartiteur, mais qui ne serait pas connecté sur le processeur et la RAM

Enfin, il ne faut pas oublier les autres composants présents sur l'IBM PC originel. Le BIOS est toujours là, de même que les timers Intel 8253 PIT, le contrôleur d'interruption Intel 8259 et le contrôleur DMA Intel 8237. Les PC 16 bits ont aussi intégré une Real Time Clock (RTC). Pour rappel, c'est un composant qui permet au PC de mémoriser la date et l'heure courante, à la seconde près. Le tout est résumé dans le schéma ci-dessous.

Architecture de l'IBM PC compatible

Un point important est que le bus ISA allait à la même fréquence que le processeur, vu que c'était un bus système. Les processeurs de l'époque étaient des CPU 286 d'Intel, ou le 386 d'Intel. Les Intel 286 allaient de 4 MHz minimum, à 25 MHz maximum. Le 386, quant à lui, allait de 12 à 40 MHz. Le bus ISA devait aller à cette fréquence, il était synchrone avec le processeur.

Par la suite, les processeurs ont gagné en performance, ce qui fait que le bus ISA est devenu trop lent pour le processeur. Une idée a alors été de conserver le bus ISA, pour des raisons de compatibilité, mais de le reléguer comme bus secondaire. L'ordinateur contient alors deux bus : un bus système, et un bus ISA secondaire. Le lien entre les deux est réalisé par un pont ISA, ISA Bridge en anglais. Le bus ISA fonctionnait alors sa fréquence usuelle, alors que le bus système était beaucoup plus rapide. Le bus système fonctionnait à une fréquence bien plus élevée, ce qui fait que le processeur pouvait communiquer à pleine vitesse, notamment avec la RAM. Le processeur n'était alors plus forcé à aller à la même fréquence que le bus ISA

Architecture de l'IBM PC compatible avec bridge ISA

Les PC de l'époque intégraient donc plusieurs bus séparés. Vous avez bien lu : plusieurs bus ! Ici, il s'agit de ce que j'appelle des bus en cascade, à savoir qu'un bus est connecté à un autre bus par un intermédiaire. Au passage, si j'aborde ces exemples, car c'est pareil sur les ordinateurs modernes. Le pont ISA a été remplacé par des circuits différents, mais qui ont un rôle assez similaire. Le chipset de votre carte mère n'est qu'un lointain descendant du pont ISA, qui s'interface avec des bus différents.

L'arrivée des standards AT et IDE pour les disques durs

[modifier | modifier le wikicode]

Initialement, les disques durs étaient placés dans l'ordinateur et étaient connectés sur le bus ISA, via une carte d'extension ISA. En clair, il fallait connecter le disque dur sur une carte d'extension, et non sur la carte mère. Les cartes d'extension en question permettaient de connecter un ou plusieurs disques durs, parfois des lecteurs de disquette supplémentaires. Les cartes ISA de ce type faisaient juste l'interface entre le bus ISA et les disques durs, rien de plus. L'interface en question a été standardisée, ce qui a donné le standard AT Bus Attachment, qui a été abrévié en ATA.

Et ce n'était pas que pour les disques durs, de nombreux composants étaient dans ce cas. Une carte d'extension servait d'intermédiaire entre eux et la carte mère. Les cartes d'extension en question étaient appelées des Host bus adapter.

Carte ISA d'interface disque dur, de marque Acculogic.

Mais les choses ont rapidement évoluées, que ce soit du côté des cartes mères que du côté des disques durs. Le standard IDE a permis de brancher un disque dur directement sur la carte mère, sans passer par une carte d'interface ISA. Pour cela, la carte mère réservait un connecteur ISA pour le disque dur, renommé connecteur ATA. Pour que cela soit possible, il a fallu rajouter des circuits sur la carte mère. Tout ce qui était sur les cartes d'interface ISA s'est retrouvé sur la carte mère.

Ajout des ports IDE sur la carte mère

En réalité, les connecteurs ATA étaient des connecteurs ISA simplifiés. Un connecteur ISA avait en tout 98 broches, alors qu'un connecteur ATA n'en contient que 40. Les broches qui étaient inutiles pour les disques durs ont simplement été enlevées. Et qui dit connecteur spécialisé, dit câble spécialisé. Les disques durs étaient branchés sur le connecteur AT grâce à un câble ATA, sur lequel on pouvait connecter deux disques durs.

Connecteur ATA.
Cable ATA.

Il était donc possible de connecter deux disques durs sur un seul connecteur ATA. Et cette possibilité est devenue d'autant plus utile par la suite. A partir de la version 2, ATA supportait aussi les lecteurs de disquettes, les lecteurs de CD/DVD, et bien d'autres supports de stockage. Il était alors possible de connecter un lecteur CD et un disque dur sur un seul connecteur. Les cartes mères avaient généralement deux connecteurs ATA, et n'avaient pas besoin de plus. C'était suffisant pour connecter un disque dur, un lecteur de disquette et un lecteur CD, configuration courante entre les années 90 et 2000.

Un câble est donc connecté à deux supports de stockage. Pour distinguer les deux, le standard ATA ajoute une possibilité de configuration. Sur un câble, il doit y avoir un support de stockage "maitre" et un support "esclave". C'était la terminologie de l'époque, que je reproduis ici, même si elle est fortement trompeuse. N'allez pas croire que cela implique que l'un ait des avantages sur l'autre. Le support 'maitre" n'a pas droit à plus de bande passante, il n'a pas la priorité sur l'autre, rien du tout. Il s'agit juste d'un nombre qui permet de savoir avec qui le processeur communique, qui vaut 0 pour le premier support, 1 pour l'autre. Une sorte d'adresse de 1 bit, si l'on veut.

Configuration ATA.

Pour configurer un support de stockage en mode "maitre" ou "esclave", le support de stockage avait quelques pins dédiés. Il suffisait de placer un détrompeur en plastique sur les pins adéquats. Les pins se trouvaient à l'arrière du disque dur ou du lecteur de CD/DVD/Disquette/autre.

Configuration Master/Slave.

L'architecture d'un PC avec un processeur Intel 486

[modifier | modifier le wikicode]

Maintenant, passons aux ordinateurs 32 bits, avec l'exemple d'un PC avec un processeur 486 d'Intel. A cette époque, le bus ISA était devenu trop limité et était en place d'être remplacé par le bus PCI, qui avait la même fonction. De nombreuses cartes d'extension utilisaient déjà ce standard et étaient branchées sur des connecteurs PCI dédiés, différents des connecteurs ISA. Intuitivement, on se dit que le bus PCI remplaçait le bus ISA, mais les choses étaient plus compliquées. Les disques durs gardaient leur connecteur ATA, et ne passaient pas par le bus PCI. Ils avaient un bus IDE séparé, qui était un bus ISA modifié.

Là encore, les processeurs étaient devenus beaucoup plus rapides que le bus PCI. Les deux allaient à des fréquences assez différentes, ce qui fait que le bus PCI était séparé du bus système. Il y avait alors deux implémentations possibles.

  • La première utilise un répartiteur unique, relié au processeur, à la RAM, au bus PCI, et au bus IDE.
  • La seconde utilise un bus système séparé du bus PCI, avec un pont PCI pour faire l'interface entre les deux.

Le System Controler était un circuit intégré, placé sur la carte mère, qui peut servir soit de pont PCI, soit de répartiteur. Le répartiteur PCI sert d'intermédiaire avec le bus PCI, mais aussi avec le bus IDE, utilisé pour les disques durs, aussi appelé le bus Parallel ATA. Il peut aussi être connecté au processeur, à la mémoire RAM, ainsi qu'à la mémoire cache, mais cela ne sert que quand il est utilisé comme répartiteur.

Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur

Pour des raisons de compatibilité, le bus ISA avait été conservé, aux côtés du bus PCI. Il y avait un pont ISA en plus du pont/répartiteur PCI. Une implémentation possible aurait été de connecter les deux ponts ISA et PCI à un bus système unique. Mais cette solution n'a pas été retenue. La raison est que le bus PCI et le bus ISA ont des performances très différentes. Le bus PCI est très rapide, le bus ISA beaucoup plus lent. La différence est d'un ordre de grandeur, environ. Dans ces conditions, il est possible de faire passer les communications ISA à travers le bus PCI. Pour cela, le pont ISA est directement connecté sur le pont PCI, comme illustré ci-dessous.

Et il en est de même pour le bus dédié aux disques durs. En effet, les disques durs étaient autrefois reliés au bus ISA, mais cela a changé depuis. Ils disposent maintenant de leur propre bus dédié, le bus IDE, qui est un bus ISA simplifié. Et ce bus ISA simplifié était connecté directement sur le pont PCI.

Architecture de l'IBM PC compatible avec pont PCI

Dans ce qui va suivre, nous allons étudier un exemple qui utilise un bus système séparé, avec un pont PCI, sans répartiteur. Voilà pour les grandes lignes, mais le schéma ci-dessous montre que tout est plus complexe. Vous remarquerez des connexions optionnelles entre le pont PCI et la mémoire RAM et la mémoire cache. La raison est que le pont PCI peut aussi servir de répartiteur en remplacement du bus système. Concrètement, on peut alors retirer le bus système. La mémoire, le bus PCI, le bus ISA, le bus IDE, le processeur et la RAM sont alors connectés au répartiteur PCI, qui sert d'intermédiaire central entre tous ces composants. Mais ce n'est pas la solution qui a été retenue dans notre exemple.

PC IBM compatible avec un 486, un bus PCI et un bus ISA. Le host bus est le bus système.

Le pont ISA sert ici d'intermédiaire entre le bus système et le bus ISA. De plus, il a été amélioré sur de nombreux points. Il inclut notamment des circuits qui étaient autrefois sur la carte mère, à savoir le contrôleur DMA 82C87 et le contrôleur d'interruption 82C59, ainsi que les timers Intel 82C54. Les composants restants sont eux reliés sur un quatrième bus : le bus X, l'ancêtre du bus Low Pin Count. Le bus X était celui du BIOS, du contrôleur de clavier, de la Real Time Clock, et du contrôleur de périphérique 82091AA d'Intel.

ISA Bridge.

L'architecture des PC des années 90-2000

[modifier | modifier le wikicode]

Par la suite, les ponts PCI et ISA ont évolué avec l'évolution des bus de l'ordinateur. Le bus ISA a progressivement été remplacé par d'autres bus, comme le bus Low Pin Count, le bus PCI a été remplacé par le PCI Express, d'autres bus ont été ajoutés, etc. Mais la séparation du chipset en deux a été conservée.

Chipset séparé en northbridge et southbridge.

Le pont PCI et le pont ISA ont été remplacés respectivement par le pont nord et le pont sud, plus connus par leurs noms anglais de northbridge et de southbridge. Le pont nord servait d'interface entre le processeur, la mémoire et la carte graphique et est connecté à chacun par un bus dédié. Il intégrait aussi le contrôleur mémoire. Le pont sud est le répartiteur pour les composants lents, à savoir l'USB, l'Ethernet, etc. Le bus qui relie le processeur au pont nord était appelé le Front Side Bus, abrévié en FSB.

Chipset séparé en northbridge et southbridge.

Un point important est que le bus PCI est devenu un bus assez lent, ce qui fait qu'il a finit par être connecté au pont sud. Le pont PCI est donc devenu le pont sud, dans le courant des années 2000. Durant un moment, un équivalent du pont ISA a subsisté dans un circuit de Super IO. Concrètement, il s'occupait du lecteur de disquette, du port parallèle, du port série, et des ports PS/2 pour le clavier et la souris. Mais il ne gérait pas le bus ISA, mais son remplaçant, le bus Low Pin Count.

Carte mère avec circuit Super IO.

L'architecture des PC depuis les années 2000

[modifier | modifier le wikicode]

Depuis la sortie du processeur AMD Athlon 64, le pont nord a été fusionné dans le processeur. La fusion ne s'est pas faite en une fois, des fonctionnalités ont progressivement été progressivement intégrées dans le processeur. Le pont sud est resté, mais il a alors été progressivement connecté directement au processeur. La raison derrière cette intégration est que les processeurs avaient de plus en plus de transistors à leur disposition. Ils en ont profité pour intégrer le pont nord. Et cela permettait de simplifier le câblage des cartes mères, sans pour autant rendre vraiment plus complexe la fabrication du processeur. Les industriels y trouvent leur compte.

La première étape a été l'intégration du contrôleur mémoire a été intégré au processeur. Concrètement, le résultat était que la mémoire RAM n'était plus connectée au pont nord, mais était connectée directement au processeur ! Il y a donc eu un retour d'un bus mémoire, mais spécialisé pour la mémoire RAM. En théorie, une telle intégration permet diverses optimisations quant aux transferts avec la mémoire RAM. Les transferts ne passent pas par un répartiteur, ce qui réduit le temps d'accès à la mémoire RAM. Ajoutons de sombres histoires de prefetching, d'optimisation des commandes, et j'en passe. Toujours est-il que le pont nord ne servait alors d'intermédiaire que pour les ports PCI Express, et le pont sud.

Chipset X58 d'Intel.

Par la suite, la carte graphique fût aussi connectée directement sur le processeur. Le processeur incorpore pour cela des contrôleurs PCI-Express. Le pont nord a alors disparu complétement, son intégration dans le processeur était complète. Sur les cartes mères Intel récentes, le pont sdud subsiste, il est appelé le Platform Controler Hub, ou PCH. L'organisation des bus sur la carte mère qui résulte de cette connexion du processeur à la carte graphique, est illustrée ci-dessous, avec l'exemple du PCH.

Intel 5 Series architecture