Crunchez vos adresses URL
|
Rejoignez notre discord
|
Hébergez vos photos
Affichage des résultats 1 à 17 sur 17
  1. #1
    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
    Dernière modification par Kannagi ; 04/12/2020 à 07h08.

  2. #2
    C'est super intéréssant

    Je n'ai pas encore pris le temps de bien réfléchir, mais si tu veux voir du VLIW récent il y a Kalray (cocorico) et il me semble qu'ils utilisent LLVM pour le compilo et que c'est pas forcément plus la folie qu'avant (on me contredira si il faut). Après, ça dépend un peu de ta philosophie, si tu cherches à faire un processeur au niveau des superscalaires OoO sans prédiction de branchement, mon intuition me dit que ça va être tendu.

    Aussi, moi penser que 1 seul LD/ST par cycle quand on a 4 ALU c'est un peu optimiste.
    Citation Envoyé par François
    L'ordinateur cantique, c'est l'avenir.

  3. #3
    hé hé Merci , oui mais Kalray ne filtre rien si ?

    J'ai vu aucune info dans les détails ^^
    (Parce que oui , je voulais en savoir plus sur leur proc).

    Je compte utiliser Clang vu qu'il fourni un code IR , après je verrais , mais j'ai un peu confiance ne moi vu que j'ai pas mal d'expérience en asm et sur les proc VLIW pour traduire ça sur un code "optimisé".

    Après tu as VLIW et VLIW , j'étais tombé sur du VLIW qui faisait du double exécution, mais un dédié aux FPU et l'autre pour le reste ,donc oui , c'est sous optimal , quand tu fait pas de calcul flottant.
    Pareil pour Transmeta ,c'était je crois 4 , mais sur les 4 chaqu'un était dédié...
    Donc si tu fait que de l'ALU , ben tu en utilise qu'un , et tu fait des nop sur les 3 autres, ça tue le cache et les perfs qui vont avec

    Donc je ne sais pas ce que fait Kalray , et quel type de VLIW il utilise , la gestion des caches et j'y passe.
    Par contre le soucis de très grand nombre de processeur , c'est qu'il faut avoir un bus énorme pour gérer autant de cœur.

    si tu cherches à faire un processeur au niveau des superscalaires OoO sans prédiction de branchement, mon intuition me dit que ça va être tendu.
    ce n'est pas un superscalaire OoO , mais un VLIW in order , je n'ai pas de prédiction de branchement , parce que je veux faire le decode + jmp p , donc un branchement me coûte qu'un cycle + un cycle de delay.
    bien sur , ça demande d'avoir un decode rapide (ce que sont en général les proc RISC et VLIW).


    Aussi, moi penser que 1 seul LD/ST par cycle quand on a 4 ALU c'est un peu optimiste.
    Mais je suis totalement d'accord , le truc ,c'est est ce possible sur mon architecture d'avoir 2 lecture/écriture ?
    ça me semble tendu , mais si quelqu'un de compétent peut le confirmer ou pas , je changerai cela parce que oui , 2 LD/ST serait le minimun
    Mais je trouvais ça complexe d'avoir 2 accès en même temps sur la SRAM (surtout sur un cycle).
    J'ai vu aucun proc le faire donc bon.
    Il y'a bien sur les x86 qui ont 3 LD/ST , mais il se base sur un "mini buffer" avant d'écrire sur la SRAM donc différent de ce que je voudrais faire.
    Dernière modification par Kannagi ; 03/12/2020 à 11h36.

  4. #4
    Débarquant dans le monde l'archi mat, je n'avais jamais vu ton approche et elle est très intéressante !

    L'absence d’exécution spéculative est quand même un point fort important de ton archi au vu des vulns exploitant la micro-architecture d'aujourd'hui

    Je ne vais pas pouvoir te fournir de conseils sur ton archi, par contre j'ai quelques questions. Si tu fais de l’exécution dans l'ordre, la présence de plusieurs unités de calcul (alu, etc.) c'est bien pour tirer parti du VLIW et non pas pour du dispatch en µops comme on vois sur les procos classiques grand public ?

    De même, tes caches L2/L3 sont adressables car c'est au dev de les gérer ?

    Ça se passe comment pour ton branchement du coup ? Faut attendre la fin de ton pipeline ? Tu dis 1 instruction de délai, mais si tu as 4-5 instructions dans le pipeline ça colle pas... Qu'est ce que j'ai mal compris ?

  5. #5
    Mon approche est très original ,je le conviens ,mais on est resté trop conventionnel à mon sens , alors qu'on devrait avoir plein d'architecture différente (j'ai vu un gars faire un CPU assez original sur sa pipeline comme quoi ^^ ).
    Je suis persuadé qu'il y'a plein de technique à explorer ^^
    La mienne se base beaucoup sur mon expérience personnel sur les différentes archi que j'ai touché.

    Ah Ah , pour troll , je pourrais mettre "aucune faille Spectre et Meltdown" mais oui c'est un plus ^^

    Pour te répondre :
    Si tu fais de l’exécution dans l'ordre, la présence de plusieurs unités de calcul (alu, etc.) c'est bien pour tirer parti du VLIW et non pas pour du dispatch en µops comme on vois sur les procos classiques grand public ?
    Oui ,c'est pour tirer parti du VLIW

    De même, tes caches L2/L3 sont adressables car c'est au dev de les gérer ?
    Exact , l'OS te filera un cache dédié (ou pas)
    Ensuite l'utilisation est pas compliqué , au lieu de charger en mémoire, tu charge en cache (vu qu'il a une adresse).
    (ça sera surtout savoir quoi garder le plus difficile comme choix)

    Ça se passe comment pour ton branchement du coup ? Faut attendre la fin de ton pipeline ? Tu dis 1 instruction de délai, mais si tu as 4-5 instructions dans le pipeline ça colle pas... Qu'est ce que j'ai mal compris ?
    Non ,c'est une bonne question , parce que je me posais la même question (mais plus de comment ça marche) , vu que ce principe là je le connaissais ,il existe sur les proco MIPS et d'autre ^^
    Donc je te conseille de lire ceci :
    https://cseweb.ucsd.edu/classes/su06...rd_adv-1up.pdf
    (je trouve ça pas mal qu'il explique en détails et étape par étape , et donc oui un branchement , ça peut prendre 4- 5 cycles , mais il y'a un moyen de résoudre ceci).

    Si tu es plus à l'aise niveau code asm , un exemple :
    Code:
    cmp IF
    nop ID
    nop RR
    bra EX/IF
    add WB/ID (delay slot) ; l'addiction est quand même exécuter (a cause du delay) , le branchement est exécuter pendant la phase de decode
    nop ; ici pas de delay , on est hors de la boucle
    (j'ai fait exprès de mettre qu'une instruction/cycle pour faciliter la lecture)
    Dernière modification par Kannagi ; 03/12/2020 à 12h24.

  6. #6
    Citation Envoyé par Kannagi Voir le message
    Mon approche est très original ,je le conviens ,mais on est resté trop conventionnel à mon sens , alors qu'on devrait avoir plein d'architecture différente (j'ai vu un gars faire un CPU assez original sur sa pipeline comem quoi ^^ ).
    Je suis persuadé qu'il y'a de technique à explorer ^^
    La mienne se base beaucoup sur mon expérience personnel sur les différentes archi que j'ai touché.

    Ah Ah , pour troll , je pourrais mettre "aucune faille Spectre et Meltdown" mais oui c'est un plus ^^

    Pour te répondre :

    Oui ,c'est pour tirer parti du VLIW


    Exact , l'OS te filera un cache dédié (ou pas)
    Ensuite l'utilisation est pas compliqué , au lieu de charger en mémoire, tu charge en cache (vu qu'il a une adresse).
    (ça sera surtout savoir quoi garder le plus difficile comme choix)
    Ok mais du coup au lieu d'avoir du stalling quand tu tapes dans de la mémoire qui n'est pas caché, le programmeur doit insérer des instructions pour mettre des zones mémoires en cache ? Je suppose que si tu as choisi cette approche c'est qu'il y a un avantage (réduction du nombre de cache miss car on peut supposer que le programmeur saura optimisé son programme) mais la contrepartie c'est que ton cpu se retrouve à exécuter des instructions dédié à la mise en cache des données, là où il me semble que c'est transparent sur du x86/arm. Tu perds du temps à exécuter des instructions "inutiles", mais tu en gagnes car tes données sont toujours proches du proco. C'est vraiment si intéressant ?


    Non ,c'est une bonne question , parce que je me posais la même question (mais plus de comment ça marche) , vu que ce principe là je le connaissais ,il existe sur les proco MIPS et d'autre ^^
    Donc je te conseille de lire ceci :
    https://cseweb.ucsd.edu/classes/su06...rd_adv-1up.pdf
    (je trouve ça pas mal qu'il explique en détails et étape par étape , et donc oui un branchement , ça peut prendre 4- 5 cycles , mais il y'a un moyen de résoudre ceci).

    Si tu es plus à l'aise niveau code asm , un exemple :
    Code:
    cmp IF
    nop ID
    nop RR
    bra EX/IF
    nop WB/ID (delay slot)
    add --/-- ; l'addiction est quand même exécuter (a cause du delay) , le branchement est exécuter pendant la phase de decode
    nop ; ici pas de delay , on est hors de la boucle
    (j'ai fait exprès de mettre qu'une instruction/cycle pour faciliter la lecture)
    Je vois l'idée, mais ses slides n'explique pas comment il passe d'un stall de 3 instructions à un stall de 1 instructions ... (je suppose que c'est un truc qu'il explique à l'oral)

  7. #7
    Ok mais du coup au lieu d'avoir du stalling quand tu tapes dans de la mémoire qui n'est pas caché, le programmeur doit insérer des instructions pour mettre des zones mémoires en cache ? Je suppose que si tu as choisi cette approche c'est qu'il y a un avantage (réduction du nombre de cache miss car on peut supposer que le programmeur saura optimisé son programme) mais la contrepartie c'est que ton cpu se retrouve à exécuter des instructions dédié à la mise en cache des données, là où il me semble que c'est transparent sur du x86/arm. Tu perds du temps à exécuter des instructions "inutiles", mais tu en gagnes car tes données sont toujours proches du proco. C'est vraiment si intéressant ?
    C'est vrai qu'on fait pas mal de pub sur l'IPC , mais pour moi le soucis actuelle n'est plus là , il est dans la latence de la RAM (un cache miss c'est 100 cycles ).
    Donc oui, faut mieux sacrifier 100 cycles au départ et ne pas en avoir pour les 100 prochaines cache miss que le contraire ^^
    (et ça pas que pour le cache des instructions mais aussi des data, j’explique qu'on peut paralléliser l’exécution et la lecture/écriture en SRAM , tout en préchargeant dans la RAM).
    Le cache à pour but d’être rapide, mais aussi de ne pas trop solliciter le BUS (qui sera forcément partagé avec les autres cores).

    Je vois l'idée, mais ses slides n'explique pas comment il passe d'un stall de 3 instructions à un stall de 1 instructions ... (je suppose que c'est un truc qu'il explique à l'oral)
    effectivement , je trouvais ça parlant , mais bon tu sais que le décodage des instructions ,c'est juste séparer chaque phase.
    Tu peux très bien faire : decode/read register /exe/WB sur un cycle
    Par contre il faut avoir un truc simple à faire (ou alors tu fait un truc qui tourne sur 20 MHZ )
    C'est ce que fait le branchement (cela suppose plein de chose, un decode rapide , une lecture de registre dédié (uniquement sur le flag/PC) et une exécution simple (bon ici , c'est simple , mon branchement c'est une addition 16 bits) et mettre le résultat sur le PC.

  8. #8
    Citation Envoyé par Kannagi Voir le message
    ce n'est pas un superscalaire OoO , mais un VLIW in order , je n'ai pas de prédiction de branchement , parce que je veux faire le decode + jmp p , donc un branchement me coûte qu'un cycle + un cycle de delay. bien sur , ça demande d'avoir un decode rapide (ce que sont en général les proc RISC et VLIW).
    J'avais saisi l'idée, je parlais simplement du niveau de performance. Après, c'est vrai que vu le diagramme, il n'y en a pas vraiment besoin (enfin ça serait pas mal de faire sauter le cycle de délai ), mais j'ai vaguement l'impression que tu t'es crée un delay slot : si tu récupère ALU + BR avec BR qui dépend de l'ALU, tu ne peux pas calculer le branchement juste après au decode, si ? Donc quelque part, il faut que tu sois capable de caler des instructions entre le "producteur" du branchement et le branchement, ce qui ressemble un peu à un delay slot (et ses dérives). Ou alors j'ai mal compris ?
    Citation Envoyé par Kannagi Voir le message
    hé hé Merci , oui mais Kalray ne filtre rien si ? Mais je suis totalement d'accord , le truc ,c'est est ce possible sur mon architecture d'avoir 2 lecture/écriture ? ça me semble tendu , mais si quelqu'un de compétent peut le confirmer ou pas , je changerai cela parce que oui , 2 LD/ST serait le minimun Mais je trouvais ça complexe d'avoir 2 accès en même temps sur la SRAM (surtout sur un cycle). J'ai vu aucun proc le faire donc bon. Il y'a bien sur les x86 qui ont 3 LD/ST , mais il se base sur un "mini buffer" avant d'écrire sur la SRAM donc différent de ce que je voudrais faire.
    Tu as des références sur ce "mini-buffer" ? La SRAM peut s'implémenter en 10T si tu veux avoir deux ports de lecture (ou avoir deux copies de 6T/8T), ou tu peux banker ta SRAM pour pouvoir faire deux accès tant que ce sont des bancs différents (Intel faisait ça jusqu'à Ivy Bridge). La Doc Amd sur Zen1/2 suggère aussi que le L1D a toujours plusieurs bancs, alors que la doc Intel dit qu'à partir de Haswell il n'y a plus de conflits de bancs (donc on peut toujours faire deux loads/cycle). Après je ne designe pas des circuits, mais c'est clairement ce qui est fait dans les CPU haute performance pour augmenter le débit en load.
    Citation Envoyé par François
    L'ordinateur cantique, c'est l'avenir.

  9. #9
    Citation Envoyé par Kannagi Voir le message
    C'est vrai qu'on fait pas mal de pub sur l'IPC , mais pour moi le soucis actuelle n'est plus là , il est dans la latence de la RAM (un cache miss c'est 100 cycles ).
    Donc oui, faut mieux sacrifier 100 cycles au départ et ne pas en avoir pour les 100 prochaines cache miss que le contraire ^^
    (et ça pas que pour le cache des instructions mais aussi des data, j’explique qu'on peut paralléliser l’exécution et la lecture/écriture en SRAM , tout en préchargeant dans la RAM).
    Le cache à pour but d’être rapide, mais aussi de ne pas trop solliciter le BUS (qui sera forcément partagé avec les autres cores).
    Ok je n'avais pas l'ordre de grandeur temporel d'un cache miss, ça fait sens maintenant !

    effectivement , je trouvais ça parlant , mais bon tu sais que le décodage des instructions ,c'est juste séparer chaque phase.
    Tu peux très bien faire : decode/read register /exe/WB sur un cycle
    Par contre il faut avoir un truc simple à faire (ou alors tu fait un truc qui tourne sur 20 MHZ )
    C'est ce que fait le branchement (cela suppose plein de chose, un decode rapide , une lecture de registre dédié (uniquement sur le flag/PC) et une exécution simple (bon ici , c'est simple , mon branchement c'est une addition 16 bits) et mettre le résultat sur le PC.
    Donc, si j'ai bien compris ce que tu fais c'est que tu as un chemin dédié pour les branchements où tu fais tout d'un coup. Par contre tu gère comment les problèmes de dépendances ? Tu as toujours besoin d'avoir le résultat des instructions précédentes pour déterminer ton saut... Est-ce que du coup tu as autant de d'instructions de délais que d'étages de pipeline entre ton decode et la sortie de tes ALUs ?

  10. #10
    Citation Envoyé par Thamior Voir le message
    J'avais saisi l'idée, je parlais simplement du niveau de performance. Après, c'est vrai que vu le diagramme, il n'y en a pas vraiment besoin (enfin ça serait pas mal de faire sauter le cycle de délai ), mais j'ai vaguement l'impression que tu t'es crée un delay slot : si tu récupère ALU + BR avec BR qui dépend de l'ALU, tu ne peux pas calculer le branchement juste après au decode, si ? Donc quelque part, il faut que tu sois capable de caler des instructions entre le "producteur" du branchement et le branchement, ce qui ressemble un peu à un delay slot (et ses dérives). Ou alors j'ai mal compris ?.
    Le BRU ne peut pas dépendre de l'ALU
    Par exemple :
    Code:
    bne label   add r0,r1,r2
    Aucune dépendance.

    Et tu ne peut pas (dans mon VLIW) avoir un cmp et un branchement en même temps.
    Tu as obligatoirement :
    Code:
    cmp r3,r4  add r0,r1,r2
    bne label  move r6,r7
    Ouais du coup , je pense que les flag des add et autre n'existe pas (ou que le branchement ne le lit pas toujours ,donc avoir le choix entre les deux ) , sinon ça rendrait bien trop complexe pour faire des conditions ou boucles ^^'

    Oui ça serait cool de ne pas avoir de delay , mais bon je réserve le premier cycle pour le fetch donc bon


    Citation Envoyé par Thamior Voir le message
    Tu as des références sur ce "mini-buffer" ? La SRAM peut s'implémenter en 10T si tu veux avoir deux ports de lecture (ou avoir deux copies de 6T/8T), ou tu peux banker ta SRAM pour pouvoir faire deux accès tant que ce sont des bancs différents (Intel faisait ça jusqu'à Ivy Bridge). La Doc Amd sur Zen1/2 suggère aussi que le L1D a toujours plusieurs bancs, alors que la doc Intel dit qu'à partir de Haswell il n'y a plus de conflits de bancs (donc on peut toujours faire deux loads/cycle). Après je ne designe pas des circuits, mais c'est clairement ce qui est fait dans les CPU haute performance pour augmenter le débit en load.
    Pour la référence du mini buffer :
    https://en.wikichip.org/w/images/8/8...ck_diagram.svg
    (c'est du ARM , mais c'est assez pareil sur un x86).
    Mais oui tu as raison , les graph montre 2 lectures et 1 écriture.
    Bon ça va donc demande à mon VLIW de ne pas "coder" le store sur une de ces unités.


    Pur le x86/ARM , Load buffer /Store buffer sert sûrement parce qu'ils ont 3-4 AGU/LSU.
    Donc le buffer permet de gérer au cas où il y'a plus de 2 Load + 1 Store par cycle

    Donc, si j'ai bien compris ce que tu fais c'est que tu as un chemin dédié pour les branchements où tu fais tout d'un coup. Par contre tu gère comment les problèmes de dépendances ? Tu as toujours besoin d'avoir le résultat des instructions précédentes pour déterminer ton saut... Est-ce que du coup tu as autant de d'instructions de délais que d'étages de pipeline entre ton decode et la sortie de tes ALUs ?
    bon ben j'ai un peu répondu en haut.
    Donc oui je fait le branchement tout d'un coup (dans la phase de decode).

    J'ai répondu a cette question plus haut avec du code du coup.
    Et donc pour préciser , il faut 2 cycles entre le cmp et le branchement (pour éviter un pipeline stall).
    Cela peut poser "soucis" pour des petites boucles (vu les dépendance et la longueur de pipeline).
    Sinon pour les grosses boucles et les conditions, normalement aucun soucis.
    Dernière modification par Kannagi ; 03/12/2020 à 13h37.

  11. #11
    Citation Envoyé par Kannagi Voir le message
    Le BRU ne peut pas dépendre de l'ALU Pour la référence du mini buffer : https://en.wikichip.org/w/images/8/8...ck_diagram.svg (c'est du ARM , mais c'est assez pareil sur un x86). Mais oui tu as raison , les graph montre 2 lectures et 1 écriture. Bon ça va donc demande à mon VLIW de ne pas "coder" le store sur une de ces unités. Pur le x86/ARM , Load buffer /Store buffer sert sûrement parce qu'ils ont 3-4 AGU/LSU. Donc le buffer permet de gérer au cas où il y'a plus de 2 Load + 1 Store par cycle
    Oui les buffers permettent de garer les instructions si le cache ne suit pas (c'est le concept de l'OoO de manière générale) pour pouvoir continuer à récupérer des instructions, mais au final le nombre maximum de ld/st sera bien dicté par la structure du cache (et de certaines optimisations qu'on peut faire à côté). Pour Zen3 qui fait trois loads/cycle, le cache doit a priori gérer ça (avec du banking à mon avis), sauf si c'est 3/cycle seulement dans certain cas rares (mais j'en doute).
    Citation Envoyé par François
    L'ordinateur cantique, c'est l'avenir.

  12. #12
    Oui c'est cela , j'ai bien fait de le presenter ici , vu que ça permet d'améliorer les choses

    Ok je n'avais pas l'ordre de grandeur temporel d'un cache miss, ça fait sens maintenant !
    oui , quand on a ça en tête , on comprend mieux pourquoi j'ai choisis cette structure.
    d'ailleurs l'avantage d'avoir un DMA/gérer sa mémoire ,c'est qu'on peut plus facilement profiter du mode burst de la RAM (donc quand tu lis des donné contiguë , tu as beaucoup moins de latence pour le reste des données).
    En gros , il est plus judicieux de lire genre 16 000 octets , donc 100 cycles de latence + 1000 cycles pour le burst (si on a une RAM qui donne 16 octet par cycles)
    Que de faire 1000 cache miss est donc d'avoir 100*1000 cycles
    Dernière modification par Kannagi ; 03/12/2020 à 18h53.

  13. #13
    Le projet n'est pas mort je vous assure ,je l'avance tout les jours y'a pas mal de nouveauté.
    La gestion des posits : https://en.wikipedia.org/wiki/Unum_(number_format)
    Donc une alternative aux float et donc à IEEE 754.
    J'ai totalement refait l'ISA , il y'a un début de VM et de documentation (nous sommes trois au final à bosser sur ce projet).
    J'ai fait aussi un début de GPU (qui se base sur une partie de l'architecture du CPU ) : https://github.com/Kannagi/Altair/blob/main/GPU.md
    Dernière modification par Kannagi ; 12/01/2021 à 05h23.

  14. #14
    Pouah super intéressant le topic, je vais passer un moment sur tes posts et ton github pour comprendre tout ça. C'est un peu trop bas niveau vis à vis de mon domaine (je suis plus côté software en ce moment) mais en ce moment je cross compile énormément (voire mon topic sur ce sous forum) pour plein d'architectures (ARM, MIPS, RISC-V, X86, etc., en veux tu en voilà), je programme sur des GPU, etc. donc fatalement je m'intéresse de plus en plus à ces problématiques.

    Je suis curieux de savoir ce que ça donnerait avec un benchmark simple. Je sais pas si c'est pertinent mais de mon point de vue software mon input c'est le programme, donc je verrais bien 2 programmes type, un pur séquentiel et un qui exploite plus les forces de ton archi (a priori) et on voit ce que ça donne ultimement en terme de perf.

    Un benchmark de base quoi, comme point de comparaison.

    C'est peut être une remarque idiote mais je me demande pas si au final cette tâche n'est déjà pas prise en compte par les GPUs quelques part, y'a-t-il un vrai besoin?

  15. #15
    Merci pour ton intérêt !
    Oui la cross compilation , j'en fais souvent aussi ^^

    Ah non c'est super pertinent , je serais curieux de savoir si mon archi aura besoin ou pas de gros changement niveau code pour bien être exploité.
    La VM est divisé en deux partie, une version "rapide" pour tester ces futurs programmes rapidement et une aux cycles près (du coup ça sera long à émuler) mais ça permettra de voir les point fort/faible de la machine et donc aussi de voir ces capacités "réel".

    Bien sur la version GPU aura bien besoin de test (juste sur un compute unit) , pour voir si l'architecture GPU peut calculer assez rapidement les triangles + shader + rastérisation + rendu

  16. #16
    Je regardais un peu l'encodage sur le git. Est-ce que tu comptes forcer les adresses de branchement à être alignée sur 16 bytes ? Sinon, tu auras potentiellement des fetch d'instructions qui ont besoin de lire 8B dans une ligne et 8B dans l'autre, et c'est peut-être embêtant (enfin pas trop ça complexifie le cache d'instructions juste pour ça).

    Je me dis aussi que pour ce paradigme, quand tu traites ton jeu de données, tu dois connaître l'emplacement du prochain jeu de données à précharger pour pouvoir cacher la latence, ce qui n'est pas forcément toujours le cas. Par exemple, si on fait un parcours de graphe, on ne peut pas vraiment savoir quelle partie du graphe on va traverser dans le futur avant d'avoir traverser la partie actuelle. Si j'ai bien compris on est donc plutôt dans le "streaming processor".

    L'idée de changer de mode pour éviter les nop est sympa aussi si la taille du binaire devient problématique.
    Citation Envoyé par François
    L'ordinateur cantique, c'est l'avenir.

  17. #17
    Citation Envoyé par Thamior Voir le message
    Je regardais un peu l'encodage sur le git. Est-ce que tu comptes forcer les adresses de branchement à être alignée sur 16 bytes ? Sinon, tu auras potentiellement des fetch d'instructions qui ont besoin de lire 8B dans une ligne et 8B dans l'autre, et c'est peut-être embêtant (enfin pas trop ça complexifie le cache d'instructions juste pour ça).
    Cela ne poserait pas de soucis , si on à un PC qui fait un +8B ? (vu qu'il fait +8/+16) , mais ça simplifiait le cache et sa vitesse , vu qu'il sera sur une voie.

    Citation Envoyé par Thamior Voir le message
    Je me dis aussi que pour ce paradigme, quand tu traites ton jeu de données, tu dois connaître l'emplacement du prochain jeu de données à précharger pour pouvoir cacher la latence, ce qui n'est pas forcément toujours le cas. Par exemple, si on fait un parcours de graphe, on ne peut pas vraiment savoir quelle partie du graphe on va traverser dans le futur avant d'avoir traverser la partie actuelle. Si j'ai bien compris on est donc plutôt dans le "streaming processor".
    Exact j'aime bien le terme "streaming processor" ^^
    Alors pour ce genre de cas , il faudra utiliser la mémoire cache Direct Mapped (pour ça que je l'ai mis d'ailleurs :D )

    Citation Envoyé par Thamior Voir le message
    L'idée de changer de mode pour éviter les nop est sympa aussi si la taille du binaire devient problématique.
    Techniquement ,je pense qu'il est mieux pour les boucles (mais à voir bien sur )

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •