https://lafor.ge/feed.xml

La mémoire physique

2023-01-12

Architecture de Von Neumann

Tous les ordinateurs que vous utilisez aujourd'hui au quotidien sont basés sur une architecture à comprendre une manière d'agencer des composants et de les faire se parler.

Cette architecture se nomme von Neumann nommée d'après le nom du touche à tout John von Neunamm.

Il a été le premier à théoriser le concept de mémoire unique à la fois pour le programme et pour les données.

L'architecture se compose de 3 éléments principaux :

  • Une unité de traitement appelée généralement CPU : elle réalise les traitements et les calculs sur les données
  • Une mémoire : stocke les données du programme et le programme lui-même.
  • Un bus de communication : un ensemble de fils de même longueur
Deux rectangles relié par une série de traits parallèles signaler comme étant un bus de données. Le premier rectangle à la mention CPU, l'autre mémoire

 

L'architecture précédente séparait le programme de la donnée.

Elle s'appelait l'architecture Harvard. Plus compliqué à construire que son homologue du jour.

La RAM

Dans les ordinateurs de tous les jours, votre tour, le laptop, etc ...

Le bloc de mémoire se nomme une RAM pour Random Access Memory.

Deux rectangles relié par une série de traits parallèles signaler comme étant un bus de données. Le premier rectangle à la mention CPU, l'autre R.A.M

Si l'on zoom sur le bloc RAM, on s'aperçoit que celui est composé d'une série de lignes de blocs.

Un rectangle appelé RAM, contient des rectangles tout en longueur subdivisé horizontalement en des rectangles plus petits. Les rectangles subdivisés sont empilés verticalement et numéroté @1 jusqu'à @N

Chaque ligne est désignée par une adresse.

La première adresse étant @0 et la dernière @N.

N le nombre total de lignes dans la RAM.

Zoomons encore sur une ligne de blocs.

Chaque bloc est numéroté par rapport à sa position dans la ligne.

Arbitrairement, on choisit la droite comme étant l'origine, mais on pourrait totalement faire l'inverse.

Un rectangle subdivisé en 64 parties. La partie à l'extrême gauche noté 64 et celle à l'extrême droit 0. La ligne elle-même est notée @0

Chaque bloc est appelé une cellule mémoire.

Continuons de descendre.

Cellule mémoire

On est maintenant au niveau d'une cellule mémoire.

Il s'agit d'un bloc qui peut avoir deux états.

Un état 0 logique.

Un rectangle avec un 0 bleu

Un état 1 logique.

Un rectangle avec un 1 rouge

Il est possible de lire sa valeur.

Pour cela branche un fil de donnée à notre cellule.

Pour le moment la valeur stockée dans la cellule est inconnue de l'extérieur.

Un rectangle avec un 0 bleu relié à un rectangle avec un point d'interrogation par un trait appelé fil de données

Pour pouvoir lire l'information contenue, il faut en quelque sorte activer la cellule.

Ceci est fait au moyen d'un second fil, appelé fil d'adressage.

Un rectangle avec un 0 bleu relié à un rectangle avec un point d'interrogation par un trait appelé fil de données. Un autre trait part de la gauche du premier rectangle et est nommé fil d'adressage.

Pour lire l'information, on vient activer le fil d'adressage.

Cela a pour effet d'extraire la donnée de la cellule qui se propage dans le fil de donnée, ici un état logique 0.

Un rectangle avec un 0 bleu relié à un rectangle avec un 0 bleu par un trait appelé fil de données bleu. Un autre trait rouge part de la gauche du premier rectangle et est nommé fil d'adressage activé.

De la même manière si 1 logique est stocké, activer la cellule au travers du fil d'adressage permettra de récupérer ce 1 dans le fil de donnée.

Un rectangle avec un 1 rouge relié à un rectangle avec un 1 rouge par un trait appelé fil de données rouge. Un autre trait rouge part de la gauche du premier rectangle et est nommé fil d'adressage activé.

Il est possible d'imposer l'état de la cellule au travers du fil de donnée.

Mais tant que la cellule n'a pas été activée au travers du fil d'adressage, l'état de la cellule reste inchangée.

Deux rectangles sont reliés par un trait bleu vertical. Le premier est un rectangle muni d'un 1 rouge à l'intérieur. Le deuxième d'un 0 bleu. Le premier rectangle possède un trait horizontal blanc sur son côté gauche mentionné fil d'adressage désactivé

Pour cela, il faut activer le fil d'adressage, qui permet d'imposer l'état 0 à notre cellule.

Deux rectangles sont reliés par un trait bleu vertical. Le premier est un rectangle muni d'un 0 bleu à l'intérieur. Le deuxième d'un 0 bleu. Le premier rectangle possède un trait horizontal rouge sur son côté gauche mentionné fil d'adressage activé

Un fois le fil d'adressage désactivé notre cellule conserve son état 0.

Deux rectangles sont reliés par un trait bleu vertical. Le premier est un rectangle muni d'un 0 bleu à l'intérieur. Le deuxième d'un point d'interrogation . Le premier rectangle possède un trait horizontal blanc sur son côté gauche

De cet état 0, on peut alors venir appliquer l'état 1.

Deux rectangles sont reliés par un trait bleu vertical. Le premier est un rectangle muni d'un 1 rouge à l'intérieur. Le deuxième d'un 1 rouge. Le premier rectangle possède un trait horizontal rouge sur son côté gauche

Lorsque le fil d'adressage se désactive, le 1 est conservé.

Deux rectangles sont reliés par un trait bleu vertical. Le premier est un rectangle muni d'un 0 bleu à l'intérieur. Le deuxième d'un point d'interrogation . Le premier rectangle possède un trait horizontal blanc sur son côté gauche

Mot binaire

Bon c'est cool on peut stocker 0 et 1 et les lire / écrire à notre convenance.

Mais on n'ira pas loin avec une seule cellule. 🙄

C'est ici qu'intervient la représentation binaire des nombres.

Dans notre système, on nomme bit une cellule mémoire.

bit : binary digit => deux états

Avec 2 bits, il est possible de représenter:

  • 00 => 0
  • 01 => 1
  • 10 => 2
  • 11 => 3

Nous allons donc agencer deux cellules pour pouvoir de manière indépendante, stocker les digits du nombre que l'on souhaite stocker.

Il est à remarquer que le fil d'adressage est commun au deux cellules.

Ici nous allons représenter le nombre décimal 2 en mémoire. Pour cela on définit le bit 1 à 1 et le bit 0 à 0.

Deux cellules mémoires. Les deux partagent le même fil d'adressage. La cellule de gauche contient un 1 rouge. La cellule de droite un 0 bleu.

Si l'on veut lire les données stockées dans notre couple de cellule.

On active les deux cellules.

Ce qui permet de lire le mot binaire c'est à dire un ensemble de cellules ordonnées.

Ici ce mot vaut 10 en binaire ou 2 en décimale.

Deux cellules mémoires. Les deux partagent le même fil d'adressage activé en rouge. La cellule de gauche contient un 1 rouge. La cellule de droite un 0 bleu. Les deux cellules vont respectivement indiquer une valeur de 1 et de 0 à l'extérieur.

De la même manière si l'on désire enregistrer une valeur, mettons 01. On active le fil d'adressage. On applique la valeur respectivement voulue pour les cellules.

Ici :

  • un 0 sur le bit1
  • un 1 sur le bit0
Deux cellules mémoires. Les deux partagent le même fil d'adressage activé en rouge. La cellule de gauche contient un 0 bleu. La cellule de droite un 1 rouge. Un texte annonce, on impose l'état 01.

Pour stocker de plus grand nombre, on peut alors augmenter le nombre de cases qui constitue notre mot binaire, d'un mot de 2 bits, on passe à un mot de 8 bits.

Que l'on nomme plus communément un octet.

octet, signifie 8 pour "oct" comme dans octogone.

un ensemble de 8 bits.

8 cellules mémoire partageant le même fil d'adressage.

Que l'on peut ainsi manipuler comme notre mot binaire de 2 bits.

En activant le fil d'adressage de la ligne du mot, on peut en lire sa valeur.

8 cellules mémoire partageant le même fil d'adressage. Fil d'adressage actif. Dont lit leur valeur.

On peut alors également modifier le mot. En appliquant en entrée la valeur du mot voulu et en activant le fil d'adressage.

8 cellules mémoire partageant le même fil d'adressage. Fil d'adressage actif. Dont on impose la valeur

Et comme toujours, ce qui est vrai pour 1, 2, 8 est valable pour 1000. Faut juste beaucoup de fils. 🤣

Plein de cellules mémoire partageant le même fil d'adressage.

Matrice de mémoire

Bon! On peut stocker des nombres aussi grands que l'on veut, mais on ne peut en stocker qu'un seul. 😕

Il faut trouver un moyen d'en stocker déjà 2.

La solution est toute trouvée, nous allons les empiler.

Deux mots binaires supperposé. Mot @0 est 00. Mot @1 est 01. Celui du haut possède l'adresse @0 et celui du bas @1.

Nous avons donc 2 mots différents.

Les lignes d'adressage sont communes aux mots et les colonnes de données sont communes aux bits des mots.

Pouvant de manière indépendante activer ou non une ligne d'adressage, on est dans la capacité de sélectionner le mot désiré.

Par exemple, ic, l'on désire modifier le mot à l'adresse @1.

On active la ligne correspondante et on applique la valeur.

Deux mots binaires superposés. Mot @0 est 00. Mot @1 est 11. Celui du haut possède l'adresse @0 et celui du bas @1. La ligne @1 est active. On applique 11 en entrée de la matrice

Pour lire la valeur, c'est également la même chose.

On peut de manière indépendante sélectionner l'adresse @0. Et lire le mot qui y est contenu.

Deux mots binaires superposés. Mot @0 est 00. Mot @1 est 11. Celui du haut possède l'adresse @0 et celui du bas @1. La ligne @0 est active. On lit 00 en entrée de la matrice.

On a désormais un système complet qui permet de lire et écrire deux mots de 2 bits.

On peut alors généraliser !

On créé alors une matrice de M mots binaires de N bits.

Une matrice de M mots binaires de N bits supperposés. Le mot du haut est @0 et le mot du bas @M

Nous pouvons désormais, stocker la Terre entière et conquérir le monde !! 🌍

Adressage

Très bien, on a un joli système tout propre, capable de stocker de la donnée.

Pour le moment, j'ai passé sous silence ce souci.

Mais comment peut-on sélectionner la ligne que l'on désire ?

Surtout lorsqu'on a plus de deux mots.

Decodeur

C'est alors qu'intervient un système qui se nomme un décodeur.

Il s'agit d'une sorte de gare de routage.

On lui dit quelle voie doit être activée et lui active la voie correspondante.

Prenons un exemple avec 4 voies.

Comment pouvons nous piloter l'entrée de gauche pour que la voie2 soit la seule activée ?

Un rectangle appelé décodeur avec un fil à gauche surmonté de point d'interrogation et à droite 4 fils respectivement appelé voie0, voie1, voie2 point d'interrogation et voie3 de haut en bas

Mettons que l'on veille définir directement la sortie par son numéro.

Le décodeur mais avec un fil surmonté 2 point d'interrogation à gauche

Et bien on va encoder ce nombre avec des fils.

Le décodeur mais avec deux fils appelé respectivement bit1 et bit2 de haut en bas

On définit binairement ce 2.

Le décodeur mais avec deux fils appelé respectivement bit1 et bit2 de haut en bas. bit1 allumé pas le bit0. la voie 2 est allumée

De cette manière, on vient sélectionner la voie que l'on désire.

On peut alors le faire pour toutes les voies, ici un 3.

Le décodeur mais avec deux fils appelé respectivement bit1 et bit2 de haut en bas. bit1 et bit0 allumés. la voie 2 est allumée

Par contre on a un souci, même quand on ne veut rien sélectionner, la voie 0, reste active.

Le décodeur, bit1 et bit0 éteint. la voie 0 est allumée

On ajoute alors un troisième fil Enable qui permet de contrôler la sortie du décodeur:

  • si état bas, aucune voie n'est allumée
Le décodeur mais avec un troisième fil appelé Enable à gauche éteint, bit1 et bit0 éteint. la voie 0 est éteinte
  • si état haut, la voie sélectionnée est allumée
Le décodeur mais avec un troisième fil appelé Enable à gauche allumée, bit1 et bit0 éteint. la voie 0 est allumée

On peut alors contrôler ce que l'on désire comme voie en maintenant un état haut sur Enable.

Le décodeur mais avec un troisième fil appelé Enable à gauche allumé, bit1 et bit0 allumés. la voie 3 est allumlée

Ou inhiber la sortie même si les bits d'entrées sont actifs

Le décodeur mais avec un troisième fil appelé Enable à gauche éteint, bit1 et bit0 allumés. la voie 3 est éteinte

Si l'on a besoin de plus de voies que 4, il nous faut un fil d'entrées supplémentaire.

Car 2^3 = 8

Un décodeur de 3 entrées et 8 voies

Celui-ci se contrôle de la même manière.

Un décodeur de 3 entrées et 8 voies. bit 2 et 0 allumés. Enable actif. voie 5 active

On peut alors généraliser.

Un décodeur de N entrées et 2 puissance N moins 1 voies

Selection de la ligne

On a donc un système qui nous permet de sélectionner une ligne parmi un ensemble d'autres.

On va donc coler un décodeur sur notre matrice de mémoire.

Un décodeur 8 voies acollées à une matrice de 8 par 8 cellules. les bit 0 et 2 sont actif, Enable aussi. La ligne d'adresse 5 de la matrice est active

On peut alors en faire une jolie boîte.

On peut alors, sortir 3 fils qui constitueront notre bus d'adresses. Ici de 3 bits.

Et un bus de données de 8 bits.

Avec supplément un signal d'activation de la boîte. Qui correspond au Enable de notre décodeur.

Ce qui permet de pouvoir stocker un mot de 8 lettres.

Un boitier d'où sors 2 bus, un premier de 3 fils d'adresse, un second de 8 fils de données. Un texte indique que la valeur totale est de 8 octets stockables. Soit 1 lettre.

On peut alors augmenter le nombre de fils d'adresse pour venir faire grandir en hauteur la matrice.

Ici, on passe à 8 bits d'adresses et donc 256 lignes possibles.

On augmente alors d'autant la quantité de données stockable à une valeur incroyable de 256 octets.

Un boitier d'où sors 2 bus, un premier de 8 fils d'adresse, un second de 8 fils de données. Un texte indique que la valeur totale est de 256 octets stockables. Soit 256 lettres.

On peut également augmenter la largeur du bus de données pour lui faire atteindre les 64 fils.

Mais on reste ridicule en termes de stockage. 2 kilo-octets soit un fichier.

Un boitier d'où sors 2 bus, un premier de 8 fils d'adresse, un second de 64 fils de données. Un texte indique que la valeur totale est de 2048 octets stockables. Soit un fichier de 2 kilo-octets.

Si on augmente à 17 fils le bus de d'adresse.

On atteint péniblement les 1 méga-octet, une pauvre image. 😫

Un boitier d'où sors 2 bus, un premier de 17 fils d'adresse, un second de 64 fils de données. Un texte indique que la valeur totale est de 2048 octets stockables. Soit un fichier de 2 kilo-octets.

On pourrait augmenter le nombre de fils du bus de données, mais celui-ci ne peut pas grandir excessivement.

Je crois l'on ne va pas y arriver comme ça ...

Il nous faut un autre angle.

Multiplexeur

Avant de continuer notre chemin vers de plus grande valeur de stockage.

Nous allons faire un tour sur un autre système.

Celui-ci possède deux entrées appelées voie 0 et voie 1.

L'idée du composant est de venir connecter l'une des voies à la sortie selon le signal de contrôle.

Un trapèze régulier dont le coté gauche est le grand côté, il possède deux entrées voie 0 et voie 1 de haut en bas. Le petit côté à droite possède une sortie appelée Sortie. Le côté oblique possède une entré contrôle. Le tout est appelé Mux

Si le signal de contrôle est à 1, alors on connecte la voie 1 à la sortie.

Ici, le signal de la voie 1 vaut 0 donc la Sortie vaut également 0.

Le trapèze est détaillé, la voie 1 est connectée à la sortie. Le signal de contrôle vaut 1

Si la voie 1 possède un signal 1, la Sortie recopie ce comportement.

Le trapèze est détaillé, la voie 1 est connectée à la sortie. Le signal de contrôle vaut 1

Si le signal de contrôle bascule à 0, alors c'est la voie 0 qui est connectée à la Sortie.

La voie 1 même à 1 est ignorée.

Le trapèze est détaillé, la voie 0 est connectée à la sortie. Le signal de contrôle vaut 0

De la même manière, si la voie 0 passe à 1, la Sortie vaut 1.

Le trapèze est détaillé, la voie 0 est connectée à la sortie. Le signal de contrôle vaut 0

On peut alors utiliser le même système d'adressage que pour le decodeur pour venir connecter plus de 2 voies à une sortie.

On contrôle alors avec autant de bits que nécessaire, ici 2 pour contrôler 4 voies.

Le trapèze possède 4 voies, 2 contrôle et une sortie. les voie 1 et 2 sont alumées. le bit 1 du contrôle est allumé. la sortie recopie le comportement de la voie 2

Et on peut venir augmenter le nombre de voies.

Le trapèze possède 8 voies et 3 bits de contrôle.

Et finalement généraliser à N voies.

Pour déterminer le nombre de fils de contrôle nécessaires. On va poser deux choses :

  • soit x le nombre de fils de contrôle
  • soit N le nombre de voies
N = 2 puissance x alors x = log2 de N

On voit aussi que le nombre de voies sera toujours une puissance de 2.

Le trapèze possède N voies et log 2 de N bits de contrôle.

Ce système ce nomme un multiplexeur.

Selection de la colonne

Notre système précédent avait comme problème le faible stockage.

On a aussi vu que l'on ne pouvait pas faire grandir en largeur notre matrice, car la taille du bus de données auquel la matrice est rattachée doit rester raisonnable.

L'idée qui semble moins optimisée va être de selectionner une unique cellule et plus toute la largeur.

Ainsi on peut faire grandir la largeur de la matrice indépendamment de la largeur du bus de données.

Pour cela on vient brancher un multiplexeur sur la sortie de la matrice.

On branche également des fils de contrôle sur celui-ci.

Ayant 8 bits de données en sortie, nous avons besoin de 3 bits de contrôle.

Une matrice de 8 par 8 avec un multiplexeur de 3 bits de contrôle.

On peut alors sélectionner indépendamment, la ligne et la colonner.

Ici on sélectionne la ligne 5 et la colonne 5.

La case aux coordonnées (5; 5) vaut 1.

Et ainsi la sortie vaut également 1.

Une matrice de 8 par 8 avec un multiplexeur de 3 bits de contrôle. Bits 2 et bit 0 sur decodeur activés. Bits 2 et 0 du multiplexeur activés. ligne d'adresse 5 activée.

On peut alors sélectionner n'importe quelle cellule de la matrice.

Ici les coordonnées (2; 3):

Une matrice de 8 par 8 avec un multiplexeur de 3 bits de contrôle. Bits 1 et bit 0 sur decodeur activés. Bit 1 du multiplexeur activé. ligne d'adresse 3 activée.

On vient alors diviser notre bus d'adresses entre le décodage de la ligne et la sélection de la colonne.

La matrice, son décodeur de ligne et son multiplexeur de colonne enfermé dans une boîte. Le fil Enable, le bus de données et la sortie traversent la boîte vers l'extérieur. Les 3 premiers fils du bus d'adresse sont appelés ligne et les 3 seconds colonne.

On peut alors synthétiser en:

Un carré avec une matrice de 8 par 8 carrés rouge et bleus disposé aléatorement. Un gros trait est appelé bus d'adresse 6 fils. Il y a aussi le fil Enable et la sortie.

On vient d'encapsuler la sélection d'un bit de données.

Qui peut se généraliser avec autant de bits du bus d'adresse, ici 20 bits.

Une matrice de 20 fils d'adresse

Bank

Pour le moment, nous sommes capable de sélectionner un seul bit.

Or pour créer un octet de donnée. Il nous en faut 8.

L'idée alors est d'utiliser 8 matrices.

Mais de partager le bus d'adresse avec chacune des 8 matrices.

On attribue alors à chaque matrice un bit différent.

8 matrices différentes connectées à un même bus de données.

Lorsque l'on demande un octet. On vient simultanément sélectionner la même case dans chacune des matrices.

8 matrices différentes connectées à un même bus de données. Dont on selectionne les mêmes cases.

Ainsi l'on récupère notre octet de données.

On encapsule alors les 8 matrices dans une bank.

Celle-ci prend en entré le bus d'adresses et en sortie le bus de données.

Un rectangle entoure 8 matrices. Appelé bank

Bus de données complet

Nous avons récupéré notre octet mais pas les 64 bits que l'on possédait avant.

Nous allons donc continuer à paralléliser les matrices.

Et donc pour se faire, utiliser 8 banks.

On va alors attribuer un octet différent à chaque bank.

8 banks en parrallèle paratageant le même bus d'adresse. Chaque bus de données de 8 bits est fusionnés en un bus de 64 bits.

On peut alors sélectionner des mots de 64 bits formés par les octets de chaque bank.

On sélectionne la même cases dans les 8 matrices des 8 banks simultannément.

Chaque case des matrices est alors accessible par une adresse unique que l'on peut représenter via ce tableau de correspondance, ici pour un bus d'adresse de 6 bits.

Tableau de comparaiseon bus de données, coordonnées, adresse. Par exemple 111001, (1, 7), 254. Ou 001001, (1,1), 9

On se retrouve alors virtuellement avec notre système de départ.

Une série de N ligne d'adresses de cases mémoire et aujourd'hui nous savons désormais que chaque case est dans les faits une matrice contenu dans une bank.

Un rectangle appelé RAM, contient des rectangles tout en longueur subdivisé horizontalement en des rectangles plus petits. Les rectangles subdivisés sont empilés verticalement et numéroté @1 jusqu'à @N

La taille de la ligne étant alors la largeur du bus de données. Ici 64 bits. 😀

Un rectangle subdivisé en 64 partie. La partie à l'extrême gauche noté 64 et celle à l'extrême droit 0. La ligne elle-même est notée @0

Stockage

On va voir jusqu'où on peut monter avec notre nouvelle architecture. 😀

Commençons avec une matrice de 8 par 8.

Calcule de nombre d'octets d'un système composé de matrice de 8 lignes par 8 colonnes

On obtient un stockage de 512 octets.

Augmentons la largeur du bus d'adresses à 24 bits.

On utilise alors des matrices rectangulaires de 14 lignes de hauteur et de 10 colonnes de largeur.

Calcule de nombre d'octets d'un système composé de matrice de 14 lignes par 10 colonnes

On passe alors a 128 Mo de stockage ! 😁

En dissociant la largeur du bus de données de la largeur de la matrice, on a dramatiquement augmenté la densité de stockage.

Vous imaginez si l'on devait gérer 1024 fils !

Et on continue alors à augmenter notre bus de données.

Calcule de nombre d'octets d'un système composé de matrice de 20 lignes par 10 colonnes

Eh! Mais ça commence à ressembler à ce que l'on connaît. 😉

Maintenant! Le dernier clou dans le cercueil. Rajoutons 2 fils de plus, juste 2...

Calcule de nombre d'octets d'un système composé de matrice de 18 lignes par 14 colonnes

Faites les calculs pour 40 bits de largeur de bus d'adresse. Vous verrez que vous trouverez quelque chose de massif !

réponse

40 bits d'adressage => 4 To de stockage

Bien sûr l'adressage ne suffit, il faut aussi les cellules mémoire correspondantes et donc les 32 Téra de cellules.

Ceci étant conditionné à la fois par la surface de la mémoire et de la taille de chaque cellules.

Ce qui explique la Loi de Moore appliqué au stockage, plus les cellules seront petites, plus on pourra en caser beaucoup sur une surface réduite!

Ecriture

C'est fantistique on est capable stocker en théorie ce que l'on veut!

En théorie seulement...

Pour le moment, il est impossible d'écrire quoique ce soit en mémoire.

Architecture Von Neumann partie 2

Reprenons le schéma du début.

On a un bus d'adresse de largeur variable et un bus de données de 64 bits.

On peut interroger la mémoire grâce au bus d'adresse et lire la réponse grâce au bus de données.

Un CPU relié à une RAM par un bus d'adresse

Par contre, comment peut-on écrire dans cette mémoire ?

Un CPU relié à une RAM par un bus d'adresse. Et une flèche écriture point d'interrogation.

Et bien, nous allons rajouter un nouveau fil !

Celui-ci sera responsable de définir si l'on désire lire depuis une adresse ou y écrire.

Un CPU relié à une RAM par un bus d'adresse. Et fil d'écriture.

Avant de pouvoir nous attaquer à l'écriture, nous avons besoin de plusieurs outils.

Demultiplexeur

Le demultiplexeur est simplement un multiplexeur monté à l'envers.

On dispose d'une entrée que l'on souhaite recopier sur une voie.

Un trapèze régulier dont le coté gauche est le grand côté, il possède deux entrées voie 0 et voie 1 de haut en bas. Le petit côté à droite possède une sortie appelée Sortie. Le côté oblique possède une entré contrôle. Le tout est appelé Mux

Le mutiplexeur était l'inverse, on avait une multitude de voies que l'on souhaitait recopier sur une sortie unique.

Un trapèze régulier dont le coté droit est le grand côté, il possède deux entrées voie 0 et voie 1 de haut en bas. Le petit côté à gauche possède une sortie appelée Entrée. Le côté oblique possède une entré contrôle. Le tout est appelé DeMux

Ici même principe, si le fil de contrôle vaut 0 alors la l'entrée est connectée à la voie 0, la voie 1, est elle laissée complètement dans le vide, l'équivalent d'un fil coupé.

Un DeMux dont le controle vaut 0;  l'entrée est directement relié à la voie 0, la voie 1 laissée dans le vide

Ce qui fait que si l'entrée vaut 0, la sortie vaudra également 0.

Ceci est la différence fondamentale par rapport au décodeur qui n'était capable que de définir un état haut sur une voie en fonction d'un signal de contrôle.

Un DeMux dont le controle vaut 0;  l'entrée est directement relié à la voie 0, la voie 1 laissée dans le vide

L'aiguillage de l'entrée peut être modifié pour être connecté à la voie 1 en passant le contrôle à 1.

Un DeMux dont le controle vaut 1;  l'entrée est directement relié à la voie 1, la voie 0 laissée dans le vide

On peut alors augmenter le nombre de voies, ici 8.

Un DeMux 8 voies et 3 contrôles

Et comme toujours, vous commencez à connaître la chanson, on peut généraliser à N voies. Et par conséquent log2(N) contrôles.

Un DeMux N voies et log2 de N contrôles

Mux/DeMux

Comme on peut le voir le Multiplexeur et le Démultiplexeur sont très semblables. Ils partagent tout deux les même connexions. Seuls les entrées et les sorties sont inversées.

On va ainsi pouvoir définir un nouveau composant qui se nomme un Mux/DeMux qui possède un fil de contrôle supplémentaire mode.

Un Mux avec la mention Mux/DeMux et un fil supplémentaire mode à côté du bus de contôle.

Dans ce composant hybride, les connexions sont à la fois des entrées et des sorties.

Tout dépend de l'état du fil mode.

Si celui-ci est à l'état 0. Le composant se comporte comme un Multiplexeur.

Les voies sont les entrées et la sortie, et bien la sortie. 😅

Un Mux/DeMux avec mode qui vaut 0.

Si mode vaut 1 alors la sortie devient l'entrée et les voies les sorties.

Un Mux/DeMux avec mode qui vaut 1.

Buffer I/O

Jusqu'à présent on ne faisait que lire de l'information depuis la mémoire, mais si l'on se met à écrire également de la données.

Comment empêcher que ce qui est contenu dans le CPU n'aille écraser le contenu de la RAM ?

Tant que la cellule n'est pas sélectionnée, pas de souci. Elle est physiquement déconnecter du reste.

Deux carrés séparé par un fil coupé, l'un à gauche appelé CPU avec comme valeur 1 et l'autre à droite appelé RAM avec comme valeur 0.

Par contre dès que le bus d'adresse sélectionne la cellule, elle devient physiquement relié à l'extérieur et l'extéreur peut très bien être un 1.

Un fil relis désormais les deux carrés

Si la valeur était à la base un 0, on peut très bien avoir écrasé la donnée avant d'avoir été capable de la lire.

On se retrouve dans un état indécis, peut-être qu'il y a un 0 ou peut-être un 1, possiblement quelque chose entre les deux.

Les valeurs de ces carrés deviennent imprédictibles

Le fil allant dans les deux sens, l'inverse est également vrai.

Il nous faut un mécanisme, nous permettant d'isoler notre système lors de la lecture mais aussi de l'écriture.

Les deux carrés reliés par un fil sont maintenant séparé par un carré avec des triples point d'interrogation.

Déjà nous allons avoir besoin d'un système qui n'est passant que dans un seul sens, on nomme ceci un buffer.

Schéma d'un buffer. Un triangle orienté pointe vers la droite. Un flèche de gauche vers la droite passante et une flèche de droite vers la gauche bloquante.

On va alors contrôler ce buffer pour le rendre ou non passant.

Schéma d'un buffer. avec un fil de contrôle.
  • Si le contrôle vaut 0, le système est bloquant et se comporte comme un fil coupé.
Schéma d'un buffer. avec un fil de contrôle à 0. Ce qui équivaut un fil coupé
  • Si le contrôle vaut 1, le système est passant.
Schéma d'un buffer. avec un fil de contrôle à 1. Un buffer

On appelle ça un Tri State Buffer car du point de vue de la sortie on a:

  • état 0
  • état 1
  • état fil coupé

On définit alors un autre composant qui va permettre de faire l'inverse. On nomme ceci une porte NON.

Schéma d'une porte NON. Un triangle orienté pointe vers la droite avec un rond sur la pointe.

Si l'entrée vaut 1 alors la sortie vaut 0 et inversement.

L'idée est d'avoir un système symétrique.

On va alors agencé tête bêche nos deux tri state buffer, connecté l'entré de l'un à la sortie de gauche et connecter l'entrée de l'autre à la sortie de droite. Que l'on contrôle simultanément avec un même contrôle. On inverse le signal sur l'autre buffer.

Montage de deux buffers en sens inverse contrôlés par un même signal mais l'un est derrière une porte NON

Ce signal peut avoir deux valeurs:

-Si le signal est à l'état 1 les données transitent de la gauche vers la droite.

Schéma avec un contrôle à 1

-Si le signal est à l'état 0 les données transitent de la gauche vers la droite.

Schéma avec un contrôle à 0

On peut alors en faire un composant à 2 connexions de données et 1 fil de contrôle.

Le montage enfermé dans un boîtier. Deux entrées/sorties et un fil de contrôle.

Ce composant se nomme un Buffer I/O.

Que l'on peut alors intercalé dans notre système de tout à l'heure.

On vient également brancher le CPU au contrôle, ainsi c'est lui qui devient moteur de la désicion du flux de données

En Lecture

Buffer I/O contrôle à 1. le flux va de la mémoire vers le CPU

Ou en Ecriture

Buffer I/O contrôle à 1. le flux va du CPU vers la mémoire

Ce choix est purement arbitraire, le Buffer I/O pourrait-être monté dans le sens inverse.

Modifier les matrices

Nous avons désormais tous les outils pour travailler.

Nous allons temporairement remplacer le multiplexeur par un démultiplexeur.

Une cellule mémoire, un décodeur et un démultiplexeur

Imaginons que l'on souhaite modifier la case à l'adresse 011010.

Soit colonne 2 et ligne 3.

Sa valeur est actuellement de 0. On désire y inscrire 1.

Le démultiplexeur est réglé pour rediriger l'entrée sur la voie 2.

On applique un 1 sur l'entrée.

Ce qui a pour effet de modifier la cellule aux coordonnées (2, 3) mais laisse inchangées les autres.

Comme nous désirons à la fois écrire et lire dans la matrice.

On utilise notre Mux/DeMux.

On ajoute également un fil supplémentaire pour réaliser le changement de mode du Mux/DeMux.

On rajoute également le Buffer I/O que l'on contrôle avec le même signal que le Mux/DeMux.

Ce qui permet de ne pas modifier par inadvertance une case mémoire.

On peut alors faire un composant intégré de ce système.

On verra dans la suite des méthode pour optimiser le nombre d'éléments nécessaires.

On en reviens alors à l'organisation précédente mais avec désormais la possibilité de lire et d'écrire des mots de 64bits.

Rank

Il est alors possible de subdiviser nos banks en des banks plus petite. Pour cela nous allons utiliser la même astuce que toujours: réserver une partie des fils du bus d'adresse pour un usage différents.

Ici cet usage va être de sélectionne la bank qui possède le bon octet.

Pour cela, on utilise un décodeur qui vient selectionner la bank en fonction de l'adressage que l'on lui fourni.

Un assemblage de 4 bank relié à un même bus d'adresse et partageant un même bus de donnés.

Si par exemple on souhaite sélectionner un octet situé dans la bank 1, on va alors activer le bit 1 et laisser le bit 0.

Ce qui va activer le signal Enable de la bank 1 et ainsi permettre le décodage de l'adresse de l'octet voulu.

Un assemblage de 4 bank relié à un même bus d'adresse et partageant un même bus de donnés.

Ce qui permet un adressage non plus en 2 dimensions mais en 3 !

Tableau de correspondance entre le triplet de nombre (bank, ligne, colonne) et l'adress. (0;0;0) => adresse 0. (0;0;1) => adresse 1. (4; 7; 7) => adresse 1023

Chaque bank contient un certain nombre d'octets différents.

On peut alors en faire un composant que l'on appelle une puce ou Chip.

L'assemblage précécédent enfermé dans une bôite avec 3 entrées: lecture/écriture, Enable, bus d'adresse. Et un bus de données

Qui peut se symboliser par une version simplifiée.

Un rectangle composé de 4 banks. Appelé Chip

On agence chacun de nos chips comme nous l'avions fait avec les banks, chaque chip représentant un octet. Il nous en faut également 8 pour atteindre les 64 bits.

Un assemblage de 8 chips paratageant, le même bus d'adresse, de donnée, le signal de lecture/écriture ainsi que le signal d'activation.

Et là ça devient fou et c'est le but de tout ce qu'on vient de voir.

Une barrette de RAM

Les 8 rectangles noirs sur la barette de RAM sont les fameux chips !

Lorsque j'ai vu ça, ça m'a donné envie d'écrire cet article mais surtout de comprendre le comment de ce bloc noir. 😁

Optimisation

Maintenant que l'on a en quelque sorte le schéma de principe d'une barette de RAM. Nous allons pouvoir opérer quelques optimisation.

D'une part en matière de nombre de composants utilisés, d'autre part en terme de place prise en mm2.

L'idée restant de maximiser le stockage et de minimiser le nombre de composants nécessaires.

Souvenez vous une bank est composé d'une série 8 matrice posédant chacune leur décodeur de ligne et un multiplexeur.

Et bien il est possible de simplifier cela en permettant de au multiplexeur de manipuler des groupe de 8 cases.

Ainsi lorsque l'on sélectionne une case dans la matrice, c'est en fait 8 cases qui sont sélectionnées simultannément.

On a ainsi des matrice de largeur multiple de 8. Ici 16384. Ce qui donne 16384 / 8 = 2048 octets par lignes multiplié par le nombre de lignes, ici 65536, ce qui donne 2048 * 65536 = 134217728 adresses où 128 Mo.

On complexifie le Mux/DeMux mais l'on divise par 8 le nombre de decodeur de lignes nécessaire !

Et de fait, cette bank a le même comportement qu'auparavant, nous avons un décodeur qui se charge de sélectionner la ligne dans la matrice de mémoire et un Mux/DeMux qui décode la colonne sélectionnée.

La différence est que l'on a un décodeur pour sélectionner un octet complet et plus seulement un bit. De même le Mux/DeMux est lié à un octet complet.

Cette optimisation provoque une différence fondamentale: l'unité de base de la mémoire n'est plus le bit mais l'octet. De fait, il n'est plus possible d'écrire ou de lire un bit spécifique, seulement le paquet de 8 qu'il contient.

On peut alors agencer tout ce beau monde dans le chip pour stocker notre octet.

Et en étant intelligent dans le placement on peut mettre le nombre que l'on désire de banks.

De cette manière on minimise l'utilisation de composants onéreux comme les décodeurs et on maximise le nombre de cellules mémoires pour plus de stockage !

Il existe aussi tout un tas d'optimisations lié au fait que l'on puisse lire plusieurs banks en même temps et donc créer des files d'entrées/sorties, mais je vais être honnête avec vous, j'ai pas tout compris ^^'

Donc on va s'arrêter là 😄

Channel

Dernière chose avant de se quitter.

Une barrette de RAM c'est cool mais pour les plus grosses dans le commerce on tourne aux alentours de 8Go / 16Go. Sauf que pour lancer des monstres comme Cyberpunk 2077, il faut déjà 8Go. Il ne va pas rester grand chose pour le reste du système ^^'

Du coup dernière pièce du puzzle.

On va brancher plusieurs barrette de RAM qui commenceront toutes à l'adresse 0.

Mais on va les rattacher à un composant, un contrôleur mémoire qui va se charger de mapper les addresses suppérieures à la taille de la RAM sur la seconde barette par exemple. Ce qui permet avec des barettes de 8Go de créer des octets à des adresses à 15Go ou plus.

On va alors brancher un unique bus d'adresses, bus de données et bus de contrôle (lecture/écriture). Puis avec un fil d'activation unique à la barrette de RAM décider de quelle barette on souhaite choisir le paquet de 64 bits.

On a donc une barette de RAM dans chaque fente.

Et on branche tout le monde sur le contrôleur mémoire.

On peut alors généraliser le système de channel.

Ici, un channel A et un channel B. Chaque channel gérant 16Go de mémoire qui mis ensemble créé un bloc unifié de 32Go adressables !

Il existe des barettes de RAM dual channels, ce qui signifie que channels sont rattaché à chaque barettes de RAM.

On a aussi la possibilité de scinder un channel de 64 bits en deux channels de 32 bits, et ainsi pouvoir parralléliser encore plus d'action, c'est ce qui est par exemple utiliser dans la technologie DDR5.

Le nombre de channel est généralement limité à 2 car il est très onéreux de mettre en place un channel, sur les technolgies modernes ça représent 288 fils ! 288 fils qui faut réussir à placer sur la carte mère sans qu'ils ne se croisent ni n'intèfèrent entre eux. Il y a également des contraintes sur la longueurs des fils.

Ils doivent tous être de la même longeur, sinon les signaux du bit 1 du bit12 serait désynchronisés et quand on est dans des fréquences de plusieurs GHz, le moindre micro-mètre voir nanomètre de trajet supplémentaire peut avoir des conséquences.

C'est pour toutes ces raisons que l'on tente à tout prix d'augmenter la taille des barettes de RAM et non le nombres de slots sur la carte-mère.

Un channel n'a pas besoin que ses deux fentes soient remplies, par contre si c'est le cas, les barettes doivent être identiques !

Conclusion

J'espère que cette petite introduction au principe de fonctionnement vous aura plus, ce n'est évidemment pas un cours, j'ai pris des raccourci que même sur Mario Kart on ne prendrait pas.

J'ai également passé sous silence l'aspect dynamique du système qui aurait demander beaucoup trop temps à expliquer dans un article écrit.

Ma volonté quand j'ai écrit ce post était de moi-même comprendre comment ça marchait.

J'espère ne pas avoir dit trop de bêtises, le sujet est très vaste, j'ai fait de mon mieux pour vulgariser sans trop déformer la réalité.

A la prochaine fois pour un nouvel article sur autre chose ❤️

avatar

Auteur: Akanoa

Je découvre, j'apprends, je comprends et j'explique ce que j'ai compris dans ce blog.

Ce travail est sous licence CC BY-NC-SA 4.0.