Wikilivres
frwikibooks
https://fr.wikibooks.org/wiki/Accueil
MediaWiki 1.46.0-wmf.21
first-letter
Média
Spécial
Discussion
Utilisateur
Discussion utilisateur
Wikilivres
Discussion Wikilivres
Fichier
Discussion fichier
MediaWiki
Discussion MediaWiki
Modèle
Discussion modèle
Aide
Discussion aide
Catégorie
Discussion catégorie
Transwiki
Discussion Transwiki
Wikijunior
Discussion Wikijunior
TimedText
TimedText talk
Module
Discussion module
Event
Event talk
Photographie/Personnalités/S/Edward Linley Sambourne
0
53955
762516
399991
2026-03-30T15:53:20Z
Marcus Cyron
4892
([[c:GR|GR]]) [[c:COM:FR|File renamed]]: [[File:Nude-Sambourne.jpg]] → [[File:Kate Manning by Edward Linley Sambourne (1888) - 2.jpg]]
762516
wikitext
text/x-wiki
{{Ph s Personnalités}}
'''Edward Linley Sambourne''' était un caricaturiste et photographe anglais, né à Pentonville le 4 Janvier 1844 et décédé le 3 Août 1910. Il a travaillé notamment pour le ''Punch''.
== Galerie de photographies ==
<gallery widths="240px" heights="240px">
File:Kate Manning by Edward Linley Sambourne (1888) - 2.jpg
File:Edward Linley Sambourne Lady.jpg
File:LG as a Gypsy Edward Linley Sambourne 1898.jpg
File:Sambourne Apple Girl.jpg
File:Sambourne Kate Manning semi draped.jpg
File:Sambourne Modieuze dame op Cromwell Road.jpg
</gallery>
i86fycy4woithqn4h4u2x9cy6gfionr
762559
762516
2026-03-30T22:09:38Z
Marcus Cyron
4892
([[c:GR|GR]]) [[c:COM:FR|File renamed]]: [[File:Sambourne Kate Manning semi draped.jpg]] → [[File:Kate Manning by Edward Linley Sambourne (1888) - 3.jpg]] Standardizing the names of an image series
762559
wikitext
text/x-wiki
{{Ph s Personnalités}}
'''Edward Linley Sambourne''' était un caricaturiste et photographe anglais, né à Pentonville le 4 Janvier 1844 et décédé le 3 Août 1910. Il a travaillé notamment pour le ''Punch''.
== Galerie de photographies ==
<gallery widths="240px" heights="240px">
File:Kate Manning by Edward Linley Sambourne (1888) - 2.jpg
File:Edward Linley Sambourne Lady.jpg
File:LG as a Gypsy Edward Linley Sambourne 1898.jpg
File:Sambourne Apple Girl.jpg
File:Kate Manning by Edward Linley Sambourne (1888) - 3.jpg
File:Sambourne Modieuze dame op Cromwell Road.jpg
</gallery>
cfdrva47o5co17jf35xdtfdwzo6ww3d
Fonctionnement d'un ordinateur/L'adressage des périphériques
0
65771
762564
762332
2026-03-30T22:35:44Z
Mewtow
31375
/* Le contrôleur DMA sur un bus partagé ou avec un répartiteur */
762564
wikitext
text/x-wiki
Dans le chapitre précédent, nous avons vu que les périphériques, leurs registres d’interface et leurs contrôleurs, ont chacun une adresse bien précise. Nous avions vu comment le contrôleur de périphérique adresse les périphériques et comment les contrôleurs de périphériques eux-mêmes ont des adresses. Mais nous n'avons pas vu comment le processeur utilise ces adresses.
==Rappels : l'espace d'adressage unifié ou séparé==
Comment s'opère le mélange entre adresses mémoires et adresses de périphérique ? Comment le processeur évite les confusions entre adresses de périphériques et adresses mémoire. Pour cela, il y a plusieurs manières. La plus simple revient à séparer les adresses mémoire et les adresses périphériques, qui ne sont pas transmises sur les mêmes bus. L'autre méthode revient à utiliser un seul ensemble d'adresse, certaines étant allouées à la mémoire, d'autres aux périphériques. Les deux techniques portent des noms assez clairs : l''''espace d'adressage séparé''' pour la première, l''''espace d'adressage unifié''' pour la seconde. Voyons dans le détail ces deux techniques.
===L'espace d’adressage séparé===
Avec la première technique, mémoire et entrées-sorties sont adressées séparément, comme illustré dans le schéma ci-dessous. La mémoire et les entrées-sorties ont chacune un ensemble d'adresse, qui commence à 0 et va jusqu’à une adresse maximale. On dit que la mémoire et les entrées-sorties ont chacune leur propre espace d'adressage.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|Espaces d'adressages séparés entre mémoire et périphérique.]]
Avec cette technique, 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. L'existence de ces instructions séparées permet de faire la différence entre mémoire et périphérique. Sans cela, le processeur ne saurait pas si une adresse est destinée à un périphérique ou à la mémoire.
===Les entrées-sorties mappées en mémoire===
La seconde technique s'appelle l'espace d'adressage unifie, ou encore les '''entrées-sorties mappées en mémoire'''. Avec cette technique, certaines adresses mémoires sont redirigées automatiquement vers les périphériques. Le périphérique se retrouve inclus dans l'ensemble des adresses utilisées pour manipuler la mémoire : on dit qu'il est mappé en mémoire.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
L'avantage de cette méthode est la simplicité pour les programmeurs. Il n'y a pas besoin d'instructions différentes pour accéder aux périphériques et à la mémoire. Tout peut être fait par une seule instruction, qui n'a pas besoin de positionner un quelconque bit IO qui n'existe plus. Le processeur possède donc un nombre plus limité d'instructions machines, et est donc plus simple à fabriquer. Mais surtout, les programmeurs peuvent accéder aux périphériques beaucoup plus simplement, en lisant ou écrivant directement dans certaines adresses associées aux périphériques. Les transferts entre mémoire et périphériques sont fortement simplifiés, par exemple.
==Les bus unifiés et les bus d'entrée-sortie==
Maintenant que nous venons de rappeler ce que sont les espaces d'adressage unifiés et séparés, il est temps de voir comment ils sont implémentés en matériel. Et pour cela, nous allons encore une fois faire un rappel sur les bus.
Nous avons vu dans les chapitres précédents qu'il existe en gros trois configurations de base pour les bus.
La première est celle du '''bus système''', un bus unique qui relie la mémoire RAM, la mémoire ROM, le processeur, et les entrées-sorties.
[[File:Bus unique avec entrées mappées en mémoire.png|centre|vignette|upright=2.0|Bus unique avec entrées mappées en mémoire.]]
La seconde est celle d'un bus séparé pour les entrées-sorties, appelé le '''bus d'entrée-sortie'''. Il est en théorie possible d'avoir un bus séparé par controleur de périphérique ou entrée-sortie, mais le nombre de broches utilisé devient rapidement important, ce qui fait que cette technique n'est jamais implémentée.
[[File:Bus d'entrées-sorties multiplexé.png|centre|vignette|upright=2|Bus entre processeur et contrôleur de périphérique.]]
La troisième intercale un '''circuit répartiteur''' entre le processeur et les deux bus. Il s'occupe alors de la gestion des adresses.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|IO mappées en mémoire avec séparation des bus, usage d'un répartiteur]]
===L'implémentation d'un bus IO dédié avec un multiplexeur d'IO===
Les anciens ordinateurs des années 80-90 utilisaient un mélange des techniques 2 et 3 présentées juste au-dessus. Les processeurs avaient un bus d'entrée-sortie séparé des autres, et notamment séparé du bus mémoire. Mais ce bus était connecté à un répartiteur spécialisé dans les IO, qui s'occupait uniquement des entrées-sorties. Les répartiteurs étaient nombreux à l'époque et étaient appelés des circuits de '''''parallel IO''''', bien que ce terme signifie autre chose de nos jours. Les plus connus sont le 8255 d'Intel, le Motorola 6820 PIA (Peripheral Interface Adapter), le WDC 65C21, le MOS Technology 6522 et le MOS Technology CIA.
Pour simplifier les explications, le circuit répartiteur sera appelé un '''multiplexeur d'entrées-sorties''' ou encore un IO MUX. En effet, c'est fondamentalement un multiplexeur/démultiplexeur amélioré. Pour simplifier, un IO MUX dispose de plusieurs ports d'entrée-sortie, un pour le processeur et les autres pour les contrôleurs de périphérique. La liaison point à point entre le CPU et l'IOMUX se faisait sur des broches dédiées, regroupées dans le '''port CPU''', ou port ''processeur''. L'IO MUX avait plusieurs '''ports IO''', ou ports d'entrées-sorties, sur lesquels on connectait un contrôleur de périphérique via une liaison point à point.
[[File:IO MUX.png|centre|vignette|upright=2|IO MUX]]
[[File:8255.svg|vignette|8255]]
Un exemple est celui du 8255, qui disposait de trois ports IO et d'un port CPU. Le port CPU est un port de 8 bits, qui correspond aux broches D0 à D7. Les ports IO sont des ports de 8 bits et sont appelés les ports A, B et C. Leurs broches sont respectivement les broches PA0 à PA7 pour le port A, les broches PB0 à PB7 pour le port B, les broches PC0 à PC7 pour le port C.
: Le 8255 était plus complexe que ce qui est décrit. Le port C servait soit de port IO proprement dit, soit regroupait les bits de contrôle des ports A et B, à savoir les bits de contrôle pour les interruptions et le ''handshaking''. Le 8255 avait aussi plusieurs modes de fonctionnement où les ports IO étaient configurés différemment, le choix du mode étant fait en configurant un registre de contrôle interne au 8255. Le registre de contrôle était adressé via les lignes 10 et A1 qu'on verra plus bas.
Les ports CPU et IO pouvaient fonctionner comme entrée ou sortie et changeaient de rôle suivant la situation, suivant que le CPU pouvait émettre des données en direction d'un périphérique, ou en recevoir. L'IO MUX fonctionnait soit comme un multiplexeur, soit comme un démultiplexeur. Lorsque le processeur envoyait une donnée vers un périphérique, il fonctionnait en démultiplexeur, pour envoyer la donnée vers le bon périphérique, le bon port. En réception, il fonctionnait en multiplexeur et choisissait quel port était connecté au port CPU, quel port envoyait ses données vers le CPU.
Le choix entre multiplexage et démultiplexage se faisait selon que le processeur voulait faire une lecture ou une écriture. Le choix entre les deux était donc le fait d'une entrée de l'IO MUX, l'entrée R/W, qui indiquait s'il fallait faire une lecture ou une écriture.
Qui dit multiplexage/démultiplexage dit : choisir le port IO à connecter au port CPU. Pour cela, les ports étaient numérotés et le CPU pouvait préciser le numéro du port voulu. Et le numéro du port voulu était présenté sur une entrée dédiée, comme sur un MUX ou DEMUX normal. En soit, ce numéro est équivalent à une adresse de périphérique/port, ce qui fait que cette entrée était en réalité un bus d'adresse, appartenant au port CPU. Sur le 8255, l'envoi de l'adresse se faisait sur les deux broches A0 et A1, qui codaient un numéro de 2 bits. Les valeurs étaient les suivantes : 00 = port A, 01 = port B, 10 = port C, 11 = registre de contrôle.
Mais l'IO MUX n'est pas qu'un simple MUX/DEMUX configurable. Il pouvait ''générer des signaux d'interruption''. Quand un périphérique envoyait une donnée à l'IO MUX, il générait un signal d'interruption pour prévenir le processeur qu'une IO a envoyé une donnée. De plus, le répartiteur pouvait ''mettre en attente les données dans des registres'', qui servaient de registres d’interfaçage. Par exemple, une donnée lue sur un port IO était mémorisée dans le répartiteur en attendant que le processeur la récupère. Et inversement, le processeur pouvait envoyer une donnée à un périphérique par l'intermédiaire d'un registre dans le répartiteur. Il écrivait dans ce registre, la donnée était mise en attente dedans en attendant que le périphérique soit libre, et le répartiteur envoyait la donnée quand ce dernier était libéré.
[[File:MOS6526.svg|vignette|MOS 6526.]]
Il faut noter que les ports IO peuvent être aussi bien série que parallèle. Le 8255 avait trois ports IO de 8 bits, qui sont donc tous les trois des ports parallèles. Mais il a existé des IO MUX disposant de deux ports parallèles et un port série. Tel est le cas du MOS Technology 6522 et de son successeur, le MOS Technology CIA. C'était des IO MUX utilisés dans les ordinateurs Commodore, l'Apple III, et quelques autres ordinateurs anciens renommés.
Ils disposaient de deux ports parallèles de 8 bits (PA0-7, PB0-7), chacun ayant 4 lignes de contrôles à leur disposition pour les interruptions, et d'un port série (CB1 et CB2). Le port série était connecté à un registre à décalage de 8 bits, ce qui lui permettait d'envoyer/recevoir un octet à la fois. Ils intégraient aussi des ''timers'' de 16 bits, ainsi qu'une ''Real Time Clock'' pour gérer l'heure.
===Le contrôleur DMA sur un bus partagé ou avec un répartiteur===
L'usage d'un bus dédié a des avantages et des désavantages. L'un des désavantages est lié à l'implémentation du ''Direct Memory Access''. Un bus dédié aux IO marche assez mal avec le DMA. Les échanges entre mémoire RAM et IO doivent passer par le processeur, vu que le bus mémoire est séparé du bus des IO et que le seul point de contact entre les deux est le CPU. En clair : impossible d'utiliser le ''Direct Memory Access''.
À l'opposé, un contrôleur DMA est très adapté à un système avec un bus système, un bus partagé entre CPU, RAM et IO. Le controleur DMA est alors connecté au bus et il se réserve l'accès au bus quand il effectue un transfert DMA.
[[File:Controleur DMA.png|centre|vignette|upright=2.5|Controleur DMA]]
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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
===Les coprocesseurs d'entrée-sortie sur les bus partagés===
Les bus partagés étaient parfois couplés avec des contrôleurs DMA améliorés, qui étaient rendus programmables. De tels contrôleurs DMA améliorés étaient appelés avec des termes très divers : ''Channel I/O'', ''I/O processor'', ''I/O controller'', ''I/O synchronizer'', et autres. Dans ce qui va suivre, nous allons utiliser le terme de '''coprocesseur périphérique'''.
De tels coprocesseurs périphériques permettent de décharger le processeur principal, le CPU (''Central Processing Unit''), de tout ce qui a trait aux entrées-sorties. Il est moins performant en calcul que le processeur principal, l'accent étant mis sur les accès mémoire. Sauf erreur, ils ne sont présents que sur les systèmes avec un bus partagé, il n'en existe pas pour les systèmes avec un répartiteur ou uns IO dédié.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les coprocesseurs périphériques exécutent un programme qui agit sur les entrées-sorties, souvent appelé un '''programme périphérique'''. Il y a généralement un programme périphérique pour chaque périphérique. Par exemple, il y a un programme pour le contrôleur de disquette, un autre pour le contrôleur du lecteur de bande magnétique, un autre pour la carte graphique, etc. Les programmes périphériques sont fournis par le système d'exploitation et on peut les voir comme des pilotes de périphériques simplifiés. Ils sont équivalents à ce que donnerait des routines d'interruptions déportées sur un autre processeur .
Avec un coprocesseur périphérique, le CPU ne dispose que d'une seule instruction liées aux entrées-sorties. Elle initie l'exécution d'un programme d'entrée-sortie sur le coprocesseur périphérique, en lui fournissant un pointeur qui pointe vers le programme périphérique (l'adresse du programme). Suite à cette instruction, le coprocesseur périphérique exécute son programme dans son coin, séparément du processeur. Quand le programme périphérique s'est terminé, le coprocesseur périphérique envoie une interruption au CPU pour le prévenir qu'il a terminé. Idem en cas d'erreur lors de la transmission.
Dans le cas général, le programme émule les transferts de données entre RAM et périphériques, qui sont autrement gérés par des transferts DMA. Pour cela, les coprocesseurs périphériques peuvent émuler le DMA avec un programme spécialisé qui copie les mots mémoire un par un avec une boucle. Le coprocesseur périphérique incorpore pour cela plusieurs registres spécialisés : des registres contenant des pointeurs, des registres pour des indices de boucle ou des compteurs. Les registres pointeurs sont généralement incrémentés ou décrémentés, suivant que le transfert se fasse par adresses croissantes ou décroissantes. Les compteurs de boucles sont décrémentés à chaque itération et mémorisent à tout instant combien de mots mémoire il reste à copier.
Le jeu d'instruction du coprocesseur périphérique est conçu pour implémenter de telles boucles. Il peut exécuter des instructions assez diverses : branchements, instructions d'accès mémoire, additions/soustractions. Ses instructions se concentrent surtout sur les accès mémoire et laissent de côté les instructions de calcul. Il ne dispose souvent que d'instructions d'addition/soustraction/comparaisons, pas d'instructions de multiplication ou de divisions. Les opérations arithmétiques complexes sont inutiles pour les tâches de gestion des périphériques, elles ne sont donc pas implémentées.
La connexion entre le coprocesseur périphérique et les contrôleurs de périphérique peut s'implémenter de deux manières. La première utilise un bus qui relie le coprocesseur périphérique et les contrôleurs de périphériques. L'implémentation demande peu de circuits et peu gérer un grand nombre de contrôleurs et de périphériques. En contrepartie que le coprocesseur ne peut communiquer qu'avec un seul contrôleur de périphérique à la fois. De tels coprocesseurs périphériques sont appelés des '''''Selector Channel'''''.
Une autre possibilité connecte chaque contrôleur de périphérique sur un port dédié, avec une liaison point à point dédiée. Le cout en interconnexion est grand, cela ne marche pas au-delà de quelques périphériques, mais cela permet de gérer plusieurs communications simultanées. De tels coprocesseurs IO sont appelés des '''''Multiplexer Channel'''''. Il est possible de les voir comme une sorte d'équivalent programmable du multiplexeur d'entrée-sortie des bus dédiés, mais pour les bus partagés.
==L'implémentation matérielle de l'espace d'adressage séparé/unifié==
Intuitivement, on se dit que le bus système va de concert avec un espace d'adressage unifié, avec des entrées-sorties mappées en mémoire. De même, utiliser un bus séparé pour les entrées-sorties va de pair avec des espaces d'adressage séparés. Et dans les grandes lignes, c'est autant vrai que faux.
Un bus système peut implémenter les deux solutions d'adressage, tout dépend de comment on gère le décodage d'adresse (voir plus bas). Il en est de même que la solution avec un répartiteur, tout dépend de comment le répartiteur gère l'espace d'adressage. Par contre, deux bus séparés implique forcément un espace d'adressage séparé. Dans le sens inverse, un espace d'adressage séparé peut être réalisé par toutes les configurations, alors que les entrées-sorties mappées en mémoire impliquent forcément un bus système.
{|class="wikitable"
|-
!
! Espace d'adressage unifié (entrées-sorties mappées en mémoire)
! Espace d'adressage séparé
|-
! Bus système
| rowspan="2" colspan="2" | Oui
|-
! Bus séparé avec répartiteur
|-
! Bus séparé pour les IO
| Non, sauf exceptions
| Oui, obligatoire
|}
Il est possible d'utiliser des configurations intermédiaires, qui permettent d'implémenter des espaces d'adressages séparés ou unifiés. Mais nous verrons cela dans ce qui suit.
===Les entrées-sorties mappées en mémoire avec un bus système===
Dans son implémentation la plus simple, les entrées-sorties mappées en mémoire utilisent un bus système, un bus unique pour les mémoires et les contrôleurs de périphériques. L'avantage est que cela économise beaucoup de fils, sans compter que le bit IO disparait. Par contre, impossible d'accéder à la fois à la mémoire et à un contrôleur d'entrées-sorties en parallèle.
Le principe des entrées-sorties mappées en mémoire est qu'une partie des adresses pointe vers un périphérique, d'autres vers la RAM ou la ROM. L'important est que le bon composant réponde lors d'un accès mémoire/périphérique. Si on accède à une adresse attribuée à la RAM, la RAM doit répondre, les périphériques doivent ignorer l'accès. Et inversement pour un accès périphérique.
La redirection vers le bon destinataire est faite par décodage partiel d'adresse. Pour rappel, chaque périphérique/mémoire possède une entrée CS, qui connecte ou déconnecte le composant du bus. Le circuit de décodage d'adresse prend en entrée l'adresse et commande les bits CS pour désactiver les composants non-concernés et activer la destination. Le circuit de décodage partiel d'adresse va ainsi placer le bit CS de la mémoire à 1 pour les adresses invalidées, l’empêchant de répondre à ces adresses.
[[File:Décodage d'adresse avec entrées-sorties mappées en mémoire.png|centre|vignette|upright=2.0|Décodage d'adresse avec entrées-sorties mappées en mémoire.]]
Le principe est de connecter la mémoire et les entrées-sorties sur le bus système. Le bus d'adresse est connecté à la fois sur la mémoire RAM, sur la mémoire ROM, et sur les entrées-sorties (si elles ont une entrée d'adresse). Le bus de données est lui aussi connecté aux mémoires et aux entrée-sorties. Le décodeur d'adresse est lui relié aux entrées CS de tous ces composants.
[[File:Chipselectfr.png|centre|vignette|upright=1.5|Exemple détaillé.]]
===L'espace d'adressage séparé avec un bus système===
Il est possible d'implémenter l'espace d'adressage séparé sans recourir à des bus séparés. Toutes les configurations de bus possibles sont compatibles avec un espace d'adressage séparé pour les IO, même un bus système unique. Mais comment faire pour l'implémenter avec un bus système ? Là encore, on utilise un système de décodage partiel d'adresse, mais qui est simplifié par rapport à celui des entrée-sorties mappées en mémoire.
Le décodage d'adresse part du principe que le bit de poids fort de l'adresse indique si l'adresse est celle d'un périphérique ou d'une mémoire. Le bit de poids fort de l'adresse, appelé le '''bit I/O''', est mis à 0 pour une adresse mémoire, 1 pour un registre d’interfaçage. Tout cela est réalisé par l'instruction adéquate : une instruction d'accès mémoire positionnera ce bit à 0, alors qu'une instruction d'accès IO le positionnera à 1. L'adresse envoyée sur le bus est formée en récupérant l'adresse à lire/écrire et en positionnant le bit I/O à sa bonne valeur.
Un défaut de cette solution est qu'elle impose d'avoir deux espaces d'adressage de même taille, un pour la/les mémoires, un autre pour les périphériques. Pas question d'avoir un espace d'adressage plus petit pour les périphériques, alors que ce serait possible avec deux bus séparés.
[[File:Bit IO.png|centre|vignette|upright=2|Bit IO.]]
Un avantage de cette méthode est qu'elle marche avec des configurations de bus un peu spéciales, qui sont intermédiaire entre des bus séparés et un bus système. Par exemple, il est possible d'avoir un bus d'adresse partagé, mais pas les autres. Ou encore, il est possible de mutualiser le bus d'adresse et de données, en conservant deux bus de commandes, un pour le périphérique et un pour la mémoire. Le bit IO fonctionne avec toutes ces configurations, la seule contrainte est que le bus d'adresse soit partagé. Mais le processeur doit gérer correctement le bus de données et envoyer les données sur le bon bus de données.
[[File:Espace d'adressage séparé.png|centre|vignette|upright=2|Espace d'adressage séparé.]]
===Les entrées-sorties mappées en mémoire avec des configurations de bus spéciales===
Il est possible d'implémenter les entrées-sorties mappées en mémoire sans utiliser un bus unique, avec des configurations de bus assez spéciales, dans lesquelles on a bien deux bus séparés, mais qui communiquent entre eux. Elles sont très rares, et nous en parlons ici par pur but d'exhaustivité.
La première, de loin la plus simple, consiste à accéder à la RAM d'abord, puis aux périphériques si elle ne répond pas. Une tentative d'accès en RAM fonctionnera du premier coup si l'adresse en question est attribuée à la RAM. Mais si l'adresse est associée à un périphérique, la RAM ne répondra pas et on doit retenter l'accès sur le bus pour les périphériques. L'implémentation est cependant compliquée, sans compter que les performances sont alors réduites, du fait des deux tentatives consécutives.
Les autres solutions font communiquer les deux bus pour que la RAM ou les périphériques détectent précocement les accès qui leur sont dédiés. La première solution de ce type consiste à ajouter un dispositif qui transmet les accès du bus mémoire vers le bus des périphériques. Mais le bus pour les périphériques est souvent moins rapide que le bus mémoire et l'adaptation des vitesses pose des problèmes.
[[File:Espace d'adressage séparé, implémentation avec deux bus séparés.png|centre|vignette|upright=2|IO mappées en mémoire avec séparation des bus]]
{{AutoCat}}
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=Les méthodes de synchronisation entre processeur et périphériques
| prevText=Les méthodes de synchronisation entre processeur et périphériques
| next=Les périphériques et les cartes d'extension
| nextText=Les périphériques et les cartes d'extension
}}
</noinclude>
gv95go4u4f64ba5hfm9jfvf82umvgki
762568
762564
2026-03-30T22:43:27Z
Mewtow
31375
/* L'implémentation matérielle de l'espace d'adressage séparé/unifié */
762568
wikitext
text/x-wiki
Dans le chapitre précédent, nous avons vu que les périphériques, leurs registres d’interface et leurs contrôleurs, ont chacun une adresse bien précise. Nous avions vu comment le contrôleur de périphérique adresse les périphériques et comment les contrôleurs de périphériques eux-mêmes ont des adresses. Mais nous n'avons pas vu comment le processeur utilise ces adresses.
==Rappels : l'espace d'adressage unifié ou séparé==
Comment s'opère le mélange entre adresses mémoires et adresses de périphérique ? Comment le processeur évite les confusions entre adresses de périphériques et adresses mémoire. Pour cela, il y a plusieurs manières. La plus simple revient à séparer les adresses mémoire et les adresses périphériques, qui ne sont pas transmises sur les mêmes bus. L'autre méthode revient à utiliser un seul ensemble d'adresse, certaines étant allouées à la mémoire, d'autres aux périphériques. Les deux techniques portent des noms assez clairs : l''''espace d'adressage séparé''' pour la première, l''''espace d'adressage unifié''' pour la seconde. Voyons dans le détail ces deux techniques.
===L'espace d’adressage séparé===
Avec la première technique, mémoire et entrées-sorties sont adressées séparément, comme illustré dans le schéma ci-dessous. La mémoire et les entrées-sorties ont chacune un ensemble d'adresse, qui commence à 0 et va jusqu’à une adresse maximale. On dit que la mémoire et les entrées-sorties ont chacune leur propre espace d'adressage.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|Espaces d'adressages séparés entre mémoire et périphérique.]]
Avec cette technique, 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. L'existence de ces instructions séparées permet de faire la différence entre mémoire et périphérique. Sans cela, le processeur ne saurait pas si une adresse est destinée à un périphérique ou à la mémoire.
===Les entrées-sorties mappées en mémoire===
La seconde technique s'appelle l'espace d'adressage unifie, ou encore les '''entrées-sorties mappées en mémoire'''. Avec cette technique, certaines adresses mémoires sont redirigées automatiquement vers les périphériques. Le périphérique se retrouve inclus dans l'ensemble des adresses utilisées pour manipuler la mémoire : on dit qu'il est mappé en mémoire.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
L'avantage de cette méthode est la simplicité pour les programmeurs. Il n'y a pas besoin d'instructions différentes pour accéder aux périphériques et à la mémoire. Tout peut être fait par une seule instruction, qui n'a pas besoin de positionner un quelconque bit IO qui n'existe plus. Le processeur possède donc un nombre plus limité d'instructions machines, et est donc plus simple à fabriquer. Mais surtout, les programmeurs peuvent accéder aux périphériques beaucoup plus simplement, en lisant ou écrivant directement dans certaines adresses associées aux périphériques. Les transferts entre mémoire et périphériques sont fortement simplifiés, par exemple.
==Les bus unifiés et les bus d'entrée-sortie==
Maintenant que nous venons de rappeler ce que sont les espaces d'adressage unifiés et séparés, il est temps de voir comment ils sont implémentés en matériel. Et pour cela, nous allons encore une fois faire un rappel sur les bus.
Nous avons vu dans les chapitres précédents qu'il existe en gros trois configurations de base pour les bus.
La première est celle du '''bus système''', un bus unique qui relie la mémoire RAM, la mémoire ROM, le processeur, et les entrées-sorties.
[[File:Bus unique avec entrées mappées en mémoire.png|centre|vignette|upright=2.0|Bus unique avec entrées mappées en mémoire.]]
La seconde est celle d'un bus séparé pour les entrées-sorties, appelé le '''bus d'entrée-sortie'''. Il est en théorie possible d'avoir un bus séparé par controleur de périphérique ou entrée-sortie, mais le nombre de broches utilisé devient rapidement important, ce qui fait que cette technique n'est jamais implémentée.
[[File:Bus d'entrées-sorties multiplexé.png|centre|vignette|upright=2|Bus entre processeur et contrôleur de périphérique.]]
La troisième intercale un '''circuit répartiteur''' entre le processeur et les deux bus. Il s'occupe alors de la gestion des adresses.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|IO mappées en mémoire avec séparation des bus, usage d'un répartiteur]]
===L'implémentation d'un bus IO dédié avec un multiplexeur d'IO===
Les anciens ordinateurs des années 80-90 utilisaient un mélange des techniques 2 et 3 présentées juste au-dessus. Les processeurs avaient un bus d'entrée-sortie séparé des autres, et notamment séparé du bus mémoire. Mais ce bus était connecté à un répartiteur spécialisé dans les IO, qui s'occupait uniquement des entrées-sorties. Les répartiteurs étaient nombreux à l'époque et étaient appelés des circuits de '''''parallel IO''''', bien que ce terme signifie autre chose de nos jours. Les plus connus sont le 8255 d'Intel, le Motorola 6820 PIA (Peripheral Interface Adapter), le WDC 65C21, le MOS Technology 6522 et le MOS Technology CIA.
Pour simplifier les explications, le circuit répartiteur sera appelé un '''multiplexeur d'entrées-sorties''' ou encore un IO MUX. En effet, c'est fondamentalement un multiplexeur/démultiplexeur amélioré. Pour simplifier, un IO MUX dispose de plusieurs ports d'entrée-sortie, un pour le processeur et les autres pour les contrôleurs de périphérique. La liaison point à point entre le CPU et l'IOMUX se faisait sur des broches dédiées, regroupées dans le '''port CPU''', ou port ''processeur''. L'IO MUX avait plusieurs '''ports IO''', ou ports d'entrées-sorties, sur lesquels on connectait un contrôleur de périphérique via une liaison point à point.
[[File:IO MUX.png|centre|vignette|upright=2|IO MUX]]
[[File:8255.svg|vignette|8255]]
Un exemple est celui du 8255, qui disposait de trois ports IO et d'un port CPU. Le port CPU est un port de 8 bits, qui correspond aux broches D0 à D7. Les ports IO sont des ports de 8 bits et sont appelés les ports A, B et C. Leurs broches sont respectivement les broches PA0 à PA7 pour le port A, les broches PB0 à PB7 pour le port B, les broches PC0 à PC7 pour le port C.
: Le 8255 était plus complexe que ce qui est décrit. Le port C servait soit de port IO proprement dit, soit regroupait les bits de contrôle des ports A et B, à savoir les bits de contrôle pour les interruptions et le ''handshaking''. Le 8255 avait aussi plusieurs modes de fonctionnement où les ports IO étaient configurés différemment, le choix du mode étant fait en configurant un registre de contrôle interne au 8255. Le registre de contrôle était adressé via les lignes 10 et A1 qu'on verra plus bas.
Les ports CPU et IO pouvaient fonctionner comme entrée ou sortie et changeaient de rôle suivant la situation, suivant que le CPU pouvait émettre des données en direction d'un périphérique, ou en recevoir. L'IO MUX fonctionnait soit comme un multiplexeur, soit comme un démultiplexeur. Lorsque le processeur envoyait une donnée vers un périphérique, il fonctionnait en démultiplexeur, pour envoyer la donnée vers le bon périphérique, le bon port. En réception, il fonctionnait en multiplexeur et choisissait quel port était connecté au port CPU, quel port envoyait ses données vers le CPU.
Le choix entre multiplexage et démultiplexage se faisait selon que le processeur voulait faire une lecture ou une écriture. Le choix entre les deux était donc le fait d'une entrée de l'IO MUX, l'entrée R/W, qui indiquait s'il fallait faire une lecture ou une écriture.
Qui dit multiplexage/démultiplexage dit : choisir le port IO à connecter au port CPU. Pour cela, les ports étaient numérotés et le CPU pouvait préciser le numéro du port voulu. Et le numéro du port voulu était présenté sur une entrée dédiée, comme sur un MUX ou DEMUX normal. En soit, ce numéro est équivalent à une adresse de périphérique/port, ce qui fait que cette entrée était en réalité un bus d'adresse, appartenant au port CPU. Sur le 8255, l'envoi de l'adresse se faisait sur les deux broches A0 et A1, qui codaient un numéro de 2 bits. Les valeurs étaient les suivantes : 00 = port A, 01 = port B, 10 = port C, 11 = registre de contrôle.
Mais l'IO MUX n'est pas qu'un simple MUX/DEMUX configurable. Il pouvait ''générer des signaux d'interruption''. Quand un périphérique envoyait une donnée à l'IO MUX, il générait un signal d'interruption pour prévenir le processeur qu'une IO a envoyé une donnée. De plus, le répartiteur pouvait ''mettre en attente les données dans des registres'', qui servaient de registres d’interfaçage. Par exemple, une donnée lue sur un port IO était mémorisée dans le répartiteur en attendant que le processeur la récupère. Et inversement, le processeur pouvait envoyer une donnée à un périphérique par l'intermédiaire d'un registre dans le répartiteur. Il écrivait dans ce registre, la donnée était mise en attente dedans en attendant que le périphérique soit libre, et le répartiteur envoyait la donnée quand ce dernier était libéré.
[[File:MOS6526.svg|vignette|MOS 6526.]]
Il faut noter que les ports IO peuvent être aussi bien série que parallèle. Le 8255 avait trois ports IO de 8 bits, qui sont donc tous les trois des ports parallèles. Mais il a existé des IO MUX disposant de deux ports parallèles et un port série. Tel est le cas du MOS Technology 6522 et de son successeur, le MOS Technology CIA. C'était des IO MUX utilisés dans les ordinateurs Commodore, l'Apple III, et quelques autres ordinateurs anciens renommés.
Ils disposaient de deux ports parallèles de 8 bits (PA0-7, PB0-7), chacun ayant 4 lignes de contrôles à leur disposition pour les interruptions, et d'un port série (CB1 et CB2). Le port série était connecté à un registre à décalage de 8 bits, ce qui lui permettait d'envoyer/recevoir un octet à la fois. Ils intégraient aussi des ''timers'' de 16 bits, ainsi qu'une ''Real Time Clock'' pour gérer l'heure.
===Le contrôleur DMA sur un bus partagé ou avec un répartiteur===
L'usage d'un bus dédié a des avantages et des désavantages. L'un des désavantages est lié à l'implémentation du ''Direct Memory Access''. Un bus dédié aux IO marche assez mal avec le DMA. Les échanges entre mémoire RAM et IO doivent passer par le processeur, vu que le bus mémoire est séparé du bus des IO et que le seul point de contact entre les deux est le CPU. En clair : impossible d'utiliser le ''Direct Memory Access''.
À l'opposé, un contrôleur DMA est très adapté à un système avec un bus système, un bus partagé entre CPU, RAM et IO. Le controleur DMA est alors connecté au bus et il se réserve l'accès au bus quand il effectue un transfert DMA.
[[File:Controleur DMA.png|centre|vignette|upright=2.5|Controleur DMA]]
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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
===Les coprocesseurs d'entrée-sortie sur les bus partagés===
Les bus partagés étaient parfois couplés avec des contrôleurs DMA améliorés, qui étaient rendus programmables. De tels contrôleurs DMA améliorés étaient appelés avec des termes très divers : ''Channel I/O'', ''I/O processor'', ''I/O controller'', ''I/O synchronizer'', et autres. Dans ce qui va suivre, nous allons utiliser le terme de '''coprocesseur périphérique'''.
De tels coprocesseurs périphériques permettent de décharger le processeur principal, le CPU (''Central Processing Unit''), de tout ce qui a trait aux entrées-sorties. Il est moins performant en calcul que le processeur principal, l'accent étant mis sur les accès mémoire. Sauf erreur, ils ne sont présents que sur les systèmes avec un bus partagé, il n'en existe pas pour les systèmes avec un répartiteur ou uns IO dédié.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les coprocesseurs périphériques exécutent un programme qui agit sur les entrées-sorties, souvent appelé un '''programme périphérique'''. Il y a généralement un programme périphérique pour chaque périphérique. Par exemple, il y a un programme pour le contrôleur de disquette, un autre pour le contrôleur du lecteur de bande magnétique, un autre pour la carte graphique, etc. Les programmes périphériques sont fournis par le système d'exploitation et on peut les voir comme des pilotes de périphériques simplifiés. Ils sont équivalents à ce que donnerait des routines d'interruptions déportées sur un autre processeur .
Avec un coprocesseur périphérique, le CPU ne dispose que d'une seule instruction liées aux entrées-sorties. Elle initie l'exécution d'un programme d'entrée-sortie sur le coprocesseur périphérique, en lui fournissant un pointeur qui pointe vers le programme périphérique (l'adresse du programme). Suite à cette instruction, le coprocesseur périphérique exécute son programme dans son coin, séparément du processeur. Quand le programme périphérique s'est terminé, le coprocesseur périphérique envoie une interruption au CPU pour le prévenir qu'il a terminé. Idem en cas d'erreur lors de la transmission.
Dans le cas général, le programme émule les transferts de données entre RAM et périphériques, qui sont autrement gérés par des transferts DMA. Pour cela, les coprocesseurs périphériques peuvent émuler le DMA avec un programme spécialisé qui copie les mots mémoire un par un avec une boucle. Le coprocesseur périphérique incorpore pour cela plusieurs registres spécialisés : des registres contenant des pointeurs, des registres pour des indices de boucle ou des compteurs. Les registres pointeurs sont généralement incrémentés ou décrémentés, suivant que le transfert se fasse par adresses croissantes ou décroissantes. Les compteurs de boucles sont décrémentés à chaque itération et mémorisent à tout instant combien de mots mémoire il reste à copier.
Le jeu d'instruction du coprocesseur périphérique est conçu pour implémenter de telles boucles. Il peut exécuter des instructions assez diverses : branchements, instructions d'accès mémoire, additions/soustractions. Ses instructions se concentrent surtout sur les accès mémoire et laissent de côté les instructions de calcul. Il ne dispose souvent que d'instructions d'addition/soustraction/comparaisons, pas d'instructions de multiplication ou de divisions. Les opérations arithmétiques complexes sont inutiles pour les tâches de gestion des périphériques, elles ne sont donc pas implémentées.
La connexion entre le coprocesseur périphérique et les contrôleurs de périphérique peut s'implémenter de deux manières. La première utilise un bus qui relie le coprocesseur périphérique et les contrôleurs de périphériques. L'implémentation demande peu de circuits et peu gérer un grand nombre de contrôleurs et de périphériques. En contrepartie que le coprocesseur ne peut communiquer qu'avec un seul contrôleur de périphérique à la fois. De tels coprocesseurs périphériques sont appelés des '''''Selector Channel'''''.
Une autre possibilité connecte chaque contrôleur de périphérique sur un port dédié, avec une liaison point à point dédiée. Le cout en interconnexion est grand, cela ne marche pas au-delà de quelques périphériques, mais cela permet de gérer plusieurs communications simultanées. De tels coprocesseurs IO sont appelés des '''''Multiplexer Channel'''''. Il est possible de les voir comme une sorte d'équivalent programmable du multiplexeur d'entrée-sortie des bus dédiés, mais pour les bus partagés.
==L'implémentation matérielle de l'espace d'adressage séparé/unifié==
Intuitivement, on se dit que le bus système va de concert avec un espace d'adressage unifié, avec des entrées-sorties mappées en mémoire. De même, utiliser un bus séparé pour les entrées-sorties va de pair avec des espaces d'adressage séparés. Et dans les grandes lignes, c'est autant vrai que faux.
Un bus système peut implémenter les deux solutions d'adressage, tout dépend de comment on gère le décodage d'adresse (voir plus bas). Il en est de même que la solution avec un répartiteur, tout dépend de comment le répartiteur gère l'espace d'adressage. Par contre, deux bus séparés implique forcément un espace d'adressage séparé. Dans le sens inverse, un espace d'adressage séparé peut être réalisé par toutes les configurations, alors que les entrées-sorties mappées en mémoire impliquent forcément un bus système et/ou un répartiteur.
{|class="wikitable"
|-
!
! Espace d'adressage unifié (entrées-sorties mappées en mémoire)
! Espace d'adressage séparé
|-
! Bus système
| rowspan="2" colspan="2" | Oui
|-
! Bus séparé avec répartiteur
|-
! Bus séparé pour les IO
| Non, sauf exceptions
| Oui, obligatoire
|}
Il est possible d'utiliser des configurations intermédiaires, qui permettent d'implémenter des espaces d'adressages séparés ou unifiés. Mais nous verrons cela dans ce qui suit.
===Les entrées-sorties mappées en mémoire avec un bus système===
Dans son implémentation la plus simple, les entrées-sorties mappées en mémoire utilisent un bus système, un bus unique pour les mémoires et les contrôleurs de périphériques. L'avantage est que cela économise beaucoup de fils, sans compter que le bit IO disparait. Par contre, impossible d'accéder à la fois à la mémoire et à un contrôleur d'entrées-sorties en parallèle.
Le principe des entrées-sorties mappées en mémoire est qu'une partie des adresses pointe vers un périphérique, d'autres vers la RAM ou la ROM. L'important est que le bon composant réponde lors d'un accès mémoire/périphérique. Si on accède à une adresse attribuée à la RAM, la RAM doit répondre, les périphériques doivent ignorer l'accès. Et inversement pour un accès périphérique.
La redirection vers le bon destinataire est faite par décodage partiel d'adresse. Pour rappel, chaque périphérique/mémoire possède une entrée CS, qui connecte ou déconnecte le composant du bus. Le circuit de décodage d'adresse prend en entrée l'adresse et commande les bits CS pour désactiver les composants non-concernés et activer la destination. Le circuit de décodage partiel d'adresse va ainsi placer le bit CS de la mémoire à 1 pour les adresses invalidées, l’empêchant de répondre à ces adresses.
[[File:Décodage d'adresse avec entrées-sorties mappées en mémoire.png|centre|vignette|upright=2.0|Décodage d'adresse avec entrées-sorties mappées en mémoire.]]
Le principe est de connecter la mémoire et les entrées-sorties sur le bus système. Le bus d'adresse est connecté à la fois sur la mémoire RAM, sur la mémoire ROM, et sur les entrées-sorties (si elles ont une entrée d'adresse). Le bus de données est lui aussi connecté aux mémoires et aux entrée-sorties. Le décodeur d'adresse est lui relié aux entrées CS de tous ces composants.
[[File:Chipselectfr.png|centre|vignette|upright=1.5|Exemple détaillé.]]
===L'espace d'adressage séparé avec un bus système===
Il est possible d'implémenter l'espace d'adressage séparé sans recourir à des bus séparés. Toutes les configurations de bus possibles sont compatibles avec un espace d'adressage séparé pour les IO, même un bus système unique. Mais comment faire pour l'implémenter avec un bus système ? Là encore, on utilise un système de décodage partiel d'adresse, mais qui est simplifié par rapport à celui des entrée-sorties mappées en mémoire.
Le décodage d'adresse part du principe que le bit de poids fort de l'adresse indique si l'adresse est celle d'un périphérique ou d'une mémoire. Le bit de poids fort de l'adresse, appelé le '''bit I/O''', est mis à 0 pour une adresse mémoire, 1 pour un registre d’interfaçage. Tout cela est réalisé par l'instruction adéquate : une instruction d'accès mémoire positionnera ce bit à 0, alors qu'une instruction d'accès IO le positionnera à 1. L'adresse envoyée sur le bus est formée en récupérant l'adresse à lire/écrire et en positionnant le bit I/O à sa bonne valeur.
Un défaut de cette solution est qu'elle impose d'avoir deux espaces d'adressage de même taille, un pour la/les mémoires, un autre pour les périphériques. Pas question d'avoir un espace d'adressage plus petit pour les périphériques, alors que ce serait possible avec deux bus séparés.
[[File:Bit IO.png|centre|vignette|upright=2|Bit IO.]]
Un avantage de cette méthode est qu'elle marche avec des configurations de bus un peu spéciales, qui sont intermédiaire entre des bus séparés et un bus système. Par exemple, il est possible d'avoir un bus d'adresse partagé, mais pas les autres. Ou encore, il est possible de mutualiser le bus d'adresse et de données, en conservant deux bus de commandes, un pour le périphérique et un pour la mémoire. Le bit IO fonctionne avec toutes ces configurations, la seule contrainte est que le bus d'adresse soit partagé. Mais le processeur doit gérer correctement le bus de données et envoyer les données sur le bon bus de données.
[[File:Espace d'adressage séparé.png|centre|vignette|upright=2|Espace d'adressage séparé.]]
===Les entrées-sorties mappées en mémoire avec des configurations de bus spéciales===
Il est possible d'implémenter les entrées-sorties mappées en mémoire sans utiliser un bus unique, avec des configurations de bus assez spéciales, dans lesquelles on a bien deux bus séparés, mais qui communiquent entre eux. Elles sont très rares, et nous en parlons ici par pur but d'exhaustivité.
La première, de loin la plus simple, consiste à accéder à la RAM d'abord, puis aux périphériques si elle ne répond pas. Une tentative d'accès en RAM fonctionnera du premier coup si l'adresse en question est attribuée à la RAM. Mais si l'adresse est associée à un périphérique, la RAM ne répondra pas et on doit retenter l'accès sur le bus pour les périphériques. L'implémentation est cependant compliquée, sans compter que les performances sont alors réduites, du fait des deux tentatives consécutives.
Les autres solutions font communiquer les deux bus pour que la RAM ou les périphériques détectent précocement les accès qui leur sont dédiés. La première solution de ce type consiste à ajouter un dispositif qui transmet les accès du bus mémoire vers le bus des périphériques. Mais le bus pour les périphériques est souvent moins rapide que le bus mémoire et l'adaptation des vitesses pose des problèmes.
[[File:Espace d'adressage séparé, implémentation avec deux bus séparés.png|centre|vignette|upright=2|IO mappées en mémoire avec séparation des bus]]
{{AutoCat}}
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=Les méthodes de synchronisation entre processeur et périphériques
| prevText=Les méthodes de synchronisation entre processeur et périphériques
| next=Les périphériques et les cartes d'extension
| nextText=Les périphériques et les cartes d'extension
}}
</noinclude>
6spoig0yexnt6s0m2e2qcmgjdw0e0su
762569
762568
2026-03-30T22:43:48Z
Mewtow
31375
/* L'implémentation matérielle de l'espace d'adressage séparé/unifié */
762569
wikitext
text/x-wiki
Dans le chapitre précédent, nous avons vu que les périphériques, leurs registres d’interface et leurs contrôleurs, ont chacun une adresse bien précise. Nous avions vu comment le contrôleur de périphérique adresse les périphériques et comment les contrôleurs de périphériques eux-mêmes ont des adresses. Mais nous n'avons pas vu comment le processeur utilise ces adresses.
==Rappels : l'espace d'adressage unifié ou séparé==
Comment s'opère le mélange entre adresses mémoires et adresses de périphérique ? Comment le processeur évite les confusions entre adresses de périphériques et adresses mémoire. Pour cela, il y a plusieurs manières. La plus simple revient à séparer les adresses mémoire et les adresses périphériques, qui ne sont pas transmises sur les mêmes bus. L'autre méthode revient à utiliser un seul ensemble d'adresse, certaines étant allouées à la mémoire, d'autres aux périphériques. Les deux techniques portent des noms assez clairs : l''''espace d'adressage séparé''' pour la première, l''''espace d'adressage unifié''' pour la seconde. Voyons dans le détail ces deux techniques.
===L'espace d’adressage séparé===
Avec la première technique, mémoire et entrées-sorties sont adressées séparément, comme illustré dans le schéma ci-dessous. La mémoire et les entrées-sorties ont chacune un ensemble d'adresse, qui commence à 0 et va jusqu’à une adresse maximale. On dit que la mémoire et les entrées-sorties ont chacune leur propre espace d'adressage.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|Espaces d'adressages séparés entre mémoire et périphérique.]]
Avec cette technique, 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. L'existence de ces instructions séparées permet de faire la différence entre mémoire et périphérique. Sans cela, le processeur ne saurait pas si une adresse est destinée à un périphérique ou à la mémoire.
===Les entrées-sorties mappées en mémoire===
La seconde technique s'appelle l'espace d'adressage unifie, ou encore les '''entrées-sorties mappées en mémoire'''. Avec cette technique, certaines adresses mémoires sont redirigées automatiquement vers les périphériques. Le périphérique se retrouve inclus dans l'ensemble des adresses utilisées pour manipuler la mémoire : on dit qu'il est mappé en mémoire.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
L'avantage de cette méthode est la simplicité pour les programmeurs. Il n'y a pas besoin d'instructions différentes pour accéder aux périphériques et à la mémoire. Tout peut être fait par une seule instruction, qui n'a pas besoin de positionner un quelconque bit IO qui n'existe plus. Le processeur possède donc un nombre plus limité d'instructions machines, et est donc plus simple à fabriquer. Mais surtout, les programmeurs peuvent accéder aux périphériques beaucoup plus simplement, en lisant ou écrivant directement dans certaines adresses associées aux périphériques. Les transferts entre mémoire et périphériques sont fortement simplifiés, par exemple.
==Les bus unifiés et les bus d'entrée-sortie==
Maintenant que nous venons de rappeler ce que sont les espaces d'adressage unifiés et séparés, il est temps de voir comment ils sont implémentés en matériel. Et pour cela, nous allons encore une fois faire un rappel sur les bus.
Nous avons vu dans les chapitres précédents qu'il existe en gros trois configurations de base pour les bus.
La première est celle du '''bus système''', un bus unique qui relie la mémoire RAM, la mémoire ROM, le processeur, et les entrées-sorties.
[[File:Bus unique avec entrées mappées en mémoire.png|centre|vignette|upright=2.0|Bus unique avec entrées mappées en mémoire.]]
La seconde est celle d'un bus séparé pour les entrées-sorties, appelé le '''bus d'entrée-sortie'''. Il est en théorie possible d'avoir un bus séparé par controleur de périphérique ou entrée-sortie, mais le nombre de broches utilisé devient rapidement important, ce qui fait que cette technique n'est jamais implémentée.
[[File:Bus d'entrées-sorties multiplexé.png|centre|vignette|upright=2|Bus entre processeur et contrôleur de périphérique.]]
La troisième intercale un '''circuit répartiteur''' entre le processeur et les deux bus. Il s'occupe alors de la gestion des adresses.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|IO mappées en mémoire avec séparation des bus, usage d'un répartiteur]]
===L'implémentation d'un bus IO dédié avec un multiplexeur d'IO===
Les anciens ordinateurs des années 80-90 utilisaient un mélange des techniques 2 et 3 présentées juste au-dessus. Les processeurs avaient un bus d'entrée-sortie séparé des autres, et notamment séparé du bus mémoire. Mais ce bus était connecté à un répartiteur spécialisé dans les IO, qui s'occupait uniquement des entrées-sorties. Les répartiteurs étaient nombreux à l'époque et étaient appelés des circuits de '''''parallel IO''''', bien que ce terme signifie autre chose de nos jours. Les plus connus sont le 8255 d'Intel, le Motorola 6820 PIA (Peripheral Interface Adapter), le WDC 65C21, le MOS Technology 6522 et le MOS Technology CIA.
Pour simplifier les explications, le circuit répartiteur sera appelé un '''multiplexeur d'entrées-sorties''' ou encore un IO MUX. En effet, c'est fondamentalement un multiplexeur/démultiplexeur amélioré. Pour simplifier, un IO MUX dispose de plusieurs ports d'entrée-sortie, un pour le processeur et les autres pour les contrôleurs de périphérique. La liaison point à point entre le CPU et l'IOMUX se faisait sur des broches dédiées, regroupées dans le '''port CPU''', ou port ''processeur''. L'IO MUX avait plusieurs '''ports IO''', ou ports d'entrées-sorties, sur lesquels on connectait un contrôleur de périphérique via une liaison point à point.
[[File:IO MUX.png|centre|vignette|upright=2|IO MUX]]
[[File:8255.svg|vignette|8255]]
Un exemple est celui du 8255, qui disposait de trois ports IO et d'un port CPU. Le port CPU est un port de 8 bits, qui correspond aux broches D0 à D7. Les ports IO sont des ports de 8 bits et sont appelés les ports A, B et C. Leurs broches sont respectivement les broches PA0 à PA7 pour le port A, les broches PB0 à PB7 pour le port B, les broches PC0 à PC7 pour le port C.
: Le 8255 était plus complexe que ce qui est décrit. Le port C servait soit de port IO proprement dit, soit regroupait les bits de contrôle des ports A et B, à savoir les bits de contrôle pour les interruptions et le ''handshaking''. Le 8255 avait aussi plusieurs modes de fonctionnement où les ports IO étaient configurés différemment, le choix du mode étant fait en configurant un registre de contrôle interne au 8255. Le registre de contrôle était adressé via les lignes 10 et A1 qu'on verra plus bas.
Les ports CPU et IO pouvaient fonctionner comme entrée ou sortie et changeaient de rôle suivant la situation, suivant que le CPU pouvait émettre des données en direction d'un périphérique, ou en recevoir. L'IO MUX fonctionnait soit comme un multiplexeur, soit comme un démultiplexeur. Lorsque le processeur envoyait une donnée vers un périphérique, il fonctionnait en démultiplexeur, pour envoyer la donnée vers le bon périphérique, le bon port. En réception, il fonctionnait en multiplexeur et choisissait quel port était connecté au port CPU, quel port envoyait ses données vers le CPU.
Le choix entre multiplexage et démultiplexage se faisait selon que le processeur voulait faire une lecture ou une écriture. Le choix entre les deux était donc le fait d'une entrée de l'IO MUX, l'entrée R/W, qui indiquait s'il fallait faire une lecture ou une écriture.
Qui dit multiplexage/démultiplexage dit : choisir le port IO à connecter au port CPU. Pour cela, les ports étaient numérotés et le CPU pouvait préciser le numéro du port voulu. Et le numéro du port voulu était présenté sur une entrée dédiée, comme sur un MUX ou DEMUX normal. En soit, ce numéro est équivalent à une adresse de périphérique/port, ce qui fait que cette entrée était en réalité un bus d'adresse, appartenant au port CPU. Sur le 8255, l'envoi de l'adresse se faisait sur les deux broches A0 et A1, qui codaient un numéro de 2 bits. Les valeurs étaient les suivantes : 00 = port A, 01 = port B, 10 = port C, 11 = registre de contrôle.
Mais l'IO MUX n'est pas qu'un simple MUX/DEMUX configurable. Il pouvait ''générer des signaux d'interruption''. Quand un périphérique envoyait une donnée à l'IO MUX, il générait un signal d'interruption pour prévenir le processeur qu'une IO a envoyé une donnée. De plus, le répartiteur pouvait ''mettre en attente les données dans des registres'', qui servaient de registres d’interfaçage. Par exemple, une donnée lue sur un port IO était mémorisée dans le répartiteur en attendant que le processeur la récupère. Et inversement, le processeur pouvait envoyer une donnée à un périphérique par l'intermédiaire d'un registre dans le répartiteur. Il écrivait dans ce registre, la donnée était mise en attente dedans en attendant que le périphérique soit libre, et le répartiteur envoyait la donnée quand ce dernier était libéré.
[[File:MOS6526.svg|vignette|MOS 6526.]]
Il faut noter que les ports IO peuvent être aussi bien série que parallèle. Le 8255 avait trois ports IO de 8 bits, qui sont donc tous les trois des ports parallèles. Mais il a existé des IO MUX disposant de deux ports parallèles et un port série. Tel est le cas du MOS Technology 6522 et de son successeur, le MOS Technology CIA. C'était des IO MUX utilisés dans les ordinateurs Commodore, l'Apple III, et quelques autres ordinateurs anciens renommés.
Ils disposaient de deux ports parallèles de 8 bits (PA0-7, PB0-7), chacun ayant 4 lignes de contrôles à leur disposition pour les interruptions, et d'un port série (CB1 et CB2). Le port série était connecté à un registre à décalage de 8 bits, ce qui lui permettait d'envoyer/recevoir un octet à la fois. Ils intégraient aussi des ''timers'' de 16 bits, ainsi qu'une ''Real Time Clock'' pour gérer l'heure.
===Le contrôleur DMA sur un bus partagé ou avec un répartiteur===
L'usage d'un bus dédié a des avantages et des désavantages. L'un des désavantages est lié à l'implémentation du ''Direct Memory Access''. Un bus dédié aux IO marche assez mal avec le DMA. Les échanges entre mémoire RAM et IO doivent passer par le processeur, vu que le bus mémoire est séparé du bus des IO et que le seul point de contact entre les deux est le CPU. En clair : impossible d'utiliser le ''Direct Memory Access''.
À l'opposé, un contrôleur DMA est très adapté à un système avec un bus système, un bus partagé entre CPU, RAM et IO. Le controleur DMA est alors connecté au bus et il se réserve l'accès au bus quand il effectue un transfert DMA.
[[File:Controleur DMA.png|centre|vignette|upright=2.5|Controleur DMA]]
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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
===Les coprocesseurs d'entrée-sortie sur les bus partagés===
Les bus partagés étaient parfois couplés avec des contrôleurs DMA améliorés, qui étaient rendus programmables. De tels contrôleurs DMA améliorés étaient appelés avec des termes très divers : ''Channel I/O'', ''I/O processor'', ''I/O controller'', ''I/O synchronizer'', et autres. Dans ce qui va suivre, nous allons utiliser le terme de '''coprocesseur périphérique'''.
De tels coprocesseurs périphériques permettent de décharger le processeur principal, le CPU (''Central Processing Unit''), de tout ce qui a trait aux entrées-sorties. Il est moins performant en calcul que le processeur principal, l'accent étant mis sur les accès mémoire. Sauf erreur, ils ne sont présents que sur les systèmes avec un bus partagé, il n'en existe pas pour les systèmes avec un répartiteur ou uns IO dédié.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les coprocesseurs périphériques exécutent un programme qui agit sur les entrées-sorties, souvent appelé un '''programme périphérique'''. Il y a généralement un programme périphérique pour chaque périphérique. Par exemple, il y a un programme pour le contrôleur de disquette, un autre pour le contrôleur du lecteur de bande magnétique, un autre pour la carte graphique, etc. Les programmes périphériques sont fournis par le système d'exploitation et on peut les voir comme des pilotes de périphériques simplifiés. Ils sont équivalents à ce que donnerait des routines d'interruptions déportées sur un autre processeur .
Avec un coprocesseur périphérique, le CPU ne dispose que d'une seule instruction liées aux entrées-sorties. Elle initie l'exécution d'un programme d'entrée-sortie sur le coprocesseur périphérique, en lui fournissant un pointeur qui pointe vers le programme périphérique (l'adresse du programme). Suite à cette instruction, le coprocesseur périphérique exécute son programme dans son coin, séparément du processeur. Quand le programme périphérique s'est terminé, le coprocesseur périphérique envoie une interruption au CPU pour le prévenir qu'il a terminé. Idem en cas d'erreur lors de la transmission.
Dans le cas général, le programme émule les transferts de données entre RAM et périphériques, qui sont autrement gérés par des transferts DMA. Pour cela, les coprocesseurs périphériques peuvent émuler le DMA avec un programme spécialisé qui copie les mots mémoire un par un avec une boucle. Le coprocesseur périphérique incorpore pour cela plusieurs registres spécialisés : des registres contenant des pointeurs, des registres pour des indices de boucle ou des compteurs. Les registres pointeurs sont généralement incrémentés ou décrémentés, suivant que le transfert se fasse par adresses croissantes ou décroissantes. Les compteurs de boucles sont décrémentés à chaque itération et mémorisent à tout instant combien de mots mémoire il reste à copier.
Le jeu d'instruction du coprocesseur périphérique est conçu pour implémenter de telles boucles. Il peut exécuter des instructions assez diverses : branchements, instructions d'accès mémoire, additions/soustractions. Ses instructions se concentrent surtout sur les accès mémoire et laissent de côté les instructions de calcul. Il ne dispose souvent que d'instructions d'addition/soustraction/comparaisons, pas d'instructions de multiplication ou de divisions. Les opérations arithmétiques complexes sont inutiles pour les tâches de gestion des périphériques, elles ne sont donc pas implémentées.
La connexion entre le coprocesseur périphérique et les contrôleurs de périphérique peut s'implémenter de deux manières. La première utilise un bus qui relie le coprocesseur périphérique et les contrôleurs de périphériques. L'implémentation demande peu de circuits et peu gérer un grand nombre de contrôleurs et de périphériques. En contrepartie que le coprocesseur ne peut communiquer qu'avec un seul contrôleur de périphérique à la fois. De tels coprocesseurs périphériques sont appelés des '''''Selector Channel'''''.
Une autre possibilité connecte chaque contrôleur de périphérique sur un port dédié, avec une liaison point à point dédiée. Le cout en interconnexion est grand, cela ne marche pas au-delà de quelques périphériques, mais cela permet de gérer plusieurs communications simultanées. De tels coprocesseurs IO sont appelés des '''''Multiplexer Channel'''''. Il est possible de les voir comme une sorte d'équivalent programmable du multiplexeur d'entrée-sortie des bus dédiés, mais pour les bus partagés.
==L'implémentation matérielle de l'espace d'adressage séparé/unifié==
Intuitivement, on se dit que le bus système va de concert avec un espace d'adressage unifié, avec des entrées-sorties mappées en mémoire. De même, utiliser un bus séparé pour les entrées-sorties va de pair avec des espaces d'adressage séparés. Et dans les grandes lignes, c'est autant vrai que faux.
Un bus système peut implémenter les deux solutions d'adressage, tout dépend de comment on gère le décodage d'adresse (voir plus bas). Il en est de même que la solution avec un répartiteur, tout dépend de comment le répartiteur gère l'espace d'adressage. Par contre, deux bus séparés implique forcément un espace d'adressage séparé. Dans le sens inverse, un espace d'adressage séparé peut être réalisé par toutes les configurations, alors que les entrées-sorties mappées en mémoire impliquent forcément un bus système et/ou un répartiteur.
{|class="wikitable"
|-
!
! Espace d'adressage unifié (entrées-sorties mappées en mémoire)
! Espace d'adressage séparé
|-
! Bus système
| rowspan="2" colspan="2" | Possible, dépend du décodage d'adresse utilisé
|-
! Bus séparé avec répartiteur
|-
! Bus séparé pour les IO
| Non, sauf exceptions
| Oui, obligatoire
|}
Il est possible d'utiliser des configurations intermédiaires, qui permettent d'implémenter des espaces d'adressages séparés ou unifiés. Mais nous verrons cela dans ce qui suit.
===Les entrées-sorties mappées en mémoire avec un bus système===
Dans son implémentation la plus simple, les entrées-sorties mappées en mémoire utilisent un bus système, un bus unique pour les mémoires et les contrôleurs de périphériques. L'avantage est que cela économise beaucoup de fils, sans compter que le bit IO disparait. Par contre, impossible d'accéder à la fois à la mémoire et à un contrôleur d'entrées-sorties en parallèle.
Le principe des entrées-sorties mappées en mémoire est qu'une partie des adresses pointe vers un périphérique, d'autres vers la RAM ou la ROM. L'important est que le bon composant réponde lors d'un accès mémoire/périphérique. Si on accède à une adresse attribuée à la RAM, la RAM doit répondre, les périphériques doivent ignorer l'accès. Et inversement pour un accès périphérique.
La redirection vers le bon destinataire est faite par décodage partiel d'adresse. Pour rappel, chaque périphérique/mémoire possède une entrée CS, qui connecte ou déconnecte le composant du bus. Le circuit de décodage d'adresse prend en entrée l'adresse et commande les bits CS pour désactiver les composants non-concernés et activer la destination. Le circuit de décodage partiel d'adresse va ainsi placer le bit CS de la mémoire à 1 pour les adresses invalidées, l’empêchant de répondre à ces adresses.
[[File:Décodage d'adresse avec entrées-sorties mappées en mémoire.png|centre|vignette|upright=2.0|Décodage d'adresse avec entrées-sorties mappées en mémoire.]]
Le principe est de connecter la mémoire et les entrées-sorties sur le bus système. Le bus d'adresse est connecté à la fois sur la mémoire RAM, sur la mémoire ROM, et sur les entrées-sorties (si elles ont une entrée d'adresse). Le bus de données est lui aussi connecté aux mémoires et aux entrée-sorties. Le décodeur d'adresse est lui relié aux entrées CS de tous ces composants.
[[File:Chipselectfr.png|centre|vignette|upright=1.5|Exemple détaillé.]]
===L'espace d'adressage séparé avec un bus système===
Il est possible d'implémenter l'espace d'adressage séparé sans recourir à des bus séparés. Toutes les configurations de bus possibles sont compatibles avec un espace d'adressage séparé pour les IO, même un bus système unique. Mais comment faire pour l'implémenter avec un bus système ? Là encore, on utilise un système de décodage partiel d'adresse, mais qui est simplifié par rapport à celui des entrée-sorties mappées en mémoire.
Le décodage d'adresse part du principe que le bit de poids fort de l'adresse indique si l'adresse est celle d'un périphérique ou d'une mémoire. Le bit de poids fort de l'adresse, appelé le '''bit I/O''', est mis à 0 pour une adresse mémoire, 1 pour un registre d’interfaçage. Tout cela est réalisé par l'instruction adéquate : une instruction d'accès mémoire positionnera ce bit à 0, alors qu'une instruction d'accès IO le positionnera à 1. L'adresse envoyée sur le bus est formée en récupérant l'adresse à lire/écrire et en positionnant le bit I/O à sa bonne valeur.
Un défaut de cette solution est qu'elle impose d'avoir deux espaces d'adressage de même taille, un pour la/les mémoires, un autre pour les périphériques. Pas question d'avoir un espace d'adressage plus petit pour les périphériques, alors que ce serait possible avec deux bus séparés.
[[File:Bit IO.png|centre|vignette|upright=2|Bit IO.]]
Un avantage de cette méthode est qu'elle marche avec des configurations de bus un peu spéciales, qui sont intermédiaire entre des bus séparés et un bus système. Par exemple, il est possible d'avoir un bus d'adresse partagé, mais pas les autres. Ou encore, il est possible de mutualiser le bus d'adresse et de données, en conservant deux bus de commandes, un pour le périphérique et un pour la mémoire. Le bit IO fonctionne avec toutes ces configurations, la seule contrainte est que le bus d'adresse soit partagé. Mais le processeur doit gérer correctement le bus de données et envoyer les données sur le bon bus de données.
[[File:Espace d'adressage séparé.png|centre|vignette|upright=2|Espace d'adressage séparé.]]
===Les entrées-sorties mappées en mémoire avec des configurations de bus spéciales===
Il est possible d'implémenter les entrées-sorties mappées en mémoire sans utiliser un bus unique, avec des configurations de bus assez spéciales, dans lesquelles on a bien deux bus séparés, mais qui communiquent entre eux. Elles sont très rares, et nous en parlons ici par pur but d'exhaustivité.
La première, de loin la plus simple, consiste à accéder à la RAM d'abord, puis aux périphériques si elle ne répond pas. Une tentative d'accès en RAM fonctionnera du premier coup si l'adresse en question est attribuée à la RAM. Mais si l'adresse est associée à un périphérique, la RAM ne répondra pas et on doit retenter l'accès sur le bus pour les périphériques. L'implémentation est cependant compliquée, sans compter que les performances sont alors réduites, du fait des deux tentatives consécutives.
Les autres solutions font communiquer les deux bus pour que la RAM ou les périphériques détectent précocement les accès qui leur sont dédiés. La première solution de ce type consiste à ajouter un dispositif qui transmet les accès du bus mémoire vers le bus des périphériques. Mais le bus pour les périphériques est souvent moins rapide que le bus mémoire et l'adaptation des vitesses pose des problèmes.
[[File:Espace d'adressage séparé, implémentation avec deux bus séparés.png|centre|vignette|upright=2|IO mappées en mémoire avec séparation des bus]]
{{AutoCat}}
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=Les méthodes de synchronisation entre processeur et périphériques
| prevText=Les méthodes de synchronisation entre processeur et périphériques
| next=Les périphériques et les cartes d'extension
| nextText=Les périphériques et les cartes d'extension
}}
</noinclude>
hrqnow5a3g11lfu2zu1qt5721um78cw
Fonctionnement d'un ordinateur/L'architecture de base d'un ordinateur
0
65780
762504
762499
2026-03-30T14:16:49Z
Mewtow
31375
/* Les bus spécialisés */
762504
wikitext
text/x-wiki
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 :
* les '''entrées/sorties''', qui permettent à l'ordinateur de communiquer avec l'extérieur ;
* une '''mémoire''' qui mémorise les données à manipuler ;
* un '''processeur''', qui manipule l'information et donne un résultat.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|Architecture d'un système à mémoire.]]
Pour faire simple, le processeur est un circuit qui s'occupe de faire des calculs et de traiter des informations. La mémoire s'occupe purement de la mémorisation des informations. 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. Ces composants communiquent via un '''bus''', un ensemble de fils électriques qui relie les différents éléments d'un ordinateur.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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 moins une mémoire ROM et une mémoire RWM (souvent une RAM). La mémoire ROM stocke un programme, alors que la mémoire RWM sert essentiellement pour maintenir des résultats de calculs.
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. Idéalement, les mémoires ROM stockent le programme à exécuter et éventuellement d'autres informations. Mais son rôle principal est de mémoriser le programme à exécuter. La mémoire RWM stocke des données temporaires, manipulées en lecture et écriture par le processeur. Les deux sont lues directement par le processeur
Pour les mémoires RWM, nous allons nous concentrer sur une mémoire électronique 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 sert donc essentiellement pour maintenir des résultats de calculs, à mémoriser temporairement des données temporaires, nécessaires pour que le programme en mémoire ROM fonctionne. Elle 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
La mémoire ROM stocke le programme à exécuter et est accessible directement par le processeur. Mais elle peut aussi stocker les constantes, à savoir des données qui peuvent être lues mais ne sont jamais accédées en écriture durant l'exécution du programme. Elles ne sont donc jamais modifiées et gardent la même valeur quoi qu'il se passe lors de l'exécution du programme.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|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, ou bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. 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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur n'est pas très compliqué. Il contient évidemment des circuits de calcul qui sont regroupés dans une ou plusieurs unité de calcul. Nous avons déjà vu dans les chapitres précédents comment fabriquer une unité de calcul simple, dans un chapitre dédié, et il s'agit de la même unité de calcul qu'on trouve dans le processeur. Elle est cependant complétée par d'autres circuits, pour les multiplications/division/autres.
L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. L'unité de contrôle est assez complexe et aura droit à plusieurs chapitres dédié dans la suite de ce cours, le réseau d'interconnexion et les registres auront droit à un chapitre dédié.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Un processeur contient des registres et communique avec la mémoire===
Tout processeur contient des '''registres''' pour fonctionner, leur utilité dépendant du registre considéré. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre, ou du moins une petite suite de quelques bits. Les registres du processeur peuvent servir à plein de choses : stocker des données afin de les manipuler plus facilement, stocker l'adresse de la prochaine instruction, stocker l'adresse d'une donnée à aller chercher en mémoire, etc.
Les registres les plus simples à comprendre contiennent les opérandes et les résultats des opérations de calcul, appelons-les '''registres de données'''. La capacité des registres de données dépend fortement du processeur, et elle détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres de données de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Notons qu'un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Sans cela, les registres seraient un peu difficiles à utiliser. Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importante que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large. Mais cela sera certainement plus claire quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
Tous les circuits vus précédemment sont des circuits qui se chargent de traiter 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 se chargent de traduire 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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''. Une telle organisation implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire !
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. De plus, l'on a pas à gérer les conflits d'accès au bus entre la mémoire et les entrées/sorties. Mais surtout, les bus peuvent être adaptés et simplifiés. Par exemple, le bus pour les entrées-sorties peut se passer de bus d'adresse, avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. Il est ainsi possible d'avoir un bus mémoire capable de lire/écrire 16 bits à la fois, alors que la communication avec les entrées-sorties se fait octet par octet !
Plutôt que d'avoir un seul bus qui s'adapte aux mémoires et entrées-sorties, on a des bus spécialisés. L'avantage principal de cette adaptation est que la mémoire et les périphériques ne vont pas à la même vitesse du tout. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus plus simple, moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler, bien que moins performant. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
7er9v0n8qqcfrk7rzqhnxgcryzdf736
762505
762504
2026-03-30T14:20:54Z
Mewtow
31375
/* Les bus spécialisés */
762505
wikitext
text/x-wiki
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 :
* les '''entrées/sorties''', qui permettent à l'ordinateur de communiquer avec l'extérieur ;
* une '''mémoire''' qui mémorise les données à manipuler ;
* un '''processeur''', qui manipule l'information et donne un résultat.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|Architecture d'un système à mémoire.]]
Pour faire simple, le processeur est un circuit qui s'occupe de faire des calculs et de traiter des informations. La mémoire s'occupe purement de la mémorisation des informations. 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. Ces composants communiquent via un '''bus''', un ensemble de fils électriques qui relie les différents éléments d'un ordinateur.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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 moins une mémoire ROM et une mémoire RWM (souvent une RAM). La mémoire ROM stocke un programme, alors que la mémoire RWM sert essentiellement pour maintenir des résultats de calculs.
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. Idéalement, les mémoires ROM stockent le programme à exécuter et éventuellement d'autres informations. Mais son rôle principal est de mémoriser le programme à exécuter. La mémoire RWM stocke des données temporaires, manipulées en lecture et écriture par le processeur. Les deux sont lues directement par le processeur
Pour les mémoires RWM, nous allons nous concentrer sur une mémoire électronique 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 sert donc essentiellement pour maintenir des résultats de calculs, à mémoriser temporairement des données temporaires, nécessaires pour que le programme en mémoire ROM fonctionne. Elle 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
La mémoire ROM stocke le programme à exécuter et est accessible directement par le processeur. Mais elle peut aussi stocker les constantes, à savoir des données qui peuvent être lues mais ne sont jamais accédées en écriture durant l'exécution du programme. Elles ne sont donc jamais modifiées et gardent la même valeur quoi qu'il se passe lors de l'exécution du programme.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|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, ou bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. 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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur n'est pas très compliqué. Il contient évidemment des circuits de calcul qui sont regroupés dans une ou plusieurs unité de calcul. Nous avons déjà vu dans les chapitres précédents comment fabriquer une unité de calcul simple, dans un chapitre dédié, et il s'agit de la même unité de calcul qu'on trouve dans le processeur. Elle est cependant complétée par d'autres circuits, pour les multiplications/division/autres.
L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. L'unité de contrôle est assez complexe et aura droit à plusieurs chapitres dédié dans la suite de ce cours, le réseau d'interconnexion et les registres auront droit à un chapitre dédié.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Un processeur contient des registres et communique avec la mémoire===
Tout processeur contient des '''registres''' pour fonctionner, leur utilité dépendant du registre considéré. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre, ou du moins une petite suite de quelques bits. Les registres du processeur peuvent servir à plein de choses : stocker des données afin de les manipuler plus facilement, stocker l'adresse de la prochaine instruction, stocker l'adresse d'une donnée à aller chercher en mémoire, etc.
Les registres les plus simples à comprendre contiennent les opérandes et les résultats des opérations de calcul, appelons-les '''registres de données'''. La capacité des registres de données dépend fortement du processeur, et elle détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres de données de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Notons qu'un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Sans cela, les registres seraient un peu difficiles à utiliser. Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importante que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large. Mais cela sera certainement plus claire quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
Tous les circuits vus précédemment sont des circuits qui se chargent de traiter 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 se chargent de traduire 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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
Enfin, une telle organisation implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire !
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
mzh2engn72em5ij0ypmq492gxatkest
762506
762505
2026-03-30T14:25:06Z
Mewtow
31375
/* Les bus spécialisés */
762506
wikitext
text/x-wiki
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 :
* les '''entrées/sorties''', qui permettent à l'ordinateur de communiquer avec l'extérieur ;
* une '''mémoire''' qui mémorise les données à manipuler ;
* un '''processeur''', qui manipule l'information et donne un résultat.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|Architecture d'un système à mémoire.]]
Pour faire simple, le processeur est un circuit qui s'occupe de faire des calculs et de traiter des informations. La mémoire s'occupe purement de la mémorisation des informations. 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. Ces composants communiquent via un '''bus''', un ensemble de fils électriques qui relie les différents éléments d'un ordinateur.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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 moins une mémoire ROM et une mémoire RWM (souvent une RAM). La mémoire ROM stocke un programme, alors que la mémoire RWM sert essentiellement pour maintenir des résultats de calculs.
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. Idéalement, les mémoires ROM stockent le programme à exécuter et éventuellement d'autres informations. Mais son rôle principal est de mémoriser le programme à exécuter. La mémoire RWM stocke des données temporaires, manipulées en lecture et écriture par le processeur. Les deux sont lues directement par le processeur
Pour les mémoires RWM, nous allons nous concentrer sur une mémoire électronique 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 sert donc essentiellement pour maintenir des résultats de calculs, à mémoriser temporairement des données temporaires, nécessaires pour que le programme en mémoire ROM fonctionne. Elle 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
La mémoire ROM stocke le programme à exécuter et est accessible directement par le processeur. Mais elle peut aussi stocker les constantes, à savoir des données qui peuvent être lues mais ne sont jamais accédées en écriture durant l'exécution du programme. Elles ne sont donc jamais modifiées et gardent la même valeur quoi qu'il se passe lors de l'exécution du programme.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|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, ou bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. 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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur n'est pas très compliqué. Il contient évidemment des circuits de calcul qui sont regroupés dans une ou plusieurs unité de calcul. Nous avons déjà vu dans les chapitres précédents comment fabriquer une unité de calcul simple, dans un chapitre dédié, et il s'agit de la même unité de calcul qu'on trouve dans le processeur. Elle est cependant complétée par d'autres circuits, pour les multiplications/division/autres.
L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. L'unité de contrôle est assez complexe et aura droit à plusieurs chapitres dédié dans la suite de ce cours, le réseau d'interconnexion et les registres auront droit à un chapitre dédié.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Un processeur contient des registres et communique avec la mémoire===
Tout processeur contient des '''registres''' pour fonctionner, leur utilité dépendant du registre considéré. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre, ou du moins une petite suite de quelques bits. Les registres du processeur peuvent servir à plein de choses : stocker des données afin de les manipuler plus facilement, stocker l'adresse de la prochaine instruction, stocker l'adresse d'une donnée à aller chercher en mémoire, etc.
Les registres les plus simples à comprendre contiennent les opérandes et les résultats des opérations de calcul, appelons-les '''registres de données'''. La capacité des registres de données dépend fortement du processeur, et elle détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres de données de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Notons qu'un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Sans cela, les registres seraient un peu difficiles à utiliser. Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importante que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large. Mais cela sera certainement plus claire quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
Tous les circuits vus précédemment sont des circuits qui se chargent de traiter 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 se chargent de traduire 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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
68rul7qazn2tlr6ey4c2454apt308xx
762507
762506
2026-03-30T14:26:05Z
Mewtow
31375
/* L'adressage mémoire */
762507
wikitext
text/x-wiki
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 :
* les '''entrées/sorties''', qui permettent à l'ordinateur de communiquer avec l'extérieur ;
* une '''mémoire''' qui mémorise les données à manipuler ;
* un '''processeur''', qui manipule l'information et donne un résultat.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|Architecture d'un système à mémoire.]]
Pour faire simple, le processeur est un circuit qui s'occupe de faire des calculs et de traiter des informations. La mémoire s'occupe purement de la mémorisation des informations. 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. Ces composants communiquent via un '''bus''', un ensemble de fils électriques qui relie les différents éléments d'un ordinateur.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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 moins une mémoire ROM et une mémoire RWM (souvent une RAM). La mémoire ROM stocke un programme, alors que la mémoire RWM sert essentiellement pour maintenir des résultats de calculs.
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. Idéalement, les mémoires ROM stockent le programme à exécuter et éventuellement d'autres informations. Mais son rôle principal est de mémoriser le programme à exécuter. La mémoire RWM stocke des données temporaires, manipulées en lecture et écriture par le processeur. Les deux sont lues directement par le processeur
Pour les mémoires RWM, nous allons nous concentrer sur une mémoire électronique 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 sert donc essentiellement pour maintenir des résultats de calculs, à mémoriser temporairement des données temporaires, nécessaires pour que le programme en mémoire ROM fonctionne. Elle 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
La mémoire ROM stocke le programme à exécuter et est accessible directement par le processeur. Mais elle peut aussi stocker les constantes, à savoir des données qui peuvent être lues mais ne sont jamais accédées en écriture durant l'exécution du programme. Elles ne sont donc jamais modifiées et gardent la même valeur quoi qu'il se passe lors de l'exécution du programme.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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, ou bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. 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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur n'est pas très compliqué. Il contient évidemment des circuits de calcul qui sont regroupés dans une ou plusieurs unité de calcul. Nous avons déjà vu dans les chapitres précédents comment fabriquer une unité de calcul simple, dans un chapitre dédié, et il s'agit de la même unité de calcul qu'on trouve dans le processeur. Elle est cependant complétée par d'autres circuits, pour les multiplications/division/autres.
L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. L'unité de contrôle est assez complexe et aura droit à plusieurs chapitres dédié dans la suite de ce cours, le réseau d'interconnexion et les registres auront droit à un chapitre dédié.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Un processeur contient des registres et communique avec la mémoire===
Tout processeur contient des '''registres''' pour fonctionner, leur utilité dépendant du registre considéré. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre, ou du moins une petite suite de quelques bits. Les registres du processeur peuvent servir à plein de choses : stocker des données afin de les manipuler plus facilement, stocker l'adresse de la prochaine instruction, stocker l'adresse d'une donnée à aller chercher en mémoire, etc.
Les registres les plus simples à comprendre contiennent les opérandes et les résultats des opérations de calcul, appelons-les '''registres de données'''. La capacité des registres de données dépend fortement du processeur, et elle détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres de données de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Notons qu'un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Sans cela, les registres seraient un peu difficiles à utiliser. Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importante que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large. Mais cela sera certainement plus claire quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
Tous les circuits vus précédemment sont des circuits qui se chargent de traiter 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 se chargent de traduire 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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
tvkyokdk1j0h9411apam2575cp6psxa
762508
762507
2026-03-30T14:31:33Z
Mewtow
31375
/* Le processeur effectue des instructions, dont des calculs */
762508
wikitext
text/x-wiki
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 :
* les '''entrées/sorties''', qui permettent à l'ordinateur de communiquer avec l'extérieur ;
* une '''mémoire''' qui mémorise les données à manipuler ;
* un '''processeur''', qui manipule l'information et donne un résultat.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|Architecture d'un système à mémoire.]]
Pour faire simple, le processeur est un circuit qui s'occupe de faire des calculs et de traiter des informations. La mémoire s'occupe purement de la mémorisation des informations. 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. Ces composants communiquent via un '''bus''', un ensemble de fils électriques qui relie les différents éléments d'un ordinateur.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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 moins une mémoire ROM et une mémoire RWM (souvent une RAM). La mémoire ROM stocke un programme, alors que la mémoire RWM sert essentiellement pour maintenir des résultats de calculs.
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. Idéalement, les mémoires ROM stockent le programme à exécuter et éventuellement d'autres informations. Mais son rôle principal est de mémoriser le programme à exécuter. La mémoire RWM stocke des données temporaires, manipulées en lecture et écriture par le processeur. Les deux sont lues directement par le processeur
Pour les mémoires RWM, nous allons nous concentrer sur une mémoire électronique 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 sert donc essentiellement pour maintenir des résultats de calculs, à mémoriser temporairement des données temporaires, nécessaires pour que le programme en mémoire ROM fonctionne. Elle 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
La mémoire ROM stocke le programme à exécuter et est accessible directement par le processeur. Mais elle peut aussi stocker les constantes, à savoir des données qui peuvent être lues mais ne sont jamais accédées en écriture durant l'exécution du programme. Elles ne sont donc jamais modifiées et gardent la même valeur quoi qu'il se passe lors de l'exécution du programme.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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, ou bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. 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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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 ? Deux solutions à cela : elles sont lues directement depuis la mémoire RAM, ou elles sont mémorisées dans le processeur. Quelques vieux processeurs lisaient les opérandes en mémoire RAM, et enregistraient le résultat dans la RAM. De tels processeurs étaient appelés des '''architectures mémoire-mémoire''', il y avait aussi les '''machines à pile''', mais les deux ne sont plus utilisées de nos jours. Un chapitre entier sera dédié à ces processeurs, aussi nous les passons sous silence.
Tous les processeurs actuels utilisent la seconde solution. Ils enregistrent les opérandes des calculs dans des registres, des mémoires chacune capable de mémoriser un nombre.
L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. L'unité de contrôle est assez complexe et aura droit à plusieurs chapitres dédié dans la suite de ce cours, le réseau d'interconnexion et les registres auront droit à un chapitre dédié.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Un processeur contient des registres et communique avec la mémoire===
Tout processeur contient des '''registres''' pour fonctionner, leur utilité dépendant du registre considéré. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre, ou du moins une petite suite de quelques bits. Les registres du processeur peuvent servir à plein de choses : stocker des données afin de les manipuler plus facilement, stocker l'adresse de la prochaine instruction, stocker l'adresse d'une donnée à aller chercher en mémoire, etc.
Les registres les plus simples à comprendre contiennent les opérandes et les résultats des opérations de calcul, appelons-les '''registres de données'''. La capacité des registres de données dépend fortement du processeur, et elle détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres de données de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Notons qu'un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Sans cela, les registres seraient un peu difficiles à utiliser. Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importante que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large. Mais cela sera certainement plus claire quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
Tous les circuits vus précédemment sont des circuits qui se chargent de traiter 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 se chargent de traduire 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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
mw9dzlugqmbnid27m21q7c4bs9c2cvd
762509
762508
2026-03-30T14:34:58Z
Mewtow
31375
/* Le processeur */
762509
wikitext
text/x-wiki
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 :
* les '''entrées/sorties''', qui permettent à l'ordinateur de communiquer avec l'extérieur ;
* une '''mémoire''' qui mémorise les données à manipuler ;
* un '''processeur''', qui manipule l'information et donne un résultat.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|Architecture d'un système à mémoire.]]
Pour faire simple, le processeur est un circuit qui s'occupe de faire des calculs et de traiter des informations. La mémoire s'occupe purement de la mémorisation des informations. 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. Ces composants communiquent via un '''bus''', un ensemble de fils électriques qui relie les différents éléments d'un ordinateur.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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 moins une mémoire ROM et une mémoire RWM (souvent une RAM). La mémoire ROM stocke un programme, alors que la mémoire RWM sert essentiellement pour maintenir des résultats de calculs.
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. Idéalement, les mémoires ROM stockent le programme à exécuter et éventuellement d'autres informations. Mais son rôle principal est de mémoriser le programme à exécuter. La mémoire RWM stocke des données temporaires, manipulées en lecture et écriture par le processeur. Les deux sont lues directement par le processeur
Pour les mémoires RWM, nous allons nous concentrer sur une mémoire électronique 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 sert donc essentiellement pour maintenir des résultats de calculs, à mémoriser temporairement des données temporaires, nécessaires pour que le programme en mémoire ROM fonctionne. Elle 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
La mémoire ROM stocke le programme à exécuter et est accessible directement par le processeur. Mais elle peut aussi stocker les constantes, à savoir des données qui peuvent être lues mais ne sont jamais accédées en écriture durant l'exécution du programme. Elles ne sont donc jamais modifiées et gardent la même valeur quoi qu'il se passe lors de l'exécution du programme.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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, ou bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. 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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? Deux solutions à cela : elles sont lues directement depuis la mémoire RAM, ou elles sont mémorisées dans le processeur. Quelques vieux processeurs lisaient les opérandes en mémoire RAM, et enregistraient le résultat dans la RAM. De tels processeurs étaient appelés des '''architectures mémoire-mémoire''', il y avait aussi les '''machines à pile''', mais les deux ne sont plus utilisées de nos jours. Un chapitre entier sera dédié à ces processeurs, aussi nous les passons sous silence.
Tous les processeurs actuels utilisent la seconde solution. Ils enregistrent les opérandes des calculs dans des '''registres''', chacun mémorisant un opérande ou un résultat de calcul. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre, ou du moins une petite suite de quelques bits. Les registres du processeur peuvent servir à plein de choses : stocker des données afin de les manipuler plus facilement, stocker l'adresse de la prochaine instruction, stocker l'adresse d'une donnée à aller chercher en mémoire, etc.
Les registres les plus simples à comprendre contiennent les opérandes et les résultats des opérations de calcul, appelons-les '''registres généraux'''. La capacité des registres généraux dépend fortement du processeur, et elle détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Un processeur communique avec la mémoire===
Néanmoins, les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Sans cela, les registres seraient un peu difficiles à utiliser. Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importante que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large. Mais cela sera certainement plus claire quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. L'unité de contrôle est assez complexe et aura droit à plusieurs chapitres dédié dans la suite de ce cours, le réseau d'interconnexion et les registres auront droit à un chapitre dédié.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
Tous les circuits vus précédemment sont des circuits qui se chargent de traiter 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 se chargent de traduire 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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
5b1bmgh7sx1flj8vuhlabudahywgjyo
762510
762509
2026-03-30T14:37:22Z
Mewtow
31375
/* Un processeur communique avec la mémoire */
762510
wikitext
text/x-wiki
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 :
* les '''entrées/sorties''', qui permettent à l'ordinateur de communiquer avec l'extérieur ;
* une '''mémoire''' qui mémorise les données à manipuler ;
* un '''processeur''', qui manipule l'information et donne un résultat.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|Architecture d'un système à mémoire.]]
Pour faire simple, le processeur est un circuit qui s'occupe de faire des calculs et de traiter des informations. La mémoire s'occupe purement de la mémorisation des informations. 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. Ces composants communiquent via un '''bus''', un ensemble de fils électriques qui relie les différents éléments d'un ordinateur.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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 moins une mémoire ROM et une mémoire RWM (souvent une RAM). La mémoire ROM stocke un programme, alors que la mémoire RWM sert essentiellement pour maintenir des résultats de calculs.
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. Idéalement, les mémoires ROM stockent le programme à exécuter et éventuellement d'autres informations. Mais son rôle principal est de mémoriser le programme à exécuter. La mémoire RWM stocke des données temporaires, manipulées en lecture et écriture par le processeur. Les deux sont lues directement par le processeur
Pour les mémoires RWM, nous allons nous concentrer sur une mémoire électronique 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 sert donc essentiellement pour maintenir des résultats de calculs, à mémoriser temporairement des données temporaires, nécessaires pour que le programme en mémoire ROM fonctionne. Elle 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
La mémoire ROM stocke le programme à exécuter et est accessible directement par le processeur. Mais elle peut aussi stocker les constantes, à savoir des données qui peuvent être lues mais ne sont jamais accédées en écriture durant l'exécution du programme. Elles ne sont donc jamais modifiées et gardent la même valeur quoi qu'il se passe lors de l'exécution du programme.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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, ou bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. 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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? Deux solutions à cela : elles sont lues directement depuis la mémoire RAM, ou elles sont mémorisées dans le processeur. Quelques vieux processeurs lisaient les opérandes en mémoire RAM, et enregistraient le résultat dans la RAM. De tels processeurs étaient appelés des '''architectures mémoire-mémoire''', il y avait aussi les '''machines à pile''', mais les deux ne sont plus utilisées de nos jours. Un chapitre entier sera dédié à ces processeurs, aussi nous les passons sous silence.
Tous les processeurs actuels utilisent la seconde solution. Ils enregistrent les opérandes des calculs dans des '''registres''', chacun mémorisant un opérande ou un résultat de calcul. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre, ou du moins une petite suite de quelques bits. Les registres du processeur peuvent servir à plein de choses : stocker des données afin de les manipuler plus facilement, stocker l'adresse de la prochaine instruction, stocker l'adresse d'une donnée à aller chercher en mémoire, etc.
Les registres les plus simples à comprendre contiennent les opérandes et les résultats des opérations de calcul, appelons-les '''registres généraux'''. La capacité des registres généraux dépend fortement du processeur, et elle détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
Tous les circuits vus précédemment sont des circuits qui se chargent de traiter 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 se chargent de traduire 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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
k3ytuadbkahx37s82drcnjiwo54hyrl
762511
762510
2026-03-30T15:19:36Z
Mewtow
31375
/* Un processeur contient des registres */
762511
wikitext
text/x-wiki
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 :
* les '''entrées/sorties''', qui permettent à l'ordinateur de communiquer avec l'extérieur ;
* une '''mémoire''' qui mémorise les données à manipuler ;
* un '''processeur''', qui manipule l'information et donne un résultat.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|Architecture d'un système à mémoire.]]
Pour faire simple, le processeur est un circuit qui s'occupe de faire des calculs et de traiter des informations. La mémoire s'occupe purement de la mémorisation des informations. 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. Ces composants communiquent via un '''bus''', un ensemble de fils électriques qui relie les différents éléments d'un ordinateur.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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 moins une mémoire ROM et une mémoire RWM (souvent une RAM). La mémoire ROM stocke un programme, alors que la mémoire RWM sert essentiellement pour maintenir des résultats de calculs.
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. Idéalement, les mémoires ROM stockent le programme à exécuter et éventuellement d'autres informations. Mais son rôle principal est de mémoriser le programme à exécuter. La mémoire RWM stocke des données temporaires, manipulées en lecture et écriture par le processeur. Les deux sont lues directement par le processeur
Pour les mémoires RWM, nous allons nous concentrer sur une mémoire électronique 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 sert donc essentiellement pour maintenir des résultats de calculs, à mémoriser temporairement des données temporaires, nécessaires pour que le programme en mémoire ROM fonctionne. Elle 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
La mémoire ROM stocke le programme à exécuter et est accessible directement par le processeur. Mais elle peut aussi stocker les constantes, à savoir des données qui peuvent être lues mais ne sont jamais accédées en écriture durant l'exécution du programme. Elles ne sont donc jamais modifiées et gardent la même valeur quoi qu'il se passe lors de l'exécution du programme.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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, ou bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. 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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème : elle demande de faire plusieurs accès à la mémoire simultanés. Il faut lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois. Il y a donc un problème qu'il faut résoudre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais seules les mémoires dites SRAM en sont capables et elles sont presque toujours intégrées dans les processeurs.
Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les opérandes l'une après l'autre, quitte à mémoriser au moins une opérande dans le processeur. Pour mémoriser une ou plusieurs opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
Les anciens processeurs utilisaient un registre unique appelé l'accumulateur, qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération.
De nos jours, les processeurs modernes vont beaucoup plus loin. Ils disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres, pas besoin d'en enregistrer un en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux dépend fortement du processeur, et elle détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
Tous les circuits vus précédemment sont des circuits qui se chargent de traiter 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 se chargent de traduire 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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
5xvnpajszaj10w0blhszqye9ktoa28c
762513
762511
2026-03-30T15:31:08Z
Mewtow
31375
/* Un processeur contient des registres */
762513
wikitext
text/x-wiki
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 :
* les '''entrées/sorties''', qui permettent à l'ordinateur de communiquer avec l'extérieur ;
* une '''mémoire''' qui mémorise les données à manipuler ;
* un '''processeur''', qui manipule l'information et donne un résultat.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|Architecture d'un système à mémoire.]]
Pour faire simple, le processeur est un circuit qui s'occupe de faire des calculs et de traiter des informations. La mémoire s'occupe purement de la mémorisation des informations. 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. Ces composants communiquent via un '''bus''', un ensemble de fils électriques qui relie les différents éléments d'un ordinateur.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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 moins une mémoire ROM et une mémoire RWM (souvent une RAM). La mémoire ROM stocke un programme, alors que la mémoire RWM sert essentiellement pour maintenir des résultats de calculs.
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. Idéalement, les mémoires ROM stockent le programme à exécuter et éventuellement d'autres informations. Mais son rôle principal est de mémoriser le programme à exécuter. La mémoire RWM stocke des données temporaires, manipulées en lecture et écriture par le processeur. Les deux sont lues directement par le processeur
Pour les mémoires RWM, nous allons nous concentrer sur une mémoire électronique 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 sert donc essentiellement pour maintenir des résultats de calculs, à mémoriser temporairement des données temporaires, nécessaires pour que le programme en mémoire ROM fonctionne. Elle 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
La mémoire ROM stocke le programme à exécuter et est accessible directement par le processeur. Mais elle peut aussi stocker les constantes, à savoir des données qui peuvent être lues mais ne sont jamais accédées en écriture durant l'exécution du programme. Elles ne sont donc jamais modifiées et gardent la même valeur quoi qu'il se passe lors de l'exécution du programme.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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, ou bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. 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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème : elle demande de faire plusieurs accès à la mémoire simultanés. Il faut lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois. Il y a donc un problème qu'il faut résoudre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais seules les mémoires dites SRAM en sont capables et elles sont presque toujours intégrées dans les processeurs.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
Les anciens processeurs utilisaient un registre unique appelé l'accumulateur, qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
Tous les circuits vus précédemment sont des circuits qui se chargent de traiter 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 se chargent de traduire 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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
1gvlrxzre5td3gu4ia2oyqps0au03d8
762519
762513
2026-03-30T16:34:10Z
Mewtow
31375
/* Un processeur contient des registres */
762519
wikitext
text/x-wiki
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 :
* les '''entrées/sorties''', qui permettent à l'ordinateur de communiquer avec l'extérieur ;
* une '''mémoire''' qui mémorise les données à manipuler ;
* un '''processeur''', qui manipule l'information et donne un résultat.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|Architecture d'un système à mémoire.]]
Pour faire simple, le processeur est un circuit qui s'occupe de faire des calculs et de traiter des informations. La mémoire s'occupe purement de la mémorisation des informations. 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. Ces composants communiquent via un '''bus''', un ensemble de fils électriques qui relie les différents éléments d'un ordinateur.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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 moins une mémoire ROM et une mémoire RWM (souvent une RAM). La mémoire ROM stocke un programme, alors que la mémoire RWM sert essentiellement pour maintenir des résultats de calculs.
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. Idéalement, les mémoires ROM stockent le programme à exécuter et éventuellement d'autres informations. Mais son rôle principal est de mémoriser le programme à exécuter. La mémoire RWM stocke des données temporaires, manipulées en lecture et écriture par le processeur. Les deux sont lues directement par le processeur
Pour les mémoires RWM, nous allons nous concentrer sur une mémoire électronique 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 sert donc essentiellement pour maintenir des résultats de calculs, à mémoriser temporairement des données temporaires, nécessaires pour que le programme en mémoire ROM fonctionne. Elle 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
La mémoire ROM stocke le programme à exécuter et est accessible directement par le processeur. Mais elle peut aussi stocker les constantes, à savoir des données qui peuvent être lues mais ne sont jamais accédées en écriture durant l'exécution du programme. Elles ne sont donc jamais modifiées et gardent la même valeur quoi qu'il se passe lors de l'exécution du programme.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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, ou bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. 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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM. Occasionnellement, le processeur devait copier le contenu de l'accumulateur en mémoire RAM, ce qui était fait via une instruction STORE.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
Tous les circuits vus précédemment sont des circuits qui se chargent de traiter 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 se chargent de traduire 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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
rb29z31i8uuz0rtbs5touct1fzexeu9
762521
762519
2026-03-30T19:54:09Z
Mewtow
31375
762521
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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, sur lesquelles faire des calculs.
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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 moins une mémoire ROM et une mémoire RWM (souvent une RAM). La mémoire ROM stocke un programme, alors que la mémoire RWM sert essentiellement pour maintenir des résultats de calculs.
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. Idéalement, les mémoires ROM stockent le programme à exécuter et éventuellement d'autres informations. Mais son rôle principal est de mémoriser le programme à exécuter. La mémoire RWM stocke des données temporaires, manipulées en lecture et écriture par le processeur. Les deux sont lues directement par le processeur
Pour les mémoires RWM, nous allons nous concentrer sur une mémoire électronique 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 sert donc essentiellement pour maintenir des résultats de calculs, à mémoriser temporairement des données temporaires, nécessaires pour que le programme en mémoire ROM fonctionne. Elle 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
La mémoire ROM stocke le programme à exécuter et est accessible directement par le processeur. Mais elle peut aussi stocker les constantes, à savoir des données qui peuvent être lues mais ne sont jamais accédées en écriture durant l'exécution du programme. Elles ne sont donc jamais modifiées et gardent la même valeur quoi qu'il se passe lors de l'exécution du programme.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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, ou bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. 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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM. Occasionnellement, le processeur devait copier le contenu de l'accumulateur en mémoire RAM, ce qui était fait via une instruction STORE.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
Tous les circuits vus précédemment sont des circuits qui se chargent de traiter 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 se chargent de traduire 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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
7hr7awnrlpki2qkwxghnlvjq4gm870f
762522
762521
2026-03-30T19:56:02Z
Mewtow
31375
/* Les entrées-sorties */
762522
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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, sur lesquelles faire des calculs.
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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 moins une mémoire ROM et une mémoire RWM (souvent une RAM). La mémoire ROM stocke un programme, alors que la mémoire RWM sert essentiellement pour maintenir des résultats de calculs.
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. Idéalement, les mémoires ROM stockent le programme à exécuter et éventuellement d'autres informations. Mais son rôle principal est de mémoriser le programme à exécuter. La mémoire RWM stocke des données temporaires, manipulées en lecture et écriture par le processeur. Les deux sont lues directement par le processeur
Pour les mémoires RWM, nous allons nous concentrer sur une mémoire électronique 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 sert donc essentiellement pour maintenir des résultats de calculs, à mémoriser temporairement des données temporaires, nécessaires pour que le programme en mémoire ROM fonctionne. Elle 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
La mémoire ROM stocke le programme à exécuter et est accessible directement par le processeur. Mais elle peut aussi stocker les constantes, à savoir des données qui peuvent être lues mais ne sont jamais accédées en écriture durant l'exécution du programme. Elles ne sont donc jamais modifiées et gardent la même valeur quoi qu'il se passe lors de l'exécution du programme.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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, ou bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. 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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM. Occasionnellement, le processeur devait copier le contenu de l'accumulateur en mémoire RAM, ce qui était fait via une instruction STORE.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
6dyxa95s1jkab6tsc5yl5xk7ra68a32
762523
762522
2026-03-30T20:21:32Z
Mewtow
31375
762523
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Afin de simplifier les explications, on va supposer que le réseau d'interconnexion est le suivant. Tout est connecté au processeur.
[[File:Réseau d'interconnexion avec un processeur au centre.png|thumb|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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 moins une mémoire ROM et une mémoire RWM (souvent une RAM). La mémoire ROM stocke un programme, alors que la mémoire RWM sert essentiellement pour maintenir des résultats de calculs.
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. Idéalement, les mémoires ROM stockent le programme à exécuter et éventuellement d'autres informations. Mais son rôle principal est de mémoriser le programme à exécuter. La mémoire RWM stocke des données temporaires, manipulées en lecture et écriture par le processeur. Les deux sont lues directement par le processeur
Pour les mémoires RWM, nous allons nous concentrer sur une mémoire électronique 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 sert donc essentiellement pour maintenir des résultats de calculs, à mémoriser temporairement des données temporaires, nécessaires pour que le programme en mémoire ROM fonctionne. Elle 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
La mémoire ROM stocke le programme à exécuter et est accessible directement par le processeur. Mais elle peut aussi stocker les constantes, à savoir des données qui peuvent être lues mais ne sont jamais accédées en écriture durant l'exécution du programme. Elles ne sont donc jamais modifiées et gardent la même valeur quoi qu'il se passe lors de l'exécution du programme.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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, ou bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. 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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM. Occasionnellement, le processeur devait copier le contenu de l'accumulateur en mémoire RAM, ce qui était fait via une instruction STORE.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
5h59s1xpayf62uhcozjwhlh5p7ku54u
762524
762523
2026-03-30T20:22:14Z
Mewtow
31375
762524
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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 moins une mémoire ROM et une mémoire RWM (souvent une RAM). La mémoire ROM stocke un programme, alors que la mémoire RWM sert essentiellement pour maintenir des résultats de calculs.
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. Idéalement, les mémoires ROM stockent le programme à exécuter et éventuellement d'autres informations. Mais son rôle principal est de mémoriser le programme à exécuter. La mémoire RWM stocke des données temporaires, manipulées en lecture et écriture par le processeur. Les deux sont lues directement par le processeur
Pour les mémoires RWM, nous allons nous concentrer sur une mémoire électronique 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 sert donc essentiellement pour maintenir des résultats de calculs, à mémoriser temporairement des données temporaires, nécessaires pour que le programme en mémoire ROM fonctionne. Elle 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
La mémoire ROM stocke le programme à exécuter et est accessible directement par le processeur. Mais elle peut aussi stocker les constantes, à savoir des données qui peuvent être lues mais ne sont jamais accédées en écriture durant l'exécution du programme. Elles ne sont donc jamais modifiées et gardent la même valeur quoi qu'il se passe lors de l'exécution du programme.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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, ou bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. 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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM. Occasionnellement, le processeur devait copier le contenu de l'accumulateur en mémoire RAM, ce qui était fait via une instruction STORE.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
o290fwo5obsnic3ewc5cfir4l6w0fjo
762525
762524
2026-03-30T20:23:03Z
Mewtow
31375
762525
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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 interconnexion, pour les partager entre la ROM et la RAM, par exemple. Mais pour le moment, gardez le schéma ci-dessous en tête.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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 moins une mémoire ROM et une mémoire RWM (souvent une RAM). La mémoire ROM stocke un programme, alors que la mémoire RWM sert essentiellement pour maintenir des résultats de calculs.
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. Idéalement, les mémoires ROM stockent le programme à exécuter et éventuellement d'autres informations. Mais son rôle principal est de mémoriser le programme à exécuter. La mémoire RWM stocke des données temporaires, manipulées en lecture et écriture par le processeur. Les deux sont lues directement par le processeur
Pour les mémoires RWM, nous allons nous concentrer sur une mémoire électronique 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 sert donc essentiellement pour maintenir des résultats de calculs, à mémoriser temporairement des données temporaires, nécessaires pour que le programme en mémoire ROM fonctionne. Elle 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
La mémoire ROM stocke le programme à exécuter et est accessible directement par le processeur. Mais elle peut aussi stocker les constantes, à savoir des données qui peuvent être lues mais ne sont jamais accédées en écriture durant l'exécution du programme. Elles ne sont donc jamais modifiées et gardent la même valeur quoi qu'il se passe lors de l'exécution du programme.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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, ou bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. 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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM. Occasionnellement, le processeur devait copier le contenu de l'accumulateur en mémoire RAM, ce qui était fait via une instruction STORE.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
7q03eyyf3tv7jc8fldogflllamvtdsj
762526
762525
2026-03-30T20:25:22Z
Mewtow
31375
762526
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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 moins une mémoire ROM et une mémoire RWM (souvent une RAM). La mémoire ROM stocke un programme, alors que la mémoire RWM sert essentiellement pour maintenir des résultats de calculs.
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. Idéalement, les mémoires ROM stockent le programme à exécuter et éventuellement d'autres informations. Mais son rôle principal est de mémoriser le programme à exécuter. La mémoire RWM stocke des données temporaires, manipulées en lecture et écriture par le processeur. Les deux sont lues directement par le processeur
Pour les mémoires RWM, nous allons nous concentrer sur une mémoire électronique 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 sert donc essentiellement pour maintenir des résultats de calculs, à mémoriser temporairement des données temporaires, nécessaires pour que le programme en mémoire ROM fonctionne. Elle 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
La mémoire ROM stocke le programme à exécuter et est accessible directement par le processeur. Mais elle peut aussi stocker les constantes, à savoir des données qui peuvent être lues mais ne sont jamais accédées en écriture durant l'exécution du programme. Elles ne sont donc jamais modifiées et gardent la même valeur quoi qu'il se passe lors de l'exécution du programme.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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, ou bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. 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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM. Occasionnellement, le processeur devait copier le contenu de l'accumulateur en mémoire RAM, ce qui était fait via une instruction STORE.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
mk5a79569rriyb2p6rep5ueq3r3pr91
762527
762526
2026-03-30T20:35:00Z
Mewtow
31375
/* Lecture et écriture : mémoires ROM et RWM */
762527
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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, ou bien d'autres choses. Nous détaillerons d'ailleurs les mécanismes pour dans les chapitres portant sur les modes d'adressage du processeur. 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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM. Occasionnellement, le processeur devait copier le contenu de l'accumulateur en mémoire RAM, ce qui était fait via une instruction STORE.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
p2phm6ij1gpunj8lij3s5g5byrf2abl
762528
762527
2026-03-30T20:37:42Z
Mewtow
31375
/* L'adressage mémoire */
762528
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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. 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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Bus mémoire : bus d'adresse et de données.]]
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM. Occasionnellement, le processeur devait copier le contenu de l'accumulateur en mémoire RAM, ce qui était fait via une instruction STORE.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
iiy7734y04zuuo7ikhayi1rbut322e8
762529
762528
2026-03-30T20:48:01Z
Mewtow
31375
/* L'adressage mémoire */
762529
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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. 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.
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM. Occasionnellement, le processeur devait copier le contenu de l'accumulateur en mémoire RAM, ce qui était fait via une instruction STORE.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
ecwtgr2yvcxo6my9rpw6zqp8f3gkeh4
762530
762529
2026-03-30T20:48:43Z
Mewtow
31375
/* L'adressage mémoire */
762530
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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).]]
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.
===Les échanges entre mémoire RAM/ROM et processeur===
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. 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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM. Occasionnellement, le processeur devait copier le contenu de l'accumulateur en mémoire RAM, ce qui était fait via une instruction STORE.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
hr9n607bv90zr14jf4dtai9929j8li0
762531
762530
2026-03-30T20:49:42Z
Mewtow
31375
/* La mémoire */
762531
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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. 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.
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM. Occasionnellement, le processeur devait copier le contenu de l'accumulateur en mémoire RAM, ce qui était fait via une instruction STORE.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
03hl3oymy3loe8m977di6dbu3qkdxaj
762532
762531
2026-03-30T20:56:13Z
Mewtow
31375
/* Un processeur contient des registres */
762532
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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. 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.
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Mais les registres de données ce ne sont pas les seuls. Pour pouvoir fonctionner, tout processeur doit mémoriser un certain nombre d’informations nécessaires à son fonctionnement : il faut qu'il se souvienne à quel instruction du programme il en est, qu'il connaisse la position en mémoire des données à manipuler, etc. Et ces informations sont mémorisées dans des registres spécialisés, appelés des '''registres de contrôle'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres.
La plupart ont des noms assez barbares (registre d'état, ''program counter'') et nous ne pouvons pas en parler à ce moment du cours car nous n'en savons pas assez sur le fonctionnement d'un processeur pour expliquer à quoi ils servent. Il y a cependant une exception, un registre particulier présent sur presque tous les ordinateurs existants au monde, qu'il est important de voir maintenant : le ''program counter''.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
owqc6qldbxznphjuz9l1geo3pi82zp1
762533
762532
2026-03-30T20:59:49Z
Mewtow
31375
/* Le processeur */
762533
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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. 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.
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
16ps8z9mn69otubjjlpu948bek47v8u
762534
762533
2026-03-30T21:04:03Z
Mewtow
31375
/* L'architecture Harvard */
762534
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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. 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.
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
fhvew4qmey43rnkk9vqvx3da9cqf1ou
762535
762534
2026-03-30T21:13:50Z
Mewtow
31375
/* L'architecture Harvard */
762535
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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. 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.
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
ht9gki5wwly9sqvq5dfnimn1xzk3rnp
762536
762535
2026-03-30T21:14:56Z
Mewtow
31375
/* L'architecture Harvard */
762536
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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. 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.
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
mvjmm9p2kh7abx60d8fsyul8ue9m2g1
762537
762536
2026-03-30T21:16:23Z
Mewtow
31375
/* L'adressage mémoire */
762537
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
aes7cym5a0btfyd9dd02xtfmootnjyy
762538
762537
2026-03-30T21:17:03Z
Mewtow
31375
/* La mémoire */
762538
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
Le processeur est relié à la mémoire ainsi qu'aux entrées-sorties 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. Tout ordinateur contient au moins un bus, qui relie le processeur, la mémoire, les entrées et les sorties ; et leur permet d’échanger des données ou des instructions.
Pour permettre au processeur (ou aux périphériques) de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
Tous les ordinateurs ne sont pas organisés de la même manière, pour ce qui est de leurs bus. Dans les grandes lignes, on peut distinguer deux possibilités : soit l'ordinateur a un seul bus, soit il en a plusieurs.
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
6srqpreoix253n2dmnlbhmk542wgv61
762539
762538
2026-03-30T21:31:01Z
Mewtow
31375
/* Le bus de communication */
762539
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
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. 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 parait alors intéressant d'utiliser trois interconnexions, au minimum CPU-ROM, CPU-RAM et CPU-IO.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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 fils entre 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.
Une autre mutualisation possible est de fusionner le bus mémoire avec les bus pour les entrées-sorties. L'utilité est que les entrées-sorties peuvent aussi 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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
Si l'ordinateur dispose d'un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Il s'agissait de l'organisation 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.
[[File:Computer structure.svg|centre|vignette|upright=2|Bus système basique.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. Le processeur peut communiquer directement avec la mémoire et les entrées-sorties, les périphériques peuvent communiquer avec la mémoire, etc. Il n'y a pas de limitations quant aux échanges de données. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire et entrées-sorties fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
Mais ils ont aussi des désavantages. Par exemple, il é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
===Les bus spécialisés===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a un bus séparé pour la mémoire, 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
pj3342zu93is74kzzj66i0m0nn54dt5
762543
762539
2026-03-30T21:38:35Z
Mewtow
31375
/* Le bus de communication */
762543
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
===Un processeur communique avec la mémoire===
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
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. 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 parait alors intéressant d'utiliser trois interconnexions, au minimum CPU-ROM, CPU-RAM et CPU-IO.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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 fils entre 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.
Une autre mutualisation possible est de fusionner le bus mémoire avec les bus pour les entrées-sorties. L'utilité est que les entrées-sorties peuvent aussi 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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Maintenant que nous savons qui doit échanger avec qui, voyosn comment il est possible d'interconnecter tout ça.
===Les bus systèmes===
La première solution utilise un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. 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. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire RAM, mémoire ROM et entrées-sorties ; fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
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===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
6hqkghwrz8trd9wdpj1m18gzavd7wxm
762544
762543
2026-03-30T21:41:36Z
Mewtow
31375
/* Un processeur communique avec la mémoire */
762544
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Un processeur contient des registres===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
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. 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 parait alors intéressant d'utiliser trois interconnexions, au minimum CPU-ROM, CPU-RAM et CPU-IO.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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 fils entre 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.
Une autre mutualisation possible est de fusionner le bus mémoire avec les bus pour les entrées-sorties. L'utilité est que les entrées-sorties peuvent aussi 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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Maintenant que nous savons qui doit échanger avec qui, voyosn comment il est possible d'interconnecter tout ça.
===Les bus systèmes===
La première solution utilise un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. 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. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire RAM, mémoire ROM et entrées-sorties ; fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
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===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
m55jiib22otuvfdhhfht6dh28eupzps
762546
762544
2026-03-30T21:42:17Z
Mewtow
31375
/* Un processeur contient des registres */
762546
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
===Le processeur effectue des instructions, dont 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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
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. 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 parait alors intéressant d'utiliser trois interconnexions, au minimum CPU-ROM, CPU-RAM et CPU-IO.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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 fils entre 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.
Une autre mutualisation possible est de fusionner le bus mémoire avec les bus pour les entrées-sorties. L'utilité est que les entrées-sorties peuvent aussi 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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Maintenant que nous savons qui doit échanger avec qui, voyosn comment il est possible d'interconnecter tout ça.
===Les bus systèmes===
La première solution utilise un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. 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. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire RAM, mémoire ROM et entrées-sorties ; fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
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===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
sd995eept2ckntwy6sia6lcy166jddw
762547
762546
2026-03-30T21:42:29Z
Mewtow
31375
/* Le processeur */
762547
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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.
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. 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 '''entrées-sorties''' incluent les périphériques, mais aussi d'autres composants comme les cartes d'extensions ou des composants installés sur la carte mère. Les '''cartes d'extension''' sont les composants 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. Mais par simplicité, nous parlerons parfois de périphériques au lieu d'entrées-sorties.
===L'interface avec le reste de l'ordinateur===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
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. 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 parait alors intéressant d'utiliser trois interconnexions, au minimum CPU-ROM, CPU-RAM et CPU-IO.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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 fils entre 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.
Une autre mutualisation possible est de fusionner le bus mémoire avec les bus pour les entrées-sorties. L'utilité est que les entrées-sorties peuvent aussi 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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Maintenant que nous savons qui doit échanger avec qui, voyosn comment il est possible d'interconnecter tout ça.
===Les bus systèmes===
La première solution utilise un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. 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. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire RAM, mémoire ROM et entrées-sorties ; fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
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===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
ez3880qrn831wv96l4v2dht8kx3bwrq
762548
762547
2026-03-30T21:45:21Z
Mewtow
31375
/* Les entrées-sorties */
762548
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|IO mappées en mémoire]]
===Le pilote de périphérique===
Utiliser une entrée/sortie se résume donc à lire ou écrire les valeurs adéquates dans les registres d’interfaçage. Les registres en question ont une adresse, similaire à l'adresse mémoire des RAM/ROM. Les adresses en question ne sont pas forcément mélangées, la relation entre adresses mémoire et adresses de périphériques est compliquée et sera vue dans la suite du chapitre. Communiquer avec une entrée/sortie est similaire à ce qu'on a avec les mémoires, c'est simple : lire ou écrire dans des registres.
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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
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. 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 parait alors intéressant d'utiliser trois interconnexions, au minimum CPU-ROM, CPU-RAM et CPU-IO.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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 fils entre 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.
Une autre mutualisation possible est de fusionner le bus mémoire avec les bus pour les entrées-sorties. L'utilité est que les entrées-sorties peuvent aussi 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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Maintenant que nous savons qui doit échanger avec qui, voyosn comment il est possible d'interconnecter tout ça.
===Les bus systèmes===
La première solution utilise un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. 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. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire RAM, mémoire ROM et entrées-sorties ; fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
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===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
19kz7f5eu3qcaxi6gvj2jpvigyxmxdx
762549
762548
2026-03-30T21:47:48Z
Mewtow
31375
/* Le pilote de périphérique */
762549
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
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. 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 parait alors intéressant d'utiliser trois interconnexions, au minimum CPU-ROM, CPU-RAM et CPU-IO.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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 fils entre 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.
Une autre mutualisation possible est de fusionner le bus mémoire avec les bus pour les entrées-sorties. L'utilité est que les entrées-sorties peuvent aussi 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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Maintenant que nous savons qui doit échanger avec qui, voyosn comment il est possible d'interconnecter tout ça.
===Les bus systèmes===
La première solution utilise un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. 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. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire RAM, mémoire ROM et entrées-sorties ; fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
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===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
6qr7zwklvnmaobq5ikquyc2nbn5r8t0
762550
762549
2026-03-30T21:48:29Z
Mewtow
31375
/* Les adresses des registres d’interfaçage */
762550
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
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. 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 parait alors intéressant d'utiliser trois interconnexions, au minimum CPU-ROM, CPU-RAM et CPU-IO.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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 fils entre 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.
Une autre mutualisation possible est de fusionner le bus mémoire avec les bus pour les entrées-sorties. L'utilité est que les entrées-sorties peuvent aussi 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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Maintenant que nous savons qui doit échanger avec qui, voyosn comment il est possible d'interconnecter tout ça.
===Les bus systèmes===
La première solution utilise un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. 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. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire RAM, mémoire ROM et entrées-sorties ; fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
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===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
nj7388289xa63g053bwupz7rabqfme7
762551
762550
2026-03-30T21:57:39Z
Mewtow
31375
/* Le bus de communication */
762551
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
La première solution utilise un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. 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. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire RAM, mémoire ROM et entrées-sorties ; fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
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===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
810sng81p0zyj9zfcwqe71dcigsbz4n
762553
762551
2026-03-30T22:04:17Z
Mewtow
31375
/* Le réseau d'interconnexion : généralités */
762553
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
La première solution utilise un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. 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. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire RAM, mémoire ROM et entrées-sorties ; fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
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===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
1agfyvomciex8g47rz0mgyexr87gc49
762554
762553
2026-03-30T22:05:08Z
Mewtow
31375
762554
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
La première solution utilise un bus unique, celui-ci est appelé le '''bus système''', aussi appelé ''backplane bus''. Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. 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. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire RAM, mémoire ROM et entrées-sorties ; fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
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===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
m7pdzeo2palbx5m2twjsj7kefywdi3l
762556
762554
2026-03-30T22:06:22Z
Mewtow
31375
/* Les bus systèmes */
762556
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
De tels bus avaient pour avantage la simplicité. 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. Un autre avantage est que le processeur n'est connecté qu'à un seul bus, ce qui utilise peu de broches. Le fait de partager le bus entre mémoire RAM, mémoire ROM et entrées-sorties ; fait qu'on économise des fils. Le câblage est plus simple, la fabrication aussi.
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===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
lcmwkae2rt2nq7nc2874z6ma4n4hvvd
762560
762556
2026-03-30T22:17:21Z
Mewtow
31375
/* Les bus systèmes */
762560
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
Les bus systèmes ont de nombreux problèmes, ce qui fait que beaucoup d'ordinateurs font autrement. A la place d'un bus système unique, ils disposent de plusieurs bus, plus ou moins spécialisés. Nous verrons des exemples de tels systèmes à la fin du chapitre. Pour le moment, citons un exemple assez courant : le cas où on a 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'''.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Les avantages de tels bus sont nombreux. Par exemple, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde, sans trop de problèmes. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. Par contre, cela implique d'avoir des adresses séparées pour les registres d’interfaçage et la mémoire. Pas d'entrée-sortie mappée en mémoire ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la mémoire.
Mais surtout, les bus peuvent être spécialisés et simplifiés. Par exemple, le bus pour les entrées-sorties peut avoir un bus de commande différent de celui de la mémoire, avoir des bus de données de taille différentes, etc. 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 !
Il est aussi possible d'adapter les fréquences de chaque bus. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM. Il est alors possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. Au lieu d'avoir un bus système moyen en vitesse, on a deux bus qui vont chacun à la vitesse adéquate.
Mais il y a d'autres défauts. Par exemple, il faut câbler deux bus distincts sur le processeur. Le nombre de broches nécessaires augmente drastiquement. Et cela peut poser problème si le processeur n'a pas beaucoup de broches à la base. Aussi, les processeurs avec peu de broches utilisent de préférence un bus système, plus simple à câbler. 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. De tels échanges ne sont pas forcément nécessaires, mais les performances s'en ressentent s’ils le sont.
===Les bus avec répartiteur===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
633uu1h064j5i7s0a5s8gn7hlq7eo4y
762561
762560
2026-03-30T22:26:50Z
Mewtow
31375
/* Les bus d'entrées-sorties */
762561
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|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. 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. 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 ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la 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'' !
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
064s4lspy6vx9pokyigvazw3h3vzqxw
762562
762561
2026-03-30T22:32:19Z
Mewtow
31375
/* Les bus d'entrées-sorties */
762562
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de les conflits d'accès au bus entre la mémoire et les entrées/sorties. 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 ! Sans cela, il serait impossible de pouvoir envoyer deux adresses en même temps, une à destination de la mémoire, une autre à destination de la 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'' !
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
0r7wlqzogpu2d5l0x0f8i4rz3dl1t2a
762563
762562
2026-03-30T22:33:40Z
Mewtow
31375
/* Les bus d'entrées-sorties */
762563
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
ov06a5lhkbs9w86sfsh7o68qeobyr22
762565
762563
2026-03-30T22:36:38Z
Mewtow
31375
/* Les bus avec répartiteur */
762565
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe de faire des calculs et de manipuler l'information provenant des entrées-sorties ou récupérée dans la mémoire. Tout ordinateur contient au moins un processeur. Je dis au moins un, car un ordinateur peut avoir plusieurs processeurs.
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'''. Elles se classent en quelques grands types très simples. Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division. Les instructions de test comparent deux nombres entre eux et agissent en fonction. Les instructions d'accès mémoire échangent des données entre la mémoire et le processeur. Et il y en d'autres.
L'important est de retenir qu'un processeur fait beaucoup de 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. Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
L'intérieur d'un processeur contient donc des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
nraim5itwi4no916y14umtk4dm9gtsc
762566
762565
2026-03-30T22:40:26Z
Mewtow
31375
/* Le processeur */
762566
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser les opérandes, le processeur utilise un ou plusieurs '''registres'''. Pour rappel, ce sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Les anciens processeurs utilisaient un registre unique appelé l''''accumulateur''', qui mémorisait la première opérande. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
ie0ryjnphf3owxcf496vl5y5m9ebuki
762567
762566
2026-03-30T22:42:22Z
Mewtow
31375
/* Introduction historique : les processeurs à accumulateur */
762567
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
g3869snllqkc64wsfr9y4eb5ihg712h
762570
762567
2026-03-30T22:43:59Z
Mewtow
31375
/* Introduction historique : les processeurs à accumulateur */
762570
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
Le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
qz9pbx250zb0rmcwcauw85aems69bkc
762571
762570
2026-03-30T22:44:18Z
Mewtow
31375
/* Introduction historique : les processeurs à accumulateur */
762571
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande ou un résultat de calcul. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Par exemple, si une instruction C utilise les résultats des instructions A et B, il est possible de mémoriser les deux résultats dans des registres généraux. Alors qu'avec un accumulateur, on aurait du enregistrer un résultat en RAM pour le relire ensuite. Comme autre exemple, prenons le cas où une opérande est utilisée par plusieurs opérations. Avec un accumulateur, elle devrait être lue en mémoire RAM à chaque opération. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Par exemple, un processeur avec des registres généraux de 8 bits ne peut pas gérer des données plus grandes qu'un octet, sauf en trichant de manière logicielle. De même, un processeur ayant des registres de 32 bits ne peut pas gérer des opérandes de plus de 32 bits, idem pour les résultats ce qui fait que les débordements d'entiers apparaissent quand un résultat dépasse les 32 bits.
Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM).
Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul. Tout cela pour dire qu'il ne faut pas confondre instruction avec opération mathématique, la notion d'instruction est plus large et englobe aussi les accès mémoire. Mais cela sera certainement plus clair quand on verra l'ensemble des instructions que peut gérer un processeur, dans un chapitre dédié.
Maintenant que l'on sait pour l'unité de calcul, les registres et les échanges avec la mémoire, on peut expliquer ce qu'il y a dans un processeur, dans les grandes lignes. L'unité de calcul d'un processeur est associée à des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
ryxbync7zahl5dwkyiie5mx4f5kvq40
762572
762571
2026-03-30T22:56:33Z
Mewtow
31375
/* Les processeurs modernes : les processeurs à registres généraux */
762572
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes en même temps depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", rien de bien compliqué : il suffit de relier les registres à deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement. Nous détaillerons l'intérieur d'un processeur de ce type dans une série de chapitres dédiés.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
aa0lcoxq8c7iabblxsxrppo0am8q4uv
762573
762572
2026-03-30T23:00:34Z
Mewtow
31375
/* Les processeurs modernes : les processeurs à registres généraux */
762573
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. Il faut aussi ajouter des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. L'unité de contrôle lit les instructions en mémoire, puis commande l'unité de calcul, les registres et la mémoire pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
tb1kt6jlfthovwwk6busjr5bhupjie1
762574
762573
2026-03-30T23:02:21Z
Mewtow
31375
/* Les processeurs modernes : les processeurs à registres généraux */
762574
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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 permettre au processeur de 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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
prom97rd67nl1pmd3ntoiu204k865fx
762575
762574
2026-03-30T23:03:14Z
Mewtow
31375
/* Le bus de communication */
762575
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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''' est un ensemble de fils par lequel s'échangent les données entre les composants.
* Le '''bus de commande''' permet au processeur de configurer la mémoire et les entrées-sorties.
* Le '''bus d'adresse''', facultatif, permet au processeur de sélectionner l'entrée, la sortie ou la portion de mémoire avec qui il veut échanger des données.
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
o7w6uo2jfc1kbe18i42527iepgc2f8r
762576
762575
2026-03-30T23:04:05Z
Mewtow
31375
/* Le bus de communication */
762576
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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.
==Le bus de communication==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
Mais pour le moment, laissons de côté le ''Direct Memory Access''. 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 fils entre 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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
Cette mutualisation des bus de la RAM et de la ROM mérite d'être expliqué en détail. Mais nous verrons cela dans la section suivante. Pour le moment, nous allons voir ce qu'il est possible de faire avec les bus 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.
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les architectures Harvard et Von Neumann==
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''. Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
097zr6xdmskaqfjbej6s5e11kguvowh
762577
762576
2026-03-30T23:19:36Z
Mewtow
31375
762577
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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. 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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions a beau être l'avantage majeur des architectures Von Neumann, elle est aussi à 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 le programme exécuté est bugué, le cas le plus courant étant l'exploitation de ces bugs par les pirates informatiques. Il arrive que des pirates informatiques vous fournissent des données corrompues, destinées à être accédées par un programme bugué. Les données corrompues contiennent en fait un virus ou un programme malveillant, caché dans les données. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus. En clair, exécuter des données demande que le processeur ne fasse pas ce qui est demandé ou que le programme exécuté soit bugué. Pour éviter cela, le système d'exploitation fournit des mécanismes de protection pour éviter cela. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Nous avons vu plus haut que les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées. Il y a des architectures où cette séparation est nette et sans bavures. Mais d'autres ne respectent pas cette séparation à dessin. Cela permet de faire la différence entre les architectures Harvard où la séparation entre données et instructions est stricte, des architectures Von Neumann où données et instructions sont traitées de la même façon par le processeur.
Sur les architectures Harvard, la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Le bus de communication==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. Il est plus ou moins complexe suivant l'ordinateur. Dans le cas le plus intuitif, il y a trois interconnexions : CPU-ROM, CPU-RAM et CPU-IO.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
brinkhprq7c8bj25vbb3po5tcsd017r
762578
762577
2026-03-30T23:27:32Z
Mewtow
31375
/* Les architectures Harvard et Von Neumann */
762578
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre. Des mécanismes de décodage d'adresse garantissent 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é.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. 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.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions est cependant à 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 le programme exécuté est bugué, et que 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. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus.
Pour éviter cela, le système d'exploitation fournit des mécanismes de protection mémoire. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Un point important d'un ordinateur est la séparation entre données et instructions. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. En théorie, les données sont censées être placées en mémoire RAM, alors que les instructions sont placées en mémoire ROM. En fait, les choses sont plus compliquées.
Sur les architecture Harvard, cette séparation est nette et sans bavures : la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail. Par exemple, on pourrait imaginer le cas où le programme est stocké sous forme compressée dans la mémoire ROM, et est décompressé pour être exécuté en mémoire RWM. Le programme de décompression est lui aussi 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Le bus de communication==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. Il est plus ou moins complexe suivant l'ordinateur. Dans le cas le plus intuitif, il y a trois interconnexions : CPU-ROM, CPU-RAM et CPU-IO.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
nivyxbqtbu3rj213g92i5srad751zfu
762579
762578
2026-03-30T23:32:20Z
Mewtow
31375
/* L'architecture Harvard modifiée */
762579
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre. Des mécanismes de décodage d'adresse garantissent 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é.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. 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.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 recopié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.
L'impossibilité de séparer données et instructions est cependant à 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 le programme exécuté est bugué, et que 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. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus.
Pour éviter cela, le système d'exploitation fournit des mécanismes de protection mémoire. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
Sur les architectures Von Neumann, il est possible de copier des programmes et de les exécuter dans la RAM. Par exemple, on pourrait imaginer le cas 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). Mais un cas d'utilisation bien plus familier est celui de votre ordinateur personnel, comme nous le verrons plus bas.
===L'architecture Harvard modifiée===
Depuis le début de ce chapitre, nous sont partis du principe que les données sont en mémoire RAM, et que les instructions sont en mémoire ROM. En fait, les choses sont plus compliquées. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Sur les architecture Harvard, cette séparation est nette et sans bavures : la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Le bus de communication==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. Il est plus ou moins complexe suivant l'ordinateur. Dans le cas le plus intuitif, il y a trois interconnexions : CPU-ROM, CPU-RAM et CPU-IO.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
6zqilwoxgtvy823tt6jwh3o0dg6hbig
762580
762579
2026-03-30T23:33:58Z
Mewtow
31375
/* L'architecture Von Neumann */
762580
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre. Des mécanismes de décodage d'adresse garantissent 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é.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. 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.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 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).
L'impossibilité de séparer données et instructions est cependant à 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 le programme exécuté est bugué, et que 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. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus.
Pour éviter cela, le système d'exploitation fournit des mécanismes de protection mémoire. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Depuis le début de ce chapitre, nous sont partis du principe que les données sont en mémoire RAM, et que les instructions sont en mémoire ROM. En fait, les choses sont plus compliquées. Dans ce qui va suivre, nous allons faire la distinction entre la '''mémoire programme''', qui stocke les programmes à exécuter, et la '''mémoire travail''' qui mémorise des variables nécessaires au fonctionnement des programmes. Sur les architecture Harvard, cette séparation est nette et sans bavures : la mémoire ROM est une mémoire programme, alors que la mémoire RWM est une mémoire travail. À l’opposé, les architectures Von Neumann permettent de copier des programmes et de les exécuter dans la RAM. La mémoire RWM sert alors en partie de mémoire programme, en partie de mémoire travail.
[[File:Répartition des données et du programme entre la ROM et les RWM.png|centre|vignette|upright=3|Répartition des données et du programme entre la ROM et les RWM.]]
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures ne suivent pas à la lettre les critères des architectures Harvard et Von Neumann et mélangent les deux, et sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. On peut par exemple imaginer une architecture où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. On peut aussi imaginer le cas où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes.
Prenons le premier cas, où les adresses sont partagées, mais où les voies d'accès aux instructions et aux données sont séparées. C'est le cas sur les ordinateurs personnels modernes, où programmes et données sont stockés dans la même mémoire comme dans l'architecture Von Neumann. Cependant, les voies d'accès aux instructions et aux données ne sont pas les mêmes au-delà d'un certain point. La séparation se fait au niveau de la mémoire intégrée dans le processeur, la fameuse mémoire cache dont nous parlerons dans le prochain chapitre. Aussi, nous repartons les explications sur ces architectures dans le chapitre suivant, nous n’avons pas le choix que de faire ainsi.
Le deuxième type d'architecture Harvard modifiée est celle où les voies d'accès aux données et instructions sont les mêmes, mais les adresses différentes. Concrètement, cela ne signifie pas qu'il n'y a qu'un seul bus, mais que des mécanismes sont prévus pour que les deux bus d’instruction et de données interagissent et échangent des informations. Et là, on en trouve deux types.
Le cas le plus simple d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Là où les architectures précédentes pouvaient lire des données en ROM et en RWM, mais chargent leurs instructions depuis la ROM seulement, d'autres architectures font l'inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Le bus de communication==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. Il est plus ou moins complexe suivant l'ordinateur. Dans le cas le plus intuitif, il y a trois interconnexions : CPU-ROM, CPU-RAM et CPU-IO.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
kpojrq9vf0jpgqc8r0dxbxdtqgtd3dt
762581
762580
2026-03-30T23:43:59Z
Mewtow
31375
/* L'architecture Harvard modifiée */
762581
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre. Des mécanismes de décodage d'adresse garantissent 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é.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. 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.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 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).
L'impossibilité de séparer données et instructions est cependant à 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 le programme exécuté est bugué, et que 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. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus.
Pour éviter cela, le système d'exploitation fournit des mécanismes de protection mémoire. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. Par exemple, on pourrait avoir des adresses partagées, mais des voies d'accès séparées pour les instructions et les données. Mais un tel exemple implique que le processeur intègre des mémoires caches, que nous n'avons pas encore vu pour le moment. Aussi nous allons les passer sous silence.
Le deuxième type d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM. Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Le bus de communication==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. Il est plus ou moins complexe suivant l'ordinateur. Dans le cas le plus intuitif, il y a trois interconnexions : CPU-ROM, CPU-RAM et CPU-IO.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
eh01e4w9a5fw2q8jhtq2cv4um9zzjub
762582
762581
2026-03-30T23:44:14Z
Mewtow
31375
/* L'architecture Harvard modifiée */
762582
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre. Des mécanismes de décodage d'adresse garantissent 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é.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. 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.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 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).
L'impossibilité de séparer données et instructions est cependant à 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 le programme exécuté est bugué, et que 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. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus.
Pour éviter cela, le système d'exploitation fournit des mécanismes de protection mémoire. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Pour rappel, les architectures Harvard et Von neumman se distinguent sur deux points :
* Les adresses pour la mémoire ROM (le programme) et la mémoire RAM (les données) sont séparées sur les architectures Harvard, partagées sur l’architecture Von Neumann.
* L'accès aux données et instructions se font par des voies séparées sur l'architecture Harvard, sur le même bus avec l'architecture Von Neumann.
Les deux points sont certes reliés, mais on peut cependant les décorréler. Par exemple, on pourrait avoir des adresses partagées, mais des voies d'accès séparées pour les instructions et les données. Mais un tel exemple implique que le processeur intègre des mémoires caches, que nous n'avons pas encore vu pour le moment. Aussi nous allons les passer sous silence.
Le deuxième type d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM.
Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Le bus de communication==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. Il est plus ou moins complexe suivant l'ordinateur. Dans le cas le plus intuitif, il y a trois interconnexions : CPU-ROM, CPU-RAM et CPU-IO.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
g22q4x3finkwfeiceo1hwnmmgthgogl
762583
762582
2026-03-30T23:50:58Z
Mewtow
31375
/* L'architecture Harvard modifiée */
762583
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre. Des mécanismes de décodage d'adresse garantissent 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é.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. 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.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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 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).
L'impossibilité de séparer données et instructions est cependant à 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 le programme exécuté est bugué, et que 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. Le bug en question permet justement à ces données d'être exécutées, ce qui exécute le virus.
Pour éviter cela, le système d'exploitation fournit des mécanismes de protection mémoire. Par exemple, il 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.
Il existe cependant des cas très rares où un programme informatique est volontairement codé pour exécuter des données. Par exemple, cela permet de créer des programmes qui modifient leurs propres instructions : cela s'appelle du '''code auto-modifiant'''. Ce genre de choses servait autrefois à écrire certains programmes sur des ordinateurs rudimentaires, pour gérer des tableaux et autres fonctionnalités de base utilisées par les programmeurs. Au tout début de l'informatique, où 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 recopier le programme dans la mémoire RWM et corriger les adresses au besoin. De nos jours, ces techniques peuvent être utilisées occasionnellement pour compresser un programme, le cacher et le rendre indétectable dans la mémoire (les virus informatiques utilisent beaucoup ce genre de procédés). Mais passons !
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Précisons que la différence entre architectures Harvard pures et modifiées n'est pas bien cernée, actuellement. La terminologie n'est pas claire, beaucoup d'auteurs mettent des définitions différentes derrière ces deux termes. Par exemple, il est parfois dit que les processeurs avec un cache d'instruction séparé du cache de données sont des architectures Harvard modifiée. Mais dans ce cours, nous utiliserons une définition très stricte de ce qu'est une architecture Harvard modifiée.
Le premier type d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM.
Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Le bus de communication==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. Il est plus ou moins complexe suivant l'ordinateur. Dans le cas le plus intuitif, il y a trois interconnexions : CPU-ROM, CPU-RAM et CPU-IO.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
g1n8etm62vcv4c80tvbtou69bmkx630
762584
762583
2026-03-31T00:06:46Z
Mewtow
31375
/* L'architecture Von Neumann */
762584
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre. Des mécanismes de décodage d'adresse garantissent 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é.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. 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.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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.
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Précisons que la différence entre architectures Harvard pures et modifiées n'est pas bien cernée, actuellement. La terminologie n'est pas claire, beaucoup d'auteurs mettent des définitions différentes derrière ces deux termes. Par exemple, il est parfois dit que les processeurs avec un cache d'instruction séparé du cache de données sont des architectures Harvard modifiée. Mais dans ce cours, nous utiliserons une définition très stricte de ce qu'est une architecture Harvard modifiée.
Le premier type d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM.
Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Le bus de communication==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. Il est plus ou moins complexe suivant l'ordinateur. Dans le cas le plus intuitif, il y a trois interconnexions : CPU-ROM, CPU-RAM et CPU-IO.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
tqmmdi6vhby09azcwyj6gknrpvsahfi
762585
762584
2026-03-31T00:07:15Z
Mewtow
31375
/* Le bus de communication */
762585
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre. Des mécanismes de décodage d'adresse garantissent 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é.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. 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.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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.
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Précisons que la différence entre architectures Harvard pures et modifiées n'est pas bien cernée, actuellement. La terminologie n'est pas claire, beaucoup d'auteurs mettent des définitions différentes derrière ces deux termes. Par exemple, il est parfois dit que les processeurs avec un cache d'instruction séparé du cache de données sont des architectures Harvard modifiée. Mais dans ce cours, nous utiliserons une définition très stricte de ce qu'est une architecture Harvard modifiée.
Le premier type d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM.
Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Le bus de communication avec les entrées-sorties==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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. Il est plus ou moins complexe suivant l'ordinateur. Dans le cas le plus intuitif, il y a trois interconnexions : CPU-ROM, CPU-RAM et CPU-IO.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
hwry7l2phlyy2c0xm2htejruwz1c6rq
762586
762585
2026-03-31T00:08:16Z
Mewtow
31375
/* Le réseau d'interconnexion : généralités */
762586
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre. Des mécanismes de décodage d'adresse garantissent 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é.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. 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.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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.
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Précisons que la différence entre architectures Harvard pures et modifiées n'est pas bien cernée, actuellement. La terminologie n'est pas claire, beaucoup d'auteurs mettent des définitions différentes derrière ces deux termes. Par exemple, il est parfois dit que les processeurs avec un cache d'instruction séparé du cache de données sont des architectures Harvard modifiée. Mais dans ce cours, nous utiliserons une définition très stricte de ce qu'est une architecture Harvard modifiée.
Le premier type d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM.
Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Le bus de communication avec les entrées-sorties==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
1gotaih7nba835eiddth858sc18rtk2
762587
762586
2026-03-31T00:10:15Z
Mewtow
31375
/* Le réseau d'interconnexion : généralités */
762587
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre. Des mécanismes de décodage d'adresse garantissent 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é.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. 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.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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.
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Précisons que la différence entre architectures Harvard pures et modifiées n'est pas bien cernée, actuellement. La terminologie n'est pas claire, beaucoup d'auteurs mettent des définitions différentes derrière ces deux termes. Par exemple, il est parfois dit que les processeurs avec un cache d'instruction séparé du cache de données sont des architectures Harvard modifiée. Mais dans ce cours, nous utiliserons une définition très stricte de ce qu'est une architecture Harvard modifiée.
Le premier type d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM.
Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Le bus de communication avec les entrées-sorties==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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.
{|
|[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec une architecture Harvard.]]
|[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec 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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
gynug6zsq2k8yrcpc66bnozf4y5av5b
762588
762587
2026-03-31T00:10:37Z
Mewtow
31375
/* Le réseau d'interconnexion : généralités */
762588
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre. Des mécanismes de décodage d'adresse garantissent 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é.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. 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.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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.
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Précisons que la différence entre architectures Harvard pures et modifiées n'est pas bien cernée, actuellement. La terminologie n'est pas claire, beaucoup d'auteurs mettent des définitions différentes derrière ces deux termes. Par exemple, il est parfois dit que les processeurs avec un cache d'instruction séparé du cache de données sont des architectures Harvard modifiée. Mais dans ce cours, nous utiliserons une définition très stricte de ce qu'est une architecture Harvard modifiée.
Le premier type d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM.
Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
D'autres architectures font l’inverse. Il leur est possible d’exécuter des instructions peut importe qu'elles viennent de la ROM ou de la RAM. Par contre, quand les instructions sont exécutées depuis la mémoire RAM, les performances s'en ressentent, car on ne peut plus accéder à une donnée en même temps qu'on charge une instruction.
==Le bus de communication avec les entrées-sorties==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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.
{|
|[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec une architecture Harvard.]]
|[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
ouzb2yogiyvz5txabvhsl0f47fwxuab
762589
762588
2026-03-31T00:18:49Z
Mewtow
31375
/* L'architecture Harvard modifiée */
762589
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre. Des mécanismes de décodage d'adresse garantissent 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é.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. 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.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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.
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Précisons que la différence entre architectures Harvard pures et modifiées n'est pas bien cernée, actuellement. La terminologie n'est pas claire, beaucoup d'auteurs mettent des définitions différentes derrière ces deux termes. Par exemple, il est parfois dit que les processeurs avec un cache d'instruction séparé du cache de données sont des architectures Harvard modifiée. Mais dans ce cours, nous utiliserons une définition très stricte de ce qu'est une architecture Harvard modifiée.
Le premier type d'architecture Harvard modifiée est une architecture Harvard, où le processeur peut lire des données constantes depuis la mémoire ROM. Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM.
Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
==Le bus de communication avec les entrées-sorties==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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.
{|
|[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec une architecture Harvard.]]
|[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
fajtj6mbsdn26ep8kqknsqhz3ive8pk
762590
762589
2026-03-31T00:24:08Z
Mewtow
31375
/* L'architecture Harvard modifiée */
762590
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre. Des mécanismes de décodage d'adresse garantissent 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é.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. 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.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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.
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Précisons que la différence entre architectures Harvard pures et modifiées n'est pas bien cernée, actuellement. La terminologie n'est pas claire, beaucoup d'auteurs mettent des définitions différentes derrière ces deux termes. Par exemple, il est parfois dit que les processeurs avec un cache d'instruction séparé du cache de données sont des architectures Harvard modifiée. 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, alors que les architectures Harvard modifiées le permettent.
Vu que les adresses des données et des instructions sont séparées, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM.
Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
==Le bus de communication avec les entrées-sorties==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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.
{|
|[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec une architecture Harvard.]]
|[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
dmhdxu0xl435b7q9p118kbnbvw6vieh
762591
762590
2026-03-31T00:24:27Z
Mewtow
31375
/* L'architecture Harvard modifiée */
762591
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
Dans les ordinateurs, l'unité de traitement porte le nom de '''processeur''', ou encore de '''''Central Processing Unit''''', abrévié en CPU. Un processeur est un circuit qui s'occupe 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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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'''. Elles se classent en quelques grands types, dont les trois principaux sont les suivants :
* Les instructions arithmétiques font des calculs, comme l'addition, la soustractions, la multiplication, la division.
* Les instructions d'accès mémoire échangent des données entre la mémoire RAM et le processeur.
* Les instructions de test comparent deux nombres entre eux et agissent en fonction.
Les autres instructions ne sont pas très intuitives, aussi passons-les sous silence pour le moment, nous n'aurons besoin de les comprendre que dans la section du cours sur le processeur.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre. Des mécanismes de décodage d'adresse garantissent 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é.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. 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.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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.
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Précisons que la différence entre architectures Harvard pures et modifiées n'est pas bien cernée, actuellement. La terminologie n'est pas claire, beaucoup d'auteurs mettent des définitions différentes derrière ces deux termes. Par exemple, il est parfois dit que les processeurs avec un cache d'instruction séparé du cache de données sont des architectures Harvard modifiée. 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, alors que les architectures Harvard modifiées le permettent.
Pour cela, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM.
Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
==Le bus de communication avec les entrées-sorties==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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.
{|
|[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec une architecture Harvard.]]
|[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
glh78bwk86ijx0dnt6rbq7y8wj9jcya
762592
762591
2026-03-31T01:45:34Z
Mewtow
31375
/* Le processeur */
762592
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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 soustractions, la multiplication, la division. On peut aussi citer les instructions d'accès mémoire, qui échangent des données entre la mémoire RAM et le processeur, qu'on détaillera dans ce qui suit. 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.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Le problème est que les mémoires RAM ne peuvent faire qu'un seul accès à la fois. Elles ne peuvent pas lire deux opérandes à la fois.
: Pour être plus précis, il existe des mémoires RAM qui sont capables de faire plusieurs accès mémoire à la fois. Mais ce sont des mémoires SRAM, qui sont presque toujours intégrées dans les processeurs. Elles servent pour les registres ou le cache, pas pour la RAM principale de l'ordinateur. le problème demeure, donc.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre. Des mécanismes de décodage d'adresse garantissent 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é.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. 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.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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.
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Précisons que la différence entre architectures Harvard pures et modifiées n'est pas bien cernée, actuellement. La terminologie n'est pas claire, beaucoup d'auteurs mettent des définitions différentes derrière ces deux termes. Par exemple, il est parfois dit que les processeurs avec un cache d'instruction séparé du cache de données sont des architectures Harvard modifiée. 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, alors que les architectures Harvard modifiées le permettent.
Pour cela, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM.
Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
==Le bus de communication avec les entrées-sorties==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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.
{|
|[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec une architecture Harvard.]]
|[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
q4rkz3afco9zf98bk7f9xgk2s1snttp
762593
762592
2026-03-31T01:46:26Z
Mewtow
31375
/* Introduction historique : les processeurs à accumulateur */
762593
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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 soustractions, la multiplication, la division. On peut aussi citer les instructions d'accès mémoire, qui échangent des données entre la mémoire RAM et le processeur, qu'on détaillera dans ce qui suit. 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.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Mais les mémoires RAM ne peuvent faire qu'un seul accès à la fois, ce qui implique qu'elles ne peuvent pas lire deux opérandes à la fois.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre. Des mécanismes de décodage d'adresse garantissent 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é.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. 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.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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.
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Précisons que la différence entre architectures Harvard pures et modifiées n'est pas bien cernée, actuellement. La terminologie n'est pas claire, beaucoup d'auteurs mettent des définitions différentes derrière ces deux termes. Par exemple, il est parfois dit que les processeurs avec un cache d'instruction séparé du cache de données sont des architectures Harvard modifiée. 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, alors que les architectures Harvard modifiées le permettent.
Pour cela, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM.
Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
==Le bus de communication avec les entrées-sorties==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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.
{|
|[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec une architecture Harvard.]]
|[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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, des systèmes d'exploitation sur des 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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
dwlcq0ims1jio02tanlubt2lu3m3bvp
762594
762593
2026-03-31T01:48:21Z
Mewtow
31375
/* Étude de quelques exemples d'architectures */
762594
wikitext
text/x-wiki
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.
[[File:Architecture Von Neumann.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
==La mémoire==
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.
{|class="wikitable"
|+ 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===
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.
{|class="wikitable"
|-
!Préfixe!!Capacité mémoire en octets!!Puissance de deux
|-
||Kio||1024||2<sup>10</sup> octets
|-
||Mio||1 048 576||2<sup>20</sup> octets
|-
||Gio||1 073 741 824||2<sup>30</sup> 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===
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.
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===
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.
[[File:Adressage mémoire.png|centre|vignette|upright=2|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.
[[File:CPT-System-Architecture-gapfill1-ANS.svg|centre|vignette|upright=2|Architecture avec une ROM et une RAM.]]
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre]]
===L'alignement mémoire : introduction===
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.
==Le processeur==
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.
L'intérieur d'un processeur contient des circuits de calcul qui 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é. Il s'agit de la même unité de calcul qu'on trouve dans le 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.
Mais 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 soustractions, la multiplication, la division. On peut aussi citer les instructions d'accès mémoire, qui échangent des données entre la mémoire RAM et le processeur, qu'on détaillera dans ce qui suit. 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.
===Introduction historique : les processeurs à accumulateur===
Si le processeur fait des calculs, qu'en est-il des opérandes ? La solution la plus simple serait de lire les opérandes dans la mémoire RAM, puis d'enregistrer le résultat là aussi en RAM. Cependant, bien qu'intuitive, cette solution a un gros problème. La majorité des opérations, comme l'addition ou la multiplication ont deux opérandes. Elles sont dites ''dyadiques''. Pour les exécuter, le processeur doit lire deux opérandes en même temps, puis écrire le résultat. Mais les mémoires RAM ne peuvent faire qu'un seul accès à la fois, ce qui implique qu'elles ne peuvent pas lire deux opérandes à la fois.
[[File:Isaccumulator.png|vignette|Processeur avec un accumulateur.]]
Il y a donc un problème qu'il faut résoudre. Et il n'a pas 36 solutions, le seul moyen de le résoudre est de lire les deux opérandes l'une après l'autre, quitte à mémoriser une opérande dans le processeur. Pour mémoriser l'opérande, le processeur utilise un registre unique appelé l''''accumulateur'''. La seconde opérande était lue depuis la mémoire RAM, et le résultat était mémorisé dans le registre accumulateur. Les instructions de calcul ne faisaient ainsi qu'un seul accès à la mémoire RAM, par opération. Elles étaient conçues pour lire la première opérande depuis l'accumulateur, et la seconde opérande dans la mémoire RAM.
: Pour rappel, les '''registres''' sont de petites mémoires très rapides et de faible capacité, capables de mémoriser un nombre.
En plus des instructions de calcul, le processeur a des instructions pour échanger des données entre la mémoire RAM et l'accumulateur. Les échanges de données peuvent se faire dans les deux sens : lecture comme écriture. Dans le cas le plus simple, le processeur a une instruction pour la lecture et une autre instruction pour l'écriture. L'instruction de lecture s'appelle LOAD, elle copie une donnée de la RAM dans l'accumulateur, elle lit une adresse mémoire. L'instruction d'écriture s'appelle STORE, elle copie le contenu de l'accumulateur en mémoire RAM, à une adresse mémoire précisée par l'instruction.
L'intérieur d'un processeur à accumulateur est relativement simple. Il y a une unité de calcul, le registre accumulateur, et l'unité de contrôle qui commande tout le reste. Le tout est relié comme indiqué ci-dessous. L'accumulateur est relié à l'unité de calcul, mais aussi à la mémoire RAM (pour les instructions LOAD et STORE). L'unité de contrôle reçoit une instruction, lue depuis la mémoire ROM, et configure le processeur pour qu'il exécute cette instruction. Il configure l'unité de calcul pour qu'elle fasse le calcul voulu, en lui envoyant le code opération adéquat. Il configure aussi le bus mémoire, et notamment le bus d'adresse. Et ce que ce soit pour les instructions LOAD et STORE, que les instructions arithmétiques. Pour les instructions arithmétiques, c'est pour lire la seconde opérande.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
De telles architectures étaient très simples, faciles à concevoir, et marchaient bien à une époque où la mémoire était rapide et les registres couteux à produire. Mais elles sont devenues plus confidentielles, de nos jours. La raison est que les processeurs ont évolués pour accueillir plus de registres.
===Les processeurs modernes : les processeurs à registres généraux===
Les architectures à accumulateur sont une bonne solution pour gérer les instructions dyadiques, tout en lisant qu'une opérande à la fois. Par contre, elles sont particulièrement limitées. De nombreux accès mémoires pourraient être évités si on disposait de plus de registres.
Par exemple, prenons le calcul suivant : A * B + C * D. Le processeur doit alors faire les deux multiplications, et les additionner. Le problème est que le résultat de la première multiplication doit être enregistré en mémoire RAM, pour être relu lors de l'addition finale. Si on avait un second registre accumulateur, on aurait pu éviter d'enregistrer le résultat de la première multiplication, pour le relire ensuite.
Comme autre exemple, si une opérande est utilisée par deux ou trois instructions, les architectures à accumulateur imposent de la lire plusieurs fois, une fois par instruction. Si on disposait d'un second ou troisième accumulateur, voire d'un troisième, on pourrait éviter ça. Et les exemples de ce type sont vraiment nombreux. En soi, rien de bien grave, mais les performances ne sont pas terribles. Le processeur est alors très dépendant de la performance de la mémoire RAM.
[[File:Isreg2reg.png|vignette|Processeur avec des registres généraux.]]
Pour éviter ces problèmes, les processeurs modernes disposent de plusieurs '''registres généraux''', chacun mémorisant un opérande. Les opérations lisent leurs opérandes depuis les registres et enregistrent leur résultat dans les registres. Notons qu'il est parfaitement possible de lire deux opérandes depuis les registres, ce n'est pas un problème. Les registres sont même l'idéal pour ça.
L'avantage est que cela réduit beaucoup les lectures en mémoire RAM. Si je reprend l'exemple de l'opération A * B + C * D, on élimine totalement les accès mémoire. Les deux multiplications enregistrent leurs résultats dans des registres généraux, la troisième lit ces deux registres. Pas besoin d'enregistrer un résultat en RAM pour le relire ensuite. Et il en est de même pour l'autre exemple précédent, celui avec une opérande utilisée par plusieurs opérations. Avec des registres généraux, elle est lue/copiée dans les registres une seule fois, et les différentes opérations utiliseront la copie dans les registres.
Les registres ne serviraient pas à grand chose si on ne pouvait pas échanger des données entre registres et mémoire RAM. Pour cela, un processeur incorpore souvent des instructions pour copier des données provenant de la mémoire RAM dans un registre, et des instructions qui font l'inverse (d'un registre vers la mémoire). Les instructions en question sont appelées LOAD (copie RAM vers registre) et STORE (copie registre vers RAM). Les échanges de données entre RAM et registres sont fréquents, les instructions LOAD et STORE sont tout aussi importantes que les instructions de calcul.
La capacité des registres généraux détermine la taille des données manipulée par le processeur. Au tout début de l'informatique, il n'était pas rare de voir des registres généraux de 3, 4, voire 8 bits. Par la suite, la taille de ces registres a augmenté, passant rapidement de 16 à 32 bits, voire 48 bits sur certaines processeurs spécialisés. De nos jours, les processeurs des PC utilisent des registres de 64 bits, même s'il existe toujours des processeurs de faible performance avec des registres relativement petits, de 8 à 16 bits.
Voyons maintenant l'intérieur d'un processeur à registres généraux. Il contient une unité de calcul, des registres et une interface de communication avec la mémoire RAM. Le tout est interconnecté, afin de pouvoir échanger des données. L'esnemble 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 des circuits pour commander le tout, qui sont regroupés dans l'unité de contrôle. Elle lit les instructions en mémoire, puis commande le chemin de données pour que l'instruction soit exécutée correctement.
[[File:Microarchitecture d'un processeur.png|centre|vignette|upright=2|Microarchitecture d'un processeur]]
Un point important est qu'il y a plusieurs registres généraux, au lieu d'un accumulateur unique. Les registres sont regroupés dans un circuit unique, appelé le '''banc de registres'''. Pour ceux qui se rappellent du chapitre "Les registres et mémoires adressables", nous avons déjà vu comment créer un banc de registre. Rien de bien compliqué : il suffit de relier les registres à un multiplexeur et un démultiplexeur. Le multiplexeur permet de sélectionner quel registre lire, le démultiplexeur sélectionne le registre à écrire. Si on souhaite lire deux registres à la fois, il suffit de rajouter un second multiplexeur. Au final, on a deux multiplexeurs, un par sortie de lecture, un par entrée de l'unité de calcul. Les multiplexeurs et le démultiplexeur sont commandés par l'unité de contrôle, afin de sélectionner les registres adéquats.
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
===Le processeur exécute un programme, une suite d'opérations===
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. La totalité des logiciels présents sur un ordinateur sont des programmes comme les autres. Un programme est stocké dans la mémoire de l'ordinateur, comme les données : sous la forme de suites de bits. 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.
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. 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.
{|class="wikitable"
|+ 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. Le processeur mémorise l'adresse de la prochaine instruction dans un registre spécialisé appelé '''Program Counter'''. Cette adresse qui permet de localiser la prochaine instruction en mémoire. Cette adresse ne sort pas de nulle part : on peut la déduire de l'adresse de l'instruction en cours d’exécution assez simplement. Il suffit de prendre l'adresse de l'instruction en cours, et en ajoutant la longueur de l'instruction (le nombre de case mémoire qu'elle occupe). En clair, il suffit d'incrémenter le ''program counter'' de la longueur de l'instruction. Le ''program counter'' fait partie de l'unité de contrôle.
Mais sur d'autres processeurs, chaque instruction précise l'adresse de la suivante. Ces processeurs n'ont pas besoin de calculer une adresse qui leur est fournie sur un plateau d'argent. Sur de tels processeurs, chaque instruction précise quelle est la prochaine instruction, directement dans la suite de bit représentant l'instruction en mémoire. 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 des registres pour les données, mais aussi un ''program counter''. Le ''program counter'' est à part, dans le sens où il ne mémorise pas de données. D'ailleurs, il fait partie de l'unité de contrôle. 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'''. Ils sont intégrés dans l'unité de contrôle et ne sont pas relié aux unités de calcul, contrairement aux autres registres. 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.
===Un ordinateur peut avoir plusieurs processeurs===
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.
[[File:Architecture de Von Neumann Princeton multi processeurs.svg|centre|vignette|upright=2|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===
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.
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.
[[File:Asmp 2.gif|centre|vignette|upright=2|Co-processeur pour l'accès aux entrées-sorties.]]
Les '''coprocesseurs arithmétiques''' sont un peu à part des autres. Ils permettent de faire certains calculs que le processeur ne peut pas faire. Les plus connus d'entre eux étaient utilisés pour implémenter les calculs en virgule flottante, à une époque où les CPU de l'époque 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.
Les coprocesseurs arithmétiques étaient optionnels et il était parfaitement possible de monter un PC qui n'en avait pas. En conséquence, les programmeurs devaient coder des programmes qui peuvent fonctionner avec et sans co-processeur. La solution la plus simple était de fournir deux versions du logiciel : une sans usage du coprocesseur, et une autre qui en fait usage, plus rapide. Sans ces coprocesseurs, les calculs flottants étaient émulés en logiciel, par des fonctions et libraires spécialisées, très lentes. Certaines applications conçues pour le coprocesseur étaient capables d'en tirer profit : des logiciels de conception assistée par ordinateur, par exemple. Ils sont aujourd'hui tombés en désuétude, depuis que les CPU sont devenus capables de faire des calculs sur des nombres flottants.
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 co-processeurs arithmétiques se distinguent des autres car ils fonctionnent en tandem avec le processeur principal, pas en parallèle. Les co-processeurs précédents sont autonomes, à savoir qu'ils exécutent un programme différent de celui exécuté par le CPU. Mais les co-processeurs arithmétiques ne sont pas dans ce cas. Il n'y a qu'un seul programme à exécuter, qui contient des instructions à destination du CPU, d'autres à destination du co-processeur. Les instructions sont exécutées soit par le CPU, soit par le co-processeur, une par une.
==Les entrées-sorties==
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===
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.
[[File:Registres d'interfaçage.png|centre|vignette|upright=2|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===
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.
[[File:Espaces d'adressages séparés entre mémoire et périphérique.png|centre|vignette|upright=2.5|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.
[[File:IO mappées en mémoire.png|centre|vignette|upright=2.0|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==
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.
[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre et une architecture Harvard]]
===L'architecture Harvard===
Avec l''''architecture Harvard''', la mémoire ROM et la mémoire RAM sont reliées au processeur par deux bus séparés. 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.
[[File:Harvard Architecture.png|centre|vignette|upright=2|Architecture Harvard, avec une ROM et une RAM séparées.]]
Sur ces architectures, le processeur voit bien deux mémoires séparées avec leur lot d'adresses distinctes.
[[File:Vision de la mémoire par un processeur sur une architecture Harvard.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Harvard.]]
Sur ces architectures, 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.
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 aussi 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é. Les deux mémoires communiquent donc avec deux portions séparées du processeur : le chemin de données pour la RAM, l'unité de contrôle pour la ROM.
[[File:Architecture Harvard - échanges de données.png|centre|vignette|upright=2|Architecture Harvard - échanges de données]]
===L'architecture Von Neumann===
Avec l''''architecture Von Neumann''', mémoire ROM et mémoire RAM sont reliées au processeur par un bus unique. Quand une adresse est envoyée sur le bus, les deux mémoires vont la recevoir mais une seule va répondre. Des mécanismes de décodage d'adresse garantissent 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é.
[[File:Architecture Von Neumann, avec deux bus séparés.png|centre|vignette|upright=2|Architecture Von Neumann, avec deux bus séparés.]]
Avec l'architecture Von Neumann, tout se passe comme si les deux mémoires étaient fusionnées en une seule mémoire. 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.
[[File:Vision de la mémoire par un processeur sur une architecture Von Neumann.png|centre|vignette|upright=2|Vision de la mémoire par un processeur sur une architecture Von Neumann.]]
Une particularité de ces architectures est qu'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.
===L'architecture Harvard modifiée===
Les architectures Von Neumann et Harvard sont des cas purs, qui sont encore très utilisés dans des microcontrôleurs ou des DSP (processeurs de traitement de signal). Mais quelques architectures sont des sortes d'intermédiaires entre les deux. De telles architectures sont appelées des '''architectures Harvard modifiée'''.
Précisons que la différence entre architectures Harvard pures et modifiées n'est pas bien cernée, actuellement. La terminologie n'est pas claire, beaucoup d'auteurs mettent des définitions différentes derrière ces deux termes. Par exemple, il est parfois dit que les processeurs avec un cache d'instruction séparé du cache de données sont des architectures Harvard modifiée. 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, alors que les architectures Harvard modifiées le permettent.
Pour cela, le processeur doit disposer 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. Ce n'est pas le cas sur les architectures Harvard, où la lecture des données en ROM est interdite, ni sur les architectures Von Neumann, où la lecture des données se fait avec une unique instruction qui peut lire n'importe quelle adresse aussi bien en ROM qu'en RAM.
Une autre possibilité est que le processeur copie ces données constantes depuis la mémoire ROM dans la mémoire RAM, au lancement du programme, avec des instructions adaptées.
[[File:Organisation des espaces d'adressage sur une archi harvard modifiée.png|centre|vignette|upright=3|Organisation des espaces d'adressage sur une archi harvard modifiée]]
==Le bus de communication avec les entrées-sorties==
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.
[[File:Bus general schematic.svg|centre|vignette|upright=2|Contenu d'un bus, généralités.]]
===Le réseau d'interconnexion : généralités===
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.
{|
|[[File:Réseau d'interconnexion avec un processeur au centre.png|centre|vignette|upright=2|Réseau d'interconnexion avec une architecture Harvard.]]
|[[File:Réseau d'interconnexion avec un processeur au centre et une architecture Harvard.png|centre|vignette|upright=2|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.
[[File:Réseau d'interconnexion avec un processeur au centre, et direct memory access.png|centre|vignette|upright=2|Réseau d'interconnexion avec un processeur au centre, et direct memory access]]
===Les bus systèmes===
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.
[[File:Architecture minimale d'un ordinateur.png|centre|vignette|upright=2|Architecture minimale d'un ordinateur.]]
Un bus système contient un bus d'adresse, de données et de commande. 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. En théorie, un bus système se marie bien avec des entrées-sorties mappées en mémoire. Il y a moyen d'implémenter un système d'adresse séparés avec, mais c'est pas l'idéal.
[[File:Architecture Von Neumann avec les bus.png|centre|vignette|upright=2|Architecture Von Neumann avec les bus.]]
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. Mais surtout, 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.
[[File:Bus système avec controleur DMA.png|centre|vignette|upright=2|Bus système avec contrôleur DMA.]]
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===
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.
[[File:Bus mémoire séparé du bus pour les IO.png|centre|vignette|upright=2|Bus mémoire séparé du bus pour les IO]]
Niveau performances, le processeur peut accéder à la mémoire en attendant qu'une entrée/sortie réponde. Et cela implique qu'il n'y a plus de conflits d'accès au bus, du moins plus de conflits entre mémoire et les entrées/sorties. 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 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.
De plus, il est aussi possible d'avoir un bus mémoire ultra-rapide et qui fonctionne à haute fréquence, pendant que le bus pour les entrées-sorties est un bus moins rapide. En effet, les entrées-sorties sont souvent plus lentes que la mémoire RAM, ce qui fait qu'elles tolèrent des fréquences bien plus basses.
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===
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.
[[File:IO mappées en mémoire avec séparation des bus.png|centre|vignette|upright=2|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.
[[File:Implémentation du DMA avec un répartiteur.png|centre|vignette|upright=2|Implémentation du DMA avec un répartiteur]]
==Les microcontrôleurs et ''system on chip''==
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.
[[File:ARMSoCBlockDiagram.svg|centre|vignette|upright=2|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===
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é.
[[File:Microcontroller 8051.gif|centre|vignette|upright=2.5|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===
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.
[[File:Phone hardware.png|centre|vignette|upright=2|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.
[[File:GPS tracker Hardware Architecture.png|centre|vignette|upright=2|Hardware d'un tracker GPS.]]
==Étude de quelques exemples d'architectures==
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===
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.
[[File:Architecture de la PC Engine, aussi appelée TurboGrafx-16.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la NES.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la SNES.png|centre|vignette|upright=2|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===
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. Elle intègre deux processeurs : un CPU Motorola 68000, et un co-processeur audio Z80. 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. Mais ici, il est utilisé comme co-processeur audio, sans doute car 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 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''.
[[File:Architecture de la Megadrive et de la Néogeo.png|centre|vignette|upright=2.5|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===
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.
[[File:Architecture de la Playstation.png|centre|vignette|upright=2.5|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.
[[File:Playstation 2 architecture.png|centre|vignette|upright=2.5|Playstation 2 architecture]]
==L'architecture des PC et son évolution==
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===
[[File:IBM PC XT 02.jpg|vignette|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.
[[File:XT Bus pins.svg|vignette|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 :
* 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'' ;
* des circuits inconnus à ce stade du cours, à savoir :
** un contrôleur de bus Intel 8288 pour gérer le bus XT ;
** un contrôleur d'interruption 8259 et un contrôleur DMA 8273 ;
** un contrôleur parallèle 8255 ;
* un paquet de multiplexeurs, de portes logiques et de registres (''latches'' et ''flip-flop'').
Les multiplexeurs, registres et portes logiques, sont liées au fait que plusieurs RAM sont combinées 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, mais cela demande d'ajouter des circuits pour. Et pareil pour la RAM : il y a entre 8 et 32 circuits intégrés, chacun étant une mémoire DRAM. Elles sont toutes combinées de manière à donner une seule RAM de 16 à 64 kibioctets. Là encore, cela demande d'ajouter des circuits sur la carte mère pour.
[[File:IBM 5150 Motherboard.svg|centre|vignette|upright=3|Carte mère de l'IBM 5150, un modèle de l'IBM PC.]]
===L'architecture d'un IBM PC compatible 16 bits===
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.
[[File:ISA Bus pins.svg|vignette|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.
[[File:Architecture de l'IBM PC compatible.png|centre|vignette|upright=2.5|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
[[File:Architecture de l'IBM PC compatible avec bridge ISA.png|centre|vignette|upright=2.5|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===
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''.
[[File:Acculogic sIDE-4 Controller ISA.jpg|centre|vignette|upright=2|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.
[[File:Ajout des ports IDE sur la carte mère.png|centre|vignette|upright=2|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.
[[File:ATA Plug.svg|centre|vignette|upright=2|Connecteur ATA.]]
[[File:ATA cables.jpg|centre|vignette|upright=2|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.
[[File:ATA-Konfiguration02.png|centre|vignette|upright=2|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.
[[File:HDD Master and Slave Description.jpg|centre|vignette|upright=2|Configuration ''Master/Slave''.]]
===L'architecture d'un PC avec un processeur Intel 486===
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.
[[File:Architecture d'un PC utilisant un bus PCI, implémentation avec un répartiteur.png|centre|vignette|upright=2|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.
[[File:Architecture de l'IBM PC compatible avec pont PCI.png|centre|vignette|upright=2|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.
[[File:Intel486-Typ PCI System.png|centre|vignette|upright=2|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.
[[File:ISA Bridge schematic.png|centre|vignette|upright=2|ISA Bridge.]]
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'interface électrique entre circuits intégrés et bus
| prevText=L'interface électrique entre circuits intégrés et bus
| next=La hiérarchie mémoire
| nextText=La hiérarchie mémoire
}}
</noinclude>
gs0fagc56bl3j72ee11gdudsyusu5r7
Mathc initiation/c34a4
0
76356
762555
736100
2026-03-30T22:05:32Z
Xhungab
23827
762555
wikitext
text/x-wiki
[[Catégorie:Mathc initiation (livre)]]
[[Mathc initiation/Fichiers h : c50a1| Sommaire]]
Installer et compiler ces fichiers dans votre répertoire de travail.
{{Fichier|c00b.c|largeur=70%|info=|icon=Crystal128-source-c.svg}}
<syntaxhighlight lang="c">
/* ---------------------------------- */
/* save as c00b.c */
/* ---------------------------------- */
#include "x_afile.h"
#include "fb.h"
/* ---------------------------------- */
int main(void)
{
clrscrn();
printf(" g : (x,y)-> %s\n\n", geq);
printf(" v : (y)-> %s \n", veq);
printf(" u : (y)-> %s\n\n", ueq);
printf(" b = %+.1f\n a = %+.1f\n\n\n",b,a);
printf(" Find the surface area for the given functions\n");
printf(" with the simpson's rule.\n\n\n");
printf(" (b (v(y)\n");
printf(" int( int( sqrt(g_x()**2 + g_y()**2 + 1) dxdy = %.3f\n",
S_dxdy(g, u,v,LOOP, a,b,LOOP));
printf(" (a (u(y)\n\n\n");
printf("\n\n Press return to continue.\n");
getchar();
return 0;
}
/* ---------------------------------- */
/* ---------------------------------- */
</syntaxhighlight>
'''Exemple de sortie écran :'''
<syntaxhighlight lang="C">
g : (x,y)-> x**2 + y
v : (y)-> 1
u : (y)-> 0
b = +1.0
a = -1.0
Find the surface area for the given functions
with the simpson's rule.
(b (v(y)
int( int( sqrt(g_x()**2 + g_y()**2 + 1) dxdy = 3.596
(a (u(y)
Press return to continue.
</syntaxhighlight>
'''Exemple de sortie écran :'''
<syntaxhighlight lang="C">
Verify with maple
> restart:
>
> g := (x,y)->x^2+y:
> Int(
> Int(
>
> sqrt( diff(g(x,y),x)^2 + diff(g(x,y),y)^2 + 1),
>
> x = 0 .. 1),
> y = -1 .. 1);
1 1
/ /
| | 2
| | sqrt(4 x + 2) dx dy
| |
/ /
-1 0
> evalf(value(%));
>
3.595705578
</syntaxhighlight>
----
{{AutoCat}}
jkn22myods0qgs3po0fx4zrd5uk3u9u
Mathc initiation/Fichiers h : c46a5
0
76559
762540
713769
2026-03-30T21:32:20Z
Xhungab
23827
762540
wikitext
text/x-wiki
[[Catégorie:Mathc initiation (livre)]]
[[Mathc initiation/Fichiers h : c50a1| Sommaire]]
Installer ce fichier dans votre répertoire de travail.
{{Fichier|x_afile.h|largeur=70%|info=|icon=Crystal Clear mimetype source h.png}}
<syntaxhighlight lang="c">
/* ---------------------------------- */
/* save as x_afile.h */
/* ---------------------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <math.h>
#include <string.h>
/* ---------------------------------- */
#include "x_def.h"
#include "x_strcp.h"
/* ---------------------------------- */
#include "x_fxy.h"
#include "x_sdxy.h"
#include "x_sdyx.h"
/* ---------------------------------- */
/* ---------------------------------- */
</syntaxhighlight>
{{AutoCat}}
hb5edxf0cm2sqcu9gyjkb27ur4jrysb
Mathc initiation/Fichiers h : c46a6
0
76560
762541
713770
2026-03-30T21:35:54Z
Xhungab
23827
762541
wikitext
text/x-wiki
[[Catégorie:Mathc initiation (livre)]]
[[Mathc initiation/Fichiers h : c50a1| Sommaire]]
Installer ce fichier dans votre répertoire de travail.
{{Fichier|x_sdxy.h|largeur=70%|info=|icon=Crystal Clear mimetype source h.png}}
<syntaxhighlight lang="c">
/* ---------------------------------- */
/* save as x_sdxy.h */
/* ---------------------------------- */
double Sint_dxy(
double (*P_g)(double x, double y),
double (*P_u)(double y),
double (*P_v)(double y),
int nx,
double y
)
{
pt2d p;
int i = 0;
double m = 0.;
double M = 0.;
for(i = 0; i <= nx; i++)
{
if(i ==0 || i== nx){m = 1.;}
else if(fmod(i,2) == 0 ){m = 2.;}
else {m = 4.;}
p.x = ((*P_u)(y)) + i*(((*P_v)(y))-((*P_u)(y)))/nx;
p.y = y;
M += m * ( sqrt(pow(fxy_x((*P_g),H,p),2) +
pow(fxy_y((*P_g),H,p),2) +
1));
}
return( ((((*P_v)(y)) -((*P_u)(y)))*M) / (3*nx) );
}
/* ---------------------------------- */
double S_dxdy(
double (*P_g)(double x, double y),
double (*P_u)(double y),
double (*P_v)(double y),
int nx,
double ay,
double by,
int ny
)
{
int i = 0;
double m = 0.;
double M = 0.;
for(i = 0; i <= ny; i++)
{
if(i ==0 || i== ny){m = 1.;}
else if(fmod(i,2) == 0){m = 2.;}
else {m = 4.;}
M += m * Sint_dxy( (*P_g),
(*P_u),(*P_v), nx,
(ay + i*(by-ay)/ny));
}
return( ((by -ay)*M) / (3*ny) );
}
/* ---------------------------------- */
/* ---------------------------------- */
</syntaxhighlight>
{{AutoCat}}
ad4g843b3a5quve90j9g65wvlqs087x
Mathc initiation/Fichiers h : c46a7
0
76561
762542
713771
2026-03-30T21:37:24Z
Xhungab
23827
762542
wikitext
text/x-wiki
[[Catégorie:Mathc initiation (livre)]]
[[Mathc initiation/Fichiers h : c50a1| Sommaire]]
Installer ce fichier dans votre répertoire de travail.
{{Fichier|x_sdyx.h|largeur=70%|info=|icon=Crystal Clear mimetype source h.png}}
<syntaxhighlight lang="c">
/* ---------------------------------- */
/* save as x_sdyx.h */
/* ---------------------------------- */
double Sint_dyx(
double (*P_g)(double x, double y),
double (*P_u)(double x),
double (*P_v)(double x),
int ny,
double x
)
{
pt2d p;
int i = 0;
double m = 0.;
double M = 0.;
for(i = 0; i <= ny; i++)
{
if(i ==0 || i== ny){m = 1.;}
else if(fmod(i,2) == 0){m = 2.;}
else {m = 4.;}
p.y = ((*P_u)(x)) + i*(((*P_v)(x))-((*P_u)(x)))/ny;
p.x = x;
M += m * ( sqrt( pow(fxy_x((*P_g),H,p),2) +
pow(fxy_y((*P_g),H,p),2) +
1));
}
return( ((((*P_v)(x)) -((*P_u)(x)))*M) / (3*ny) );
}
/* ---------------------------------- */
double S_dydx(
double (*P_g)(double x, double y),
double (*P_u)(double x),
double (*P_v)(double x),
int ny,
double ax,
double bx,
int nx
)
{
int i = 0;
double m = 0.;
double M = 0.;
for(i = 0; i <= nx; i++)
{
if(i ==0 || i== nx){m = 1.;}
else if(fmod(i,2) == 0){m = 2.;}
else {m = 4.;}
M += m * Sint_dyx( (*P_g),
(*P_u),(*P_v),ny,
(ax + i*(bx-ax)/nx));
}
return( ((bx -ax)*M) / (3*nx) );
}
/* ---------------------------------- */
/* ---------------------------------- */
</syntaxhighlight>
{{AutoCat}}
ebixinrqhqvew7nbb7udwp4bhsobr42
Mathc initiation/Fichiers h : c50a5
0
76615
762557
736226
2026-03-30T22:07:05Z
Xhungab
23827
762557
wikitext
text/x-wiki
[[Catégorie:Mathc initiation (livre)]]
[[Mathc initiation/Fichiers h : c50a1| Sommaire]]
Installer et compiler ces fichiers dans votre répertoire de travail.
{{Fichier|c00c.c|largeur=70%|info=|icon=Crystal128-source-c.svg}}
<syntaxhighlight lang="c">
/* ---------------------------------- */
/* save as c00c.c */
/* ---------------------------------- */
#include "x_afile.h"
#include "fc.h"
/* ---------------------------------- */
int main(void)
{
clrscrn();
printf(" g : (x,y)-> %s\n\n", geq);
printf(" v : (x)-> %s \n", veq);
printf(" u : (x)-> %s\n\n", ueq);
printf(" b = %+.1f\n a = %+.1f\n\n\n",b,a);
printf(" Find the surface area for the given functions\n");
printf(" with the simpson's rule.\n\n\n");
printf(" (b (v(x)\n");
printf(" int( int( sqrt(g_x()**2 + g_y()**2 + 1) dydx = %.3f\n",
S_dydx(g, u,v,LOOP, a,b,LOOP));
printf(" (a (u(x)\n\n\n");
printf("\n\n Press return to continue.\n");
getchar();
return 0;
}
/* ---------------------------------- */
/* ---------------------------------- */
</syntaxhighlight>
'''Exemple de sortie écran :'''
<syntaxhighlight lang="C">
g : (x,y)-> 4-x**2-y**2
v : (x)-> sqrt(4-x**2)
u : (x)-> 0
b = +2.0
a = +0.0
Find the surface area for the given functions
with the simpson's rule.
(b (v(x)
int( int( sqrt(g_x()**2 + g_y()**2 + 1) dydx = 9.044
(a (u(x)
Press return to continue.
</syntaxhighlight>
'''Exemple de sortie écran :'''
<syntaxhighlight lang="C">
Verify with maple
restart:
g := (x,y)->4-x^2-y^2:
Int(
Int(
sqrt( diff(g(x,y),x)^2 + diff(g(x,y),y)^2 + 1),
y = 0 .. sqrt(4-x^2)),
x = 0 .. 2);
2
2 sqrt(4 - x )
/ /
| | 2 2
| | sqrt(4 x + 4 y + 1) dy dx
| |
/ /
0 0
evalf(value(%));
9.044225799
</syntaxhighlight>
----
{{AutoCat}}
t3brqhnifn1pxnl6wyglf9n7y29eq5b
Mathc initiation/Fichiers h : c50a6
0
76616
762558
736227
2026-03-30T22:08:46Z
Xhungab
23827
762558
wikitext
text/x-wiki
[[Catégorie:Mathc initiation (livre)]]
[[Mathc initiation/Fichiers h : c50a1| Sommaire]]
Installer et compiler ces fichiers dans votre répertoire de travail.
{{Fichier|c00d.c|largeur=70%|info=|icon=Crystal128-source-c.svg}}
<syntaxhighlight lang="c">
/* ---------------------------------- */
/* save as c00d.c */
/* ---------------------------------- */
#include "x_afile.h"
#include "fd.h"
/* ---------------------------------- */
int main(void)
{
clrscrn();
printf(" g : (x,y)-> %s\n\n", geq);
printf(" v : (x)-> %s \n", veq);
printf(" u : (x)-> %s\n\n", ueq);
printf(" b = %+.1f\n a = %+.1f\n\n\n",b,a);
printf(" Find the surface area for the given functions\n");
printf(" with the simpson's rule.\n\n\n");
printf(" (b (v(x)\n");
printf(" int( int( sqrt(g_x()**2 + g_y()**2 + 1) dydx = %.3f\n",
S_dydx(g, u,v,LOOP, a,b,LOOP));
printf(" (a (u(x)\n\n\n");
printf("\n\n Press return to continue.\n");
getchar();
return 0;
}
/* ---------------------------------- */
/* ---------------------------------- */
</syntaxhighlight>
'''Exemple de sortie écran :'''
<syntaxhighlight lang="C">
g : (x,y)-> y + 1./2.*x**2
v : (x)-> 1
u : (x)-> 0
b = +1.0
a = +0.0
Find the surface area for the given functions
with the simpson's rule.
(b (v(x)
int( int( sqrt(g_x()**2 + g_y()**2 + 1) dydx = 1.525
(a (u(x)
Press return to continue.
</syntaxhighlight>
'''Exemple de sortie écran :'''
<syntaxhighlight lang="C">
Verify with maple
> restart:
>
> g := (x,y)->y+(x^2)/2:
> Int(
> Int(
>
> sqrt( diff(g(x,y),x)^2 + diff(g(x,y),y)^2 + 1),
>
> y = 0 .. 1),
> x = 0 .. 1);
1 1
/ /
| | 2
| | sqrt(x + 2) dy dx
| |
/ /
0 0
> evalf(value(%));
>
1.524504352
</syntaxhighlight>
----
{{AutoCat}}
p2k80xpn9mzzd8krm8t5g5zlzii3y6q
Mathc initiation/Fichiers h : c59ad
0
76726
762552
736270
2026-03-30T22:04:09Z
Xhungab
23827
762552
wikitext
text/x-wiki
[[Catégorie:Mathc initiation (livre)]]
[[Mathc initiation/Fichiers h : c50a1| Sommaire]]
Installer et compiler ces fichiers dans votre répertoire de travail.
{{Fichier|c00a.c|largeur=70%|info=|icon=Crystal128-source-c.svg}}
<syntaxhighlight lang="c">
/* ---------------------------------- */
/* save as c00a.c */
/* ---------------------------------- */
#include "x_afile.h"
#include "fa.h"
/* ---------------------------------- */
int main(void)
{
clrscrn();
printf(" g : (x,y)-> %s\n\n", geq);
printf(" v : (y)-> %s \n", veq);
printf(" u : (y)-> %s\n\n", ueq);
printf(" b = %+.1f\n a = %+.1f\n\n\n",b,a);
printf(" Find the surface area for the given functions\n");
printf(" with the simpson's rule.\n\n\n");
printf(" (b (v(y)\n");
printf(" int( int( sqrt(g_x()**2 + g_y()**2 + 1) dxdy = %.3f\n",
S_dxdy(g, u,v,LOOP, a,b,LOOP));
printf(" (a (u(y)\n\n\n");
printf("\n\n Press return to continue.\n");
getchar();
return 0;
}
/* ---------------------------------- */
/* ---------------------------------- */
</syntaxhighlight>
'''Exemple de sortie écran :'''
<syntaxhighlight lang="C">
g : (x,y)-> 3.*x + y**2
v : (y)-> y
u : (y)-> 0
b = +1.0
a = +0.0
Find the surface area for the given functions
with the simpson's rule.
(b (v(y)
int( int( sqrt(g_x()**2 + g_y()**2 + 1) dxdy = 1.730
(a (u(y)
Press return to continue.
</syntaxhighlight>
'''Exemple de sortie écran :'''
<syntaxhighlight lang="C">
Verify with maple
restart:
g := (x,y)->3*x+y^2:
Int(
Int(
sqrt( diff(g(x,y),x)^2 + diff(g(x,y),y)^2 + 1),
x = 0 .. y),
y = 0 .. 1);
1 y
/ /
| | 2
| | sqrt(10 + 4 y ) dx dy
| |
/ /
0 0
evalf(value(%));
1.730035569
</syntaxhighlight>
----
{{AutoCat}}
0vaovz10ayrz83ub3nki0qejbntqi8c
Mathc initiation/Fichiers h : c65a5
0
76823
762545
715338
2026-03-30T21:41:39Z
Xhungab
23827
762545
wikitext
text/x-wiki
[[Catégorie:Mathc initiation (livre)]]
[[Mathc initiation/Fichiers h : c50a1| Sommaire]]
Installer ce fichier dans votre répertoire de travail.
{| class="wikitable"
|+ Texte de la légende
|-
|
{{Fichier|fa.h|largeur=70%|info=|icon=Crystal Clear mimetype source h.png}}
<syntaxhighlight lang="c">
/* ---------------------------------- */
/* save as fa.h */
/* ---------------------------------- */
#define LOOP 2*100
/* ---------------------------------- */
double g(
double x,
double y)
{
return( (3.*x + y*y) );
}
char geq[] = "3.*x + y**2";
/* ---------------------------------- */
/* ---------------------------------- */
double v(
double y)
{
return( (y) );
}
char veq[] = "y";
/* ---------------------------------- */
double u(
double y)
{
return( (0) );
}
char ueq[] = "0";
/* ---------------------------------- */
/* ---------------------------------- */
double b = 1.; char beq[] = "1";
double a = 0.; char aeq[] = "0";
/* ---------------------------------- */
/* ---------------------------------- */
</syntaxhighlight>
||
{{Fichier|fb.h|largeur=70%|info=|icon=Crystal Clear mimetype source h.png}}
<syntaxhighlight lang="c">
/* ---------------------------------- */
/* save as fb.h */
/* ---------------------------------- */
#define LOOP 2*100
/* ---------------------------------- */
double g(
double x,
double y)
{
return( (x*x + y) );
}
char geq[] = "x**2 + y";
/* ---------------------------------- */
/* ---------------------------------- */
double v(
double y)
{
return( (1) );
}
char veq[] = "1";
/* ---------------------------------- */
double u(
double y)
{
return( (0) );
}
char ueq[] = "0";
/* ---------------------------------- */
/* ---------------------------------- */
double b = +1.; char beq[] = "+1";
double a = -1.; char aeq[] = "-1";
/* ---------------------------------- */
/* ---------------------------------- */
</syntaxhighlight>
|-
|
{{Fichier|fc.h|largeur=70%|info=|icon=Crystal Clear mimetype source h.png}}
<syntaxhighlight lang="c">
/* ---------------------------------- */
/* save as fc.h */
/* ---------------------------------- */
#define LOOP 2*100
/* ---------------------------------- */
double g(
double x,
double y)
{
return( (4-x*x-y*y) );
}
char geq[] = "4-x**2-y**2";
/* ---------------------------------- */
/* ---------------------------------- */
double v(
double x)
{
return( sqrt(4-x*x) );
}
char veq[] = "sqrt(4-x**2)";
/* ---------------------------------- */
double u(
double x)
{
return( ( 0) );
}
char ueq[] = "0";
/* ---------------------------------- */
/* ---------------------------------- */
double b = 2.; char beq[] = "2";
double a = 0.; char aeq[] = "0";
/* ---------------------------------- */
/* ---------------------------------- */
</syntaxhighlight>
||
{{Fichier|fd.h|largeur=70%|info=|icon=Crystal Clear mimetype source h.png}}
<syntaxhighlight lang="c">
/* ---------------------------------- */
/* save as fd.h */
/* ---------------------------------- */
#define LOOP 2*100
/* ---------------------------------- */
double g(
double x,
double y)
{
return( (y + 1./2.*x*x) );
}
char geq[] = "y + 1./2.*x**2";
/* ---------------------------------- */
/* ---------------------------------- */
double v(
double x)
{
return( 1 );
}
char veq[] = "1";
/* ---------------------------------- */
double u(
double x)
{
return( (0) );
}
char ueq[] = "0";
/* ---------------------------------- */
/* ---------------------------------- */
double b = 1.; char beq[] = "1";
double a = 0.; char aeq[] = "0";
/* ---------------------------------- */
/* ---------------------------------- */
</syntaxhighlight>
|-
|
||
|}
{{AutoCat}}
h857x7farj2avzay98vl23c56bssown
Fonctionnement d'un ordinateur/Les registres et mémoires adressables
0
78078
762512
733928
2026-03-30T15:30:47Z
Mewtow
31375
/* Une utilisation des registres : les mémoires SRAM */
762512
wikitext
text/x-wiki
Dans les chapitres précédents, nous avons vu comment mémoriser un bit, dans une bascule. Mais les bascules en elles-mêmes sont rarement utiles seules, car les données à mémoriser font généralement plusieurs bits, pas un seul. Stocker plusieurs bits est la raison d'être des '''registres''', des composants qui mémorisent des plusieurs bits, que l'on peut modifier et/ou récupérer plus tard. Il existe plusieurs types de registres, et nous allons faire la distinction entre les registres simples et les registres à décalage. Les registres simples sont capables de mémoriser un nombre, de taille fixe, rien de plus. Les registres à décalage sont des registres simples améliorés, capables de faire quelques petites opérations sur leur contenu.
==Les registres simples==
Les '''registres simples''' sont capables de mémoriser un nombre, codé sur une quantité fixe de bits. On peut à tout moment récupérer le nombre mémorisé dans le registre : on dit alors qu'on effectue une lecture. On peut aussi mettre à jour le nombre mémorisé dans le registre, le remplacer par un autre : on dit qu'on effectue une écriture. Les seules opérations possibles sur ces registres sont la lecture (récupérer le nombre mémorisé dans le registre) et l'écriture (mettre à jour le nombre mémorisé dans le registre, le remplacer par un autre).
===L'interface d'un registre simple===
[[File:4 Bit Data Register.svg|vignette|Registre de 4 Bits. On voit que celui-ci contient 4 entrées (à gauche), et 4 sorties (à droite). On peut aussi remarquer une entrée CLK, qui joue le rôle d'entrée d'autorisation.]]
Niveau entrées et sorties, les registres possèdent des entrées-sorties pour les données mémorisées, mais aussi des entrées-sorties de commande. Les entrées-sorties pour les données permettent de lire le contenu du registre ou d'y écrire. Les entrées de commande permettent de configurer le registre pour lui ordonner de faire une écriture, pour le remettre à zéro, ou toute autre opération.
Les entrées de données sont utilisées pour l'écriture, alors que les sorties de données servent pour la lecture. Le nombre mémorisé dans le registre est disponible sur les sorties du registre. Pour utiliser les entrées d'écriture, on envoie le nombre à mémoriser (celui qui remplacera le contenu du registre) sur les entrées d'écriture et on configure les entrées de commande adéquates.
Les entrées de commande varient suivant le registre, mais on trouve au moins une entrée Enable, qui a le même rôle que pour une bascule, à savoir autoriser une écriture. Si l'entrée Enable est à 1, le registre mémorise ce qu'il y a sur l'entrée de donnée. Mais si l'entrée Enable est à 0, le registre n'est pas mis à jour : on peut mettre n'importe quelle valeur sur les entrées, le registre n'en tiendra pas compte et ne remplacera pas son contenu par ce qu'il y a sur l'entrée. Pour résumer, l'entrée Enable sert donc à indiquer au registre si son contenu doit être mis à jour, quand une écriture a lieu.
D'autres entrées de commandes sont parfois présentes, la plus commune étant une entrée permettant de remettre à zéro le registre. La présence d'un 1 sur cette entrée remet à zéro le contenu du registre, à savoir que celui-ci contient la valeur zéro.
Enfin, il faut distinguer les registres synchrones des registres asynchrones. Les '''registres synchrones''' sont reliés au signal d’horloge. Pour cela, ils disposent d'une entrée d'horloge sur laquelle on envoie le signal d'horloge. Ils ne sont mis à jour que si on présente un front montant sur l'entrée d'horloge. Les '''registres asynchrones''' ne sont pas reliés au signal d'horloge et sont mis à jour quand on envoie ce qu'il faut sur leur entré Enable, rien de plus.
===L'intérieur d'un registre simple===
Un registre est composé de plusieurs bascules D qui sont toutes mises à jour en même temps. Cela vaut aussi bien pour les registres asynchrones que les registres synchrones. Pour cela, toutes les entrées E des bascules sont reliées à l'entrée de commande Enable. De plus, les registre synchrones envoient le signal d'horloge sur toutes les bascules. Avec un registre synchrone, toutes les bascules sont des bascules synchrones, qui ont toutes une entrée d'horloge, relié au signal d'horloge.
[[File:Register.svg|centre|vignette|upright=3|Registre.]]
==Les registres à décalage==
Les '''registres à décalage''' sont des registres dont le contenu est décalé d'un cran vers la gauche ou la droite sur commande. Nous aurons à les réutiliser plus tard dans ce cours, notamment dans la section sur les circuits de génération de nombres aléatoires, ou dans certains circuits liés au cache. Les registres à décalage sont presque tous synchrones et ce chapitre ne parlera que ce ces derniers. L'animation suivante illustre le fonctionnement d'un registre à décalage qui décale son contenu d'un cran vers la droite à chaque cycle d'horloge.
[[File:4-Bit PISO Shift Register Seq.gif|centre|vignette|upright=2|Registre à décalage.]]
===La classification des registres===
On peut classer les registres selon le caractère de l'entrée et de la sortie, qui peut être parallèle (entrée de plusieurs bits) ou série (entrée d'un seul bit).
* Sur les registres simples, les entrées et sorties pour les données sont toujours parallèles. Pour un registre de N bits, il y a une entrée d'écriture de N bits et une sortie de N bits. C'est la raison pour laquelle ils sont appelés des '''registres à entrées et sorties parallèles'''.
* Sur les registres à '''entrée et sortie série''', on peut mettre à jour un bit à la fois, de même qu'on ne peut en récupérer qu'un à la fois. Ces registres servent essentiellement à mettre en attente des bits tout en gardant leur ordre : un bit envoyé en entrée ressortira sur la sortie après plusieurs commandes de mise à jour sur l'entrée Enable.
* Les registres à décalage à '''entrée série et sortie parallèle''' sont similaires aux précédents : on peut ajouter un nouveau bit en commandant l'entrée Enable et les anciens bits sont alors décalés d'un cran. Par contre, on peut récupérer (lire) tous les bits en une seule fois. Ils permettent notamment de reconstituer un nombre qui est envoyé bit par bit sur un fil (un bus série).
* Enfin, il reste les registres à '''entrée parallèle et sortie série'''. Ces registres sont utiles quand on veut transmettre un nombre sur un fil : on peut ainsi envoyer les bits un par un.
[[File:Td5bfig1.png|centre|vignette|upright=2|Classification des registres à décalage.]]
Pour résumer, on distingue quatre types de registres (à décalage ou non), qui portent les noms de PIPO, PISO, SIPO et SISO. Les noms peuvent sembler barbares, mais il y a une logique derrière ces termes.La lettre P est pour parallèle, la lettre S est pour série. La lettre I signifie ''Input'', ce qui veut dire entrée en anglais, la lettre O est pour ''Output'', la sortie en anglais.
{|class="wikitable"
|+ Classification des registres
|-
!
! Entrée parallèle
! Entrée série
|-
! Sortie parallèle
| PIPO (registre simple)
| SIPO
|-
! Sortie série
| PISO
| SISO
|}
===L'intérieur d'un registre à décalage===
Tous les registres sont conçus en plaçant plusieurs bascules les unes à la suite des autres, que ce soit pour les registres simples ou les registres à décalage. La seule différence tient dans la manière dont les bascules sont reliées. Toutes les bascules sont reliées à l'entrée d'horloge, l'entrée Enable, l'entrée Reset, ou aux autres entrées de commandes. Mais c'est une autre paire de manche pour les entrées/sorties de données.
Dans un registre simple, les bascules sont indépendantes et ne sont pas reliées entre elles.
[[File:Register.svg|centre|vignette|upright=3|Registre simple.]]
À l'inverse, dans les registres à décalage, il existe des connexions entre bascules. Plus précisément, les bascules sont reliées les unes à la suite des autres, elles forment une chaîne de bascules reliées deux à deux. Et les connexions entre bascules sont les mêmes que l'on parle d'un registre à décalage de type SIPO, PISO ou SISO.
[[File:Shift-Register.svg|centre|vignette|upright=3|Exemple de registre à décalage]]
Outre le fait que les bascules sont reliées de la même manière, les autres connexions sont les mêmes dans tous les registres. L'entrée d'horloge (non-représentée dans les schémas qui vont suivre) est envoyée à toutes les bascules. Même chose pour l'entrée Enable, qui est reliée aux entrées E de toutes les bascules. La différence entre ces registres tient dans les endroits où se trouvent les entrées et les sorties du registre.
{|
|+ Implémentation des registres avec des bascules.
|-
|[[File:Registre à entrée parallèle et sortie série.png|vignette|upright=2|Registre à entrée et sortie série.]]
|[[File:Registre à lecture et écriture parallèle.png|vignette|upright=2|Registre à entrée et sortie parallèle.]]
|-
|[[File:Registre à entrée et sortie série.png|vignette|upright=2|Registre à entrée série et sortie parallèle.]]
|[[File:Registre à entrée série et sortie parallèle.png|vignette|upright=2|Registre à entrée parallèle et sortie série.]]
|}
==Une utilisation des registres : les bancs de registre==
Maintenant que nous avons les registres, il est temps d'en montrer une utilisation assez intéressante. Nous allons combiner les registres avec des multiplexeurs/démultiplexeurs pour former une '''mémoire adressable'''. Plus précisément, nous allons voir les '''bancs de registre''', qui peuvent être vu comme un rassemblement de plusieurs registres. Mais ces registres ne sont pas assemblés pour obtenir un registre plus gros : par exemple, on peut fabriquer un registre de 32 bits à partir de 2 registres de 16 bits, ou de 4 registres de 8 bits. Ce n'est pas ce qui est fait sur les mémoires adressables, où les registres sont regroupés de manière à ce qu'il soit possible de sélectionner le registre qu'on veut consulter ou modifier.
Pour préciser le registre à sélectionner, chacun d'entre eux se voit attribuer un nombre : l''''adresse'''. 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 registres d'une mémoire adressable. Il existe des mémoires qui ne fonctionnent pas sur ce principe, mais passons : ce sera pour la suite.
[[File:Adressage mémoire.png|centre|vignette|upright=2|Exemple : on demande à la mémoire de sélectionner le byte d'adresse 1002 et on récupère son contenu (ici, 17).]]
===L'intérieur d'un banc de registre===
Un banc de registre peut se fabriquer assez simplement : il suffit d'un ou de plusieurs multiplexeurs et de registres. Quand on présente l'adresse sur l'entrée de sélection du multiplexeur, celui-ci va connecter le registre demandé à la sortie (ou à l'entrée).
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
Voici ce que cela donne avec une RAM reliée à un bus de 1 bit, à savoir que chaque case mémoire ne contient que 1 bit, il y a un bit par adresse. Il s'agit d'un exemple bien trop simple pour avoir la moindre application pratique, mais c'est un exemple clairement pédagogique. L'entrée d'écriture est reliée à toutes les bascules, mais seule celle sélectionnée est écrite. Lors d'une lecture, l'adresse est envoyée au multiplexeur et la donnée lue sur sa sortie. Lors d'une écriture, c'est le démultiplexeur/décodeur qui est utilisé. Le décodeur active la bascule voulue, via son entrée d'horloge ou Enable. Le bit R/W précise qu'il faut effectuer une écriture. L'entrée d'écriture est alors recopiée dans la bascule sélectionnée.
[[File:MemWrite.png|centre|vignette|upright=2|Intérieur d'une RAM de 4 bits, reliée à un bus de 1 bit, fabriquée avec des registres et des multiplexeurs.]]
===L'interface d'un banc de registre===
[[File:RAM 8x4 symbol.svg|vignette|Interface d'une SRAM.]]
Niveau entrées et sorties, un banc de registre contient des entrées-sorties dédiées aux transferts de données et plusieurs entrées de commande.
Les entrées de commande permettent de configurer la mémoire pour effectuer une lecture ou écriture, la mettre en veille, ou autre. Parmi les entrées de commande, on trouve une entrée de plusieurs bits, sur laquelle on peut envoyer l'adresse, appelée l'entrée d'adressage. On trouve aussi une entrée R/W d'un bit, qui permet de préciser si on veut faire une lecture ou une écriture. On trouve aussi parfois une entrée ''Enable'' Ou ''Chip Select'', qui indique si la RAM est activée ou mise en veille, qui ressemble à l'entrée ''Enable'' des bascules.
Pour les données, tout dépend du banc de registre considéré. Sur certains bancs de registre, on trouve une sortie sur laquelle on peut récupérer le registre sélectionné (on dit qu'on lit le registre) et une entrée sur laquelle on peut envoyer une donnée destinée à être écrite dans le registre sélectionné (on dit qu'on écrit le registre). On a donc une sortie pour la lecture et une entrée pour l'écriture.
Mais sur d'autres bancs de registre, l'entrée et la sortie sont fusionnées en une seule entrée-sortie. Et d'autres bancs de registre ont au contraire plusieurs sorties de lecture. Rien de bien compliqué à cela : il suffit d'ajouter plusieurs multiplexeurs, au lieu d'un seul. Il suffit d'un multiplexeur par sortie de lecture.
==Les mémoire mortes et mémoires vives==
Les mémoires SRAM vues plus haut sont fabriquées avec des registres, eux-mêmes fabriqués avec des bascules, elles-mêmes fabriquées avec des portes logiques et/ou des transistors. Elles sont très utilisées, surtout dans les processeurs. Les mémoires sont très diverses et les mémoires SRAM ne sont qu'un type de mémoires parmi tant d'autres.
Les mémoires SRAM font elles-mêmes partie de la catégorie des mémoires vives, aussi appelées '''mémoires RAM''' (bien que ce soit un abus de langage, comme on le verra dans plusieurs chapitres). De telles mémoires sont des mémoires électroniques, qui sont adressables, dans lesquelles on peut lire et écrire. Nous verrons les différents types de RAM dans les chapitres sur les mémoires, aussi nous allons mettre cela de côté pour le moment.
Outre les mémoires RAM, il existe des mémoires qui sont elles aussi électroniques, adressables, mais dans lesquelles on ne peut pas écrire : ce sont les '''mémoires ROM'''. En général, les mémoires ROM conservent leur contenu quand on coupe l’alimentation électrique. Si on éteint l'ordinateur, le contenu de la ROM n'est pas perdu, il reste le même. C'est l'exact inverse de ce qu'on a avec les registres, mémoires SRAM, bascules et autres : tout est effacé quand on coupe le courant. Les mémoires RAM sont dites volatiles, alors que les mémoires ROM sont dites non-volatiles.
===Les mémoires ROM===
Il existe deux types de mémoires ROM : les ROM non-programmables et les ROM programmables. La différence est que les premières sont fournies telles quelle et qu'on ne peut pas changer leur contenu, alors que ce n'est pas le cas pour les secondes.
Les ROM programmables sont des ROM dans lesquelles on ne peut évidemment pas écrire, mais qui permettent cependant de réécrire intégralement leur contenu : on dit qu'on reprogramme la ROM. Insistons sur la différence entre reprogrammation et écriture : l'écriture permet de modifier un byte sélectionné/adressé, alors que la reprogrammation efface toute la mémoire et la réécrit en totalité. Ce terme de programmation vient du fait que les mémoires ROM sont souvent utilisées pour stocker des programmes sur certains ordinateurs assez simples.
Les mémoires non-programmables sont aussi appelées des '''''mask'' ROM'''. Elles sont utilisées dans quelques applications particulières, pour lesquelles on n'a pas besoin de changer leur contenu. Par exemple, elles étaient utilisées sur les vieilles consoles de jeux, pour stocker le jeu vidéo dans les cartouches. Elles servent aussi pour les ''firmware'' divers et variés, comme le ''firmware'' d'une imprimante ou d'une clé USB. De telles mémoires seront utiles dans les chapitres qui vont suivre. La raison en est que tout circuit combinatoire peut être remplacé par une mémoire adressable ! Imaginons que l'on souhaite créer un circuit combinatoire qui pour toute entrée A fournisse la sortie B. Celui-ci est équivalent à une ROM dont la lecture de l'adresse A renvoie B sur la sortie. Cette logique est notamment utilisée dans certains circuits programmables, les FPGA, comme on le verra plus tard.
===L'implémentation des mémoires ROM===
Les mémoires ROM sont conçues, sur le même principe que les mémoires SRAM : on combine des registres avec des multiplexeurs. Il y a cependant des différences importantes, liées au fait que les écritures sont interdites. Et il y a une grosse différence suivant que la mémoire soit reprogrammable ou non.
Si la mémoire est reprogrammable, la différence principale est que les registres sont conçus de manière à ne pas être effacés quand on coupe le courant. Ils ne sont pas fabriqués avec des bascules, mais avec d'autres circuits plus complexes, à base de transistors à grille flottante. Les bascules sont remplacés par un équivalent qui se comporte de la même manière, sauf qu'on ne peut pas changer leur contenu facilement (interdiction des écritures), et que leur contenu ne s'efface pas quand on coupe le courant. Il peut y avoir d'autres différences, mais nous verrons cela dans le chapitre dédié aux mémoires ROM.
Quant aux ''mask'' ROM, leur implémentation est beaucoup plus simple. Ils sont conçus sur le même principe que les SRAM. Sauf que vu que l'écriture et la reprogrammation sont interdites, on peut retirer les démultiplexeurs utilisés pour les écritures (et la reprogrammation). Quand aux registres, ils sont remplacés en connectant directement la tension d'alimentation ou la masse sur les entrées des multiplexeurs de lecture. Là où on veut mettre un 0, on connecte la masse. Là où on veut mettre un 1, on connecte la tension d'alimentation. Le circuit obtenu se simplifie alors et peut se remplacer par un circuit composé d'un décodeur connecté à un paquet de portes OU.
[[File:Rom simpel.png|centre|vignette|upright=2|Mémoire ROM simple.]]
L'implémentation d'une ''mask'' ROM est en réalité plus complexe sur certains points, notamment l'implémentation des portes OU, qui sont en réalité des OU câblés comme vu dans le chapitre sur les circuits imprimés. Mais nous reverrons cela dans quelques chapitres. L'important est que vous reteniez ce qu'est une mémoire ROM, qui n'est qu'un cas particulier de circuit combinatoire. Nous aurons à utiliser des mémoires ROM dans les chapitres suivants, à quelques endroits bien précis.
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=Les circuits synchrones et asynchrones
| prevText=Les circuits synchrones et asynchrones
| next=Les circuits compteurs et décompteurs
| nextText=Les circuits compteurs et décompteurs
}}
</noinclude>
3kg54p2l3nlvfj06xn5tkr1pl3kqyvl
762514
762512
2026-03-30T15:33:03Z
Mewtow
31375
/* Les mémoire mortes et mémoires vives */
762514
wikitext
text/x-wiki
Dans les chapitres précédents, nous avons vu comment mémoriser un bit, dans une bascule. Mais les bascules en elles-mêmes sont rarement utiles seules, car les données à mémoriser font généralement plusieurs bits, pas un seul. Stocker plusieurs bits est la raison d'être des '''registres''', des composants qui mémorisent des plusieurs bits, que l'on peut modifier et/ou récupérer plus tard. Il existe plusieurs types de registres, et nous allons faire la distinction entre les registres simples et les registres à décalage. Les registres simples sont capables de mémoriser un nombre, de taille fixe, rien de plus. Les registres à décalage sont des registres simples améliorés, capables de faire quelques petites opérations sur leur contenu.
==Les registres simples==
Les '''registres simples''' sont capables de mémoriser un nombre, codé sur une quantité fixe de bits. On peut à tout moment récupérer le nombre mémorisé dans le registre : on dit alors qu'on effectue une lecture. On peut aussi mettre à jour le nombre mémorisé dans le registre, le remplacer par un autre : on dit qu'on effectue une écriture. Les seules opérations possibles sur ces registres sont la lecture (récupérer le nombre mémorisé dans le registre) et l'écriture (mettre à jour le nombre mémorisé dans le registre, le remplacer par un autre).
===L'interface d'un registre simple===
[[File:4 Bit Data Register.svg|vignette|Registre de 4 Bits. On voit que celui-ci contient 4 entrées (à gauche), et 4 sorties (à droite). On peut aussi remarquer une entrée CLK, qui joue le rôle d'entrée d'autorisation.]]
Niveau entrées et sorties, les registres possèdent des entrées-sorties pour les données mémorisées, mais aussi des entrées-sorties de commande. Les entrées-sorties pour les données permettent de lire le contenu du registre ou d'y écrire. Les entrées de commande permettent de configurer le registre pour lui ordonner de faire une écriture, pour le remettre à zéro, ou toute autre opération.
Les entrées de données sont utilisées pour l'écriture, alors que les sorties de données servent pour la lecture. Le nombre mémorisé dans le registre est disponible sur les sorties du registre. Pour utiliser les entrées d'écriture, on envoie le nombre à mémoriser (celui qui remplacera le contenu du registre) sur les entrées d'écriture et on configure les entrées de commande adéquates.
Les entrées de commande varient suivant le registre, mais on trouve au moins une entrée Enable, qui a le même rôle que pour une bascule, à savoir autoriser une écriture. Si l'entrée Enable est à 1, le registre mémorise ce qu'il y a sur l'entrée de donnée. Mais si l'entrée Enable est à 0, le registre n'est pas mis à jour : on peut mettre n'importe quelle valeur sur les entrées, le registre n'en tiendra pas compte et ne remplacera pas son contenu par ce qu'il y a sur l'entrée. Pour résumer, l'entrée Enable sert donc à indiquer au registre si son contenu doit être mis à jour, quand une écriture a lieu.
D'autres entrées de commandes sont parfois présentes, la plus commune étant une entrée permettant de remettre à zéro le registre. La présence d'un 1 sur cette entrée remet à zéro le contenu du registre, à savoir que celui-ci contient la valeur zéro.
Enfin, il faut distinguer les registres synchrones des registres asynchrones. Les '''registres synchrones''' sont reliés au signal d’horloge. Pour cela, ils disposent d'une entrée d'horloge sur laquelle on envoie le signal d'horloge. Ils ne sont mis à jour que si on présente un front montant sur l'entrée d'horloge. Les '''registres asynchrones''' ne sont pas reliés au signal d'horloge et sont mis à jour quand on envoie ce qu'il faut sur leur entré Enable, rien de plus.
===L'intérieur d'un registre simple===
Un registre est composé de plusieurs bascules D qui sont toutes mises à jour en même temps. Cela vaut aussi bien pour les registres asynchrones que les registres synchrones. Pour cela, toutes les entrées E des bascules sont reliées à l'entrée de commande Enable. De plus, les registre synchrones envoient le signal d'horloge sur toutes les bascules. Avec un registre synchrone, toutes les bascules sont des bascules synchrones, qui ont toutes une entrée d'horloge, relié au signal d'horloge.
[[File:Register.svg|centre|vignette|upright=3|Registre.]]
==Les registres à décalage==
Les '''registres à décalage''' sont des registres dont le contenu est décalé d'un cran vers la gauche ou la droite sur commande. Nous aurons à les réutiliser plus tard dans ce cours, notamment dans la section sur les circuits de génération de nombres aléatoires, ou dans certains circuits liés au cache. Les registres à décalage sont presque tous synchrones et ce chapitre ne parlera que ce ces derniers. L'animation suivante illustre le fonctionnement d'un registre à décalage qui décale son contenu d'un cran vers la droite à chaque cycle d'horloge.
[[File:4-Bit PISO Shift Register Seq.gif|centre|vignette|upright=2|Registre à décalage.]]
===La classification des registres===
On peut classer les registres selon le caractère de l'entrée et de la sortie, qui peut être parallèle (entrée de plusieurs bits) ou série (entrée d'un seul bit).
* Sur les registres simples, les entrées et sorties pour les données sont toujours parallèles. Pour un registre de N bits, il y a une entrée d'écriture de N bits et une sortie de N bits. C'est la raison pour laquelle ils sont appelés des '''registres à entrées et sorties parallèles'''.
* Sur les registres à '''entrée et sortie série''', on peut mettre à jour un bit à la fois, de même qu'on ne peut en récupérer qu'un à la fois. Ces registres servent essentiellement à mettre en attente des bits tout en gardant leur ordre : un bit envoyé en entrée ressortira sur la sortie après plusieurs commandes de mise à jour sur l'entrée Enable.
* Les registres à décalage à '''entrée série et sortie parallèle''' sont similaires aux précédents : on peut ajouter un nouveau bit en commandant l'entrée Enable et les anciens bits sont alors décalés d'un cran. Par contre, on peut récupérer (lire) tous les bits en une seule fois. Ils permettent notamment de reconstituer un nombre qui est envoyé bit par bit sur un fil (un bus série).
* Enfin, il reste les registres à '''entrée parallèle et sortie série'''. Ces registres sont utiles quand on veut transmettre un nombre sur un fil : on peut ainsi envoyer les bits un par un.
[[File:Td5bfig1.png|centre|vignette|upright=2|Classification des registres à décalage.]]
Pour résumer, on distingue quatre types de registres (à décalage ou non), qui portent les noms de PIPO, PISO, SIPO et SISO. Les noms peuvent sembler barbares, mais il y a une logique derrière ces termes.La lettre P est pour parallèle, la lettre S est pour série. La lettre I signifie ''Input'', ce qui veut dire entrée en anglais, la lettre O est pour ''Output'', la sortie en anglais.
{|class="wikitable"
|+ Classification des registres
|-
!
! Entrée parallèle
! Entrée série
|-
! Sortie parallèle
| PIPO (registre simple)
| SIPO
|-
! Sortie série
| PISO
| SISO
|}
===L'intérieur d'un registre à décalage===
Tous les registres sont conçus en plaçant plusieurs bascules les unes à la suite des autres, que ce soit pour les registres simples ou les registres à décalage. La seule différence tient dans la manière dont les bascules sont reliées. Toutes les bascules sont reliées à l'entrée d'horloge, l'entrée Enable, l'entrée Reset, ou aux autres entrées de commandes. Mais c'est une autre paire de manche pour les entrées/sorties de données.
Dans un registre simple, les bascules sont indépendantes et ne sont pas reliées entre elles.
[[File:Register.svg|centre|vignette|upright=3|Registre simple.]]
À l'inverse, dans les registres à décalage, il existe des connexions entre bascules. Plus précisément, les bascules sont reliées les unes à la suite des autres, elles forment une chaîne de bascules reliées deux à deux. Et les connexions entre bascules sont les mêmes que l'on parle d'un registre à décalage de type SIPO, PISO ou SISO.
[[File:Shift-Register.svg|centre|vignette|upright=3|Exemple de registre à décalage]]
Outre le fait que les bascules sont reliées de la même manière, les autres connexions sont les mêmes dans tous les registres. L'entrée d'horloge (non-représentée dans les schémas qui vont suivre) est envoyée à toutes les bascules. Même chose pour l'entrée Enable, qui est reliée aux entrées E de toutes les bascules. La différence entre ces registres tient dans les endroits où se trouvent les entrées et les sorties du registre.
{|
|+ Implémentation des registres avec des bascules.
|-
|[[File:Registre à entrée parallèle et sortie série.png|vignette|upright=2|Registre à entrée et sortie série.]]
|[[File:Registre à lecture et écriture parallèle.png|vignette|upright=2|Registre à entrée et sortie parallèle.]]
|-
|[[File:Registre à entrée et sortie série.png|vignette|upright=2|Registre à entrée série et sortie parallèle.]]
|[[File:Registre à entrée série et sortie parallèle.png|vignette|upright=2|Registre à entrée parallèle et sortie série.]]
|}
==Une utilisation des registres : les bancs de registre==
Maintenant que nous avons les registres, il est temps d'en montrer une utilisation assez intéressante. Nous allons combiner les registres avec des multiplexeurs/démultiplexeurs pour former une '''mémoire adressable'''. Plus précisément, nous allons voir les '''bancs de registre''', qui peuvent être vu comme un rassemblement de plusieurs registres. Mais ces registres ne sont pas assemblés pour obtenir un registre plus gros : par exemple, on peut fabriquer un registre de 32 bits à partir de 2 registres de 16 bits, ou de 4 registres de 8 bits. Ce n'est pas ce qui est fait sur les mémoires adressables, où les registres sont regroupés de manière à ce qu'il soit possible de sélectionner le registre qu'on veut consulter ou modifier.
Pour préciser le registre à sélectionner, chacun d'entre eux se voit attribuer un nombre : l''''adresse'''. 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 registres d'une mémoire adressable. Il existe des mémoires qui ne fonctionnent pas sur ce principe, mais passons : ce sera pour la suite.
[[File:Adressage mémoire.png|centre|vignette|upright=2|Exemple : on demande à la mémoire de sélectionner le byte d'adresse 1002 et on récupère son contenu (ici, 17).]]
===L'intérieur d'un banc de registre===
Un banc de registre peut se fabriquer assez simplement : il suffit d'un ou de plusieurs multiplexeurs et de registres. Quand on présente l'adresse sur l'entrée de sélection du multiplexeur, celui-ci va connecter le registre demandé à la sortie (ou à l'entrée).
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
Voici ce que cela donne avec une RAM reliée à un bus de 1 bit, à savoir que chaque case mémoire ne contient que 1 bit, il y a un bit par adresse. Il s'agit d'un exemple bien trop simple pour avoir la moindre application pratique, mais c'est un exemple clairement pédagogique. L'entrée d'écriture est reliée à toutes les bascules, mais seule celle sélectionnée est écrite. Lors d'une lecture, l'adresse est envoyée au multiplexeur et la donnée lue sur sa sortie. Lors d'une écriture, c'est le démultiplexeur/décodeur qui est utilisé. Le décodeur active la bascule voulue, via son entrée d'horloge ou Enable. Le bit R/W précise qu'il faut effectuer une écriture. L'entrée d'écriture est alors recopiée dans la bascule sélectionnée.
[[File:MemWrite.png|centre|vignette|upright=2|Intérieur d'une RAM de 4 bits, reliée à un bus de 1 bit, fabriquée avec des registres et des multiplexeurs.]]
===L'interface d'un banc de registre===
[[File:RAM 8x4 symbol.svg|vignette|Interface d'une SRAM.]]
Niveau entrées et sorties, un banc de registre contient des entrées-sorties dédiées aux transferts de données et plusieurs entrées de commande.
Les entrées de commande permettent de configurer la mémoire pour effectuer une lecture ou écriture, la mettre en veille, ou autre. Parmi les entrées de commande, on trouve une entrée de plusieurs bits, sur laquelle on peut envoyer l'adresse, appelée l'entrée d'adressage. On trouve aussi une entrée R/W d'un bit, qui permet de préciser si on veut faire une lecture ou une écriture. On trouve aussi parfois une entrée ''Enable'' Ou ''Chip Select'', qui indique si la RAM est activée ou mise en veille, qui ressemble à l'entrée ''Enable'' des bascules.
Pour les données, tout dépend du banc de registre considéré. Sur certains bancs de registre, on trouve une sortie sur laquelle on peut récupérer le registre sélectionné (on dit qu'on lit le registre) et une entrée sur laquelle on peut envoyer une donnée destinée à être écrite dans le registre sélectionné (on dit qu'on écrit le registre). On a donc une sortie pour la lecture et une entrée pour l'écriture.
Mais sur d'autres bancs de registre, l'entrée et la sortie sont fusionnées en une seule entrée-sortie. Et d'autres bancs de registre ont au contraire plusieurs sorties de lecture. Rien de bien compliqué à cela : il suffit d'ajouter plusieurs multiplexeurs, au lieu d'un seul. Il suffit d'un multiplexeur par sortie de lecture.
==Les mémoire mortes et mémoires vives==
Les bancs de registres vus plus haut sont fabriquées avec des registres, eux-mêmes fabriqués avec des bascules, elles-mêmes fabriquées avec des portes logiques et/ou des transistors. Elles sont très utilisées, surtout dans les processeurs. Les mémoires sont très diverses et les mémoires SRAM ne sont qu'un type de mémoires parmi tant d'autres.
Les bancs de registres sont un sous-type de '''mémoire SRAM'''. Formellement, les mémoires SRAM sont des mémoires similaires aux bancs de registre, la différence étant que les bascules ne sont pas fabriquées avec des portes logiques, mais avec des transistors. Mais pour le reste, la conception reste sensiblement la même. Les SRAM sont composées de bascules de 1 bit, assemblées en "pseudo-registres", elles mêmes reliées à des multiplexeurs/démultiplexeurs.
Les mémoires SRAM font elles-mêmes partie de la catégorie des mémoires vives, aussi appelées '''mémoires RAM''' (bien que ce soit un abus de langage, comme on le verra dans plusieurs chapitres). De telles mémoires sont des mémoires électroniques, qui sont adressables, dans lesquelles on peut lire et écrire. Nous verrons les différents types de RAM dans les chapitres sur les mémoires, aussi nous allons mettre cela de côté pour le moment.
Outre les mémoires RAM, il existe des mémoires qui sont elles aussi électroniques, adressables, mais dans lesquelles on ne peut pas écrire : ce sont les '''mémoires ROM'''. En général, les mémoires ROM conservent leur contenu quand on coupe l’alimentation électrique. Si on éteint l'ordinateur, le contenu de la ROM n'est pas perdu, il reste le même. C'est l'exact inverse de ce qu'on a avec les registres, mémoires SRAM, bascules et autres : tout est effacé quand on coupe le courant. Les mémoires RAM sont dites volatiles, alors que les mémoires ROM sont dites non-volatiles.
===Les mémoires ROM===
Il existe deux types de mémoires ROM : les ROM non-programmables et les ROM programmables. La différence est que les premières sont fournies telles quelle et qu'on ne peut pas changer leur contenu, alors que ce n'est pas le cas pour les secondes.
Les ROM programmables sont des ROM dans lesquelles on ne peut évidemment pas écrire, mais qui permettent cependant de réécrire intégralement leur contenu : on dit qu'on reprogramme la ROM. Insistons sur la différence entre reprogrammation et écriture : l'écriture permet de modifier un byte sélectionné/adressé, alors que la reprogrammation efface toute la mémoire et la réécrit en totalité. Ce terme de programmation vient du fait que les mémoires ROM sont souvent utilisées pour stocker des programmes sur certains ordinateurs assez simples.
Les mémoires non-programmables sont aussi appelées des '''''mask'' ROM'''. Elles sont utilisées dans quelques applications particulières, pour lesquelles on n'a pas besoin de changer leur contenu. Par exemple, elles étaient utilisées sur les vieilles consoles de jeux, pour stocker le jeu vidéo dans les cartouches. Elles servent aussi pour les ''firmware'' divers et variés, comme le ''firmware'' d'une imprimante ou d'une clé USB. De telles mémoires seront utiles dans les chapitres qui vont suivre. La raison en est que tout circuit combinatoire peut être remplacé par une mémoire adressable ! Imaginons que l'on souhaite créer un circuit combinatoire qui pour toute entrée A fournisse la sortie B. Celui-ci est équivalent à une ROM dont la lecture de l'adresse A renvoie B sur la sortie. Cette logique est notamment utilisée dans certains circuits programmables, les FPGA, comme on le verra plus tard.
===L'implémentation des mémoires ROM===
Les mémoires ROM sont conçues, sur le même principe que les mémoires SRAM : on combine des registres avec des multiplexeurs. Il y a cependant des différences importantes, liées au fait que les écritures sont interdites. Et il y a une grosse différence suivant que la mémoire soit reprogrammable ou non.
Si la mémoire est reprogrammable, la différence principale est que les registres sont conçus de manière à ne pas être effacés quand on coupe le courant. Ils ne sont pas fabriqués avec des bascules, mais avec d'autres circuits plus complexes, à base de transistors à grille flottante. Les bascules sont remplacés par un équivalent qui se comporte de la même manière, sauf qu'on ne peut pas changer leur contenu facilement (interdiction des écritures), et que leur contenu ne s'efface pas quand on coupe le courant. Il peut y avoir d'autres différences, mais nous verrons cela dans le chapitre dédié aux mémoires ROM.
Quant aux ''mask'' ROM, leur implémentation est beaucoup plus simple. Ils sont conçus sur le même principe que les SRAM. Sauf que vu que l'écriture et la reprogrammation sont interdites, on peut retirer les démultiplexeurs utilisés pour les écritures (et la reprogrammation). Quand aux registres, ils sont remplacés en connectant directement la tension d'alimentation ou la masse sur les entrées des multiplexeurs de lecture. Là où on veut mettre un 0, on connecte la masse. Là où on veut mettre un 1, on connecte la tension d'alimentation. Le circuit obtenu se simplifie alors et peut se remplacer par un circuit composé d'un décodeur connecté à un paquet de portes OU.
[[File:Rom simpel.png|centre|vignette|upright=2|Mémoire ROM simple.]]
L'implémentation d'une ''mask'' ROM est en réalité plus complexe sur certains points, notamment l'implémentation des portes OU, qui sont en réalité des OU câblés comme vu dans le chapitre sur les circuits imprimés. Mais nous reverrons cela dans quelques chapitres. L'important est que vous reteniez ce qu'est une mémoire ROM, qui n'est qu'un cas particulier de circuit combinatoire. Nous aurons à utiliser des mémoires ROM dans les chapitres suivants, à quelques endroits bien précis.
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=Les circuits synchrones et asynchrones
| prevText=Les circuits synchrones et asynchrones
| next=Les circuits compteurs et décompteurs
| nextText=Les circuits compteurs et décompteurs
}}
</noinclude>
3h1f4na5g8x8ogevq553cagnojt87dv
762515
762514
2026-03-30T15:33:20Z
Mewtow
31375
/* Les mémoire mortes et mémoires vives */
762515
wikitext
text/x-wiki
Dans les chapitres précédents, nous avons vu comment mémoriser un bit, dans une bascule. Mais les bascules en elles-mêmes sont rarement utiles seules, car les données à mémoriser font généralement plusieurs bits, pas un seul. Stocker plusieurs bits est la raison d'être des '''registres''', des composants qui mémorisent des plusieurs bits, que l'on peut modifier et/ou récupérer plus tard. Il existe plusieurs types de registres, et nous allons faire la distinction entre les registres simples et les registres à décalage. Les registres simples sont capables de mémoriser un nombre, de taille fixe, rien de plus. Les registres à décalage sont des registres simples améliorés, capables de faire quelques petites opérations sur leur contenu.
==Les registres simples==
Les '''registres simples''' sont capables de mémoriser un nombre, codé sur une quantité fixe de bits. On peut à tout moment récupérer le nombre mémorisé dans le registre : on dit alors qu'on effectue une lecture. On peut aussi mettre à jour le nombre mémorisé dans le registre, le remplacer par un autre : on dit qu'on effectue une écriture. Les seules opérations possibles sur ces registres sont la lecture (récupérer le nombre mémorisé dans le registre) et l'écriture (mettre à jour le nombre mémorisé dans le registre, le remplacer par un autre).
===L'interface d'un registre simple===
[[File:4 Bit Data Register.svg|vignette|Registre de 4 Bits. On voit que celui-ci contient 4 entrées (à gauche), et 4 sorties (à droite). On peut aussi remarquer une entrée CLK, qui joue le rôle d'entrée d'autorisation.]]
Niveau entrées et sorties, les registres possèdent des entrées-sorties pour les données mémorisées, mais aussi des entrées-sorties de commande. Les entrées-sorties pour les données permettent de lire le contenu du registre ou d'y écrire. Les entrées de commande permettent de configurer le registre pour lui ordonner de faire une écriture, pour le remettre à zéro, ou toute autre opération.
Les entrées de données sont utilisées pour l'écriture, alors que les sorties de données servent pour la lecture. Le nombre mémorisé dans le registre est disponible sur les sorties du registre. Pour utiliser les entrées d'écriture, on envoie le nombre à mémoriser (celui qui remplacera le contenu du registre) sur les entrées d'écriture et on configure les entrées de commande adéquates.
Les entrées de commande varient suivant le registre, mais on trouve au moins une entrée Enable, qui a le même rôle que pour une bascule, à savoir autoriser une écriture. Si l'entrée Enable est à 1, le registre mémorise ce qu'il y a sur l'entrée de donnée. Mais si l'entrée Enable est à 0, le registre n'est pas mis à jour : on peut mettre n'importe quelle valeur sur les entrées, le registre n'en tiendra pas compte et ne remplacera pas son contenu par ce qu'il y a sur l'entrée. Pour résumer, l'entrée Enable sert donc à indiquer au registre si son contenu doit être mis à jour, quand une écriture a lieu.
D'autres entrées de commandes sont parfois présentes, la plus commune étant une entrée permettant de remettre à zéro le registre. La présence d'un 1 sur cette entrée remet à zéro le contenu du registre, à savoir que celui-ci contient la valeur zéro.
Enfin, il faut distinguer les registres synchrones des registres asynchrones. Les '''registres synchrones''' sont reliés au signal d’horloge. Pour cela, ils disposent d'une entrée d'horloge sur laquelle on envoie le signal d'horloge. Ils ne sont mis à jour que si on présente un front montant sur l'entrée d'horloge. Les '''registres asynchrones''' ne sont pas reliés au signal d'horloge et sont mis à jour quand on envoie ce qu'il faut sur leur entré Enable, rien de plus.
===L'intérieur d'un registre simple===
Un registre est composé de plusieurs bascules D qui sont toutes mises à jour en même temps. Cela vaut aussi bien pour les registres asynchrones que les registres synchrones. Pour cela, toutes les entrées E des bascules sont reliées à l'entrée de commande Enable. De plus, les registre synchrones envoient le signal d'horloge sur toutes les bascules. Avec un registre synchrone, toutes les bascules sont des bascules synchrones, qui ont toutes une entrée d'horloge, relié au signal d'horloge.
[[File:Register.svg|centre|vignette|upright=3|Registre.]]
==Les registres à décalage==
Les '''registres à décalage''' sont des registres dont le contenu est décalé d'un cran vers la gauche ou la droite sur commande. Nous aurons à les réutiliser plus tard dans ce cours, notamment dans la section sur les circuits de génération de nombres aléatoires, ou dans certains circuits liés au cache. Les registres à décalage sont presque tous synchrones et ce chapitre ne parlera que ce ces derniers. L'animation suivante illustre le fonctionnement d'un registre à décalage qui décale son contenu d'un cran vers la droite à chaque cycle d'horloge.
[[File:4-Bit PISO Shift Register Seq.gif|centre|vignette|upright=2|Registre à décalage.]]
===La classification des registres===
On peut classer les registres selon le caractère de l'entrée et de la sortie, qui peut être parallèle (entrée de plusieurs bits) ou série (entrée d'un seul bit).
* Sur les registres simples, les entrées et sorties pour les données sont toujours parallèles. Pour un registre de N bits, il y a une entrée d'écriture de N bits et une sortie de N bits. C'est la raison pour laquelle ils sont appelés des '''registres à entrées et sorties parallèles'''.
* Sur les registres à '''entrée et sortie série''', on peut mettre à jour un bit à la fois, de même qu'on ne peut en récupérer qu'un à la fois. Ces registres servent essentiellement à mettre en attente des bits tout en gardant leur ordre : un bit envoyé en entrée ressortira sur la sortie après plusieurs commandes de mise à jour sur l'entrée Enable.
* Les registres à décalage à '''entrée série et sortie parallèle''' sont similaires aux précédents : on peut ajouter un nouveau bit en commandant l'entrée Enable et les anciens bits sont alors décalés d'un cran. Par contre, on peut récupérer (lire) tous les bits en une seule fois. Ils permettent notamment de reconstituer un nombre qui est envoyé bit par bit sur un fil (un bus série).
* Enfin, il reste les registres à '''entrée parallèle et sortie série'''. Ces registres sont utiles quand on veut transmettre un nombre sur un fil : on peut ainsi envoyer les bits un par un.
[[File:Td5bfig1.png|centre|vignette|upright=2|Classification des registres à décalage.]]
Pour résumer, on distingue quatre types de registres (à décalage ou non), qui portent les noms de PIPO, PISO, SIPO et SISO. Les noms peuvent sembler barbares, mais il y a une logique derrière ces termes.La lettre P est pour parallèle, la lettre S est pour série. La lettre I signifie ''Input'', ce qui veut dire entrée en anglais, la lettre O est pour ''Output'', la sortie en anglais.
{|class="wikitable"
|+ Classification des registres
|-
!
! Entrée parallèle
! Entrée série
|-
! Sortie parallèle
| PIPO (registre simple)
| SIPO
|-
! Sortie série
| PISO
| SISO
|}
===L'intérieur d'un registre à décalage===
Tous les registres sont conçus en plaçant plusieurs bascules les unes à la suite des autres, que ce soit pour les registres simples ou les registres à décalage. La seule différence tient dans la manière dont les bascules sont reliées. Toutes les bascules sont reliées à l'entrée d'horloge, l'entrée Enable, l'entrée Reset, ou aux autres entrées de commandes. Mais c'est une autre paire de manche pour les entrées/sorties de données.
Dans un registre simple, les bascules sont indépendantes et ne sont pas reliées entre elles.
[[File:Register.svg|centre|vignette|upright=3|Registre simple.]]
À l'inverse, dans les registres à décalage, il existe des connexions entre bascules. Plus précisément, les bascules sont reliées les unes à la suite des autres, elles forment une chaîne de bascules reliées deux à deux. Et les connexions entre bascules sont les mêmes que l'on parle d'un registre à décalage de type SIPO, PISO ou SISO.
[[File:Shift-Register.svg|centre|vignette|upright=3|Exemple de registre à décalage]]
Outre le fait que les bascules sont reliées de la même manière, les autres connexions sont les mêmes dans tous les registres. L'entrée d'horloge (non-représentée dans les schémas qui vont suivre) est envoyée à toutes les bascules. Même chose pour l'entrée Enable, qui est reliée aux entrées E de toutes les bascules. La différence entre ces registres tient dans les endroits où se trouvent les entrées et les sorties du registre.
{|
|+ Implémentation des registres avec des bascules.
|-
|[[File:Registre à entrée parallèle et sortie série.png|vignette|upright=2|Registre à entrée et sortie série.]]
|[[File:Registre à lecture et écriture parallèle.png|vignette|upright=2|Registre à entrée et sortie parallèle.]]
|-
|[[File:Registre à entrée et sortie série.png|vignette|upright=2|Registre à entrée série et sortie parallèle.]]
|[[File:Registre à entrée série et sortie parallèle.png|vignette|upright=2|Registre à entrée parallèle et sortie série.]]
|}
==Une utilisation des registres : les bancs de registre==
Maintenant que nous avons les registres, il est temps d'en montrer une utilisation assez intéressante. Nous allons combiner les registres avec des multiplexeurs/démultiplexeurs pour former une '''mémoire adressable'''. Plus précisément, nous allons voir les '''bancs de registre''', qui peuvent être vu comme un rassemblement de plusieurs registres. Mais ces registres ne sont pas assemblés pour obtenir un registre plus gros : par exemple, on peut fabriquer un registre de 32 bits à partir de 2 registres de 16 bits, ou de 4 registres de 8 bits. Ce n'est pas ce qui est fait sur les mémoires adressables, où les registres sont regroupés de manière à ce qu'il soit possible de sélectionner le registre qu'on veut consulter ou modifier.
Pour préciser le registre à sélectionner, chacun d'entre eux se voit attribuer un nombre : l''''adresse'''. 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 registres d'une mémoire adressable. Il existe des mémoires qui ne fonctionnent pas sur ce principe, mais passons : ce sera pour la suite.
[[File:Adressage mémoire.png|centre|vignette|upright=2|Exemple : on demande à la mémoire de sélectionner le byte d'adresse 1002 et on récupère son contenu (ici, 17).]]
===L'intérieur d'un banc de registre===
Un banc de registre peut se fabriquer assez simplement : il suffit d'un ou de plusieurs multiplexeurs et de registres. Quand on présente l'adresse sur l'entrée de sélection du multiplexeur, celui-ci va connecter le registre demandé à la sortie (ou à l'entrée).
[[File:Intérieur d'une mémoire RAM.png|centre|vignette|upright=2|Intérieur d'une RAM fabriquée avec des registres et des multiplexeurs.]]
Voici ce que cela donne avec une RAM reliée à un bus de 1 bit, à savoir que chaque case mémoire ne contient que 1 bit, il y a un bit par adresse. Il s'agit d'un exemple bien trop simple pour avoir la moindre application pratique, mais c'est un exemple clairement pédagogique. L'entrée d'écriture est reliée à toutes les bascules, mais seule celle sélectionnée est écrite. Lors d'une lecture, l'adresse est envoyée au multiplexeur et la donnée lue sur sa sortie. Lors d'une écriture, c'est le démultiplexeur/décodeur qui est utilisé. Le décodeur active la bascule voulue, via son entrée d'horloge ou Enable. Le bit R/W précise qu'il faut effectuer une écriture. L'entrée d'écriture est alors recopiée dans la bascule sélectionnée.
[[File:MemWrite.png|centre|vignette|upright=2|Intérieur d'une RAM de 4 bits, reliée à un bus de 1 bit, fabriquée avec des registres et des multiplexeurs.]]
===L'interface d'un banc de registre===
[[File:RAM 8x4 symbol.svg|vignette|Interface d'une SRAM.]]
Niveau entrées et sorties, un banc de registre contient des entrées-sorties dédiées aux transferts de données et plusieurs entrées de commande.
Les entrées de commande permettent de configurer la mémoire pour effectuer une lecture ou écriture, la mettre en veille, ou autre. Parmi les entrées de commande, on trouve une entrée de plusieurs bits, sur laquelle on peut envoyer l'adresse, appelée l'entrée d'adressage. On trouve aussi une entrée R/W d'un bit, qui permet de préciser si on veut faire une lecture ou une écriture. On trouve aussi parfois une entrée ''Enable'' Ou ''Chip Select'', qui indique si la RAM est activée ou mise en veille, qui ressemble à l'entrée ''Enable'' des bascules.
Pour les données, tout dépend du banc de registre considéré. Sur certains bancs de registre, on trouve une sortie sur laquelle on peut récupérer le registre sélectionné (on dit qu'on lit le registre) et une entrée sur laquelle on peut envoyer une donnée destinée à être écrite dans le registre sélectionné (on dit qu'on écrit le registre). On a donc une sortie pour la lecture et une entrée pour l'écriture.
Mais sur d'autres bancs de registre, l'entrée et la sortie sont fusionnées en une seule entrée-sortie. Et d'autres bancs de registre ont au contraire plusieurs sorties de lecture. Rien de bien compliqué à cela : il suffit d'ajouter plusieurs multiplexeurs, au lieu d'un seul. Il suffit d'un multiplexeur par sortie de lecture.
==Les mémoire mortes et mémoires vives==
Les bancs de registres sont un sous-type de '''mémoire SRAM'''. Formellement, les mémoires SRAM sont des mémoires similaires aux bancs de registre, la différence étant que les bascules ne sont pas fabriquées avec des portes logiques, mais avec des transistors. Mais pour le reste, la conception reste sensiblement la même. Les SRAM sont composées de bascules de 1 bit, assemblées en "pseudo-registres", elles mêmes reliées à des multiplexeurs/démultiplexeurs. Elles sont très utilisées, surtout dans les processeurs. Les mémoires sont très diverses et les mémoires SRAM ne sont qu'un type de mémoires parmi tant d'autres.
Les mémoires SRAM font elles-mêmes partie de la catégorie des mémoires vives, aussi appelées '''mémoires RAM''' (bien que ce soit un abus de langage, comme on le verra dans plusieurs chapitres). De telles mémoires sont des mémoires électroniques, qui sont adressables, dans lesquelles on peut lire et écrire. Nous verrons les différents types de RAM dans les chapitres sur les mémoires, aussi nous allons mettre cela de côté pour le moment.
Outre les mémoires RAM, il existe des mémoires qui sont elles aussi électroniques, adressables, mais dans lesquelles on ne peut pas écrire : ce sont les '''mémoires ROM'''. En général, les mémoires ROM conservent leur contenu quand on coupe l’alimentation électrique. Si on éteint l'ordinateur, le contenu de la ROM n'est pas perdu, il reste le même. C'est l'exact inverse de ce qu'on a avec les registres, mémoires SRAM, bascules et autres : tout est effacé quand on coupe le courant. Les mémoires RAM sont dites volatiles, alors que les mémoires ROM sont dites non-volatiles.
===Les mémoires ROM===
Il existe deux types de mémoires ROM : les ROM non-programmables et les ROM programmables. La différence est que les premières sont fournies telles quelle et qu'on ne peut pas changer leur contenu, alors que ce n'est pas le cas pour les secondes.
Les ROM programmables sont des ROM dans lesquelles on ne peut évidemment pas écrire, mais qui permettent cependant de réécrire intégralement leur contenu : on dit qu'on reprogramme la ROM. Insistons sur la différence entre reprogrammation et écriture : l'écriture permet de modifier un byte sélectionné/adressé, alors que la reprogrammation efface toute la mémoire et la réécrit en totalité. Ce terme de programmation vient du fait que les mémoires ROM sont souvent utilisées pour stocker des programmes sur certains ordinateurs assez simples.
Les mémoires non-programmables sont aussi appelées des '''''mask'' ROM'''. Elles sont utilisées dans quelques applications particulières, pour lesquelles on n'a pas besoin de changer leur contenu. Par exemple, elles étaient utilisées sur les vieilles consoles de jeux, pour stocker le jeu vidéo dans les cartouches. Elles servent aussi pour les ''firmware'' divers et variés, comme le ''firmware'' d'une imprimante ou d'une clé USB. De telles mémoires seront utiles dans les chapitres qui vont suivre. La raison en est que tout circuit combinatoire peut être remplacé par une mémoire adressable ! Imaginons que l'on souhaite créer un circuit combinatoire qui pour toute entrée A fournisse la sortie B. Celui-ci est équivalent à une ROM dont la lecture de l'adresse A renvoie B sur la sortie. Cette logique est notamment utilisée dans certains circuits programmables, les FPGA, comme on le verra plus tard.
===L'implémentation des mémoires ROM===
Les mémoires ROM sont conçues, sur le même principe que les mémoires SRAM : on combine des registres avec des multiplexeurs. Il y a cependant des différences importantes, liées au fait que les écritures sont interdites. Et il y a une grosse différence suivant que la mémoire soit reprogrammable ou non.
Si la mémoire est reprogrammable, la différence principale est que les registres sont conçus de manière à ne pas être effacés quand on coupe le courant. Ils ne sont pas fabriqués avec des bascules, mais avec d'autres circuits plus complexes, à base de transistors à grille flottante. Les bascules sont remplacés par un équivalent qui se comporte de la même manière, sauf qu'on ne peut pas changer leur contenu facilement (interdiction des écritures), et que leur contenu ne s'efface pas quand on coupe le courant. Il peut y avoir d'autres différences, mais nous verrons cela dans le chapitre dédié aux mémoires ROM.
Quant aux ''mask'' ROM, leur implémentation est beaucoup plus simple. Ils sont conçus sur le même principe que les SRAM. Sauf que vu que l'écriture et la reprogrammation sont interdites, on peut retirer les démultiplexeurs utilisés pour les écritures (et la reprogrammation). Quand aux registres, ils sont remplacés en connectant directement la tension d'alimentation ou la masse sur les entrées des multiplexeurs de lecture. Là où on veut mettre un 0, on connecte la masse. Là où on veut mettre un 1, on connecte la tension d'alimentation. Le circuit obtenu se simplifie alors et peut se remplacer par un circuit composé d'un décodeur connecté à un paquet de portes OU.
[[File:Rom simpel.png|centre|vignette|upright=2|Mémoire ROM simple.]]
L'implémentation d'une ''mask'' ROM est en réalité plus complexe sur certains points, notamment l'implémentation des portes OU, qui sont en réalité des OU câblés comme vu dans le chapitre sur les circuits imprimés. Mais nous reverrons cela dans quelques chapitres. L'important est que vous reteniez ce qu'est une mémoire ROM, qui n'est qu'un cas particulier de circuit combinatoire. Nous aurons à utiliser des mémoires ROM dans les chapitres suivants, à quelques endroits bien précis.
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=Les circuits synchrones et asynchrones
| prevText=Les circuits synchrones et asynchrones
| next=Les circuits compteurs et décompteurs
| nextText=Les circuits compteurs et décompteurs
}}
</noinclude>
i9w82l6jz3qjrm08xxtv2e7c7p55rdo
Fonctionnement d'un ordinateur/Les architectures à accumulateur
0
82386
762517
748616
2026-03-30T16:29:33Z
Mewtow
31375
/* Les registres des anciennes architectures à accumulateur */
762517
wikitext
text/x-wiki
Les architectures que nous avons vu précédemment dans ce cours disposent de registres pour les données, en plus du pointeur de pile, d'un ''program counter'', et de quelques autres. Elles sont appelées des '''architectures à registres''', terme qui trahit bien le fait qu'elles ont des registres généraux ou spécialisés pour stocker temporairement des données. Et si on leur a donné un nom, c'est parce qu'il existe des architectures qui ne sont pas dans cette catégorie. Il en existe plusieurs types, mais ce chapitre va se concentrer sur les '''architectures à accumulateur'''.
[[File:Isaccumulator.png|vignette|Architecture à accumulateur.]]
Les architectures à accumulateur sont centrées autour d'un registre architectural appelé l''''accumulateur'''. Il est utilisé pour toutes les opérations arithmétiques dyadiques, où il sert à la fois de source et de destination. Toutes les instructions dyadiques sont de type ''load-op'' : une opérande est lue depuis l'accumulateur, le second opérande est lu depuis la mémoire RAM, le résultat de l'instruction est automatiquement mémorisé dans l'accumulateur. Les instructions monadiques peuvent utiliser un opérande dans l'accumulateur, ou dans la mémoire RAM, les deux sont théoriquement possibles.
La conséquence est que le nombre d'accès mémoire est drastiquement diminué : de 3 par instructions sur une architecture mémoire-mémoire, on passe à seulement un avec un accumulateur. Les opérations dyadiques ont besoin d'un seul accès mémoire pour lire la seconde opérande, les opérations monadique en font aussi un seul pour lire leur unique opérande.
{|class="wikitable"
|-
! Classe d'architecture
! Nombre d'accès mémoire par opération dyadique
|-
|-
! Architecture à accumulateur
| Un accès mémoire par instruction, pour lire la seconde opérande
|-
! Architecture à registres
| Zéro si les opérandes sont dans les registres, un pour les opérations ''load-op'', LOAD et STORE.
|}
==Le jeu d'instruction des architectures à accumulateur sans registres d'indice==
L'accumulateur est adressé grâce au mode d'adressage implicite, de même que le résultat de l'opération. Par contre, les autres opérandes sont localisés avec d'autres modes d'adressage, et lues en mémoire RAM. Le résultat ainsi qu'un des opérandes sont adressés de façon implicite car dans l'accumulateur, seule la seconde opérande étant adressée directement. Grâce à l'accumulateur, une instruction ne fait qu'un seul accès mémoire maximum, ce qui rend le processeur très facile à implémenter.
===Les registres des anciennes architectures à accumulateur===
[[File:IBM 701console.jpg|vignette|IBM 701, console extérieure.]]
Les architectures à accumulateur étaient communes dans les années 50-60. A l'époque, les ordinateurs étaient des ''mainframes'', à savoir des ordinateurs gigantesques, qui occupaient une pièce de bâtiment complète dans le pire des cas, une armoire entière dans le meilleur. Les ordinateurs de l'époque étaient surtout utilisés pour du calcul scientifique ou des tâches d’ingénierie demandant beaucoup de calcul, rarement pour de la comptabilité ou des tâches administratives. En conséquence, ils devaient gérer des nombres entiers, mais ne supportaient pas de texte, ni de nombres encodés en BCD. De tels processeurs utilisaient l'adressage par mot, et non par byte, vu que ce dernier est surtout utile pour adresser des caractères de texte.
Les nombres flottants n'étaient pas encore apparus. A la place, les ordinateurs de l'époque géraient des nombres entiers de grande taille, de 30 bits ou plus. En conséquence, l'accumulateur faisait facilement 30 à 60 bits. Par exemple, les ordinateurs de la Série scientifique IBM 700/7000 géraient des entiers de 36 bits, l’accumulateur faisait 38 bits : 36 bits plus deux bits pour les débordements.
Historiquement, les premières architectures à accumulateur ne contenaient aucun autre registre que l'accumulateur. Ce n'est que dans les années 60 que de nombreuses architectures à accumulateur ont ajouté un second '''registre pour les multiplication/divisions'''. Un exemple est celui de l'IBM 701, qui incorporait un registre accumulateur de 38 bits et un registre multiplieur de 36 bits. Le registre mémorise le multiplieur lors d'une opération de multiplication. Il mémorise donc un opérande, pas le résultat. Il peut aussi décaler le multiplieur vers la droite/gauche, ce qui est utile pour exécuter la multiplication. C'est ce qui est fait sur l'IBM 7094.
Une autre possibilité est que ce registre mémorise une partie du résultat de l'opération. Pour rappel, le résultat d'une multiplication/division est codé sur deux fois de bits que ses opérandes. Par exemple, multipliez deux opérandes de 30 bits, vous obtiendrez un résultat de 60 bits. Les 30 bits de poids faible du résultat vont dans l'accumulateur, les 30 bits de poids fort vont dans ce second registre.
Les architectures à accumulateur parfois un '''registre pour le pointeur de pile''', utilisé pour gérer les fonctions/procédures. Les architectures à accumulateurs supportaient une pile d'adresse de retour, souvent une pile d'appel. Mais pour cela, il fallait mémoriser le pointeur de pile dans le processeur, ce qui demandait un registre dédié.
===L'adressage indirect avec l'accumulateur===
Les instructions LOAD et STORE existent bel et bien sur les architectures à accumulateur, mais n'ont pas les mêmes modes d'adressages. L'instruction LOAD copie une donnée de la RAM vers l'accumulateur, l'instruction STORE copie l'accumulateur dans une adresse. Les deux instructions n'ont pas besoin d'adresser l'accumulateur, qui est adressé de manière implicite, juste de préciser l'adresse à lire/écrire.
Les architectures à accumulateur supportaient souvent le mode d'adressage indirect mémoire. Un exemple est celui des ordinateurs Data General Nova, qui sont des architectures à accumulateur et qui supportaient ce mode d'adressage. Les deux instructions LOAD et STORE existaient en deux versions, distinguées par un bit d'indirection. Si ce bit est à 0 dans l'opcode, alors l'instruction utilise le mode d'adressage absolu normal : l'adresse intégrée dans l'instruction est celle de la donnée. Mais s'il est à 1, alors l'adresse intégrée dans l'instruction est celle du pointeur.
Cependant, la présence de l'accumulateur permettait d'utiliser l'adressage indirect à registre, pour gérer les pointeurs. Pour rappel, avec le mode d'adressage indirect à registre, l'adresse à lire/écrire est dans un registre. Ici, l'adresse à lire/écrire est prise dans l'accumulateur, seul registre disponible pour. L'adressage indirect est plus simple à implémenter pour l'instruction LOAD, car elle prend un seul opérande : l'adresse à lire. L'adresse à lire est placée dans l'accumulateur, la donnée lue est elle aussi chargée dans l'accumulateur. Pour l'instruction STORE, il faut fournir deux opérandes, l'adresse et la donnée à écrire, ce qui peut poser problème. Mais au pire, il est toujours possible d'utiliser l'adressage absolu ou indirect mémoire : l'adresse est dans l'instruction, la donnée à écrire dans l'accumulateur.
===L'encodage des instructions===
Sur une architecture à accumulateur l'encodage d'une instruction dyadique est assez simple, vu que l'accumulateur est adressé implicitement. La seconde opérande est localisée soit par une adresse mémoire (adressage absolu), soit est une constante (adressage immédiat). L'adresse mémoire est généralement assez longue, plus que l'opcode.
{|class="wikitable"
|+ Encodage d'une instruction dyadique
|-
! rowspan="2" | Opcode
| Adresse mémoire (adressage absolu)
|-
| Constante (adressage immédiat)
|}
L'encodage d'une instruction monadique est similaire. Si l'opérande est lue depuis la mémoire RAM, alors l'instruction est encodée comme une instruction dyadique. Il en est de même pour les instructions qui copient une constante dans l'accumulateur. Par contre, si l'opérande est dans l'accumulateur, alors il y a juste besoin d'encoder l'opcode. La majorité des instructions a besoin de préciser une adresse, rares sont celles qui s'en passent. Au vu de cet encodage, les architectures à accumulateur sont qualifiées d''''architectures à une adresse''' par abus de langage.
Il est intéressant de contraster leur encodage avec les architectures à registres. Les architectures à registre doivent encoder deux opérandes en plus de l'opcode, avec éventuellement où enregistrer le résultat sur les architectures 3-adresses. Par contre, les opérandes sont généralement des noms de registre, ce qui prend moins de place qu'une adresse mémoire. A la rigueur, les instructions avec une constante immédiate prennent un peu plus de place, car elles doivent encoder un nom de registre en plus de la constante et de l'opcode. Les instructions ''load-op'' des processeurs CISC sont un peu dans le même cas, sauf qu'il faut remplacer la constante par une adresse, qui a généralement la même taille. Les instructions sont donc en moyenne plus courte sur les processeurs à registre, du fait de la présence de registres.
==La micro-architecture des architectures à accumulateur sans registres d'indice==
L'organisation interne d'une architecture à accumulateur est très différente de celle des processeurs à registre. Elle est plus ou moins la même pour tous ces processeurs, le point important étant que le chemin de données se résume à une ALU, un registre accumulateur et le bus de données. L'ALU est reliée au registre accumulateur, ainsi qu'au bus de données pour lire la seconde opérande, comme illustré ci-dessous.
[[File:Accumulator.png|centre|vignette|upright=2|Accumulateur.]]
===L'unité de calcul et l'accumulateur===
Pour simplifier l'implémentation, le résultat est mémorisé dans un registre en sortie de l'unité de calcul. La raison est qu'on ne veut pas altérer l'accumulateur tant que le résultat final n'est pas totalement calculé. Rappelons que l'ALU ne fournit pas un résultat d'un seul bloc, mais que certains bits arrivent avant les autres, typiquement les bits de poids faible. Si le résultat était écrit dans l'accumulateur directement, il écraserait des bits de l’opérande en cours d'utilisation, ce qui fausserait le résultat.
[[File:Accumulateur avec registre de sortie.png|centre|vignette|upright=2|Accumulateur avec registre de sortie]]
Une autre solution utilisait un registre entre l'accumulateur et l'unité de calcul, appelé l’'''''accumulator latch'''''. Il remplace le registre en sortie de l'ALU, dans le sens où il permet d'écrire dans l'accumulateur sans effacer l'opérande, pendant que l’opération est en cours dans l'ALU. L'accumulateur est copié dans l’''accumulator latch'', avant que l'ALU démarre ses calculs. L'opérande est donc maintenue même si on commence à écrire le résultat dans l'accumulateur.
Sur le 8085 d'Intel, l’''accumulator latch'' peut être initialisé avec une constante prédéfinie, ce qui permet d'implémenter certaines instructions très facilement. Par exemple, il peut être initialisé à 0, ce qui permet d'implémenter les instructions MOV et INC (incrémentation). Un MOV est équivalent à faire un OU entre le registre lu et 0. Une instruction INC initialise l'entrée de retenue de l'unité de calcul à 1, puis ajoute 0. La décrémentation est implémentée de la même manière, sauf que l’''accumulator latch'' est initialisé à -2 pour compenser l'entrée de retenue à 1. De plus, pour supporter les conversion de décimal à BCD, l’''accumulator latch'' peut être initialisé avec les constantes 0x00, 0x06, 0x60, or 0x66. L'''accumulator latch'' est relié à divers fils de commande provenant de l'unité de contrôle, qui décide quelle valeur d'initialisation utiliser en fonction de l'instruction décodée.
[[File:Accumulator latch.png|centre|vignette|upright=2|Accumulator latch]]
[[File:Chemin de données à un seul bus.png|vignette|Chemin de données à un seul bus]]
De même, la seconde opérande, celle lue sur le bus de données, est mémorisée dans un registre en amont de l'ALU. C'était notamment très utile si le processeur utilisait une ALU plus courte que les opérandes, avec par exemple une ALU 4 bits pour un CPU 8 bits. Les anciens processeurs à accumulateur de type ''mainframe'' utilisaient des opérandes de grande taille, du genre 36 ou 48 bits, ce qui avait des conséquences sur l'unité de calcul utilisée, ainsi que sur la communication avec la mémoire. Il arrivait que de tels processeurs utilisaient des ALU sérielles, ou du moins octet-sérielles, plutôt qu'une véritable ALU 36 bits. Nous verrons aussi que c'est très utile sur les processeurs à accumulateur avec un bus interne unique, dans la suite du chapitre.
===La micro-architecture des architectures à accumulateur avec instructions LOAD/STORE===
Nous venons de voir comment est implémenté l'unité de calcul et l'accumulateur, et comment le tout est relié au bus de données. Mais cela ne permet que d'avoir un processeur à accumulateur rudimentaire, qui ne gére que des instructions arithmétiques et logiques. Il faut aussi gérer le cas des opérations LOAD/STORE et des modes d'adressages associés, mais c'est le séquenceur qui s'en occupe. Avec l'adressage absolu, les instructions LOAD et STORE ne font que connecter l'accumulateur au bus de données. L'instruction STORE nécessite de connecter l'accumulateur au bus de données, de manière à ce que le transfert des données se fasse de l'accumulateur vers le bus de données. L'instruction LOAD s'implémente de la même manière, sauf que le sens de transfert est inversé.
Cependant, il existe une optimisation qui permet d'implémenter l'instruction LOAD sans ajouter de circuits. Pour cela, il suffit que l'unité de calcul gére les opérations ''pass through'', à savoir des opérations qui se contentent de recopier un opérande sur la sortie. Ici, l'idée est de recopier l'opérande provenant du bus de données.
[[File:Architecture à accumulateur, microarchitecture.png|centre|vignette|upright=2|Architecture à accumulateur, microarchitecture]]
Pour gérer nativement l'adressage indirect à registre, il suffit de connecter l'accumulateur au bus d'adresse. Le plus simple est d'ajouter un multiplexeur, comme illustré ci-dessous. La donnée lue est copiée dans l'accumulateur, ce qui fait qu'il vaut mieux utiliser un registre d’interfaçage, l'accumulateur n'étant pas utilisable à la fois pour le bus d'adresse et de données.
[[File:Adressage indirect sur une architecture à accumulateur.png|centre|vignette|upright=2|Adressage indirect sur une architecture à accumulateur]]
Pour finir, voyons comment le pointeur de pile et le ''program counter'' sont implémentés. Les architectures à accumulateur ont souvent des adresses de taille différente des données, ce qui fait qu'il vaut mieux utiliser un circuit incrémenteur dédié pour incrémenter le ''program counter'', plutôt que de l'incrémenter via l'unité de calcul. Les architectures à accumulateur ont parfois un pointeur de pile, qui gère une pile d'adresse de retour, pas une vraie pile d'appel. Aussi, le pointeur de pile est censé être incrémenté et décrémenté, pas plus. Pas d'addition ou de soustraction pour gérer des cadres de pile. Là encore, c'est la solution de l'incrémenteur séparé qui est retenue. Pour économiser des transistors, il n'y a qu'un seul incrémenteur partagé pour les deux.
==Les architectures à accumulateur à registres d'indice==
Les architectures à accumulateur décrites dans la section précédente sont capables de faire de l'adressage indirect, mais n'incluent pas les modes d'adressage base + indice et absolus indicés, qui prennent une adresse et y ajoute un indice. Il s'agit des toutes premières architectures à accumulateur, comme les premiers ordinateurs IBM ou le fameux PDP-8. Mais par la suite, les processeurs à accumulateurs ont inclus un support des modes d'adressages indicés, grâce à des '''registres d'indice'''.
===Les registres d'indice===
Les registres d'indice stockent des indices de tableaux. Ils permettaient de supporter deux modes d'adressage :
* Le '''mode d'adressage absolu indicé''' où une adresse fixe est additionnée à un indice variable. L'adresse fixe est intégrée dans l'instruction (adressage absolu), l'indice est dans un registre d'indice.
* Le '''mode d'adressage base + indice''', où l'adresse est dans l'accumulateur et l'indice dans le registre d'indice.
Les processeurs à accumulateur supportaient souvent des variantes des modes d'adressage précédents, où le registre d'indice était automatiquement incrémenté ou décrémenté à chaque utilisation.
Au départ, ces processeurs n'utilisaient qu'un seul registre d'indice qui se comportait comme un second accumulateur spécialisé dans les calculs d'adresses mémoire. Le processeur supportait de nouvelles instructions qui utilisaient ce registre d'indice de façon implicite. Mais avec le temps, les processeurs finirent par incorporer plusieurs de ces registres. Les instructions de lecture ou d'écriture devaient alors préciser quel registre d'indice utiliser, en précisant un nom de registre d'indice, un numéro de registre d'indice.
Il faut préciser que les registres d'indice ont une taille bien plus petite que l'accumulateur. Ils mémorisent des indices codés sur 16 bits ou moins, alors que l'accumulateur faisait typiquement 36 à 48 bits, parfois plus. La taille classique sur les anciens ''mainframes'' était de 15 bits, parfois moins. Il n'était pas rare de tomber sur des registres d'indice de 8 ou 9 bits. Leur petite taille rendait leur implémentation matérielle peu couteuse. Et c'est ce qui explique qu'ils étaient préférés à l'usage d'un second accumulateur.
Un exemple est le cas du processeur Motorola 6809, un processeur à accumulateur qui contient deux registres d'indices nommés X et Y. L'accumulateur est noté D et fait 16 bits, il peut être parfois géré comme deux accumulateurs séparés A et B de 8 bits chacun. Il contenait aussi deux pointeurs de pile, l'un pour les programmes, l'autre pour le système d'exploitation, ainsi qu'un ''program counter''. Le registre de page était utilisé pour l'adressage absolu, comme vu dans le chapitre sur les modes d'adressage.
[[File:6809 Internal Registers.svg|centre|vignette|upright=2|6809 Internal Registers]]
Les processeurs IBM avaient autrefois plusieurs registres d'indice. Par exemple, l'IBM 704 avait trois registres d'indice de 15 bits. Leur contenu était soustrait de l'adresse absolue. Une instruction pouvait utiliser plusieurs registres d'indice pour adresser son opérande. Toute instruction utilisait trois bits pour sélectionner les registres d'indice utilisés. Fait assez original, lorsque plusieurs registres d'indice sont sélectionnés, le processeur n'additionne pas les trois registres à l'adresse de base. À la place, il fait un OU bit à bit entre les registres d'indice sélectionnés, et additionne le résultat à l'adresse.
Les processeurs IBM à accumulateur ont fait ça sur toute la gamme IBM 700/7000, pour des raisons de compatibilité. Les processeurs suivants avaient 7 registres d'indices, mais conservaient les trois bits pour adresser les registres d'indices. Ils pouvaient fonctionner dans deux modes. Le premier mode est plus intuitif : les trois bits précisent un registre d'indice parmi les 7, qui est additionné avec l'adresse absolue. La valeur zéro indique qu'aucun registre d'indice n'est utilisé, ce qui explique qu'il y a 7 registres d'indice et non 8. Un second mode, compatible avec l'IBM 704, fait un OU logique entre les registres d'indice sélectionnés. Seuls les trois premiers registres d'indices peuvent être sélectionnés dans ce mode. Il y a deux instructions pour changer de mode : une pour passer en mode compatible, l'autre pour le quitter pour l'autre mode.
Quelques rares processeurs à registres généraux ont utilisés des registres d'indice, en plus des registres généraux. Ce qui fait l'association que nous avons faite entre registres d'indice et architectures à accumulateur est imparfait, bien que solide sur le principe. Un exemple d'architecture de ce type sont les architectures de la série UNIVAC 1100/2200. Ils disposaient de 128 registres, qui étaient mappés en mémoire à partir de l'adresse mémoire 0, la majorité étant inaccessibles par le programmeur. Ils regroupaient 12 registres accumulateurs, 11 registres d'indice et 4 registres hybrides qui pouvaient servir soit de registre d'indice, soit de registres accumulateurs.
===La micro-architecture des architectures à accumulateur avec registres d'indice===
La présence de registres d'indice modifie grandement l'implémentation du processeur. En effet, il faut rajouter un banc de registre pour les registres d'indice. Le banc de registre est monoport, car on a besoin de lire ou d'écrire un indice à la fois. Et il faut aussi potentiellement rajouter de quoi faire les calculs d'adresse. Deux solutions sont possibles : une ALU dédiée aux calculs d'adresse, une seule ALU pour toutes les opérations.
Dans le premier cas, il y a une ALU séparée associée aux registres d'indice. L'ALU et les registres d'indice sont placés en sortie du séquenceur, en-dehors du chemin de données, la sortie de l'ALU est directement connectée au bus d'adresse. L'unité de calcul d'adresse peut être utilisée pour incrémenter le ''program counter''. Un défaut de cette approche est qu'elle ne gère pas l'adresse indirect à registre.
[[File:Chemin de données sans support des pointeurs, avec adressage absolu indicé.png|centre|vignette|upright=2|Chemin de données sans support des pointeurs, avec adressage absolu indicé]]
Une autre option utilise un bus interne, qui interconnecte tout le chemin de données. Dans sa version la plus simple, il est relié à l'accumulateur, l'unité de calcul, le banc de registre d'indice et le bus de données. Avec cette solution, l'ALU est utilisé à la fois pour calculer les adresses et pour les instructions de calcul. En reliant le bus interne au bus d'adresse à travers un multiplexeur, on gère naturellement les adressages indirects.
[[File:Architecture à accumulateur avec registres associés.png|centre|vignette|upright=2.5|Architecture à accumulateur avec registres associés]]
Il faut noter que sur les architectures Von Neumann, le séquenceur est relié à ce bus interne. En effet, charger une instruction demande de passer par le bus mémoire, donc par l’intermédiaire de ce bus internet. Le ''program counter'' est envoyé sur ce bus pour lire l'instruction, puis l'instruction lue est recopiée dans le registre d'instruction. Le chargement d'une instruction est donc géré comme une lecture des plus classiques. De plus, cela permet d'incrémenter le ''program counter'' au niveau de l'unité de calcul entière. Le ''program counter'' est envoyé sur le bus interne, incrémenté par l'ALU, puis le résultat est recopié dans le ''program counter'' via le bus interne.
[[File:Architecture à accumulateur avec bus unique de type Von Neumann.png|centre|vignette|upright=2|Architecture à accumulateur avec bus unique de type Von Neumann]]
==Les processeurs bi-accumulateurs : le Motorola 6800==
Le Motorola 6800 était un processeur 8 bits qui gérait des adresses de 16 bits. Il contenait deux accumulateurs nommés A et B, de 8 bits chacun. Il disposait aussi d'un registre d'indice, d'un pointeur de pile et d'un ''program counter'', tous les trois de 16 bits. Le registre d'état regroupait 6 bits, qu'on ne détaillera pas ici.
[[File:MC6800 Processor Diagram.png|centre|vignette|upright=2|Interface et registres du MC6800.]]
La présence des deux accumulateurs impactait surtout les instructions dyadiques. Les instructions monadiques avaient juste à préciser où se trouvait l'opérande : soit en RAM, soit dans le premier accumulateur, soit dans le second. Pour les opérations dyadiques, la gestion était totalement différente. En théorie, le premier opérande est dans un accumulateur, soit A, soit B. La seconde opérande vient soit de l'autre accumulateur, soit de la mémoire RAM. Et selon les instructions, tout variait.
Pour l'addition, il y avait trois instructions. Les deux premières additionnaient un opérande provenant de la mémoire avec un accumulateur. L'instruction ADDA sélectionnait le premier accumulateur, l'instruction ADDB sélectionnait le second accumulateur. Mais une troisième instruction, l’instruction ABA, permettait d'additionner le contenu des deux accumulateurs.
Pour les autres opérations, il n'était pas possible d'utiliser les deux accumulateurs en même temps. La seule possibilité était de faire une opération entre un accumulateur et un opérande venant de la mémoire. Toutes les instructions étaient en double, avec une copie par accumulateur. Par exemple, l'instruction ANDA faisait un ET entre l’accumulateur A et l'opérande mémoire, l'instruction ANDB faisait pareil avec l'accumulateur B.
==Les architectures hybrides registres-accumulateur==
Il a existé quelques architectures qui étaient des hybrides entre architectures à accumulateur et architecture à registre. Elles avaient un accumulateur unique, couplé à un banc de registres généraux. D'autres registres étaient souvent présents, comme un registre d'état, des registres pour la pile, etc.
Elles sont apparues assez tôt, dès les années 50. Et c'était à une époque où les ordinateurs étaient intégralement construits avec des tubes à vides et autres mémoires spécialisées. Par exemple, le Bull Gamma 3 était un ordinateur de type ''mainframe'' qui disposait de deux accumulateurs, de 5 registres généraux, de deux registres pour la pile, d'un registre à décalage utilisé pour les opérations arithmétiques et BCD, et d'un registre d'état rudimentaire de deux bits (un bit de signe, un bit pour les résultats de comparaison).
Mais ces architectures sont restées assez confidentielles pendant les années 50 à 80. Par la suite, elles ont eu un regain de popularité durant les années 80-90. Elles ont alors servit de transition entre architectures à accumulateur proprement dites, et architectures à registres. Par exemple, les processeurs Intel 8 bits disposaient de 7 registres de 8 bits nommés A, B, C, D, E, F, H, L, SP. Ils correspondent respectivement à :
* l'accumulateur A ;
* six registres nommés B, C, D, E, H et L ;
* le registre d'état F ;
* le pointeur de pile SP.
Sur ces processeurs, les instructions dyadiques devaient mettre leur premier opérande dans l'accumulateur, la seconde provenait soit des registres, soit de la RAM, soit d'une constante immédiate. Les opérations monadiques pouvaient lire leur opérande depuis l'accumulateur, les autres registres ou la RAM, tout était permis. Les registres d'indices disparaissaient sur ces architectures, en théorie. Les registres généraux pouvaient être utilisés comme registre d'indice ou pour stocker des opérandes, ils étaient assez versatiles pour servir de registres d'indices.
La présence de registres a de nombreux avantages, comparé aux architectures à accumulateur pures. Les instructions arithmétiques sont plus rapide, lire un registre étant plus rapide qu'un accès RAM. Les performances sont donc augmentées. De plus, les instructions arithmétiques utilisant ces registres sont plus courtes : pas besoin d'encoder une adresse mémoire, un nom de registre suffit. Vu que les processeurs de l’époque avaient des instructions de taille variable, cela améliorait la densité de code.
===La micro-architecture des processeurs hybrides registres-accumulateur===
La micro-architecture de ces processeurs est très similaire à celle d'un processeur avec des registres d'indices. La seule différence est que le banc de registre contient des registres généraux et non des registres d'indices. Le banc de registre est systématiquement monoport, car il n'avait aucune raison d'être multiport. Pour les instructions dyadiques, seules à lire deux opérandes, il ne servait que pour la seconde opérande, la première était lue depuis l'accumulateur.
Les processeurs hybrides registre-accumulateur se classent en deux types principaux : ceux qui ont un seul bus interne, et ceux qui en ont deux. Le premier cas est identique à celui vu précédemment pour les architectures à accumulateur avec registres d'indice, à la seule différence est que le banc de registre contient des registres généraux et non des registres d'indices. Afin de gérer l'adressage indirect à registre, le bus interne est connecté aux deux registres d’interfaçage mémoire.
[[File:Architecture à accumulateur avec bus unique de type Von Neumann.png|centre|vignette|upright=2|Architecture à accumulateur avec bus unique de type Von Neumann]]
Notons que cela permet aussi d'implémenter facilement les branchements indirects, car le bus interne permet d'échanger des adresses entre ''program counter'' et banc de registre. De même, il est possible d'utiliser l'ALU pour gérer les branchements indirects., en plus de l'utiliser pour incrémenter le ''program counter''.
[[File:Single bus organization.jpg|centre|vignette|upright=2|Single bus organization]]
Une autre solution utilisait deux bus internes : un connecté au bus de données, un autre relié au bus d'adresse. Le bus de commande mémoire était lui commandé par le séquenceur, l'unité de contrôle. L'intermédiaire entre ces deux bus était le banc de registre, ainsi que les autres registres. Le banc de registre était connecté aux deux bus interne, avec un port de lecture relié au bus d'adresse, un port de lecture-écriture relié au bus de données. Le port de lecture était utilisé pour l'adressage indirect, l'autre l'était pour le reste.
[[File:Proz1-e.png|centre|vignette|upright=2|Intérieur d'un processeur.]]
L'organisation à deux bus simplifiait la gestion du ''program counter'' et le chargement des instructions. Le ''program counter'' était soit séparé du banc de registre, soit placé dans le banc de registre. Les deux solutions étaient utilisés, tout dépend du processeur. Il faut noter que si le ''program counter'' est intégré au banc de registres, alors la microarchitecture du processeur est bien plus simple. L'envoi du ''program counter'' sur le bus d'adresse utilise le port de lecture relié au bus d'adresse, qui sert aussi pour l'adressage indirect. L'économie de circuits, sans compter la simplicité d'implémentation que cela implique, explique sans doute que la technique a été utilisée sur quelques processeurs anciens.
Le ''program counter'' était généralement incrémenté par l'ALU, ce qui explique qu'il soit connecté au bus interne pour les données. La connexion est aussi utile pour gérer les branchements indirects, qui copient un registre dans le ''program counter'', ainsi que les branchements relatifs (addition dans l'ALU), voire les branchements directs (l'adresse vers laquelle brancher est envoyée en entrée de l'ALU et propagée en sortie avec une opération ''pass through'').
[[File:Connexion du program counter sur les bus avec PC dans le banc de registres.png|centre|vignette|upright=2|Connexion du program counter sur les bus avec PC dans le banc de registres]]
===Les registres d'interruption avec un processeur hybride-accumulateur : l'exemple du Z80===
Un exemple de processeur registre-accumulateur à deux bus interne est le Z80, un processeur fortement inspiré des CPU Intel 8 bits. Il a un jeu d'instruction similaire, mais a diverses améliorations par rapport au design original. Notamment, le processeur a des registres séparés pour les interruptions.
Sur le Z80, les registres généraux sont dupliqués avec 6 registres pour les interruptions et 6 registres pour les programmes autres. Leur copie pour les interruptions sont nommées B', C', D', E', H', L'. Les 12 registres sont placés dans le banc de registre, ce qui implique que le fenêtrage de registres est utilisé pour gérer la séparation entre registre d'interruption et normaux. Il faut noter que l'accumulateur et le registre d'état sont aussi dupliqués, leurs copies étant nommées A' et F'. Mais leur duplication se fait autrement que par fenêtrage de registre.
En plus des registres précédents, le Z80 incorporait deux registres d'indice nommés X et Y, ainsi qu'un pointeur de pile SP et un ''program counter'' PC. Ils n'étaient pas dupliqués pour les interruptions. Les registres d'indice étaient reliés à une unité de calcul d'adresse. L'unité de calcul d'adresse prenait deux opérandes : un indice, et une adresse mémoire provenant soit du banc de registre, soit de l'accumulateur. En clair, l'unité de calcul d'adresse faisait le lien entre les deux bus internet : le bus de données interne en entrée, le bus d'adresse en sortie.
À l'intérieur du processeur, tous les registres étaient regroupés dans un banc de registre unique, sauf les accumulateurs, les registres d'état et le ''program counter''. Bien que ce ne soit pas indiqué sur le schéma ci-dessous, le ''program counter'' est séparé du banc de registre, alors que le pointeur de pile est dedans. Le compteur IR est lui associé au ''program counter'', il est sorti du banc de registre. Le Z80 utilise lui aussi un incrémenteur séparé de l'ALU, qui est utilisé pour mettre à jour le ''program counter'', le pointeur de pile et un compteur de rafraichissement mémoire nommé IR sur le Z80 (pour rappel, le rafraichissement mémoire demande de balayer la mémoire d'adresse en adresse et été fait par le CPU à l'époque). De plus, il est utilisé pour les instructions INC et DEC qui incrémentent une opérande de 16 bits obtenue en combinant deux registres de 8 bits. En clair, l'incrémenteur du ''program counter'' a été réutilisé de beaucoup de manières originales.
[[File:Z80 arch.svg|centre|vignette|upright=3|Microarchitecture du Z80.]]
Le Z80 incorporait des instructions pour échanger le contenu des deux ensembles de registres, accumulateur inclus. Elles permettaient d'utiliser les registres d'interruption pour les programmes et réciproquement. En clair, cela doublait le nombre de registres si les interruptions n'étaient pas utilisées.
* L'instruction EXX échangeait les deux fenêtres de registres généraux : les registres B, C, D, E, H et L devenaient les registres B', C', D', E', H' et L' et inversement.
* L'instruction EX échangeait l'accumulateur et le registre d'état : les registres A,F devenait A',F' et inversement.
Le fenêtrage de registre était modifié par l'instruction EXX, qui échangeait les deux fenêtres de registres. Pour l'implémenter, une bascule était ajouté au processeur, appelons-la la bascule INT. Elle était relié au bus d'adresse du banc de registre, dont elle mémorisait le bit de poids fort. L'instruction EXX inversait la valeur de la bascule INT. Il est aussi possible d'échanger le contenu des registres D,E et H,L avec une instruction dédiée, ce qui est là encore fait par deux bascules : une pour les registres D,E et une autre pour les registres H,L.
Pour l'accumulateur et le registre d'état, le choix entre registre normal et registre d'interruption se faisait là encore par une seconde bascule appelée la bascule A. La bascule est reliée à un multiplexeur et un démultiplexeur, qui permet de choisir quel accumulateur relier à l'unité de calcul. L'instruction EX inverse le contenu de la bascule A.
<noinclude>
{{NavChapitre | book=Fonctionnement d'un ordinateur
| prev=L'unité de contrôle
| prevText=L'unité de contrôle
| next=Les processeurs 8 bits et moins
| nextText=Les processeurs 8 bits et moins
}}
</noinclude>
jh5ua9ahquwoje6tlcrswmbbey7al4i
Discussion Wikilivres:Le Bistro/2026
5
83406
762520
762149
2026-03-30T19:25:45Z
MediaWiki message delivery
36013
/* Actualités techniques n° 2026-14 */ nouvelle section
762520
wikitext
text/x-wiki
== Actualités techniques n° 2026-03 ==
<section begin="technews-2026-W03"/><div class="plainlinks">
Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/03|D’autres traductions]] sont disponibles.
'''En lumière cette semaine'''
* La Fondation Wikimedia a publié des questions directrices pour son plan annuel de juillet 2026 à juin 2027 sur les plateformes [[m:Special:MyLanguage/Wikimedia Foundation Annual Plan/2026-2027/Product & Technology OKRs|Meta]] et ''[[diffblog:2025/12/10/shaping-wikimedia-foundations-2026-2027-annual-goals-key-questions-for-the-wikimedia-movement/|Diff]]''. Celles-ci portent sur les tendances mondiales, une expérimentation plus rapide et plus constructive, un meilleur accompagnement des nouveaux contributeurs, le renforcement du rôle des éditeurs et des utilisateurs avancés, l'amélioration de la collaboration entre les projets, ainsi que le développement et la fidélisation du lectorat. Des commentaires et suggestions sont les bienvenus sur la [[m:Talk:Wikimedia Foundation Annual Plan/2026-2027|page de discussion]].
'''Actualités pour la contribution'''
* Dans le cadre des travaux en cours de l'équipe technique communautaire sur le projet [[m:Special:MyLanguage/Community Wishlist/W372|Listes de surveillance multiples]], l'affichage de [[Special:EditWatchlist|Modifier la liste de surveillance]] sera mis à jour entant que qu'une première étape vers la prise en charge de plusieurs listes de surveillance. De plus, la pagination de [[Special:Search|Recherche]] sera également mise à jour, dans le cadre du travail sur le souhait [[m:Special:MyLanguage/Community Wishlist/W186|Refonte de la pagination / navigation des pages]]. [https://phabricator.wikimedia.org/T411596]
* [[m:Special:GlobalWatchlist|La Liste de Surveillance Globale]] est une [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] de MediaWiki qui vous permet de voir vos listes de surveillance provenant de différents wikis sur la même page. Il a récemment été mis à jour pour ressembler davantage à la [[Special:Watchlist|Liste de surveillance]] régulière, par exemple en le préparant pour les comptes temporaires dans le masquage IP (y compris le réacheminement des liens des utilisateurs vers les pages de contributions), en mettant les titres de page en gras et en ouvrant les liens dans les résumés d'édition et les balises dans de nouveaux onglets du navigateur. [https://phabricator.wikimedia.org/T398361][https://phabricator.wikimedia.org/T298919][https://phabricator.wikimedia.org/T273526][https://phabricator.wikimedia.org/T286309]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:28|la tâche soumise|les {{formatnum:28}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:28||s}} la semaine dernière]]. Par exemple, le problème selon lequel les blocs globaux ne disposaient pas de l'option permettant de désactiver l'envoi d'e-mails a maintenant été résolu et sera disponible à l'utilisation à partir de la semaine du 13 janvier. [https://phabricator.wikimedia.org/T401293]
'''Actualités pour la contribution technique'''
* L'[[mw:Special:MyLanguage/VisualEditor/Citation tool|outil de citation VisualEditor]] et les [[mw:Special:MyLanguage/Help:Reference Previews|Aperçus de référence]] prennent désormais en charge "carte" comme type de référence. [https://phabricator.wikimedia.org/T411083]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.10|MediaWiki]]/[[mw:MediaWiki 1.46/wmf.11|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]] • [[m:Special:MyLanguage/Tech/News/2026/03|Traduire]] • [[m:Tech|Obtenir de l’aide]] • [[m:Talk:Tech/News|Donner son avis]] • [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].''
</div><section end="technews-2026-W03"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 12 janvier 2026 à 20:33 (CET)
<!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=29907192 -->
== Thank You for Last Year – Join Wiki Loves Ramadan 2026 ==
Dear Wikimedia communities,
We hope you are doing well, and we wish you a happy New Year.
''Last year, we captured light. This year, we’ll capture legacy.''
In 2025, communities around the world shared the glow of Ramadan nights and the warmth of collective iftars. In 2026, ''Wiki Loves Ramadan'' is expanding, bringing more stories, more cultures, and deeper global connections across Wikimedia projects.
We invite you to explore the ''Wiki Loves Ramadan 2026'' [[m:Special:MyLanguage/Wiki Loves Ramadan 2026|Meta page]] to learn how you can participate and [[m:Special:MyLanguage/Wiki Loves Ramadan 2026/Participating communities|sign up]] your community.
📷 ''Photo campaign on '' [[c:Special:MyLanguage/Commons:Wiki Loves Ramadan 2026|Wikimedia Commons]]
If you have questions about the project, please refer to the FAQs:
* [[m:Special:MyLanguage/Wiki Loves Ramadan/FAQ/|Meta-Wiki]]
* [[c:Special:MyLanguage/Commons:Wiki Loves Ramadan/FAQ|Wikimedia Commons]]
''Early registration for updates is now open via the '''[[m:Special:RegisterForEvent/2710|Event page]]'''''
''Stay connected and receive updates:''
* [https://t.me/WikiLovesRamadan Telegram channel]
* [https://lists.wikimedia.org/postorius/lists/wikilovesramadan.lists.wikimedia.org/ Mailing list]
We look forward to collaborating with you and your community.
'''The Wiki Loves Ramadan 2026 Organizing Team''' 16 janvier 2026 à 20:44 (CET)
<!-- Message envoyé par User:ZI Jony@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=29879549 -->
== <span lang="en" dir="ltr">Tech News: 2026-04</span> ==
<div lang="en" dir="ltr">
<section begin="technews-2026-W04"/><div class="plainlinks">
Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/04|Translations]] are available.
'''Updates for editors'''
* The tray shown on [[Special:Diff|Special:Diff]] in mobile view has been redesigned. It is now collapsed by default, and incorporates a link to undo the edit being viewed, making it easier for mobile editors and reviewers to take action while keeping the interface uncluttered. [https://phabricator.wikimedia.org/T402297]
* [[m:Special:GlobalWatchlist|The Global Watchlist]] lets you view your watchlists from multiple wikis on one page. The [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] continues to improve — it now automatically determines the text direction (ensuring correct display of sites with unusual domain names) and shows detailed descriptions for log actions. Later this week, a new permanent link for page creations and CSS classes for each entry element will be added. [https://phabricator.wikimedia.org/T412505][https://phabricator.wikimedia.org/T287929][https://phabricator.wikimedia.org/T262768][https://phabricator.wikimedia.org/T414135]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:32}} community-submitted {{PLURAL:32|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, the previously observed issue in Vector 2022, where anchor link targets were obscured by the sticky header, has now been addressed. [https://phabricator.wikimedia.org/T406114]
'''Updates for technical contributors'''
* As mentioned in the [[m:Special:MyLanguage/Tech/News/2025/44|October 2025 deprecation announcement]], MediaWiki Interfaces team will begin sunsetting all transform endpoints containing a trailing slash from the MediaWiki REST API the week of January 26. Changes are expected to roll out to all wikis on or before January 30th. All API users currently calling them are encouraged to transition to the non-trailing slash versions. Both endpoint variations can be found, compared, and tested using the [https://test.wikipedia.org/wiki/Special:RestSandbox REST Sandbox]. If you have questions or encounter any problems, please file a ticket in Phabricator to the [https://phabricator.wikimedia.org/project/view/6931/ #MW-Interfaces-Team board].
* Interactive reference documentation for the [[mw:Special:MyLanguage/Wikimedia REST API|Wikimedia REST API]] has moved. Requests to API docs previously hosted through [[mw:Special:MyLanguage/RESTBase|RESTBase]] (e.g.: <code dir=ltr>https://en.wikipedia.org/api/rest_v1/</code>) are now redirected to the [[w:en:Special:RestSandbox|REST Sandbox]].
* The [[mw:Special:MyLanguage/Wikidata Platform|WMF Wikidata Platform team]] (WDP) has published its [[d:Special:MyLanguage/Wikidata:Wikidata Platform team/Newsletter|January 2026 newsletter]]. It includes updates on the legacy full-graph endpoint decommissioning, the User-Agent policy change, the monthly Blazegraph migration office hours, and efforts to reduce regressions caused by the legacy endpoint shutdown. As a reminder, you can [[m:Special:MyLanguage/Global message delivery/Targets/WDP team updates|subscribe to the WDP newsletter]]!
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.12|MediaWiki]]
'''Meetings and events'''
* The [[mw:Wikimedia Hackathon Northwestern Europe 2026|Wikimedia Hackathon Northwestern Europe 2026]] will take place on 13-14 March 2026 in Arnhem, the Netherlands. Applications opened mid-December and will close soon or when capacity is reached. It's a two-day, technically oriented hackathon bringing together Wikimedians from the region. Hope to see you there!
'''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Contribute]] • [[m:Special:MyLanguage/Tech/News/2026/04|Translate]] • [[m:Tech|Get help]] • [[m:Talk:Tech/News|Give feedback]] • [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].''
</div><section end="technews-2026-W04"/>
</div>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 19 janvier 2026 à 21:29 (CET)
<!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=29943403 -->
== Révision annuelle du code universel de conduite et des lignes directrices de l'application ==
<section begin="announcement-content" />
Nous vous informons que la période de relecture annuelle du Code de conduite universel et des règles d'applications est actuellement ouverte. Vous pouvez faire vos commentaires sur les modifications que vous souhaitez apporter jusqu'au 9 février 2026. C'est la première d'une série d'étapes nécessaires pour la révision annuelle. Vous trouverez [[m:Special:MyLanguage/Universal Code of Conduct/Annual review/2026|d'autres informations et les discussions auxquelles participer sur la page UCoC de Meta]].
Le [[m:Special:MyLanguage/Universal Code of Conduct/Coordinating Committee|Comité de coordination du code universel de conduite]] (U4C — Universal Code of Conduct Coordinating Committee) est un groupe global dont le rôle est de fournir une implémentation équitable et cohérente de l'UCoC. Cette relecture annuelle a été envisagée et mise en place par l'U4C. Pour plus d'informations et les responsabilités de l'U4C, veuillez lire la [[m:Special:MyLanguage/Universal Code of Conduct/Coordinating Committee/Charter|Charte de l'U4C]].
Veuillez partager ces informations avec les autres membres concernés de votre communauté.
-- En coopération avec l'U4C, [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User talk:Keegan (WMF)|discussion]])<section end="announcement-content" />
19 janvier 2026 à 22:01 (CET)
<!-- Message envoyé par User:Keegan (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=29905753 -->
== Actualités techniques n° 2026-05 ==
<section begin="technews-2026-W05"/><div class="plainlinks">
Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/05|D’autres traductions]] sont disponibles.
'''Actualités pour la contribution'''
* La Fondation Wikimedia invite à donner des commentaires sur [[m:Special:MyLanguage/Product and Technology Advisory Council/Year1 Reflections and Proposed Way Forward 2026 Update|l’avenir proposé]] du [[:m:Special:MyLanguage/Product and Technology Advisory Council|Conseil consultatif des produits et technologies]] jusqu’au 28 février.
* Tous les utilisateurs disposant d'un compte enregistré peuvent désormais utiliser des clés d'accès pour la [[m:Special:MyLanguage/Help:Two-factor authentication|double authentification]] (2FA). Les clés d'accès sont un moyen simple de se connecter sans utiliser un second appareil. Elles vérifient l'identité de l'utilisateur à l'aide d'une empreinte digitale, d'une reconnaissance faciale ou d'un code PIN. Pour configurer une clé d'accès, configurez d'abord une méthode 2FA classique. Actuellement, pour se connecter avec une clé d'accès, les utilisateurs doivent également utiliser un mot de passe. Plus tard ce trimestre, la connexion sans mot de passe permettra aux utilisateurs de se connecter d'un simple clic avec une clé d'accès. Les utilisateurs disposant de droits avancés devront également avoir la 2FA activée. Cela fait partie du projet [[mw:Special:MyLanguage/Product Safety and Integrity/Account Security|Sécurité du compte]].
* Les contributeurs non enregistrés sur des IP bloquées ou des plages d'IP bloquées peuvent désormais interagir sur le wiki pour faire appel d'un blocage en créant un compte temporaire afin de contester un blocage sur la page de discussion de l'utilisateur, sauf si l'option « empêcher cet utilisateur de modifier sa propre page de discussion » est activée. Cela résout le problème des utilisateurs déconnectés incapables d'utiliser le processus de déblocage par défaut via la page de discussion de l'utilisateur. [https://phabricator.wikimedia.org/T398673]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:20|la tâche soumise|les {{formatnum:20}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:20||s}} la semaine dernière]]. Par exemple, la description des méthodes d'authentification à deux facteurs (2FA) sur la page de gestion a été mise à jour. Il est désormais plus clair et plus facile pour les utilisateurs à comprendre et à utiliser. [https://phabricator.wikimedia.org/T332385]
'''Actualités pour la contribution technique'''
* Une nouvelle variable AbuseFilter, <code>account_type</code>, a été ajoutée pour fournir un moyen fiable de déterminer le type de compte créé dans les actions <code>createaccount</code> et <code>autocreateaccount</code>. Dans le cadre de ce changement, la variable <code>accountname</code> a été renommée en <code>account_name</code>, et <code>accountname</code> est désormais obsolète. Les gestionnaires de filtres doivent mettre à jour tous les filtres qui utilisent des vérifications de type de compte codées en dur ou la variable obsolète. [https://phabricator.wikimedia.org/T414049]
* Les vignettes d'images demandées dans des tailles non standard, et en utilisant des méthodes non standard telles que les requêtes directes à <code dir=ltr><nowiki>upload.wikimedia.org/…</nowiki></code>, cesseront de fonctionner dans un proche avenir. Ce changement vise à prévenir les abus externes continus par des robots et des aspirateurs web. Certains utilisateurs ayant des CSS/JS personnalisés, les administrateurs d'interface qui peuvent corriger les gadgets et les thèmes locaux, ainsi que les auteurs d'outils, devront mettre à jour leur code pour utiliser des tailles de vignettes standard. [[phab:T414805|Des détails, des liens de recherche et des exemples de correction sont disponibles dans la tâche]].
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.13|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]] • [[m:Special:MyLanguage/Tech/News/2026/05|Traduire]] • [[m:Tech|Obtenir de l’aide]] • [[m:Talk:Tech/News|Donner son avis]] • [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].''
</div><section end="technews-2026-W05"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 26 janvier 2026 à 22:17 (CET)
<!-- Message envoyé par User:UOzurumba (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=29969530 -->
== <span lang="en" dir="ltr">Tech News: 2026-06</span> ==
<div lang="en" dir="ltr">
<section begin="technews-2026-W06"/><div class="plainlinks">
Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/06|Translations]] are available.
'''Updates for editors'''
* The "{{int:pageinfo-toolboxlink}}" feature, which gives validating information about a page ([{{fullurl:{{FULLPAGENAME}}|action=info}} example]), now automatically includes a table of contents. If there is a local [[{{ns:8}}:Pageinfo-header]] page created by individual users, it can now be removed. [https://phabricator.wikimedia.org/T363726]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:21}} community-submitted {{PLURAL:21|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, VisualEditor previously added bold or italic formatting inside link descriptions, making the wikicode complex. This has now been fixed. [https://phabricator.wikimedia.org/T409669]
'''Updates for technical contributors'''
* There was no XML dump on 20 January. Additionally, from now on, dumps will be generated once per month only. [https://phabricator.wikimedia.org/T414389]
* The MediaWiki Interfaces team removed support for all transform endpoints containing a trailing slash from the [https://www.mediawiki.org/wiki/Special:MyLanguage/API:REST%20API MediaWiki REST API]. All API users currently calling those endpoints are encouraged to transition to the non-trailing slash versions. If you have questions or encounter any problems, please file a ticket in phabricator to the [https://phabricator.wikimedia.org/project/view/6931/ #MW-Interfaces-Team board].
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.14|MediaWiki]]
'''Weekly highlight'''
* Users are reminded that the Wikimedia Foundation has shared some guiding questions for the July 2026–June 2027 Annual Plan on [[m:Special:MyLanguage/Wikimedia Foundation Annual Plan/2026-2027/Product & Technology OKRs|Meta]] and ''[[diffblog:2025/12/10/shaping-wikimedia-foundations-2026-2027-annual-goals-key-questions-for-the-wikimedia-movement/|Diff]]''. These focus on global trends, faster and healthier experimentation, better support for newcomers, strengthening editors and advanced users, improving collaboration across projects, and growing and retaining readership. Feedback and ideas are welcome on the [[m:Talk:Wikimedia Foundation Annual Plan/2026-2027|talk page]].
'''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Contribute]] • [[m:Special:MyLanguage/Tech/News/2026/06|Translate]] • [[m:Tech|Get help]] • [[m:Talk:Tech/News|Give feedback]] • [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].''
</div><section end="technews-2026-W06"/>
</div>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 2 février 2026 à 18:43 (CET)
<!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30000986 -->
== Actualités techniques n° 2026-07 ==
<section begin="technews-2026-W07"/><div class="plainlinks">
Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/07|D’autres traductions]] sont disponibles.
'''Actualités pour la contribution'''
* [[File:Maki-gift-15.svg|12px|link=|class=skin-invert|Concerne un souhait]] Les contributeurs connectés qui gèrent de grandes ou complexes listes de suivi peuvent désormais organiser et filtrer les pages surveillées de manière à améliorer leurs flux de travail grâce à la nouvelle fonctionnalité [[mw:Special:MyLanguage/Help:Watchlist labels|Étiquettes de liste de suivi]]. En ajoutant des étiquettes personnalisées (par exemple : pages que vous avez créées, pages surveillées pour vandalisme, ou pages de discussion), les utilisateurs peuvent identifier plus rapidement ce qui nécessite une attention, réduire la charge cognitive et répondre plus efficacement. Cela améliore l'utilisabilité de la liste de suivi, en particulier pour les éditeurs très actifs.
* Une nouvelle fonctionnalité disponible sur [[Special:Contributions|Special:Contributions]] montre [[mw:Special:MyLanguage/Trust and Safety Product/Temporary Accounts|des comptes temporaires]] qui sont probablement utilisés par la même personne, et rend ainsi le patrouillage moins chronophage. En vérifiant les contributions d'un compte temporaire, les utilisateurs ayant accès aux adresses IP des comptes temporaires peuvent désormais avoir une vue des contributions des comptes temporaires associés. La fonctionnalité recherche toutes les adresses IP associées à un compte temporaire donné pendant la période de conservation des données et affiche toutes les contributions de tous les comptes temporaires ayant utilisé ces adresses IP. [[mw:Special:MyLanguage/Trust and Safety Product/Temporary Accounts#February 2026: Improvements to the patroller tooling|Plus...]] [https://phabricator.wikimedia.org/T415674]
* Lorsque les éditeurs prévisualisent une modification de wikitexte, la boîte de rappel indiquant qu'ils ne voient qu'une prévisualisation (qui est affichée en haut) a désormais un fond gris/neutre au lieu d'un fond jaune/d'avertissement. Cela facilite la distinction entre les notes de prévisualisation et les avertissements réels (par exemple, les conflits de modification ou les cibles de redirection problématiques), qui seront désormais affichés dans des boîtes d'avertissement ou d'erreur séparées. [https://phabricator.wikimedia.org/T414742]
* La [[m:Special:GlobalWatchlist|Liste de suivi globale]] vous permet de consulter vos listes de suivi provenant de plusieurs wikis sur une seule page. L' [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] continue de s'améliorer — elle prend désormais en charge correctement plus d'un site Wikibase, par exemple à la fois [[d:|Wikidata]] et [[testwikidata:|testwikidata]]. De plus, des problèmes concernant la direction du texte ont été résolus pour les utilisateurs qui préfèrent Wikidata ou d'autres sites Wikibase dans des langues de droite à gauche (RTL). [https://phabricator.wikimedia.org/T415440][https://phabricator.wikimedia.org/T415458]
* <span lang="en" dir="ltr" class="mw-content-ltr">The automatic "magic links" for ISBN, RFC, and PMID numbers have been [[mw:Special:MyLanguage/Help:Magic links|deprecated in wikitext since 2021]] due to inflexibility and difficulties with localization. Several wikis have successfully replaced RFC and PMID magic links with equivalent external links, but a template was often required to replace the functionality of the ISBN magic link. There is now a new [[mw:Special:MyLanguage/Help:Magic words#isbn|built-in parser function]] <code dir=ltr><nowiki>{{#isbn}}</nowiki></code> available to replace the basic functionality of the ISBN magic link. This makes it easier for wikis who wish to migrate off of the deprecated magic link functionality to do so.</span> [https://phabricator.wikimedia.org/T145604]
* Deux nouveaux wikis ont été créés :
** un {{int:project-localized-name-group-wikipedia}} dans [[d:Q35401|Jju]] ([[w:kaj:|<code>w:kaj:</code>]]) [https://phabricator.wikimedia.org/T413283]
** un {{int:project-localized-name-group-wikipedia}} dans [[d:Q1186896|Nawat]] ([[w:ppl:|<code>w:ppl:</code>]]) [https://phabricator.wikimedia.org/T413273]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:23|la tâche soumise|les {{formatnum:23}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:23||s}} la semaine dernière]].
'''Actualités pour la contribution technique'''
* Un nouveau groupe d'utilisateurs global a été créé : [[{{int:grouppage-local-bot}}|{{int:group-local-bot}}]]. Il sera utilisé en interne par le logiciel pour permettre aux robots communautaires de contourner les limites de débit appliquées aux [[w:en:Web_scraping|web scrapers]] abusifs. Les comptes approuvés en tant que robots sur au moins un wiki Wikimedia seront automatiquement ajoutés à ce groupe. Cela ne changera pas les autorisations dont dispose le robot. [https://phabricator.wikimedia.org/T415588]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.15|MediaWiki]]
'''Rencontres et évènements'''
* La [[mw:Special:MyLanguage/MediaWiki Users and Developers Conference Spring 2026|Conférence des utilisateurs et des développeurs de MediaWiki, Printemps 2026]] se tiendra du 25 au 27 mars à Salt Lake City, États-Unis. Cet événement est organisé par et pour la communauté MediaWiki de tiers. Vous pouvez proposer des sessions et vous inscrire pour y assister. [https://lists.wikimedia.org/hyperkitty/list/wikitech-l@lists.wikimedia.org/thread/AZBWVI46SDEB65PGR5J6E4TYOQQEZXM7/]
'''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]] • [[m:Special:MyLanguage/Tech/News/2026/07|Traduire]] • [[m:Tech|Obtenir de l’aide]] • [[m:Talk:Tech/News|Donner son avis]] • [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].''
</div><section end="technews-2026-W07"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 10 février 2026 à 00:30 (CET)
<!-- Message envoyé par User:Quiddity (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30026671 -->
== Actualités techniques n° 2026-08 ==
<section begin="technews-2026-W08"/><div class="plainlinks">
Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/08|D’autres traductions]] sont disponibles.
'''En lumière cette semaine'''
* <span class="mw-translate-fuzzy">L'[[mw:Special:MyLanguage/Wikimedia Site Reliability Engineering|équipe SRE]] va procéder au nettoyage d'[[m:Special:MyLanguage/Etherpad|Etherpad]], l'éditeur web open source de documents collaboratifs en temps réel. Tous les blocs-notes seront définitivement supprimés après le 30 avril 2026 – si des projets de migration sont encore en cours à cette date, l'équipe pourra réexaminer la date au cas par cas. Veuillez effectuer des sauvegardes locales de tout contenu que vous souhaitez conserver, car les données supprimées ne pourront pas être récupérées. Ce nettoyage permet de réduire la taille de la base de données et l'empreinte de l'infrastructure. Etherpad continuera de prendre en charge la collaboration en temps réel, mais le stockage à long terme n'est plus assuré. D'autres nettoyages pourront avoir lieu ultérieurement sans préavis.</span> [https://phabricator.wikimedia.org/T415237]
'''Actualités pour la contribution'''
* L'équipe de Recherche d'Informations lancera une [[mw:Special:MyLanguage/Readers/Information Retrieval/Phase 1|expérimentation sur l'application mobile Android]], afin de tester des fonctionnalités de recherche hybrides capables de gérer à la fois les requêtes sémantiques et par mots-clés. L'amélioration de la recherche sur la plateforme permettra aux lecteurs de trouver plus facilement ce qu'ils cherchent, directement sur Wikipédia. L'expérimentation sera d'abord lancée sur Wikipédia en grec fin février, puis sur les versions anglaise, française et portugaise en mars. [https://diff.wikimedia.org/2026/01/08/semantic-search-making-it-easier-to-find-the-information-readers-want/ En savoir plus] sur le blog ''Diff''. [https://www.mediawiki.org/wiki/Readers/Information_Retrieval]
* L'équipe « Croissance des lecteurs » mènera [[mw:Special:MyLanguage/Readers/Reader Growth/WE3.10.2 Mobile Table of Contents|une expérience]] auprès des utilisateurs de la version mobile du site web qui ajoute une table des matières et développe automatiquement toutes les sections des articles, afin de mieux comprendre les problèmes de navigation qu'ils rencontrent. Le test sera disponible sur les versions arabe, chinoise, anglaise, française, indonésienne et vietnamienne de Wikipedia.
* Auparavant, les notifications ([[{{ns:8}}:Sitenotice]] et [[{{ns:8}}:Anonnotice]]) du site ne s'affichaient que sur la version ordinateur. Maintenant, elles s'afficheront désormais sur toutes les plateformes. Les utilisateurs mobiles verront ces notifications. Les administrateurs du site doivent être prêts à tester et à corriger les notifications sur les appareils mobiles afin d'éviter toute interférence avec les articles. Pour désactiver ces notifications, les administrateurs d'interface peuvent ajouter <code dir="ltr">#siteNotice { display: none; }</code> à [[{{ns:8}}:Minerva.css]]. [https://phabricator.wikimedia.org/T138572][https://phabricator.wikimedia.org/T416644]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:19|la tâche soumise|les {{formatnum:19}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:19||s}} la semaine dernière]]. Par exemple, un problème concernant la section ''[[Special:RecentChanges|Spécial:Modifications récentes]]'' a été résolu. Auparavant, cliquer sur « Masquer » dans les filtres actifs entraînait la disparition du bouton « Afficher les nouvelles modifications depuis… », alors qu'il aurait dû rester visible. Ce bouton fonctionne désormais correctement. [https://phabricator.wikimedia.org/T406339]
'''Actualités pour la contribution technique'''
* Une nouvelle documentation est désormais disponible pour aider les rédacteurs à déboguer les fonctionnalités de recherche interne. Elle facilite le dépannage lorsque des pages n'apparaissent pas dans les résultats, lorsque le classement semble inattendu et lorsqu'il est nécessaire d'inspecter le contenu indexé, ce qui permet de mieux comprendre et d'analyser le comportement de la recherche. [[mw:Help:CirrusSearch/Debug|En savoir plus]]. [https://phabricator.wikimedia.org/T411169]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.16|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]] • [[m:Special:MyLanguage/Tech/News/2026/08|Traduire]] • [[m:Tech|Obtenir de l’aide]] • [[m:Talk:Tech/News|Donner son avis]] • [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].''
</div><section end="technews-2026-W08"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 16 février 2026 à 20:17 (CET)
<!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30086330 -->
== <span lang="en" dir="ltr">Tech News: 2026-09</span> ==
<div lang="en" dir="ltr">
<section begin="technews-2026-W09"/><div class="plainlinks">
Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/09|Translations]] are available.
'''Weekly highlight'''
* [[mw:Special:MyLanguage/Edit check/Reference Check|Reference Check]] has been deployed to English Wikipedia, completing its rollout across all Wikipedias. The feature prompts newcomers to add a citation before publishing new content, helping reduce common citation-related reverts and improve verifiability. In A/B testing, the impact was substantial: newcomers shown Reference Check were approximately 2.2 times more likely to include a reference on desktop and about 17.5 times more likely on mobile web. [https://analytics.wikimedia.org/published/reports/editing/reference_check_ab_test_report_final_2025.html]
'''Updates for editors'''
* The [[mw:Special:MyLanguage/Extension:InterwikiSorting|InterwikiSorting extension]], which allowed for the [[m:Special:MyLanguage/Interwiki sorting order|sorting of interwiki links]], has been undeployed from Wikipedia. As a result, editors who had enabled interwiki link sorting in non-compact mode (full list format) will now see links reordered. The links moving forward will be listed in the alphabetical order of language code. [https://phabricator.wikimedia.org/T253764]
* Later this week, people who are editing a page-section using the mobile visual editor, will notice a new "Edit full page" button. When tapped, you will be able to edit the entire article. This helps when the change you want to make is outside the section you initially opened. [https://phabricator.wikimedia.org/T387175][https://phabricator.wikimedia.org/T409112]
* [[mw:Special:MyLanguage/Readers/Reader Experience|The Reader Experience team]] is inviting editors to assess whether dark mode should still be considered "beta" on their wiki, based on their experience of how well it functions on desktop and mobile. If the feature is deemed mature, editors can update the interface messages in <code dir=ltr>MediaWiki:skin-theme-description</code> and <code dir=ltr>MediaWiki:Vector-night-mode-beta-tag</code> to indicate that dark mode is ready and no longer considered beta.
* The improved [[mw:Wikimedia_Apps/Team/iOS/Activity_Tab|Activity tab]] which displays user-insights is now available to all users of the Wikipedia iOS app (version 7.9.0 and later). Following earlier A/B testing that showed higher account creation among users with access to the feature, it has been rolled out to 100% of users along with some updates. The Activity tab now shows your edited articles in the timeline, offers editing impact insights like contribution counts and article view trends, and customization options to improve in-app experience for users.
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:21}} community-submitted {{PLURAL:21|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, a bug that prevented [[mw:Special:MyLanguage/Extension:DiscussionTools|DiscussionTools]] from working on mobile has now been fixed, restoring full functionality. [https://phabricator.wikimedia.org/T415303]
'''Updates for technical contributors'''
* The [[m:Special:GlobalWatchlist|Global Watchlist]] lets you view your watchlists from multiple wikis on one page. The [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] that makes this possible continues to improve. The latest upgrade is the inclusion of a [[mw:Extension:GlobalWatchlist#hook|new hook]], <code dir=ltr>ext.globalwatchlist.rebuild</code>, which fires after each watchlist rebuild. This allows you to run gadgets and user scripts for the Special page. [https://phabricator.wikimedia.org/T275159]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.17|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Contribute]] • [[m:Special:MyLanguage/Tech/News/2026/09|Translate]] • [[m:Tech|Get help]] • [[m:Talk:Tech/News|Give feedback]] • [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].''
</div><section end="technews-2026-W09"/>
</div>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 23 février 2026 à 20:03 (CET)
<!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30119102 -->
== Actualités techniques n° 2026-10 ==
<section begin="technews-2026-W10"/><div class="plainlinks">
Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/10|D’autres traductions]] sont disponibles.
'''En lumière cette semaine'''
* Le [[m:Special:MyLanguage/Wikipedia 25/Easter egg experiments|mode Anniversaire]] Wikipedia 25 est maintenant disponible sur Wikipédia en français, anglais, betawi, breton, chinois, espagnol, gorontalo, indonésien, italien, luxembourgeois, madurais, néerlandais, sicilien, tchèque, thaï et vietnamien ! Cette campagne à temps limitée célèbre 25 ans de Wikipédia avec une mascotte : « Baby Globe », disponible sous la forme d'un réglage. Lorsque ce réglage est activé, Baby Globe est montrée sur [[m:Special:MyLanguage/Wikipedia 25/Easter egg experiments/article configuration|environ 2 500 articles]], attendant d'être découverte par des lecteurs. Chaque communauté peut choisir d'activer le mode Anniversaire par consensus et en demandant à un administrateur de le rendre disponible et de le personaliser via une [[m:Special:MyLanguage/Wikipedia 25/Easter egg experiments#Community Configuration Demo|configuration]] sur le wiki local.
'''Actualités pour la contribution'''
* Le [[:m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing|sous-référencement]], une nouvelle fonctionalité pour réutiliser des références avec des détails différents est maintenant disponible sur Wikipédia en suédois, polonais et [[:phab:T418209|quelques autres]]. Vous pouvez [[:m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing#test|essayer la fonctionalité]] sur ces projets ou sur testwiki et [https://en.wikipedia.beta.wmcloud.org/wiki/Sub-referencing betawiki]. Les retours des premiers essais sur Wikipédia en allemand ont été [[:m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing/Learnings|publiés dans un rapport]]. Contactez l'équipe de Wikimédia Allemagne si vous êtes [[:m:Talk:WMDE Technical Wishes/Sub-referencing#Pilot wikis|intéressés pour devenir un wiki pilote]].
* La [[mw:Special:MyLanguage/Help:Edit check#Paste check|vérification du collage clavier]] sera disponible sur tous les Wikipédias cette semaine. Cette fonctionalité avertit les nouveaux contributeurs qui collent du texte qu'ils n'ont probablement pas écrit de vérifier si laisser celui-ci risque de causer une violation du droit d'auteur. La vérification du collage clavier [[mw:Special:MyLanguage/Edit check/Tags|marque]] toutes les modifications où l'avertissement a été montré pour permettre leur vérification. Les administrateurs locaux peuvent configurer les différents aspects de cette fonctionalité à travers [[{{#special:EditChecks}}]]. Des [[mw:Special:MyLanguage/Edit check/Paste Check#A/B Experiment|études]] sur 22 wikis ont montré que cette vérification permet une réduction de 18% des annulations comparé au groupe de contrôle. Les traducteurs peuvent [https://translatewiki.net/w/i.php?title=Special%3ATranslate&group=ext-visualeditor-ve-mw-editcheck&filter=&optional=1&action=translate aider à traduire] cette fonctionalité.
* <span lang="en" dir="ltr" class="mw-content-ltr">The [[mw:Special:MyLanguage/Readers/Reader Experience|Reader Experience team]] will be standardizing the user menu in the top right for all mobile users so that it is closer to the desktop experience. Currently this user menu is only visible to users with Advanced Mobile Controls (AMC) turned on. The only change is that a couple buttons previously in the left-side menu will move to the top right for users who do not have AMC turned on. This change is expected to go out March 9 and seeks to improve the user interface.</span> [https://phabricator.wikimedia.org/T413912]
* À partir de la semaine du 2 mars, les emails envoyés lorsqu'une adresse email a été ajoutée, supprimée ou changée pour un compte changera pour adopter un formattage HTML beaucoup plus agréable et plus clair que le texte brut précédent. [https://phabricator.wikimedia.org/T410807]
* Les notifications sont actuellement limitées à 2 000 entrées historiques par utilisateur et remontent à 2013 lorsque la fonctionnalité a été publiée. Le système va être modifié pour ne stocker que les notifications des 5 dernières années, mais jusqu'à 10 000 d'entre elles. Cela contribuera à la santé à long terme des infrastructures et à empêcher que les notifications plus récentes disparaissent trop tôt. [https://phabricator.wikimedia.org/T383948]
* <span lang="en" dir="ltr" class="mw-content-ltr">The [[m:Special:GlobalWatchlist|Global Watchlist]] which lets you view your watchlists from multiple wikis on a single page continues to see improvements. The latest update improves label usage experience. The [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] now allows activating the [[mw:Special:MyLanguage/Manual:Language#Fallback languages|language fallback system]] for Wikidata items without labels in the viewed language, and showing those labels in the user’s preferred Wikidata language if no <code dir=ltr>uselang=</code> URL parameter is provided.</span> [https://phabricator.wikimedia.org/T373686][https://phabricator.wikimedia.org/T416111]
* L'équipe Wikipédia Android a commencé un test beta de la [[mw:Special:MyLanguage/Readers/Information Retrieval/Phase 1|recherche hybride]] sur Wikipédia en grec. Cette recherche hybride supporte les requêtes sémantique et par mot clés, permettant aux utilisateurs de trouver ce qu'ils cherchent plus facilement.
* Pour des raisons de sécurité, les membres de certains groupes sont [[m:Special:MyLanguage/Mandatory two-factor authentication for users with some extended rights|forcés d'avoir la double authentification]] (A2F) d'activée. Actuellement, l'A2F n'est nécessaire que pour utiliser les droits du groupe, et non pour en faire partie. Vu que ce système admet certaines failles, il sera [[phab:T418580|changé graduellement en mars]]. Les membres de ces groupes ne pourront plus désactiver la dernière méthose d'A2F sur leur compte, et il sera impossible d'ajouter des utilisateurs sans A2F à ces groupes. Il sera toujours possible de rajouter d'autres méthodes d'authentification et d'en enlever, tant qu'une est toujours activée. Dans la seconde moitié de mars, les utilisateurs sans A2F seront retirés de ces groupes. Cela s'applique aux administrateurs CentralNotice, aux vérificateurs d'utilisateurs, aux administrateurs d'interface, aux masqueurs, aux staff de Wikidata et Wikifonctions ainsi qu'aux bureaux IT et Confiance et sécurité de la WMF. Rien ne changera pour les autres utilisateurs. Voir la tâche liée pour le calendrier de déploiement. [https://phabricator.wikimedia.org/T418580]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:27|la tâche soumise|les {{formatnum:27}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:27||s}} la semaine dernière]]. Par exemple, le problème empêchant les utilisateurs de créer une instance dans [https://www.wikibase.cloud/ Wikibase.cloud] a maintenant été résolu. [https://phabricator.wikimedia.org/T416807]
'''Actualités pour la contribution technique'''
* <span lang="en" dir="ltr" class="mw-content-ltr">To help ensure [[mw:Special:MyLanguage/MediaWiki Product Insights/Responsible Reuse|fair use of infrastructure]], over the next month the Wikimedia Foundation will implement global API rate limits across our APIs. In early March, stricter limits will be applied to unidentified requests from outside Toolforge/WMCS and API requests that are made from web browsers. In April, higher limits will be applied to identified traffic. These limits are intentionally set as high as possible to minimise impact on the community. Bots running in Toolforge/WMCS or with the bot user right on any wiki should not be affected for now. However, all developers are advised to follow updated best practices. For more information, see [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits|Wikimedia APIs/Rate limits]].</span>
* <span lang="en" dir="ltr" class="mw-content-ltr">The Wikidata Query Service Linked Data Fragment (LDF) endpoint will be decommissioned in February. This endpoint served limited traffic, which was successfully migrated to other data access methods that were better suited to support existing use cases. The hardware used to support the LDF endpoint will be reallocated to support the ongoing backend migration efforts.</span> [https://phabricator.wikimedia.org/T415696]
* Le nouvel analyseur syntaxique Parsoid [[mw:Special:MyLanguage/Parsoid/Parser Unification/Updates|continue d'être déployés sur plus de wikis]], améliorant la pérennité de la platforme et rendant plus facile l'ajout de nouvelles fonctionalités de lecture et de modification. Parsoid est maintenant l'analyseur par défaut sur 488 wikis de la WMF (268 Wikipédias), couvrant plus de 10% de toutes les lectures de pages Wikipédia.
* Le processus et les critères pour [[Special:MyLanguage/Wikimedia Enterprise#Access|demander un accès exceptionnel]] au flux à fort volume de l'API ''Wikimédia Entreprise'' (sans coût pour des utilisations en rapport à notre mission) [[m:Talk:Wikimedia Enterprise#Exceptional access criteria|ont maintenant été publiés]]. Notre but est de donner une documentation plus claire et plus complète aux utilisateurs.
* [https://techblog.wikimedia.org/ Le blog Tech], dédié à la communité technique de Wikimédia [https://techblog.wikimedia.org/2026/02/24/a-tech-blog-diff/ va migrer] vers [[diffblog:|Diff]], le blog pour les nouvelles et événements de la communauté. La migration devrait être terminée en Avril 2026, après quoi les nouveaux posts seront acceptés pour être publiés. Les lecteurs pourront lire les posts - anciens ou nouveaux - sur https://diff.wikimedia.org/.
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.18|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]] • [[m:Special:MyLanguage/Tech/News/2026/10|Traduire]] • [[m:Tech|Obtenir de l’aide]] • [[m:Talk:Tech/News|Donner son avis]] • [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].''
</div><section end="technews-2026-W10"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 2 mars 2026 à 18:51 (CET)
<!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30137798 -->
== <span lang="en" dir="ltr">Tech News: 2026-11</span> ==
<div lang="en" dir="ltr">
<section begin="technews-2026-W11"/><div class="plainlinks">
Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/11|Translations]] are available.
'''Weekly highlight'''
* [[m:Special:MyLanguage/Tech/Server switch|All wikis will be read-only]] for a few minutes on Wednesday, 25 March 2026 at [https://zonestamp.toolforge.org/1774450800 15:00 UTC]. This is for the datacenter server switchover backup tests, [[wikitech:Deployments/Yearly calendar|which happen twice a year]]. During the switchover, all Wikimedia website traffic is shifted from one primary data center to the backup data center to test availability and prevent service disruption even in emergencies.
* Last week, all wikis had 2 hours of read-only time, and extended unavailability for user-scripts and gadgets. This was due to a security incident which has since been resolved. Work is ongoing to prevent re-occurrences. For current information please see the [[m:Steward's noticeboard#Statement on Meta about today's user script security incident|post on the Stewards' noticeboard]] ([[m:Special:MyLanguage/Wikimedia Foundation/Product and Technology/Product Safety and Integrity/March 2026 User Script Incident|translations]]).
'''Updates for editors'''
* Users facing multiple blocks on mobile will now see the reasons for each block separately, instead of a generic message. This helps them understand why they are blocked and what steps they can take to resolve the issue. For example, users affected for using common VPNs (such as [[Special:MyLanguage/Apple iCloud Private Relay|iCloud Private Relay]]) will receive clearer guidance on what they need to do to start editing again. [https://phabricator.wikimedia.org/T357118]
* Later this week, [[mw:Special:MyLanguage/VisualEditor/Suggestion Mode|Suggestion Mode]] will become available as a beta feature within the visual editor at all Wikipedias. This feature proactively suggests various types of actions that people can consider taking to improve Wikipedia articles, and learn about related guidelines. The feature is locally configurable, and can also be locally expanded with custom Suggestions. Current settings can be seen at [[Special:EditChecks]] and there are [[mw:Special:MyLanguage/Help:Suggestion mode#For administrators %E2%80%93 local customization|instructions for how administrators can customize]] the links to point to local guidelines. The feature is connected to [[mw:Special:MyLanguage/Help:Edit check|Edit check]] which suggests improvements while someone is writing new content. In the future, the Editing team plans to evaluate the feature's impact with newcomers through a controlled experiment. [https://phabricator.wikimedia.org/T404600]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:23}} community-submitted {{PLURAL:23|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, the issue where the cursor became misaligned during the use of CodeMirror’s syntax highlighting, which makes wikitext and code easier to read, has now been fixed. This problem specifically affected users who defined a font rule in a custom stylesheet while creating a new topic with DiscussionTools. [https://phabricator.wikimedia.org/T418793]
'''Updates for technical contributors'''
* API rate limiting update: To help ensure [[mw:Special:MyLanguage/MediaWiki Product Insights/Responsible Reuse|fair use of infrastructure]], global API rate limits will be applied this week to requests without a compliant User-Agent that originate from outside Toolforge/WMCS and to unauthenticated requests made from web browsers. Higher limits will be applied to identified traffic in April. Bots running in Toolforge/WMCS or with the bot user right on any wiki should not be affected for now. However, all developers are advised to follow updated best practices. For more information, see [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits|Wikimedia APIs/Rate limits]].
* The new GraphQL API has been released. The API was developed as a flexible alternative to select features of the Wikidata Query Service (WDQS), to improve developer experience and foster adaptability, and efficient data access. Try it out and [[d:Wikidata:Wikibase GraphQL#Feedback and development|give feedback]]. You can also [https://greatquestion.co/wikimediadeutschland/GraphQLAPI/apply sign up for usability tests].
* The [[m:Special:MyLanguage/Product and Technology Advisory Council/Unsupported Tools Working Group|PTAC Unsupported Tools Working Group]] continued improvements to [[commons:Special:MyLanguage/Commons:Video2commons#|Video2Commons]] in February, with fixes addressing authentication errors, large-file handling, task queue visibility, and clearer upload behavior. Work is still ongoing in some areas, including changes related to deprecated server-side uploads. Read [[m:Special:MyLanguage/Product and Technology Advisory Council/Unsupported Tools Working Group#February 2026|this update]] to learn more.
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.19|MediaWiki]]
'''In depth'''
* The Article Guidance team invites experienced Wikipedia editors from selected [[mw:Special:MyLanguage/Article guidance/Pilot wikis and collaborators#Collaborators|pilot wikis]] and interested contributors from other Wikipedias to fill out this questionnaire which is available in [https://docs.google.com/forms/d/e/1FAIpQLSfmLeVWnxmsCbPoI_UF2jyRcn73WRGWCVPHzerXb4Cz97X_Ag/viewform English], [https://docs.google.com/forms/d/e/1FAIpQLSd6rzr4XXQw8r4024fE3geTPFe13M_6w7Mitj-YJi0sOlWTAw/viewform?usp=header Arabic], [https://docs.google.com/forms/d/e/1FAIpQLSdok3-RfB18lcugYTUMGkpwmqG_8p760Wv4dCXitOXOszjUDw/viewform?usp=header Bengali], [https://docs.google.com/forms/d/e/1FAIpQLSfjTfYp4jEo0akA4B1e-Nfg3QZPCudUjhJzHzzDi6AHyAaMGA/viewform?usp=header Japanese], [https://docs.google.com/forms/d/e/1FAIpQLScteVoI29Aue4xc72dekk-6RYtvmMgQxzMI900UOawrFrSTWg/viewform?usp=header Portuguese], [https://docs.google.com/forms/d/e/1FAIpQLSetdxnYwL3ub2vqA7awCg5hJZPMIYcDPaiTe12rY9h0GYnVlw/viewform?usp=header Persian], and [https://docs.google.com/forms/d/e/1FAIpQLScNvfJF-Ot-4pzA4qAN771_0QDJ4Li19YcUsaTgSKW8Nc7U_Q/viewform?usp=header Turkish]. Your answers will help the team customize guidance for less experienced editors and help them learn community policies and practices while creating an article. Learn more [[mw:Special:MyLanguage/Article guidance|on the project page]].
'''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Contribute]] • [[m:Special:MyLanguage/Tech/News/2026/11|Translate]] • [[m:Tech|Get help]] • [[m:Talk:Tech/News|Give feedback]] • [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].''
</div><section end="technews-2026-W11"/>
</div>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 9 mars 2026 à 19:52 (CET)
<!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30213008 -->
== <span lang="en" dir="ltr">Tech News: 2026-12</span> ==
<div lang="en" dir="ltr">
<section begin="technews-2026-W12"/><div class="plainlinks">
Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/12|Translations]] are available.
'''Updates for editors'''
* The [[mw:Special:MyLanguage/Help:Extension:CodeMirror|{{int:codemirror-beta-feature-title}}]] beta feature, also known as [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror 6]], has been used for wikitext syntax highlighting since November 2024. It will be promoted out of beta by May 2026 in order to bring improvements and new [[mw:Special:MyLanguage/Help:Extension:CodeMirror#Features|features]] to all editors who use the standard syntax highlighter. If you have any questions or concerns about promoting the feature out of beta, [[mw:Special:MyLanguage/Help talk:Extension:CodeMirror|please share]]. [https://phabricator.wikimedia.org/T259059]
* Some changes to local user groups are performed by stewards on Meta-Wiki and logged there only. Now, interwiki rights changes will be logged both on Meta-Wiki and the wiki of the target user to make it easier to access a full record of user's rights changes on a local wiki. Past log entries for such changes will be backfilled in the coming weeks. [https://phabricator.wikimedia.org/T6055]
* On wikis using [[m:Special:MyLanguage/Flagged Revisions|Flagged Revisions]], the number of pending changes shown on [[{{#Special:PendingChanges}}]] previously counted pages which were no longer pending review, because they have been removed from the system without being reviewed, e.g. due to being deleted, moved to a different namespace, or due to wiki configuration changes. The count will be correct now. On some wikis the number shown will be much smaller than before. There should be no change to the list of pages itself. [https://phabricator.wikimedia.org/T413016]
* Wikifunctions composition language has been rewritten, resulting in a new version of the language. This change aims to increase service stability by reducing the orchestrator's memory consumption. This rewrite also enables substantial latency reduction, code simplification, and better abstractions, which will open the door to later feature additions. Read more about [[f:Special:MyLanguage/Wikifunctions:Status updates/2026-03-11|the changes]].
* Users can now sort search results alphabetically by page title. The update gives an additional option to finding pages more easily and quickly. Previously, results could be sorted by Edit date, Creation date, or Relevance. To use the new option, open 'Advanced Search' on the search results page and select 'Alphabetically' under 'Sorting Order'. [https://phabricator.wikimedia.org/T403775]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:28}} community-submitted {{PLURAL:28|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, the bug that prevented UploadWizard on Wikimedia Commons from importing files from Flickr has now been fixed. [https://phabricator.wikimedia.org/T419263]
'''Updates for technical contributors'''
* A new special page, [[{{#special:LintTemplateErrors}}]], has been created to list transcluded pages that are flagged as containing lint errors to help users discover them easily. The list is sorted by the number of transclusions with errors. For example: [[{{#special:LintTemplateErrors}}/night-mode-unaware-background-color]]. [https://phabricator.wikimedia.org/T170874]
* Users of the [[mw:Special:MyLanguage/Help:Extension:CodeMirror|{{int:codemirror-beta-feature-title}}]] beta feature have been using [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror]] instead of [[mw:Special:MyLanguage/Extension:CodeEditor|CodeEditor]] for syntax highlighting when editing JavaScript, CSS, JSON, Vue and Lua content pages, for some time now. Along with promoting CodeMirror 6 out of beta, the plan is to replace CodeEditor as the standard editor for these content models by May 2026. [[mw:Special:MyLanguage/Help talk:Extension:CodeMirror|Feedback or concerns are welcome]]. [https://phabricator.wikimedia.org/T419332]
* The [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror]] JavaScript modules will soon be upgraded to CodeMirror 6. Leading up to the upgrade, loading the <code dir=ltr>ext.CodeMirror</code> or <code dir=ltr>ext.CodeMirror.lib</code> modules from gadgets and user scripts was deprecated in July 2025. The use of the <code dir=ltr>ext.CodeMirror.switch</code> hook was also deprecated in March 2025. Contributors can now make their scripts or gadgets compatible with CodeMirror 6. See the [[mw:Special:MyLanguage/Extension:CodeMirror#Gadgets and user scripts|migration guide]] for more information. [https://phabricator.wikimedia.org/T373720]
* The MediaWiki Interfaces team is expanding coverage of REST API module definitions to include [[mw:Special:MyLanguage/API:REST API/Extensions|extension APIs]]. REST API modules are groups of related endpoints that can be independently managed and versioned. Modules now exist for [https://phabricator.wikimedia.org/T414470 GrowthExperiments] and [https://phabricator.wikimedia.org/T419053 Wikifunctions] APIs. As we migrate extension APIs to this structure, documentation will move out of the main MediaWiki OpenAPI spec and REST Sandbox view, and will instead be accessible via module-specific options in the dropdown on the [https://test.wikipedia.org/wiki/Special:RestSandbox REST Sandbox] (i.e., [[{{#Special:RestSandbox}}]], available on all wiki projects).
* The [[mw:Special:MyLanguage/Extension:Scribunto|Scribunto]] extension provides different pieces of information about the wiki where the module is being used via the [[mw:Special:MyLanguage/Extension:Scribunto/Lua reference manual|mw.site]] library. Starting last week, the library also provides a [[mw:Special:MyLanguage/Extension:Scribunto/Lua reference manual#mw.site.wikiId|way]] of accessing the [[mw:Special:MyLanguage/Manual:Wiki ID|wiki ID]] that can be used to facilitate cross-wiki module maintenance. [https://phabricator.wikimedia.org/T146616]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.20|MediaWiki]]
'''In depth'''
* The [[m:Special:MyLanguage/Coolest Tool Award|2026 Coolest Tool Award]] celebrating outstanding community tools, is now open for nominations! Nominate your favorite tool using the [https://wikimediafoundation.limesurvey.net/435684?lang=en nomination survey] form by 23 March 2026. For more information on privacy and data handling, please see the [[foundation:Special:MyLanguage/Legal:Coolest_Tool_Award_2026_Survey_Privacy_Statement|survey privacy statement]].
'''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Contribute]] • [[m:Special:MyLanguage/Tech/News/2026/12|Translate]] • [[m:Tech|Get help]] • [[m:Talk:Tech/News|Give feedback]] • [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].''
</div><section end="technews-2026-W12"/>
</div>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 16 mars 2026 à 20:35 (CET)
<!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30260505 -->
== <span lang="en" dir="ltr">Upcoming deployment of CampaignEvents extension to Wikibooks</span> ==
<div lang="en" dir="ltr">
<section begin="message"/>
Hello everyone,
We are writing to inform you that the [[mw:Help:Extension:CampaignEvents|CampaignEvents extension]] will be deployed to all Wikibooks projects during the week of '''23 March 2026'''.
This follows last year’s broader rollout across Wikimedia projects. We realized that Wikibooks was not included at the time, and we’re now addressing that to ensure consistency across all communities.
The CampaignEvents extension provides tools to support event and campaign organization on-wiki, including features like on-wiki event registration and collaboration lists(global event list).
We welcome any questions, feedback, or concerns you may have. We are also happy to support anyone interested in trying out the tools.
''Apologies if this message is not in your preferred language. If you’re able to help translate it for your community, please feel free to do so.''
<section end="message"/>
</div>
<bdi lang="en" dir="ltr">[[User:Udehb-WMF|Udehb-WMF]] ([[User talk:Udehb-WMF|discussion]]) 19 mars 2026 à 19:22 (CET)</bdi>
<!-- Message envoyé par User:Udehb-WMF@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=User:Udehb-WMF/sandbox/MM_target&oldid=30284073 -->
== <span lang="en" dir="ltr">Tech News: 2026-13</span> ==
<div lang="en" dir="ltr">
<section begin="technews-2026-W13"/><div class="plainlinks">
Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/13|Translations]] are available.
'''Weekly highlight'''
* Wikimedia site users can now log in without a password using passkeys. This is a secure method supported by fingerprint, facial recognition, or PIN. With this change, all users who opt for passwordless login will find it easier, faster, and more secure to log in to their accounts using any device. The new passkey login option currently appears as an autofill suggestion in the username field. An additional [[phab:T417120|"Log in with passkey" button]] will soon be available for users who have already registered a passkey. This update will improve security and user experience. The [[c:File:Passwordless_login_screencast.webm|screen recording]] demonstrates the passwordless login process step by step.
* [[m:Special:MyLanguage/Tech/Server switch|All wikis will be read-only]] for a few minutes on Wednesday, 25 March 2026 at [https://zonestamp.toolforge.org/1774450800 15:00 UTC]. This is for the datacenter server switchover backup tests, [[wikitech:Deployments/Yearly calendar|which happen twice a year]]. During the switchover, all Wikimedia website traffic is shifted from one primary data center to the backup data center to test availability and prevent service disruption even in emergencies.
'''Updates for editors'''
* Wikimedia site users can now export their notifications older than 5 years using a [[toolforge:echo-chamber|new Toolforge tool]]. This will ensure that users retain their important notifications and avoid them being lost based on the planned change to delete notifications older than 5 years, as previously announced. [https://phabricator.wikimedia.org/T383948]
* Wikipedia editors in Indonesian, Thai, Turkish, and Simple English now have access to Special:PersonalDashboard. This is an [[mw:Special:MyLanguage/Moderator Tools/Dashboard|early version of an experience]] that introduces newer editors to patrolling workflows, making it easier for them to move from making edits to participating in more advanced moderation work on their project. [https://phabricator.wikimedia.org/T402647]
* The [[Special:Block]] now has two minor interface changes. Administrators can now easily perform indefinite blocks through a dedicated radio button in the expiry section. Also, choosing an indefinite expiry provides a different set of common reasons to select from, which can be changed at: [[MediaWiki:Ipbreason-indef-dropdown]]. [https://phabricator.wikimedia.org/T401823]
* Mobile editors [[mw:Special:MyLanguage/Contributors/Account Creation Experiments#Logged-out|at several wikis]] can now see an improved logged-out edit warning, thanks to the recent updates from the Growth team. These changes released last week are part of ongoing efforts and tests to enhance [[mw:Special:MyLanguage/Contributors/Account Creation Experiments|account creation experience on mobile]] and then increase participation. [https://phabricator.wikimedia.org/T408484]
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:36}} community-submitted {{PLURAL:36|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, the bug that prevented mobile web users from seeing the block information when affected by multiple blocks has been fixed. They can now see messages of all the blocks currently affecting them when they access Wikipedia.
'''Updates for technical contributors'''
* Images built using Toolforge will soon get the upgraded buildpacks version, bringing support for newer language versions and other upstream improvements and fixes. If you use Toolforge Build Service, review the recent [https://lists.wikimedia.org/hyperkitty/list/cloud-announce@lists.wikimedia.org/thread/EMYTA32EV2V5SQ2JIEOD2CL66YFIZEKV/ cloud-announce email] and update your build configuration as necessary to ensure your tools are compatible. [https://wikitech.wikimedia.org/w/index.php?title=Help:Toolforge/Building_container_images&oldid=2392097#Buildpack_environment_upgrade_process][https://phabricator.wikimedia.org/T380127]
* The [https://api.wikimedia.org/wiki/Main_Page API Portal] documentation wiki will shut down in June 2026. API keys created on the API Portal will continue to work normally. api.wikimedia.org endpoints will be deprecated gradually starting in July 2026. Documentation on the API Portal is moving to [[mw:Wikimedia APIs|mediawiki.org]]. Learn more on the [[wikitech:API Portal/Deprecation|project page]].
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.21|MediaWiki]]
'''In depth'''
* [[m:Special:MyLanguage/WMDE Technical Wishes|WMDE Technical Wishes]] is considering improvements to [[m:WMDE Technical Wishes/References/VisualEditor automatic reference names|automatically generated reference names in VisualEditor]]. Please check out the [[m:WMDE Technical Wishes/References/VisualEditor automatic reference names#Proposed solutions|proposed solutions]] and participate in the [[m:Talk:WMDE Technical Wishes/References/VisualEditor automatic reference names#Request for comment|request for comment]].
'''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]] • [[m:Special:MyLanguage/Tech/News#contribute|Contribute]] • [[m:Special:MyLanguage/Tech/News/2026/13|Translate]] • [[m:Tech|Get help]] • [[m:Talk:Tech/News|Give feedback]] • [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].''
</div><section end="technews-2026-W13"/>
</div>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 23 mars 2026 à 17:51 (CET)
<!-- Message envoyé par User:UOzurumba (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30268305 -->
== Actualités techniques n° 2026-14 ==
<section begin="technews-2026-W14"/><div class="plainlinks">
Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/14|D’autres traductions]] sont disponibles.
'''En lumière cette semaine'''
* Le version Beta de [[abstract:|Abstract Wikipedia]], un nouveau projet Wikimédia indépendant du langage, a été lancée la semaine dernière. Ce projet permet aux communautés de construire des articles Wikipédia dans leur langue natale, qui peuvent directement être lus par les autres utilisateurs et utilisatrices dans leur propre langage. Le wiki fonctionne grâce à des instructions de Wikifunctions et au contenu structuré issu de Wikidata. [[:f:Special:MyLanguage/Wikifunctions:Status updates/2026-03-26|En savoir plus]].
'''Actualités pour la contribution'''
* L'équipe Croissance mène un test A/B afin d'évaluer l'effet d'un message plus clair et plus convivial encourageant à la création de comptes sur les wikis. Actuellement, lorsqu'un utilisateur mobile non connecté lance la modification, un message d'avertissement s'affiche, pouvant paraître abrupt et décourageant. Il présente également la modification par compte temporaire comme option par défaut, au lieu d'inciter à la création d'un compte. Le test est mené sur dix Wikipédia, dont les versions en arabe, français, espagnol et allemand. [[mw:Special:MyLanguage/Contributors/Account Creation Experiments#2. Improve logged-out warning message (T415160)|En savoir plus]].
* L'équipe des applications Wikimédia sollicite vos commentaires sur [[mw:Special:MyLanguage/Wikimedia Apps/Team/Future of Editing on the Mobile Apps|comment devrait fonctionner l'édition dans les applications mobiles Wikipédia]]. La discussion porte sur l'amélioration de l'accès aux outils d'édition lorsque les utilisateurs appuient sur « Modifier ». Cette initiative s'inscrit dans un effort plus large visant à offrir aux lecteurs intéressés par la contribution une expérience utilisateur plus intuitive.
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:45|la tâche soumise|les {{formatnum:45}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:45||s}} la semaine dernière]]. Par exemple, un problème avec la récupération de citations à partir du site d'archive de journaux [https://www.newspapers.com Newspapers.com], qui ne fonctionnait plus en raison d'un blocage des requêtes [[mw:Special:MyLanguage/Citoid|Citoid]], a maintenant été résolu. [https://phabricator.wikimedia.org/T419903]
'''Actualités pour la contribution technique'''
* [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.22|MediaWiki]]
'''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]] • [[m:Special:MyLanguage/Tech/News/2026/14|Traduire]] • [[m:Tech|Obtenir de l’aide]] • [[m:Talk:Tech/News|Donner son avis]] • [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].''
</div><section end="technews-2026-W14"/>
<bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 30 mars 2026 à 21:25 (CEST)
<!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30329462 -->
4sc3pqkxlv0a3a6puqn6gl0zqv4p67a
La grammaire fondamentale de l'ido/Mots grammaticaux/Pronoms
0
83710
762597
762022
2026-03-31T11:58:30Z
Francucelo
123176
/* Pronoms possessifs */
762597
wikitext
text/x-wiki
Les pronoms sont des mots grammaticaux utilisés pour remplacer les noms.
== Pronoms personnels ==
Les pronoms personnels sont utilisés pour remplacer des éléments déjà connus dans une conversation.
{| class="wikitable"
|+Pronoms personnels en ido
! rowspan="2" |
! rowspan="2" |1er
! colspan="2" |2e personne
! colspan="4" |3e personne
! rowspan="2" |indéfini
! rowspan="2" |réfléchi
|-
!familier
!formel
!masc.
!fem.
!non-humain
!neutre
|-
|Singulier
|Me
|Tu
|Vu
|Il(u)
|El(u)
|Ol(u)
|Lu
| rowspan="2" |On(u)
| rowspan="2" |Su
|-
|Pluriel
|Ni
| colspan="2" |Vi
|Ili
|Eli
|Oli
|Li
|}
{| class="wikitable"
|+
Français
! rowspan="2" |
! rowspan="2" |1er
! colspan="2" |2e personne
! colspan="4" |3e personne
! rowspan="2" |indéfini
! rowspan="2" |réfléchi
|-
!familier
!formel
!masc.
!fem.
!non-humain
!neutre
|-
|Singulier
|Je
|Tu
|Vous
|Il
|Elle
|Il, Elle
|Il, Elle
| rowspan="2" |On
| rowspan="2" |Lui-même, Eux-même, Elle(s)-même
|-
|Pluriel
|Nous
| colspan="2" |Vous
|Ils
|Elles
|Ils, Elles
|Ils, Elles
|}
Le « u » des pronoms Ilu, Elu, Olu et Onu peut être omis. Cependant, lorsque ces pronoms doivent être suivis d'une terminaison, il faut utiliser la forme complète avec le « u ».
== Pronoms possessifs ==
Les pronoms possessifs expriment la possession, comme « mon », « ton » et « son ». En ido, il suffit d'ajouter la terminaison « a » à un pronom personnel pour le convertir en pronom possessif.
{| class="wikitable"
|+Pronoms possessifs en ido
! rowspan="2" |
! rowspan="2" |1er
! colspan="2" |2e personne
! colspan="4" |3e personne
! rowspan="2" |indéfini
! rowspan="2" |réfléchi
|-
!familier
!formel
!masc.
!fem.
!non-humain
!neutre
|-
|Singulier
|Mea
|Tua
|Vua
|Ilua
|Elua
|Olua
|Lua
| rowspan="2" |Onua
| rowspan="2" |Sua
|-
|Pluriel
|Nia
| colspan="2" |Via
|Ilia
|Elia
|Olia
|Lia
|}
== Pronoms réfléchis ==
Les pronoms réfléchis « su » et « sua » servent à désigner un nom à la troisième personne dans une même phrase. Ils peuvent se traduire par « lui-même », « elle-même » ou « eux-mêmes ». Ils ne peuvent pas être utilisés comme sujet.
* Exemples de pronom personnel : « Il amas su » signifie « Il aime lui-même », tandis que « Il amas il » signifie « Il l'aime », sans qu'il soit possible de déterminer si le complément d'objet désigne la même personne ou une autre.
* Exemple de pronom possessif : « El amas sua kato » signifie « Elle aime son propre chat », tandis que « El amas elua kato » signifie « Elle aime son chat », sans qu'il soit possible de déterminer si ce chat appartient à la personne qui l'aime ou à quelqu'un d'autre.
== Pronoms démonstratifs ==
Les pronoms démonstratifs sont des mots qui servent à désigner une ou plusieurs choses ou un ou plusieurs lieux précis. Comme « celui-ci » et « celui-là ».
Voici les pronoms démonstratifs de l'ido :
{| class="wikitable"
! colspan="2" |
!Proximité (-ci)
!Éloignement (-là)
|-
| rowspan="2" |Personne / individu
|Singulier
|Ica
|Ita
|-
|Pluriel
|Ici
|Iti
|-
| colspan="2" |Non-humain
|Ico
|Ito
|-
| colspan="2" |Adjectifs démonstratifs
|Ica
|Ita
|}
Le « i » des pronoms démonstratifs peut être omis pour des raisons phonétiques, devenant ainsi « ca », « ci », « co », « ta », « ti » ou « to ».
=== Adjectifs démonstratifs ===
Les adjectifs démonstratifs sont placés devant le nom pour le désigner. Par exemple : « ce chat-ci » et « ce chat-là ».
== Pronoms relatifs ==
Les pronoms relatifs sont utilisés dans les phrases interrogatives et les propositions subordonnées, comme « qui ».
En ido, il existe trois pronoms relatifs :
* Personnes ou choses concrètes :
** Singulier : '''Qua'''
** Pluriel : '''Qui'''
* Choses abstraites : '''Quo'''
=== Exemples ===
* Tu lektis '''qui libri''' ? (Tu lisais quels livres ?)
* Ol pensas '''quo''' ? (Il pense quoi ?)
* La persono '''qua kantas'''. (La personne qui chante.)
== Pronoms indéfinis ==
Les pronoms indéfinis servent à désigner des personnes ou des choses non spécifiques. Ils ont une racine particulière et se terminent par l'une des trois terminaisons suivantes : « a », « o » et « u ». Parmi les pronoms indéfinis, la terminaison « a » est utilisée pour les adjectifs, la terminaison « o » pour désigner des choses non humaines, tandis que la terminaison « u » sert à désigner des personnes. De plus, lorsqu'il s'agit de personnes au pluriel, la terminaison « u » est remplacée par « i ».
* Par exemple, « Omna homo bezonas drinkar aqui » signifie « Tout le monde a besoin de boire de l'eau ». Ici, « omna » qualifie « homo » (homme).
* Et « Omnu bezonas drikar aqui » signifie également « Tout le monde a besoin de boire de l'eau ». Ici, « omnu » désigne les personnes.
Par ailleurs, l'utilisation de la terminaison « e » permet d'exprimer une méthode. Par exemple, « Ule » signifie « d'une manière ou d'une autre ».
{| class="wikitable"
|+Pronoms indéfinis essentiels
!Racine
!Signification
|-
|Ul-
|Quelques
|-
|Irg-
|N'importe quel
|-
|Singl-
|Chaque
|-
|Omn-
|Tout
|-
|Nul-
|Aucun
|-
|Altr-
|Autre
|}
== Exercices ==
Essayez de comprendre le sens des phrases suivantes. La signification des racines des mots lexicaux est indiquée ci-dessous :
* Ulu manjis mea kuko ! Esis qua ?
** Manj : manger
** Kuk : gâteau
** Es : être
{{Boîte déroulante|titre=Voir les réponses|contenu=* Quelqu'un a mangé mon gâteau ! C'était qui ?}}
{{AutoCat}}
6eruw4keydfry3cqkc4g4szto2kb0ft
La grammaire fondamentale de l'ido/Formation des mots
0
83763
762518
762414
2026-03-30T16:32:35Z
Francucelo
123176
/* Mots composés */
762518
wikitext
text/x-wiki
L'ido est comme un jeu de construction : en assemblant et en combinant des affixes, des terminaisons et des racines, on peut modifier le sens d'un mot et exprimer des notions complexes et précises en un seul mot.
== Mots composés ==
En ido, il est possible d'exprimer des significations spécifiques en assemblant plusieurs racines. La structure est la suivante : ''préfixe + racine modificative + racine centrale + suffixe + terminaison.''
* Par exemple, « vaporo » (vapeur) + « navo » (navire) donne « vapornavo » (navire à vapeur).
Lorsque la liaison entre deux racines est difficile à prononcer, on peut insérer un « o » entre les deux racines pour les relier.
* Par exemple, « dorm » (dormir) + « chambro » (chambre) donne « dormochambro » (chambre à coucher).
Si la racine précédente a un caractère adjectival, les racines peuvent aussi être reliées par « a ».
* Par exemple, « sam » (même) + « temp » (temps) donne « samatempe » (simultanément).
Pour faciliter la compréhension des mots composés, on peut ajouter un tiret « - » entre les racines lors de l'écriture.
* Par exemple, « vapornavo » peut s'écrire « vapor-navo ». La prononciation reste inchangée, mais la structure est ainsi plus claire.
Si un mot composé comporte plus de deux racines, sa signification précise doit être déduite du contexte. Par conséquent, bien que la grammaire de l'ido permette de former des mots d'une longueur illimitée, il n'est généralement pas recommandé de créer des mots composés comportant plus de trois racines.
== Conversion des catégories de mots ==
Pour transformer une racine en une autre catégorie de mots, il ne suffit pas de changer la terminaison. Il faut également ajouter un suffixe approprié afin de rendre le sens plus clair. Nous allons expliquer cela ci-dessous.
=== Transformer en nom ===
Pour les racines adjectivales transformées en noms, l'ajout direct de la terminaison « o » désigne « la chose/la personne… ». Si l'adjectif doit être transformé en concept abstrait, il faut ajouter le suffixe « es » suivi de la terminaison « o ».
* Par exemple, « libero » signifie « personne libre » ou « chose libre », tandis que « libereso » désigne le concept de « liberté ».
Pour les racines verbales, l'ajout de la terminaison « o » permet d'exprimer l'action elle-même.
=== Transformer en adjectif ===
En ido, la transformation en adjectif ne se limite pas à l'ajout simple de « a » ; il faut également tenir compte du type d'adjectif obtenu, qui peut être de deux types : l'un décrit une caractéristique, l'autre une relation.
Pour dire « ayant la caractéristique de… », il suffit d'ajouter un « a » à la fin.
* Par exemple, « Libera » signifie « qui possède les caractéristiques de la liberté ».
Pour exprimer « concernant… » ou « appartenant à… », il faut ajouter le suffixe « al » suivi de la terminaison « a ».
* Comme « Liberala », qui signifie « concernant la liberté ».
Pour les adjectifs se terminant par « -al », la terminaison « a » peut être omise, principalement en fonction de la phonétique du contexte. Il convient de noter que la position de l'accent tonique reste inchangée après l'omission.
* Par exemple, « Liberala » (Li-be-RA-la) se simplifie en « Liberal » (Li-be-RAL).
=== Transformer en verbe ===
Il existe cinq suffixes permettant de transformer une racine nominale ou adjectivale en verbe.
{| class="wikitable"
!Suffixe
!Explication
!Exemple
|-
|IG
|Rendre...
|Bel-ig-ar : embellir
|-
|IJ
|Devenir...
|Rich-ij-ar : devenir riche
|-
|IF
|Créer, fabriquer
|Infant-if-ar : procréer
|-
|IZ
|Conférer, recouvrir, équiper
|Sal-iz-ar : saler (verbe)
|-
|ESK
|Commencer de...
|Dorm-esk-ar : endormir
|}
{{AutoCat}}
fzje8chk5j2r4na9dyb7gbya1nbxyj6
Löve2D/Premier jeu
0
83768
762595
2026-03-31T04:53:22Z
~2026-19678-98
123380
Créateur de jeu 2d
762595
wikitext
text/x-wiki
Israël
nwmly551bd744xokepe8ah24781ciqe
Discussion:Löve2D/Premier jeu
1
83769
762596
2026-03-31T04:54:22Z
~2026-19678-98
123380
/* Créateur de jeu 2d manifestez vous */ nouvelle section
762596
wikitext
text/x-wiki
== Créateur de jeu 2d manifestez vous ==
formation en jeu 2d [[Spécial:Contributions/~2026-19678-98|~2026-19678-98]] ([[Discussion utilisateur:~2026-19678-98|discussion]]) 31 mars 2026 à 06:54 (CEST)
0r626o657e1w7h1klilslrr7o91myy3