Sacré titre n'est ce pas ?
Depuis pas mal d'années que je programme en assembleur que je m’amuse a tester un nombre incalculable de processeur et de machine.
A force , j'ai eu ma vision du proc (et de l'ordinateur) "idéale".
Pas que mon idée naîtra un jour , mais disons que j'aimerais avoir l'avis de connaisseurs , je n'ai pas envie de créer une machine "fantaisiste" qui serait irréalisable.
Le but est surtout de créer un émulateur pour pouvoir le tester avec au plus proche des contraintes réel, et savoir que mon idée est bonne (ou pas) me satisfera dans les deux grandement.
Alors mon idée est de faire un proc VLIW , et là ceux qui connaisse l'histoire de l'informatique font me dire "oulà , c'est casse gueule" , oui je suis pas le premier à avoir essayer Sony (avec l'Emotion Engine de la PS2 , le CELL avec la PS3) , Intel (avec la gamme Itanium) , ou même le fameux Transmeta (Crusoe et Efficeon) qu avait fait beaucoup parlé de lui à l'époque (notamment qu'il faisait de la conversion du x86 /VLIW à la volée ).
Bref aucun a vraiment bien marché et tous ont eu le même point commun , un proc complexe à programmer ,et celui que je vais vous présenter ne fera pas exception , mais la différence c'est que de nos jours on a Clang et qu'il permet de faire du code intermédiaire suffisamment intéressant pour pouvoir à mon avis , le transformer et l'optimiser sur un proc plus "exotique".
Je répondrais à une question si on me dit "mais pourquoi ne pas utiliser RISC-V ?", eh ben parce que de un ,je veux pas faire du RISC , et secundu , le souci de faire du RISC-V à mon sens ,et que toute l'optimisation du proc ne fait pas partie de l'ISA , et je dirai qu'il est à mon avis peu probable qu'on aurait en open source un code Verilog ou VHDL avec de l'OoO plus performant que Intel ou AMD.
Et bien sur ben je ne veux pas faire de OoO , et le in order superscalaire pour l'avoir fait sur de nombreux proc , me semble évident que ça ne sera pas la façon la plus performante pour faire un proc.
Alors pour revenir sur le proc , c'est un proc qui veut simplifier le design du proc au maximun , mais aussi d'atteindre au mieux les chiffres théorique , et pour cela les consoles de Sony donne une partie de la solution , il faut pouvoir précharger au cache en même temps que l’exécution (cela veut dire que le compilo ou le programmeur gère le cache).
Et si c'est bien foutu , on peut éviter la plupart des "caches miss".
Alors ici je parle de façon vulgariser , ça serait faux de parler de cache , en général on parle juste de mémoire SRAM interne ou de scrachpad.
Et l'itanium était une bonne idée de pouvoir rendre le VLIW un peu plus "dynamique" , le soucis du VLIW qui est trop statique , c'est qu’on a tendance à mettre pas mal d'instruction "nop" et donc le cache en souffre pas mal.
Donc j'ai fait en sorte qu'on puisse changer un peu le nombre d'instruction qu'on exécute en parallèle.
Un autre point , c'est que une mémoire gérer par le programmeur ne peut pas gérer tout les cas ,donc j'ai inclus aussi une mémoire cache "normal" (bon je dis "normal" , mais c'est surtout que je ne veux pas qu'elle soit trop lente , même si cela veut dire réduire les optimisations qu'on puisse faire dessus).
Pour donner une image de ce que ça donne :
(et du coup c'est bien plus simple qu'un Intel ou AMD Zen 2 Superscalaire Out of Order) : https://en.wikichip.org/wiki/File:ze...re_diagram.svg
L'avantage de ce genre d'architecture c'est que ça réduit de beaucoup le nombre de transistor , ça simplifie beaucoup aussi sa conception , et donc on gagne aussi en terme de dissipation de chaleur et de watts consommé , tout en ayant (normalement ) des très bonnes perfs
J'ai mis ici 128Kio de SRAM parce que la façon de programmer sur ce genre de machine et de faire un double buffer.
Je m'explique vous utilisez la moitié (64 Kio) , et pendant que vous faite vos calcul tranquille dessus , vous préchargez les donner suivante dans l'autre buffer ,sans que cela stop le CPU , donc comme ça ,vous perdez aucun temps pour vos calcul quand vous voulez lire la RAM (et ainsi de suite , vous switcher entre les deux buffers).
C'est ce que j'avais fait sur la prog PS2 , et ça permettait de n'avoir aucune latence mémoire (on avait donc les chiffres théoriques de la machines),je trouvais cette technique pas mal , et la mettre sur un CPU moderne (et adapté) , je trouve ça intéressant.
tout cela se fait via un DMA (que j'ai pas préciser ici mais que le MMU est collé sur le DMA , vu que c'est le seul point d'entrée/sortie)
Pour la prédiction de branchement il n'y en n'a pas , comme le montre le graphisme , le branchement (ou un call/ret) se fait sur le decode , donc il se fait sur 1 cycle + 1 cycle de delay.
Cette optimisation existe depuis longtemps , mais elle à été "abandonné" , parce qu'elle est complexe à mettre en place (surtout sur un x86 ou le decode se fait en plusieurs cycles ).
C'est une optimisation qui ne peut se faire que sur un proc très "simple" (la plupart des processeurs MIPS ayant cette optimisation).
Pour la pipeline , je vise un truc en 2 + 4-8 stages :
Code:
IF : Fetch (load opcode Memory SRAM instruction)
ID : decode instruction / load register flag
RR : Read Register
EX : execution
MEM : L/S memory SRAM data
WB : write back ( write register)
loadm/storem 6+ cycle (rr,exe,mem,dma,---,edma) (memory DRAM)
loadc/storec 5 cycles (rr,exe,mem,mem,wb) (load/store cache)
load 4 cycle (rr,exe,mem,wb)
store 4 cycle (rr,exe,mem,nop)
all reg/imm-reg/reg 3 cycle (rr,exe,wb)
mul 4 cycle (rr,exe,exe,wb)
div 5 cycle (rr,div,div,div,wb)
float 5 cycle (rr,fexe,fexe,fexe,wb)
fdiv 8 cycles (rr,fdiv,fdiv,fdiv,fdiv,fdiv,fdiv,wb)
C'est un proc donc qui peut faire 2-4 instructions par cycles.
Il peut switcher entre les deux (avec un delay du coup d'un cycle).
Je ne veux pas faire plus , parce que de un , par expérience , si on fait plus , on va se trouver avec pas mal de "nop" , et secundo , j'ai assez du mal à voir comment on fait plus.
Sur ce proc avec un delay en moyenne de 2-3 cycles pour les instructions les plus courantes , ça laisse 4-6 instructions (voir le double) à remplir , c'est assez énorme.
Je sais que les Intel et Ryzen peuvent avoir des pic de 4-5 IPC dans certain cas.
J'ai tenté de savoir combien ça prendrait en terme de transistor (et la forme du die) :
Le nombre me semble correct ,(même si je le compare avec le CELL qui avait je crois 200 ou 300MT par exemple ).
Je n'explique pas forcément comment j'ai calculé en détails (une partie est calcul via tout simplement avec la photo du die des CPU existant, vu que certain photo montre où se trouve les unité de calcul , il suffit juste de faire un produit en croix ensuite par rapport à la ratio pixel/nombre de transistor).
On est bien sur loin des milliard de transistor actuellement (je crois que les Ryzen 3600 6cores/12 threads fait 3800MT).
Donc oui si avec 800MT , je peux avoir 16 cores , ça serait bien
Ah et je dirais que cela demandera sûrement de "refaire"un OS vu les caractéristiques spécifiques pour gérer un exécutable ici.
J'avais écris rapidement la Memory Map de la future machine :
Code:
Memory MAP
0x00 0000 0000 - 0x00 FFFF FFFF ------- I/O (+DMA)
0x01 0000 0000 - 0x01 FFFF FFFF ------- L2 & L3 cache
0x02 0000 0000 - 0x02 FFFF FFFF ------- Sound DRAM (4 GB max )
0x03 0000 0000 - 0x03 FFFF FFFF ------- VRAM1 (4 GB max )
0x10 0000 0000 - 0x1F FFFF FFFF ------- VRAM2 (GPU)(64 GB max )
0x20 0000 0000 - 0x7F FFFF FFFF ------- SSD RAM (384 GB max )
0x80 0000 0000 - 0xFF FFFF FFFF ------- RAM (512 GB max )
Memory MAP SRAM/scratchpad
0x00000 - 0x1FFFF ------- SRAM Data
0x00000 - 0x1FFFF ------- SRAM Instruction
0x01 0000 0000 - 0x03 000F FFFF ------- L2 cache (associate)
0x01 1000 0000 - 0x03 1FFF FFFF ------- L2 cache (main core only)
0x01 2000 0000 - 0x03 2FFF FFFF ------- L3 cache (main core only)
(oui vous voyez un truc étrange comme SSD RAM , je me demandais si ce n'était pas intéressant d'avoir un SSD comme RAM en plus, celui de la PS5 pouvait atteindre une vitesse de 5-8 Go/s , qui est la vitesse d'une DDR2--1066 ce qui n'est pas rien , ça demande que les programmes soit pensé pour utiliser c'est deux type de mémoire (RAM et SSD) ^^' ).
Effectivement mes questions sont :
-est que ma pipeline est correct et réaliste ?
-mon delay pour le changement du nombre d'instruction à executer du VLIW réalisable ? (vu qu'aucun proc ne le fait vraiment) , je vois rien qui l'empeche , mais je suis pas concepteur de puce
(celà dit d'un coté l'itanium , faisait un truc plus ou moins similaire vu qu'il pouvait executer plusieurs bloc de VLIW, mais je vois pas comment , il peux pas le savoir sur un cycle ,sachant que sur un cycle ,tu peux faire que un fetch)
-le nombre de transistor correct ?
-quel fréquence on peut espérer ? (vu que la taille du scratchpad est assez gros , soit donc le réduire , ou le diviser par deux bloc distinct).
-Une question sur le VLIW qui est : est ce que deux opcode puisse viser la même unité de calcul ?
Et si vous avez des idées d'améliorations n'hésitez pas !
(désolé pour le gros pavé).
ah et vous pouvez voir tout mes brouillons ici :
https://github.com/Kannagi/Altair