Fonctionnement d'un ordinateur/Les bus électroniques

Un livre de Wikilivres.
Sauter à la navigation Sauter à la recherche

Il y a quelques chapitres, nous avons vu la différence entre bus et liaison point à point : là où ces dernières ne connectent que deux composants, les bus de communication en connectent bien plus. Ce faisant, les bus de communication font face à de nouveaux problèmes, inconnus des liaisons point à point. Et ce sont ces problèmes qui font l'objet de ce chapitre. Autant le chapitre précédent valait à a fois pour les liaisons point à point et les bus, autant ce n'est pas le cas de celui-ci. Ce chapitre va parler de ce qui n'est valable que pour les bus de communication, comme leur arbitrage, la détection des collisions, etc. Tous ces problèmes ne peuvent pas survenir, par définition, sur les liaisons point à point.

L'adressage du récepteur[modifier | modifier le wikicode]

La trame doit naturellement être envoyée à un récepteur, seul destinataire de la trame. Sur les liaisons point à point, où il n'y a toujours que deux composants de connectés, il n'y a pas besoin de préciser quel est le récepteur. On peut déduire assez facilement que le récepteur est l'autre composant, celui qui n'a pas envoyé la donnée : sa détermination est implicite. Mais sur les bus, c'est une toute autre histoire. Tous les composants reliés aux bus sont de potentiels récepteurs et l'émetteur doit préciser à qui la trame est destinée. Pour résoudre ce problème, chaque composant se voit attribuer une adresse, il est « numéroté ». Cela fonctionne aussi pour les composants qui sont des périphériques : on a vu dans le chapitre précédent que chaque périphérique/composant se voyait attribuer une adresse.

Sur les bus parallèles, l'adresse est transmise sur des fils à part, sur un sous-bus dédié appelé le bus d'adresse. Les composants ont juste à regarder l'adresse présente sur ce bus d'adresse pour savoir si la transmission leur est destinée. En général, les adresses sur les bus pour périphériques sont assez petites, de quelques bits dans le cas le plus fréquent, quelques octets tout au plus. Il n'y a pas besoin de plus pour adresser une centaine de composants ou plus. Les seuls bus à avoir des adresses de plusieurs octets sont les bus liés aux mémoires, ou ceux qui ont un rapport avec les réseaux informatiques.

Passons maintenant aux bus série (ou certains bus parallèles particuliers). Pour arriver à destination, la trame doit indiquer l'adresse du composant de destination. Les récepteurs espionnent le bus en permanence pour détecter les trames qui leur sont destinées. Ils lisent toutes les trames envoyées sur le bus et en extraient l'adresse de destination : si celle-ci leur correspond, ils lisent le reste de la trame, ils ne la prennent pas en compte sinon. L'adresse en question est intégrée à la trame et est placée à un endroit précis, toujours le même, pour que le récepteur puisse l'extraire. Le plus souvent, l'adresse de destination est placée au début de la trame, afin qu'elle soit envoyée au plus vite. Ainsi, les périphériques savent plus rapidement si la trame leur est destinée ou non, l'adresse étant connue le plus tôt possible.

L'arbitrage du bus[modifier | modifier le wikicode]

Collisions lors de l'accès à un bus.

Sur certains bus, il arrive que plusieurs composants tentent d'envoyer ou de recevoir une donnée sur le bus en même temps : c'est un conflit d'accès au bus. Cette situation arrive sur de nombreux types de bus, qu'ils soient multiplexés ou non. Sur les bus multipléxés, qui relient plus de deux composants, cette situation est fréquente du fait du nombre de récepteurs/émetteurs potentiels. Mis cela peut aussi arriver sur certains bus dédiés, les bus half-duplex étant des exemples particuliers : il se peut que les deux composants veuillent être émetteurs en même temps, ou récepteurs. Quoiqu'il en soit, ces conflits d'accès posent problème si un composant cherche à envoyer un 1 et l'autre un 0 : tout ce que l’on reçoit à l'autre bout du fil est une espèce de mélange incohérent des deux données envoyées sur le bus par les deux composants. Pour résoudre ce problème, il faut répartir l'accès au bus pour n'avoir qu'un émetteur à la fois. On doit choisir un émetteur parmi les candidats. Ce choix sera effectué différemment suivant le protocole du bus et son organisation, mais ce choix n’est pas gratuit : certains composants devront attendre leur tour pour avoir accès au bus. Les concepteurs de bus ont inventé des méthodes pour gérer ces conflits d’accès, et choisir le plus efficacement possible l’émetteur : on parle d'arbitrage du bus.

Les méthodes d'arbitrage (algorithmes)[modifier | modifier le wikicode]

Il existe plusieurs méthodes d'arbitrages, qui peuvent se classer en différents types, selon leur fonctionnement.

Pour donner un exemple d'algorithme d'arbitrage, nous allons voir l'arbitrage par multiplexage temporel. Celui-ci peut se résumer en une phrase : chacun son tour ! Chaque composant a accès au bus à tour de rôle, durant un temps fixe. Cette méthode fort simple convient très bien si les différents composants ont des besoins approximativement équilibrés. Mais elle est mal adaptée quand certains composants effectuent beaucoup de transactions sur le bus et d’autres très peu. Les composants gourmands manqueront de débit, alors que les autres monopoliseront le bus pour ne presque rien en faire. Une solution à ce problème est de permettre à un composant peut libérer le bus prématurément, s'il n'utilise pas totalement le temps qui lui est attribué. Ce faisant, les composants qui n'utilisent pas beaucoup le bus passeront leur tour, laissant la place aux composants plus gourmands.

Une autre méthode est celle de l'arbitrage par requête, qui se résume à un simple « premier arrivé, premier servi » ! L'idée est que tout composant peut réserver le bus si celui-ci est libre, mais doit attendre si le bus est déjà réservé. Pour savoir si le bus est réservé, il existe deux méthodes :

  • soit chaque composant peut vérifier à tout moment si le bus est libre ou non (aucun composant n'écrit dessus) ;
  • soit on rajoute un bit qui indique si le bus est libre ou occupé : le bit busy.

Certains protocoles permettent de libérer le bus de force pour laisser la place à un autre composant : on parle alors de bus mastering. Sur certains bus, certains composants sont prioritaires, et les circuits chargés de l'arbitrage libèrent le bus de force si un composant plus prioritaire veut utiliser le bus. Bref, les méthodes d'arbitrage sont nombreuses.

Arbitrage centralisé ou décentralisé[modifier | modifier le wikicode]

Une autre classification nous dit si un composant gère le bus, ou si cet arbitrage est délégué aux composants qui accèdent au bus.

  • Dans l'arbitrage centralisé, un circuit spécialisé s'occupe de l'arbitrage du bus.
  • Dans l'arbitrage distribué, chaque composant se débrouille de concert avec tous les autres pour éviter les conflits d’accès au bus : chaque composant décide seul d'émettre ou pas, suivant l'état du bus.
Notons qu'un même algorithme peut être implémenté soit de manière centralisée, soit de manière décentralisée.

Pour donner un exemple d'arbitrage centralisé, nous allons aborder l'arbitrage par daisy chain. Il s'agit d'un algorithme centralisé, dans lequel tout composant a une priorité fixe. Dans celui-ci, tous les composants sont reliés à un arbitre, qui dit si l'accès au bus est autorisé. Les composants sont reliés à l'arbitre via deux fils : un fil nommé Request qui part des composants et arrive dans l'arbitre, et un fil Grant qui part de l'arbitre et parcours les composants un par un. Le fil Request indique à l'arbitre qu'un composant souhaite accéder au bus : c'est un signal d'autorisation. Le composant qui veut accéder au bus va placer un sur ce fil 1 quand ils veut accéder au bus. Ce fil est unique, partagé entre tous les composants (cela remplace l'utilisation d'une porte OU). Le fil Grant permet à l'arbitre de signaler qu'un des composant pourra avoir accès au bus. Ce fil relie l'arbitre au premier composant. Celui-ci fournit un fil Grant, qui sort du premier composant pour renter dans le second, et ainsi de suite : tous les composants sont reliés en guirlande par ce fil Grant. Ce fil permet de décider quel composant peut accéder au bus. Par défaut, l'arbitre envoie un 1 quand il accepte un nouvel accès au bus (et un 0 quand il veut bloquer tout nouvel accès. Quand un composant ne veut pas accéder au bus, il transmet le bit reçu sur ce fil tel quel, sans le modifier. Mais s'il veut accéder au bus, il mettra un zéro sur ce fil : les composants précédents verront ainsi un 1 sur le fil, mais les suivants verront un zéro (interdiction d'accès). Ainsi, les composants les plus près du bus, dans l'ordre de la guirlande, seront prioritaires sur les autres.

Daisy Chain.

L'interfaçage avec le bus[modifier | modifier le wikicode]

Une fois que l'on sait quel composant a accès au bus à un instant donné, il faut trouver un moyen pour que les composants non sélectionnés par l'arbitrage ne puissent pas écrire sur le bus.

Les circuits d’interfaçage avec le bus : circuits trois-états et multiplexeurs[modifier | modifier le wikicode]

Une première solution consiste à relier les sorties des composants au bus via un multiplexeur : on est alors certain que seul un composant pourra émettre sur le bus à un moment donné. L'arbitrage du bus choisit quel composant peut émettre, et configure l'entrée de commande du multiplexeur en fonction.

Une autre solution consiste à déconnecter du bus les sorties qui n'envoient pas de données. Plus précisément, leurs sorties peuvent être mises dans un état de haute impédance, qui n'est ni un 0 ni un 1 : quand une sortie est en haute impédance, celle-ci n'a pas la moindre influence sur les composants auxquels elle est reliée. Un composant dont les sorties sont en haute impédance ne peut pas influencer le bus et ne peut donc pas y écrire. Pour mettre une sortie en état de haute impédance, on utilise des circuits trois états, qui possèdent une entrée de donnée, une entrée de commande, et une sortie : suivant ce qui est mis sur l'entrée de commande, la sortie est soit en état de haute impédance (déconnectée du bus), soit dans l'état normal (0 ou 1).

Commande Entrée Sortie
0 0 Haute impédance/Déconnexion
0 1 Haute impédance/Déconnexion
1 0 0
1 0 1

Pour simplifier, on peut voir ceux-ci comme des interrupteurs :

  • si on envoie un 0 sur l'entrée de commande, ces circuits trois états se comportent comme un interrupteur ouvert ;
  • si on envoie un 1 sur l'entrée de commande, ces circuits trois états se comportent comme un interrupteur fermé.
Tampons 3 états.

L'interfaçage avec le bus en lecture et écriture[modifier | modifier le wikicode]

On peut utiliser ces circuits trois états pour permettre à un composant d'émettre ou de recevoir des données sur un bus. Par exemple, on peut utiliser ces composants pour autoriser les émissions sur le bus, le composant étant déconnecté (haute impédance) s'il n'a rien à émettre. Le composant a accès au bus en écriture seule. L'exemple typique est celui d'une mémoire ROM reliée à un bus de données.

Bus en écriture seule.

Une autre possibilité est de permettre à un composant de recevoir des données sur le bus. Le composant peut alors surveiller le bus et regarder si des données lui sont transmises, ou se déconnecter du bus. Le composant a alors accès au bus en lecture seule.

Bus en lecture seule.

Évidemment, on peut autoriser lectures et écritures : le composant peut alors aussi bien émettre que recevoir des données sur le bus quand il s'y connecte. On doit alors utiliser deux circuits trois états, un pour l'émission/écriture et un autre pour la réception/lecture. Comme exemple, on pourrait citer les mémoires RAM, qui sont reliées au bus mémoire par des circuits de ce genre. Dans ce cas, les circuits trois états doivent être commandés par le bit CS (qui connecte ou déconnecte la mémoire du bus), mais aussi par le bit R/W qui décide du sens de transfert. Pour faire la traduction entre ces deux bits et les bits à placer sur l'entrée de commande des circuits trois états, on utilise un petit circuit combinatoire assez simple.

Bus en lecture et écriture.