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.

Rappels : l'espace d'adressage unifié ou séparé

modifier

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é

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.

 
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

modifier

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.

 
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.

L'implémentation matérielle de l'espace d'adressage séparé et unifié

modifier

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.

 
Bus unique avec entrées mappées en mémoire.

La seconde est celle d'un bus séparé pour les entrées-sorties.

 
Bus entre processeur et contrôleur de périphérique.

La troisième est un mélange des deux précédentes : elle intercale un circuit répartiteur entre le processeur et les deux bus. Il s'occupe alors de la gestion des adresses.

 
IO mappées en mémoire avec séparation des bus, usage d'un répartiteur

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.

Espace d'adressage unifié (entrées-sorties mappées en mémoire) Espace d'adressage séparé
Bus système 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

modifier

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, le décodage d'adresse agit sur la mémoire ou les périphériques, et les connecte ou déconnecte du bus suivant les besoins. 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.

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

L'espace d'adressage séparé avec un bus système

modifier

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.

 
Exemple détaillé.

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.

 
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.

 
Espace d'adressage séparé.

Les entrées-sorties mappées en mémoire avec des configurations de bus spéciales

modifier

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.

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