PROCESSEUR 16bits ~100Hz + outils de programmation - 1.14

16 Février 2014
1 944
391
217
le sud (de Melun)
Salut, quand je suis en vacances je perds toujours mon temps à jouer à factorio ou à construire des ordinateurs dans minecraft, cette fois c'était les ordinateurs.

100Hz ???? Mais dans minecraft la plus petite durée est le tick, et il y en a 20 par seconde et ça fait 20Hz au max !!! Comment c'est possible ??!!

Une chaîne de command blocks s’exécute en un tick, peu importe sa longueur. Mais un command block ne peut être exécuté qu'une seule fois par tick, sauf si on le débride en modifiant le tag "UpdateLastExecution". On peut alors faire autant de choses qu'on veut (enfin presque) dans le même tick avec un peu de magie et une utilisation abusive de la commande /clone.

En gros, à chaque tick l'unité de contrôle charge l'instruction qu'il faut exécuter mais aussi les 4 ou 5 suivantes (ou autant qu'on veut c'est juste qu'à partir de 4 mon jeu commence à ramer). Elles sont alors toutes exécutées dans le même tick mais quand il y a un saut les instructions chargées ne sont plus les bonnes, on passe au tick suivant pour recharger les bonnes (ça a les mêmes limitations qu'une pipeline pour ceux qui connaissent). Donc si on fait exécuter les instructions 5 par 5 et qu'il n'y a pas de sauts dans le programme, on arrive à 100Hz ! J'ai des pistes pour un système plus efficace, je suis en train d’expérimenter, faire de la branch prediction dans minecraft ce serait classe quand même...

Bref ça va très vite, ça prend que quelques secondes pour overflow 16bits avec la suite de fibonacci.

1556992459-2019-05-04-19-51-23.png

1556992361-2019-05-04-19-51-45.png

1556992358-2019-05-04-19-51-34.png

La mémoire du programme est séparée de la mémoire principale pour permettre de stocker des instructions déjà décodées, ce qui accélère beaucoup les choses, mais cela empêche la modification du programme par l'ordinateur lui-même. J'ai écrit un petit script pour compiler de l'assembleur et d'exporter dans la mémoire.
Il y a 256 lignes pour le programme et 1K de RAM, mais on peut monter à 64K pour chaque, après c'est un problème de place. Les 128 dernières adresses de la RAM sont réservées à l'écran.

Il y a une vingtaine d'instructions, grâce au stack le processeur supporte l'appel de fonctions et les interruptions.


Les 8 registres 16bits qui peuvent tous être utilisés de la même manières dans des opérations arithmétiques ou logiques :
  • 3 registres de données (A, B, C)
  • registre d'adresse
  • registre de segment
  • compteur ordinal
  • stack pointer
  • registre des flags (zéro, négatif et overflow, + statut)

Les interfaces (c'est pas compliqué d'en brancher d'autres sur les ports I/O) :
  • écran 16*8 caractères (qui supporte un genre d'ASCII du pauvre)
  • entrée/sortie hexadécimale
  • entrée/sortie binaire


Documentation (disponible dans le téléchargement) :

Code:
Schéma d'une instruction :
    Code de fonction  ||  op1  ||  op2  ||  op3

ou bien :
    Code de saut  ||  op1

ou bien :
    Code de saut  ||  Code de fonction  ||  op1  ||  op2  ||  op3

    Ici le résultat de la fonction sert d'adresse pour le saut.
    -> surtout pratique pour gagner une ligne avec IRET, sinon c'est gadget.



Opérandes possibles dans les instructions ('op') :

  registres (A,B,C,ADR,CS,SP,PC,FLAGS)
  nombre immédiat ('x') qui peut être décimal, binaire ('0bXXX') ou hexadécimale ('0xXXX')
  adresse ram indirecte (via ADR)
  adresse ram immédiate ('[x]')
  port I/O indirect (via ADR)
  port I/O immédiat ('{x}')
  PUSH et POP (offset possible avec POP)
  'VOID' si l'on ne veut pas garder le résultat d'une opération (ou alors pour générer un zéro)
  adresse immédiate relative au stack pointer ('(x)') :
      (0) est l'adresse pointée par le stack (qui est normalement vide)
      (1) est l'adresse qui précède celle pointée par le stack
      (2) est celle encore avant etc...
          -> on ne peut accéder qu'à des adresses "dans le passé"

  note : On peut donner autant de valeurs immédiates que l'on veut par instruction,
    on peut donc faire des opérations sur la mémoire sans passer par les registres.
    -> les valeurs immédiates prennent beaucoup de mémoire



Registre des flags :

  0-8   non utilisés
  9     overflow
  10    négatif
  11    zéro
  12    halt
  13    ne pas incrémenter PC (utilisé par les sauts)
  14    interruption
  15    flush de la pipeline

      'FL' peut être placé à la fin de n'importe quelle instruction
        pour mettre à jour les flags zéro, overflow et négatif



codes de saut :

  IRET    (pas d'opérande) retour d'interruption restaure les registres
  INT     appel d'interruption, sauvegarde tous les registres, saut vers un autre segment (via CS)
  JS      saut sans condition vers un autre segment (via CS)
  CALL    appel de fonction (push l'adresse du compteur programme)
  JMP     saut sans condition
  JNZ     saut si flag zéro = 0
  JNO     saut si flag retenue = 0
  JNN     saut si flag négatif = 0
  JZ      saut si flag zéro = 1
  JO      saut si flag retenue = 1
  JN      saut si flag négatif = 1
    op1 :
    saute à l'adresse indiquée par op1



Codes de fonction :

  MOV     copie / f(x) = x
  NOT     fonction NOT
  SHL     décalage logique vers la gauche
  RTL     rotatation vers la gauche
  SHR     décalage logique vers la droite
  RTR     rotation vers la droite
  NEG     opposé
  INC     incrémentation
  DEC     décrémentation
    op1,op2 :
    stocke le résultat de f(op2) dans op1

  AND     ET logique
  XOR     OU exclusif logique
  OR      OU logique
  ADD     addition
  SUB     soustration
    op1,op2,op3 :
    stocke f(op2,op3) dans op1

Code:
Assemblage :
  Il faut d'abord lancer l'exe ou glisser-déposer dessus le fichier qui contient le code.
  On indique ensuite le segment : l'adresse à laquelle le programme commence.
 
  Deux fichiers sont créés : "log_bin.txt" avec le programme en langage machine et "import.mcfunction" qui sert pour
  importer le programme dans minecraft.


Importation :
  Le fichier "import_*programme*.mcfunction" doit être placé dans le datapack de la map :
      donc dans C:\Users\Utilisateur\AppData\Roaming\.minecraft\saves\CB 1642\datapacks\import\data\import\functions

  Il faut ensuite recharger le datapack avec "/reload", puis importer avec "/function import:import.mcfunction"

  Il n'est pas nécessaire de reset la RAM, on peut bien sûr importer plusieurs programmes, mais il faut leur donner des adresses bien différentes :
  la gestion de la mémoire est manuelle.



Fonctions de l'assembleur :

  Ce ne sont pas des instructions qui seront exécutées par le processeur.
  Elles aident à la programmation et commencent par un point.

  .const NOM VALEUR
    Défini une constante


  .data NOM VALEUR
    La valeur peut être un nombre, un string (avec des "") -> les caractères doivent être dans la table
    (attention aux majuscules et aux espaces), ou un array de nombres (avec des {} et des virgules pour séparer)

    Des constantes sont alors définies :
      *NOM qui renvoie la valeur de la variable oar adressage ram immédiat,
          ex : 'MOV *NOM 10' change la valeur de NOM
      &NOM qui donne l'adresse de NOM en tant que nombre immédiat
      NOM.LEN qui donne la longueur si la valeur est un string ou un array


  .label NOM
    Crée une constante qui renvoie vers une adresse relative à l'origine du programme,
    -> intéressant pour les sauts


  .labelabs NOM
    Idem .label mais l'adresse est absolue (par rapport à toute la ram)
    -> intéressant pour le saut JS.


  .segment ADRESSE
    Permet de dire où se trouve le programme dans la mémoire, demandé toute façon par le complilateur.
    -> intéressant quand on a deux programmes dans le même fichier et que l'on veut les importer en même temps (risqué quand même)


  .offset ADRESSE
    Permet de définir où se trouve le code par rapport à l'origine du programme
    -> intéressant pour gérer les adresses quand on a beaucoup de fonctions dans le programme

Code:
;affiche "HELLO WORLD !"
;nécessite CBCOS

MOV {3} 2    ;on efface l'écran
MOV A 896    ;on met l'adresse du début de la ram vidéo dans A
MOV B &TEXT_HELLO    ;on met l'adresse du début du text dans B
MOV C TEXT_HELLO.LEN    ;la longueur du text dans C
INT 20        ;interruption vers une fonction de CBCOS, copie de mémoire (paramètres dans A, B et C)
MOV {3} 1    ;on rafraichit l'écran
INT 8

;définition de la variable "TEXT_HELLO"
.data TEXT_HELLO "HELLO WORLD !"

Code:
Ecran 16*8 caractères :

Pour rafraichir l'écran : écrire un 1 au port 3
Pour effacer l'écran    : écrire un 2 au port 3


Adresses de l'écran : 896 à 1023 (0x380 à 0x3FF)


Table des caractères:

    0   : SPACE ('_' dans les déclarations de strings)
    1   : BLANK
    2   : 0
    3   : 1
    4   : 2
    5   : 3
    6   : 4
    7   : 5
    8   : 6
    9   : 7
    10  : 8
    11  : 9
    12  : A
    13  : B
    14  : C
    15  : D
    16  : E
    17  : F
    18  : G
    19  : H
    20  : I
    21  : J
    22  : K
    23  : L
    24  : M
    25  : N
    26  : O
    27  : P
    28  : Q
    29  : R
    30  : S
    31  : T
    32  : U
    33  : V
    34  : W
    35  : X
    36  : Y
    37  : Z
    38  : +
    39  : -
    40  : *
    41  : /
    42  : ^
    43  : =
    44  : >
    45  : <
    46  : .
    47  : ,
    48  : :
    49  : ;
    50  : !
    51  : ?
    52  : '
    53  : "
    54  : (
    55  : )

Code:
Adresse 0x0   à 0x6F  : CBCOS --> au démarrage il affiche un message à l'écran et demande le programme qu'il faut executer via l'entrée hexadécimale.

Adresses 0x100 à 0x111 : fibonacci
Adresses 0x140 à 0x15A : hello world
Adresses 0x180 à 0x19C : test de l'écran

Adresses 0x200 à ---   : mémoire stack, allouée par CBCOS, attention à ne pas mettre des programmes trop près après 0x200
Adresses 0x380 à 0x3FF : mémoire vidéo, peut être utilisée normalement si l'écran n'est pas utilisé



Je publierai une vidéo.. un jour.
1555520074-2019-04-16-23-28-36.png

Nan c'est juste pour montrer qu'on peut afficher des couleurs sur l'écran. J'aurais pu faire un arc-en-ciel avec les 16 couleurs mais bon.

Je n'ai pas encore remis le système de overclock magique, ça va me prendre un peu de temps. x)
Pour l'instant c'est limité à 20Hz. La doc, l'assembleur et d'autres exemples de programmes sont inclus dans le téléchargement.
 

Fichiers joints

  • Processeur.zip
    2.1 Mo · Affichages: 375
Dernière édition:
  • J'aime
Reactions: Wistaro et Kaeios

Eglaios

Crétin de la commu
14 Avril 2018
310
42
89
24
Ah oui, ça ressemble vraiment à l'atari 2600 de Sethbling, sauf que pour lui, un jeu s'exécute 10 fois plus lentement que sur la vraie console, lol. C'est cool!
 

[GISED] Link

Torches, poudre et repeaters. What else ?
4 Mars 2012
341
76
140
29
VNSA, 2740 Moutier
vnsa.ch
Yop,

J'ai passé ma vie à sniffer de la poudre ... et me voilà face à un processeur qui n'en contient même pas ...
2yp03x.jpg

Sinon ça a l'air d'être assez conséquent et complet. Peux-tu ajouter des informations supplémentaires :
  • Jeu d'instruction
  • Une vidéo / plus d'images sur l'exécution, comment ça marche
  • Description d'une ligne de la ROM (apparemment ya pas mal de bit par instructions ...)
  • Une ...... map ? afin qu'on puisse... euh ... ESSAYER :bave:
  • Autres infos techniques croustillantes sur ce petit bijou

En tout cas c'est du joli
 
16 Février 2014
1 944
391
217
le sud (de Melun)
Ah oui, ça ressemble vraiment à l'atari 2600 de Sethbling, sauf que pour lui, un jeu s'exécute 10 fois plus lentement que sur la vraie console, lol. C'est cool!
Je le sien fonctionne avec un datapack et sa première version date un peu, je ne sais pas si c'est vraiment comparable.
Un jour j'essayerai de reproduire un 6502 pour voir, faudrait que je mette le nez dans les datapacks aussi.



Yop,

Sinon ça a l'air d'être assez conséquent et complet. Peux-tu ajouter des informations supplémentaires :
  • Jeu d'instruction
  • Une vidéo / plus d'images sur l'exécution, comment ça marche
  • Description d'une ligne de la ROM (apparemment ya pas mal de bit par instructions ...)
  • Une ...... map ? afin qu'on puisse... euh ... ESSAYER :bave:
  • Autres infos techniques croustillantes sur ce petit bijou

En tout cas c'est du joli

J'ai posté en faisant le pari que personne aller répondre donc j'ajouterai tout ça. ;)
Si t'as des propositions de programmes que je pourrais mettre en démo hésite pas.
Faudra aussi que je mette à disposition le compilateur mais il est pas vraiment présentable, je suis pas fier de mon code... x)

Et t'inquiète c'est le premier ordinateur que je fais avec des commands blocks, d'habitude j'utilise exclusivement la redstone.
Les command blocks c'est en fait beaucoup plus rapide et ça fait beaucoup moins ramer.
 
Dernière édition:
16 Février 2014
1 944
391
217
le sud (de Melun)
Salut petite mise à jour, j'ai mis une liste des instructions, je peux fournir plus de détails dans l'hypothèse où des gens voudrait programmer pour cette machine (je suis en train de rédiger plus de doc). Je ne mets pas la map à disposition tout de suite, je suis en train de travailler les programmes installés "d'usine", notamment un système d'exploitation primitif. Sinon je laisserai mes programmes de test comme hello world ou fibonnaci.

Je vais aussi améliorer la communication entre le CPU et le "GPU", on pourra lui envoyer des instructions via les ports I/O car pour
l'instant tout ce qu'il fait c'est scanner la mémoire pour des caractères à afficher.

Ensuite je modifierai l'assembleur pour qu'il soit utilisable par tout le monde, c'est un peu compliqué au niveau de la syntaxe (même pour moi).
Ce sera plus propre quand on pourra donner des valeurs hexadécimales.

1555794756-sans-titre.png

En gros :
  • les 3 première lignes définissent des constantes utiles un peu partout,
  • "segment" précise où dans la mémoire commence le programme
  • "lab" crée un label (ici il sert à rien mais c'est pratique pour les boucles)
  • "data" permet de définir une constante avec l'adresse de certaines données qui vont être mises dans la ram

ensuite le code qui va être exécuté pour de vrai :
  • Je push 3 adresses pour ensuite appeler une fonction qui copie un bout de la ram à un autre endroit ("hello world" -> mémorie vidéo)
  • J'appelle une fonction qui rappelle "l'OS" pour terminer le programme


Enfin je finaliserai le projet en construisant un décodeur d'instructions pour le processeur, ce qui permettra de tout stocker dans la même mémoire,
un des trucs chiant quand on importe un programme c'est qu'il faut gérer la ROM et la RAM séparément. J'ai déjà les premières briques posées avec
le registre de segment, le défi ce sera de concevoir un langage machine adapté à un décodeur instantané.

Je suis pas un expert, ce que je connais je l'ai surtout appris en construisant des processeurs en redstone et non en programmant en assembleur.
Du coup il y a sûrement des grosses incohérences. Par exemple PUSH et POP qui sont traités comme des opérandes et non comme des instructions,
ça permet par exemple de les utiliser directement sans passer par un registre, par exemple c'est possible de faire quelque chose comme "JUMP POP",
mais on est obligé de dire "MOV PUSH *** " dans les cas où on veut juste push une valeur comme dans l'exemple d'haut dessus.
C'est pas trop tard pour changer tout ça.

A la fin ce truc sera compatible x86 mdr...
 
Dernière édition:

Wistaro

Étudiant ingénieur
5 Février 2014
1 092
165
187
26
Toulouse
www.youtube.com
Wow, très beau travail. En particulier l'ajout du pipeline et de l'architecture de Harvard modifié ;)

J'ai hâte de voir ce que ça peut donner par la suite
 
16 Février 2014
1 944
391
217
le sud (de Melun)
Le Harvard il va pas rester longtemps, j'ai trouvé un décodeur, j'ai de la place dans le code machine pour rajouter des fonctions et des registres si je veux.
Ça fait plus propre sans le gros rectangle de rom. :^)

1555948119-2019-04-22-17-47-51.png
 
Dernière édition:
16 Février 2014
1 944
391
217
le sud (de Melun)
Salut je mets <enfin> à disposition la map avec un petit kit de développement.
Il y a encore du boulot, j'ai pas pu remettre le système de pseudo pipeline mais c'est pas un truc compliqué.
J'aimerai ajouter une horloge sur un port I/O pour avec plus de possibilités en terme de système "d'exploitation", et ça manquerait presque un deuxième K de ram.
L'executable de l'assembleur n'est compatible qu'avec windows je pense.
Et non ça peut pas faire tourner doom.
 
16 Février 2014
1 944
391
217
le sud (de Melun)
Bon... j'ai laissé le projet de côté mais j'ai encore des visions de processeurs dans mes rêves.



Il est encore temps de se ruer sur ce bijou de technologie de la mort qui tue tant que tout n'est pas obsolète.
 
Dernière édition: