Fonctionnement d'un ordinateur/L'adressage des périphériques

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. Il nous reste à voir comment le mélange entre adresses mémoires et adresses de périphérique peut se faire, comment le processeur évite les confusion entre adresses de périphériques et adresses mémoire.

Et pour cela, il y a plusieurs manières. La plus simple revient à séparer les deux : les adresses mémoire et les adresses périphériques sont totalement différentes et ne sont pas transmises sur les mêmes bus. L'autre méthode revient à fusionner les deux : il existe 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éModifier

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. Une même adresse peut donc adresser soit une entrée-sortie, soit une case mémoire. Pour faire la différence, chaque adresse est associée à un bit, le bit IO, qui indique s'il s'agit d'une adresse de périphérique ou une adresse mémoire. Typiquement, il vaut 0 pour une adresse mémoire, et 1 pour une adresse de périphérique.

 
Bit IO.

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 positionner le bit IO correctement et 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 et ne pourrait pas déterminer le bit IO associé.

Avec un espace d'adressage séparé, on pourrait croire qu'il est nécessaire d'avoir un bus dédié à la communication avec les périphériques et un bus spécialisé pour la mémoire. Cela arrive et c'est un cas assez fréquent. Mais en fait, il est possible de mutualiser le bus d'adresse et de données. Par contre, autant bus d'adresse et de données sont partagés, autant on a bien deux bus de commandes, un pour le périphérique et un pour la mémoire. Du fait de la mutualisation du bus d'adresse, la mémoire et les périphériques partagent les mêmes adresses. Pour éviter tout problème, on doit indiquer la destination de l'adresse, périphérique ou mémoire, via un bit IO sur le bus de commandes.

 
Espace d'adressage séparé.

Les entrées-sorties mappées en mémoireModifier

La dernière technique que nous allons voir 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. Cette technique peut aussi s'appliquer pour les mémoires ROM, ou dans les systèmes qui utilisent plusieurs mémoires.

 
IO mappées en mémoire

Évidemment, les adresses utilisées pour les périphériques ne sont plus disponibles pour la mémoire RAM. C'est ce qui causait autrefois un problème assez connu sur les ordinateurs 32 bits. Certaines personnes installaient 4 gigaoctets de mémoire sur leur ordinateur 32 bits et se retrouvaient avec « seulement » 3,5 à 3,8 gigaoctets de mémoire, les périphériques prenant le reste. Ce « bug » apparaissait sur les processeurs x86 32 bits, avec un système d'exploitation 32 bits. On remarque ainsi le défaut inhérent à cette technique : on ne peut plus adresser autant de mémoire qu'avant. Et mine de rien, quand on a une carte graphique avec 512 mégaoctets de mémoire intégrée, une carte son, une carte réseau PCI, des ports USB, un port parallèle, un port série, des bus PCI Express ou AGP, et un BIOS à stocker dans une EEPROM/Flash, ça part assez vite.

La memory map d'un ordinateurModifier

Avec certains périphériques, cette technique est poussée à l’extrême et permet de mapper non seulement des périphériques, mais aussi des mémoires ROM, des mémoires RAM de périphériques ou d'autres composants. C'est souvent le cas pour certains périphériques possédant une mémoire RAM intégrée dans leurs circuits : cartes graphiques, cartes sons, etc. Leur mémoire est directement accessible directement par le processeur en détournant suffisamment d'adresses mémoires. La mémoire du périphérique est accessible via des adresses mémoires normales : elle est ainsi en partie (voire totalement) partagée entre le processeur principal de l'ordinateur et le périphérique (et plus globalement avec tout périphérique pouvant adresser la mémoire). Notons que certains de ces périphériques intègrent un processeur pour diverses raisons, notamment les cartes son et les cartes graphiques. Ce processeur intégré exécute des programmes dédiés, souvent fournis par les pilotes du périphérique ou le système d'exploitation, parfois par des applications spécialisées (les shaders des jeux vidéos en sont un bon exemple). Ces programmes sont recopiés dans la mémoire du périphérique, par le processeur principal ou via un contrôleur DMA. Cela peut paraitre bizarre, mais sachez que c'est exactement ce qui se passe pour votre carte graphique si celle-ci a moins de vingt ans.

Voici quelques exemples tirés de vraies ordinateurs existants. On voit qu'outre la mémoire RAM principale, des mémoires vidéo et même plusieurs mémoires ROM sont mappées en mémoire. Il y a un unique espace d'adressage qui est partagé avec toutes les mémoires et tous les périphériques de l'ordinateur. Les vielles machines utilisaient cette méthode pour sa simplicité de programmation, notamment les premiers ordinateurs comme les Commodores et les Amiga, ainsi que les vielles consoles de jeux. Ces machines n'étaient pas comme les ordinateurs personnels, avec beaucoup de cartes graphiques ou de cartes sons différentes. Tous les ordinateurs d'une certaine marque avaient la même configuration matérielle, le matériel était fourni tel quel, ne pouvait pas être changé ni upgradé. Toutes les commodores 64 avaient exactement le même matériel, par exemple : la même carte son, la même carte graphique, les mêmes périphériques. Cette standardisation faisait que cela ne servait à rien de limiter l'accès au matériel. De telles machines n'avaient pas de système d'exploitation, ou bien celui-ci était rudimentaire et ne contrôlait pas vraiment l'accès au matériel. Les programmeurs avaient donc totalement accès au matériel et mapper les entrées/sorties en mémoire rendait la programmation des périphériques très simple.

L'implémentation des entrées-sorties mappées en mémoireModifier

Le mappage des entrées-sorties en mémoire va encore plus loin dans le partage des bus entre périphérique et mémoire. Là où la technique de la section précédente ne partageait pas le bus de commande, le mappage des entrées-sorties partage tous les bus. L'avantage est qu'il n'y a plus besoin de dupliquer le bus de donnée ou tout autre bus, ce qui économise beaucoup de fils. Par contre, impossible d'accéder à la fois à la mémoire et à un contrôleur d'entrées-sorties : si le bus est utilisé par un périphérique, la mémoire ne pourra pas l’utiliser et devra attendre que le périphérique ait fini sa transaction (et vice-versa). De plus, le partage du bus d'adresse est aussi plus poussé et le bit IO disparait. L'avantage est qu'on n'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.

 
Bus unique avec entrées mappées en mémoire.
 
Exemple détaillé.

Comme dit plus haut, une partie des adresses pointe alors vers un périphérique, d'autres vers la RAM ou la ROM. La redirection vers le bon destinataire est faite par décodage partiel d'adresse. 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.

 
Décodage d'adresse avec entrées-sorties mappées en mémoire.