Aller au contenu

Fonctionnement d'un ordinateur/Contrôleur mémoire externe

Un livre de Wikilivres.

Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM.

Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le contrôleur mémoire externe. Son but est de montrer au processeur une interface simple, semblable à celle d'une SRAM classique, alors qu'il commande une mémoire DRAM à l'interface plus complexe.

Les anciens contrôleurs de DRAM étaient des composants séparés du processeur, du chipset ou du reste de la carte mère. Ils étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au chipset de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs.

Ce chapitre va expliquer quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. Dans ce chapitre, quand nous parlerons de contrôleur mémoire, cela fera systématiquement référence au contrôleur mémoire externe. Et avant de poursuivre, sachez qu'il est difficile de faire des généralités sur les contrôleurs mémoire, car les mémoires DRAM elles-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les contrôleurs mémoires seront fortement différents. J'ai choisit de vous séparer les contrôleurs mémoire pour les DRAM asynchrones de ceux pour les SDRAM/DRR.

Le contrôleur d'une DRAM asynchrone

[modifier | modifier le wikicode]

Les premières DRAM asynchrones avaient des contrôleurs mémoires dédiés, qui étaient séparés du processeur et du chipset de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM asynchrones qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au chipset de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs.

Leurs fonctions étaient le multiplexage de l'adresse et le rafraichissement mémoire. Ils recevaient une adresse mémoire complète, qu'ils découpaient une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre sur le bus mémoire. Pour le rafraichissement mémoire, ils rafraichissaient la DRAM régulièrement, de manière automatique, entre deux accès mémoire normaux. Le processeur n'avait ainsi plus à rafraichir la mémoire lui-même, cette fonction était déléguée au contrôleur de DRAM. Ils étaient connectés au bus d'adresse et de commande, avec éventuellement des relations indirectes avec le bus de données.

L'interface d'un contrôleur de DRAM asynchrone

[modifier | modifier le wikicode]

L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande. Le bus de données est lui relié au processeur et/ou au bus système.

Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous.

Contrôleur mémoire externe.

Un point important est que les DRAM asynchrones n'ont pas d'entrée Chip Select ou d'entrée Output Enable. Les signaux RAS et CAS remplacent en quelque sorte ces deux signaux. Le bit RAS fait office de Chip Select, le bit CAS fait office d'Output Enable.

Pour certains contrôleurs de DRAM, il faut ajouter l'interface électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion.

Le contrôleur DRAM peut fonctionner en mode synchrone ou asynchrone, du point de vue du processeur. Quand il fonctionne en mode synchrone, il permet d'interfacer un processeur synchrone avec une mémoire DRAM asynchrone.

Un point important est que le contrôleur DRAM sert d'intermédiaire entre une mémoire DRAM et "le reste du monde". Il ne fait pas forcément office d'intermédiaire entre DRAM et processeur, mais peut aussi faire l'intermédiaire entre la DRAM et un bus système, entre une DRAM et le Video Display Controler d'une carte graphique, ou n'importe quel autre composant électronique qui utilise cette DRAM.

Le générateur de timings et la traduction d'adresse

[modifier | modifier le wikicode]

Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides.

Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures.

Bus multiplexé avec bit ALE.

Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne.

La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de timings.

Contrôleur de DRAM simple, sans rafraichissement mémoire.

Le générateur de timings est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de timings est appelé le séquenceur mémoire. C'est le séquenceur mémoire qui traduit la requête processeur en commande DRAM, le reste du contrôleur est dédié au rafraichissement mémoire ou à d'autres fonctions facultatives.

Le rafraichissement mémoire

[modifier | modifier le wikicode]

La gestion du rafraichissement mémoire est la fonction principale du contrôleur DRAM. Pour gérer le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements.

Le rafraichissement se fait à intervalle régulier, tous les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un Refresh Timer, aussi appelé le compteur de rafraichissement. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0.

Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un compteur d'adresse. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit output enable. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant.

Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement.

Controleur de DRAM avec rafraichissement mémoire.

Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci.

Contrôleur mémoire, intérieur simplifié.

Il faut noter que le rafraichissement mémoire peut être délégué non pas au contrôleur mémoire, mais au processeur où à la DRAM elle-même. Quand elle est le fait du processeur, celui-ci incorpore un refresh timer et un compteur d'adresse. Un exemple est celui du processeur Zilog Z80, qui implémentait des compteurs internes pour gérer le rafraichissement mémoire. On peut considérer que le processeur incorpore alors le contrôleur mémoire, au moins partiellement. Il est aussi possible de déléguer le rafraichissement au logiciel (certains jeux vidéos Amiga ou Commodore faisaient cela pour la mémoire vidéo). Quand la DRAM elle-même s'occupe de son propre rafraichissement, c'est elle qui intègre un refresh timer et le compteur d'adresse.

Le décodage d'adresse

[modifier | modifier le wikicode]

Le contrôleur mémoire gère aussi le décodage d'adresse. pour rappel, celui-ci est utilisé quand on combine plusieurs chips mémoire ensemble, pour combiner leurs capacités mémoire. Par exemple, on peut combiner 4 chips mémoires de 1 mébioctet chacun, pour que le processeur voit comme 4 mébioctets de RAM unique. Le premier mébioctet est placé dans le premier chip mémoire, le second mébioctet dans le second chip, etc.

Répartition des adresses sans entrelacement.

Pour cela, on active le chip mémoire adéquat, en fonction de l'adresse à consulter. Les autres chips mémoire sont désactivés pendant l'accès mémoire. En théorie, activer ou désactiver un chip mémoire se fait en utilisant son entrée Chip Select. Il faut noter que si les SDRAM disposent bien d'un signal Chip Select, ce n'est pas le cas des mémoires RAM asynchrones. À la place, ce sont les signaux RAS qui font office de Chip Select. Une RAM asynchrone est activée quand son signal RAS lui demande de lire une ligne, elle est désactivée sinon. Mais c'est un détail.

Toujours est-il que les signaux Chip Select, ou leurs équivalents, sont générés par le contrôleur de DRAM, à partir des bits de poids fort de l'adresse. Par exemple, avec 4 chips mémoire, les deux bits de poids fort de l'adresse sont utilisés pour sélectionner le chip mémoire adéquat. Le contrôleur mémoire doit avoir plusieurs sorties Chip Select, une par chip mémoire. Et le nombre de ces sorties limite le nombre de chips mémoire qu'on peut combiner. Par exemple, s'il y a seulement 4 sorties Chip Select, on ne pourra brancher que 4 chips mémoire dessus. Sauf à ruser, avec un arrangement horizontal, mais cela n'est pas le ressort du contrôleur mémoire.

Comparaison entre arrangement horizontal (à gauche) et arrangement vertical (à droite).

Exemple : l'Intel 8202-8203

[modifier | modifier le wikicode]

L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée.

Le 8202 contenait aussi un compteur de rafraichissement. Rappelons que sur les DRAM asynchrones, le rafraichissement se fait ligne par ligne. Le contrôleur mémoire a juste à présenter l'adresse de ligne, il n'a pas à envoyer l'adresse de colonne. La commande de rafraichissement se fait en mettant le signal RAS à 0, mais en laissant le CAS à 1 (je rappelle que les signaux sont actifs à 0). Le compteur d'adresse de rafraichissement a donc juste à mémoriser l'adresse de ligne. Le séquenceur mémoire était précédé par un circuit d'arbitrage, non-représenté dans le schéma ci-dessous. La microarchitecture de l'Intel 8202 est la suivante :

Microarchitecture de l'Intel 8202.

Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un Chip Select un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le refresh timer.

Pour commander les lectures et écriture, il recevait en entrée un bit Write Request et un bit Read Request, qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur.

Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, ce qui permettait d'adresser au maximum 16 kibioctets de RAM. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour le décodage d'adresse, le 8202 dispose de deux bits BO et B1 pour sélectionner le chip adéquat, ainsi que 4 sorties RAS pour activer la banque adéquate. On rappelle que le signal RAS remplace le signal Chip Select. C'est le séquenceur mémoire qui se charge de générer ces signaux RAS, à partir des deux bits B0 et B1 (qui sont techniquement des bits d'adresse).

Pour communiquer avec le processeur, l'Intel 8202 disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée.

Le signal SACK est très utile sur les configurations multiprocesseurs. Un processeur peut démarrer un accès mémoire, le signal SACK indiquera au second processeur qu'il doit attendre que l'accès soit terminé pour que ce soit son tour.

Les contrôleurs de DRAM asynchrones évolués

[modifier | modifier le wikicode]

L'Intel 8202 était un contrôleur mémoire basique, comme beaucoup d'autres à cette époque. Mais Intel a vendu des contrôleurs mémoires plus complexes. Par exemple, l'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Passons sur certains détails, comme le fait qu'il pouvait gérer jusqu'à 256 kibioctets de DRAM. Au-delà de ça, il y avait des fonctionnalités bien plus intéressantes, à savoir : un support de l'ECC, il était double port, il permettait de simuler une DRAM synchrone à partir d'une DRAM asynchrone. Il n'était pas le seul dans ce cas et des contrôleurs de DRAM très évolués étaient capables de faire des merveilles. Voyons comment cela était possible.

Les contrôleurs mémoire synchrone

[modifier | modifier le wikicode]

Il est parfaitement possible d'utiliser un contrôleur mémoire synchrone avec une DRAM asynchrone. A vrai dire, le contrôleur DRAM peut complétement simuler une mémoire synchrone alors que la DRAM associée est asynchrone. La traduction asynchrone vers synchrone se fait en ajoutant des registres sur le bus mémoire, notamment sur le bus de données et le bus d'adresse/commande. Nous avions détaillé cela dans le chapitre sur les SRAM, c'est la même chose avec une mémoire DRAM. Sauf que cette fois-ci, le contrôleur mémoire doit aussi être prévu pour.

Contrôleur mémoire synchrone utilisé avec une DRAM asynchrone

Les deux-trois registres illustrés plus haut peuvent être intégrés directement dans le contrôleur mémoire, que ce soit totalement ou en partie. Le strict minimum pour avoir un contrôleur mémoire synchrone est que celui-ci doit mémoriser adresse et commandes dans un registre. Par exemple, le 8207 d'Intel était capable de mémoriser les requêtes processeurs dans un registre interne, mais il fallait utiliser deux registres séparés pour le bus de données. Les deux registres étaient alors commandés par le contrôleur mémoire. Il est cependant possible d'aller plus loin et d'intégrer les registres du bus de données dans le contrôleur mémoire.

Contrôleur mémoire DRAM synchrone.
Il faut noter que cette fonctionnalité est parfois disponible sur les SRAM. En clair, on peut associer une SRAM asynchrone avec un contrôleur de SRAM synchrone. Le contrôleur de SRAM se charge alors de simuler une SRAM synchrone à partir de la SRAM asynchrone.

Utiliser un contrôleur mémoire synchrone a de nombreux avantages, l'un d'entre eux étant lié aux wait state. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Et pendant ce temps d'attente, il doit maintenir l'adresse mémoire sur le bus d'adresse. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des Wait states.

Utiliser un contrôleur mémoire synchrone d'éliminer les wait state, dans une certaine mesure. Avec un contrôleur mémoire synchrone, le processeur envoie l'adresse, mais c'est le contrôleur mémoire qui la maintient sur le bus d'adresse. Le processeur peut envoyer l'adresse et la donnée à écrire, elles sont recopiées dans les registres, et le controleur mémoire y a accès sans que le processeur doive les maintenir. Le processeur peut se déconnecter du bus mémoire et faire du travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les wait state disparaissent alors, du moins du point de vue du processeur.

La gestion de l'ECC

[modifier | modifier le wikicode]

L'ECC peut être géré dans le contrôleur mémoire. Pour cela, on couple les registres mentionnés dans la section précédente, avec un circuit de détection et de correction d'erreur. Le circuit d'ECC peut, comme les registres synchrones, être intégré dans le contrôleur mémoire, ou au contraire être situé dans un circuit séparé. Si le circuit d'ECC est séparé du contrôleur mémoire, il communique avec lui, histoire que le contrôleur mémoire puisse signaler toute erreur de parité ou d'ECC au processeur.

Controleur mémoire synchrone avec ECC intégré

Reprenons l'exemple du 8207 d'Intel. Le contrôleur mémoire 8207 gère le bus d'adresse et de commande, mais n'a pas de connexions directes avec le bus de données. Il ne peut donc pas prendre en charge l'ECC. Il avait besoin d'être couplé avec un circuit d'ECC séparé, relié au bus de données : l'Intel 8206. Le 8026 prenait en entrée : 16 bits de données et 8 bits d'ECC. Il fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Le 8206 détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela.

8207 avec ECC

La détection/correction d'erreur était appliquée à la fois pour les accès mémoire et pour les rafraichissements mémoire. Lors d'un rafraichissement mémoire, la donnée rafraichie est lue et réécrite. Avec l'ECC activé et configuré correctement, le rafraichissement passe par le bus de données. Au lieu d'avoir un cycle de lecture-écriture interne à la DRAM, on a un cycle de lecture-correction-écriture qui utilise le 8206. La donnée lue est envoyée sur le bus de données, puis le 8206 corrige une éventuelle erreur, et la donnée corrigée est alors réécrite en mémoire.

Au passage, si une erreur non-correctible est détectée, le 8206 ne fait rien, l'erreur est ignorée. La gestion de l'erreur sera retardée jusqu'à une lecture ultérieure. Et encore : si lecture ultérieure il y a. Si la donnée est écrasée par une écriture, la donnée corrompue sera simplement écrasée et disparaitra sans avoir pu faire le moindre dégât. Mais pour cela, le 8206 doit communiquer avec le contrôleur mémoire, pour savoir s'il est dans un cycle de rafraichissement ou un accès mémoire normal. Il prévient le 8207 lors d'une erreur, et c'est ce dernier qui décide si l'erreur doit être prise en compte ou ignorée. C'est seulement lors d'un accès mémoire normal que le processeur est prévenu qu'une erreur de parité/autre a eu lieu.

Les contrôleurs mémoires multiports

[modifier | modifier le wikicode]

Les contrôleur mémoire multiport disposent de plusieurs ports, chacun permettant de traiter un accès mémoire. Ils peuvent simuler une mémoire multiport à partir d'une DRAM monoport. Évidemment, la simulation n'est pas parfaite. Des accès mémoire simultanés, envoyés en même temps sur différents ports, sont en réalité exécutés un par un, pas en même temps. Il y a donc une petite pénalité en termes de performances, mais elle est mineure.

Encore une fois, nous allons reprendre l'exemple du 8207. Il avait deux ports séparés, et était prévu pour fonctionner dans un système à deux processeurs. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elles était mise en attente.

Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé à la priorité.

Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates. Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement.

Le contrôleur mémoire d'une DRAM Fast Page Mode

[modifier | modifier le wikicode]

Les mémoires DRAM classiques sont des mémoires à tampon de ligne, mais qui sont assez mal utilisées. Notamment, tout accès mémoire se fait en deux phases : un accès pour sélectionner la ligne, un autre pour sélectionner la colonne. Les mémoires Fast Page Mode permettent d'optimiser le tout. Elles permettent de faire plusieurs accès successifs à la même ligne, à des colonnes différentes. Et le contrôleur mémoire doit être adapté pour cela.

Sélection d'une ligne sur une mémoire FPM ou EDO.

Le contrôleur mémoire doit détecter que deux accès mémoire consécutifs se font dans la même ligne. Si deux accès consécutifs accèdent à la même ligne, on doit juste changer de colonne et altérer le signal CAS. C'est un succès de tampon de ligne, aussi appelé un succès de page. Si deux accès consécutifs accèdent à une ligne différente, c'est un défaut de tampon de ligne, aussi appelé un défaut de page. Il faut alors changer de ligne, en altérant les signaux RAS et en envoyant une adresse de ligne.

Pour détecter les succès ou défauts de page, il faut ajouter un circuit spécialisé dans le contrôleur mémoire. Il mémorise la ligne ouverte, et plus précisément son adresse de ligne (numéro de banque inclut). A chaque requête processeur, il compare l'adresse de ligne recue avec celle déjà ouverte. C'est un succès si les deux sont égales, un défaut si elles sont différentes. Le circuit qui fait cette comparaison est appelé le décodeur de commande. Il prévient le séquenceur mémoire en cas de succès de page, grâce à un signal de un bit, qui vaut 0 en cas de défaut de page et 1 en cas de succès. Le séquenceur mémoire décide alors comment gérer les signaux RAS et CAS, ainsi que l'envoi des adresses de ligne/colonne.

Controleur mémoire d'une FPM-DRAM

Le contrôleur mémoire d'une SDRAM ou d'une DDR

[modifier | modifier le wikicode]

Peu de choses sont connues sur les contrôleurs de SDRAM/DDR modernes, les fabricants ne donnant que peu de détails dessus. Les rares simulateurs qui tentent de décrire leur fonctionnement, comme DRAM SIM I et II, sont particulièrement simples et ne vont pas dans le détail. Néanmoins, le peu qu'on sait est tout de même instructif.

En général, le contrôleur de SDRAM/DDR est intégré au processeur ou au chipset de la carte mère. Les mémoires SDRAM sont arrivées sur le marché à une époque où la miniaturisation des transistors était bien entamée. Les chipsets de carte mère étaient déjà bien complets et intégraient déjà de nombreux circuits, contrôleurs mémoire inclus. Il y a cependant eu quelques rares exceptions. Un exemple est celui du POWER 8 Memory Buffer d'IBM, qui était prévu pour fonctionner avec les processeurs Power8 d'IBM, des processeurs destinés aux serveurs.

L'interface physique des SDRAM et son impact sur le contrôleur SDRAM

[modifier | modifier le wikicode]

Il est possible de connecter plusieurs barrettes sur le même contrôleur mémoire. C'est ce qui permet de placer plusieurs barrettes de mémoire sur la même carte mère : toutes les barrettes sont connectées au contrôleur de DRAM d'une manière ou d'une autre.

Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge vient bien de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela.

Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur.

Pour le décodage d'adresse, tout est plus simple sur les SDRAM/DDR. Les chips de mémoire SDRAM et DDR disposent d'une entrée Chip Select, ce qui facilite grandement le décodage d'adresse. Les bits de Chip Select sont générés par le contrôleur mémoire, et sont transmis sur le bus de commande. Le contrôleur de DRAM peut adresser un certain nombre de rangées, dispersés sur une ou plusieurs barrettes. La limite maximale dépend du contrôleur de DRAM, elle est souvent proche de 8 ou 16 rangées. Si on combine plusieurs barrettes de mémoire, il est possible de dépasser cette limite. Par exemple, pour un contrôleur de DRAM supportant maximum 8 rangées, 4 barrettes de 4 rangées chacune dépassent la limite.

Le séquenceurs mémoire pour les SDRAM/DDR

[modifier | modifier le wikicode]

Le séquenceur mémoire existe toujours pour les mémoires SDRAM, c'est toujours un circuit séquentiel qui implémente une machine à état. Il traduit toujours une requête processeur en une séquence de commandes envoyées à des timings bien précis. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, comme pour les autres DRAM. La seule différence est que la machine à état est plus complexe.

Pour rappel, une requête de lecture/écriture se fait en trois étapes maximum : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et ces commandes sont séparées par des délais mémoire bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des délais mémoire rend la conception du séquenceur plus complexe.

Il faut aussi tenir compte des commandes SDRAM anticipées, à savoir que l'on peut envoyer des commandes avant que la précédente soit terminée. Les commandes anticipées sont idéales dans le cas où des accès successifs se font dans des banques différentes. Pour les exploiter au mieux, le contrôleur mémoire doit donc détecter si des accès successifs se font dans des banques différentes, ou dans la même banque, pour décider d'envoyer des commandes anticipées ou non, mais aussi pour gérer les succès/défauts de cache. Cette détection des conflits de banque complexifie le séquenceur.

La détection des succès/défauts de page

[modifier | modifier le wikicode]

Un point important est que dans certaines conditions, certaines commandes peuvent être omises. Par exemple, en cas de succès de page, les commandes PRECHARGE et ACT ne doivent pas être envoyées, seules les commandes READ/WRITE le sont. Le contrôleur doit toujours détecter les succès et défauts de page et agir en fonction. La solution utilisée est la même que pour les mémoires FPM : il faut mémoriser quelle ligne est ouverte ou fermée.

La différence avec les FPM est qu'il faut faire cela pour chaque banque mémoire ! En effet, chaque banque a son propre tampon de ligne, ce qui fait que la gestion des lignes se fait indépendamment dans chaque banque. Le séquenceur mémoire doit donc se souvenir des lignes actives dans chaque banque. Pour cela, il mémorise ces lignes dans une petite mémoire : la table des banques, aussi appelée bank status memory.

Pour détecter un succès ou un défaut, le contrôleur doit extraire la ligne de l'adresse, mais aussi le numéro de banque. Il envoie alors le numéro de banque à la table des banques, sur son entrée d'adresse. Il récupère alors le numéro de la ligne active sur les sorties de données. Il compare alors ce numéro de ligne avec le numéro de ligne de l'adresse envoyée par le processeur. C'est un succès si les deux sont égales, un défaut sinon.

Contrôleur mémoire FPM avec plusieurs banques.

La politique de gestion du tampon de ligne

[modifier | modifier le wikicode]

Pour ce qui est des succès/défauts de page, le séquenceur mémoire peut fonctionner de plusieurs manières, dont les plus extrêmes sont appelés la politique de la page fermée et la politique de la page ouverte. Voyons à quoi elles correspondent.

Avec la politique de la page fermée, chaque accès mémoire est suivi d'une commande PRECHARGE, qui ferme la ligne courante et précharge les lignes de bits. Même si deux accès consécutifs se font dans la même ligne, la ligne est fermée et ré-ouverte entre deux accès mémoire. En clair : l'optimisation introduite par les mémoires FPM est désactivée, le contrôleur mémoire fait exprès de ne pas en profiter. On appelle cette méthode la close page autoprecharge.

Cette méthode réduit grandement les performances pour les accès à des adresses consécutives, mais fonctionne à merveille si les accès sont "aléatoires", à savoir qu'ils se font sans régularités évidentes. Un exemple classique est celui où plusieurs processeurs accèdent à la même mémoire RAM, mais accèdent à des données très éloignées en mémoire (ce n'est pas toujours le cas, mais ça l'est dans cet exemple). Leurs accès sont dispersés en mémoire, ce qui fait qu'il est rare qu'ils accèdent deux fois de suite à la même ligne. Utiliser la politique de la page fermée améliore les performances, dans ce cas précis.

Un autre avantage est que l'implémentation du séquenceur mémoire est très simple. En effet, le séquenceur mémoire se passe complétement de la table des banques, du comparateur de ligne, et de tous les circuits nécessaires pour vérifier les succès ou défauts de page. De plus, le séquenceur mémoire profite grandement des commandes READA et WRITEA, qui fusionnent une commande READ/WRITE avec une commande PRECHARGE. Le séquenceur mémoire a juste à envoyer des commandes ACT, READA, WRITEA et PREFETCH à la mémoire, pas besoin des commandes PRECHARGE, READ ou WRITE. Et ce détail simplifie grandement la conception du séquenceur mémoire.

À l'opposé, la politique de la page ouverte ne ferme pas automatiquement la ligne. Elle la laisse ouverte, en espérant que le prochain accès mémoire se fasse dans cette ligne. Lorsqu'un nouvel accès mémoire arrive, elle doit détecter les succès ou défauts de page et agir en fonction. En cas de défaut de page, la ligne est fermée, le séquenceur mémoire envoie une commande PRECHARGE, puis l'accès suivant effectue les deux commandes ACT + READ ou WRITE. En cas de succès de page, les commandes PRECHARGE et ACT ne sont pas envoyées, seules la commande READ ou WRITE l'est.

Un désavantage est que le contrôleur mémoire doit inclure une table des banques et un comparateur, comme vu plus haut dans la section sur les mémoires FPM. Un autre défaut est que garder une ligne ouverte consomme beaucoup d'énergie, comparé à un simple état de PRECHARGE. En conséquence, il est préférable de fermer les lignes dès que possible. Par contre, les performances sont d'autant meilleures que les accès mémoire consécutifs à une même ligne soient assez fréquents.

Si les accès mémoire sont aléatoires, les performances sont moins bonnes. La politique de la page fermée fermait les lignes en avance, avec des commandes READA ou WRITEA, avant même que l'accès suivant démarre. Avec la politique de la page ouverte, on doit attendre pour détecter un défaut de page, puis fermer la ligne avec une commande PRECHARGE séparée. La ligne est donc fermée avec un peu temps de retard, et envoyer deux commandes au lieu d'une prend plus de temps.

Les lignes ne restent pas ouvertes indéfiniment, elles sont automatiquement fermées lorsqu'elles sont rafraichies. Vu que c'est le contrôleur mémoire qui décide du rafraichissement mémoire, il sait quelles lignes sont rafraichies à quel moment. Et il sait donc quand elles sont fermées.

Les contrôleurs mémoires basiques utilisent une des deux solutions précédentes. Soit la page est toujours fermée, soit elle est toujours laissée ouverte jusqu'à ce qu'un accès mémoire la referme. Mais les contrôleurs plus évolués utilisent des politiques hybrides, capables de switcher entre les deux suivant la situation. La méthode la plus simple laisse une ligne ouverte un temps prédéterminé avant de fermer la ligne.

Il existe aussi des politiques prédictives. En clair, il, qui tentent de prédire s'il faut fermer ou laisser ouvertes les pages ouvertes. Elles regardent, pour les N derniers accès, s'ils ont fait un succès ou un défaut de page. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage de N bits, chaque bit indiquant si le énième accès précédent a été un succès de page ou non. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. Une prédiction simple fait la moyenne des bits à 1 dans ce registre et ferme la page si elle est inférieure à 1/2. Pour améliorer un petit peu l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Il existe sans doute d'autres solutions plus évoluées, mais il est difficile de savoir ce qu'il y a dans les contrôleurs de SDRAM modernes.

Le fait de laisser ouverte une ligne ou au contraire de la fermer systématiquement, se fait pour chaque banque.

Les caches intégrés aux contrôleurs de SDRAM

[modifier | modifier le wikicode]

Il arrive que des contrôleurs de SDRAM intègrent des mémoires caches. Cela peut sembler étrange, car les mémoires caches sont censées être soit dans le processeur, soit entre le processeur et le contrôleur de SDRAM. Mais ces caches sont un peu différents des caches du processeur : ils servent à mettre en attente les écritures, ils ne servent à rien pour les lectures. L'idée est la suivante : quand le processeur lance une écriture dans la RAM, l'écriture est mise en attente dans ce cache. Les lectures consultent ce cache, dans le cas où la donnée à lire soit dedans, mais elles ne chargent pas de données dans le cache. Seules les écritures copient des données dans ce cache.

L'intérêt est multiple. Le premier est que cela rend certaines lectures plus rapides. Quand on relit une donnée récemment écrite, la donnée est encore dans le cache, et elle est relue depuis le cache, sans passer par la RAM. Le résultat est qu'on a économisé un peu de bande passante, on n'a pas besoin d’accéder à la RAM pour cette lecture. Et la lecture est plus rapide. Mais ce n'est pas l'intérêt principal, car de telles situations sont assez rares.

La vraie optimisation est que cela permet de faire des écritures en bloc, idem pour les lectures. Les écritures sont retardées, elles se font quand le cache est plein. Le cache est alors vidé d'un seul coup en mémoire RAM, en bloc. De plus, entre deux vidanges du cache, la mémoire RAM ne voit que des lectures. Le résultat est que ce cache permet de regrouper les lectures ensemble, et les écritures ensemble. Or, nous avons vu dans le chapitre précédent qu'alterner entre lectures et écriture entraine une performance sous-optimale. Les SDRAM préfèrent enchainer une succession de lecture ou une succession d’écriture, ce que permet ce cache.

La présence de ce cache permet d'ajouter d'autres optimisations au contrôleur mémoire. Par exemple, le contrôleur mémoire peut fusionner plusieurs écritures dans la même adresse en une seule. Par exemple, si une écriture modifie une adresse, et qu'une écriture ultérieure écrit une autre valeur à la même adresse, seule la dernière écriture est envoyée à la mémoire RAM. Le contrôleur mémoire peut aussi regrouper plusieurs accès à des adresses consécutives en un seul accès en rafale. Le contrôleur mémoire analyse les écritures mises en attente et détecte si certaines se font à des adresses consécutives. Si c'est le cas, il fusionne ces requêtes en une écriture en rafale. Les deux optimisations, bien que différentes sur le fond, et n'ayant rien à voir, portent pourtant le même nom. Elles sont appelées la combinaison d'écriture.

L'optimisation ne paraît pas payer de mine, mais elle devient plus compréhensible quand on sait que certains contrôleurs mémoire peuvent mettre en attente beaucoup de données. Par exemple, l'Intel E8870 peut mettre en attente 64 lignes de cache dans la mémoire FIFO, soit 8 kibioctets de RAM ! Un autre exemple est le POWER 8 Memory Buffer d'IBM, mentionné plus haut. Il intégrait une mémoire de type eDRAM (de la RAM dans un circuit imprimé), 16 mébioctets en tout.