Salut !
Je m’appelle Adrien, Ardakaniz sur internet, j’ai 16 ans, je suis donc lycéen, en première S SI.
Vers mes 10/11 ans j’ai commencé la programmation en C puis rapidement en C++ qui est maintenant mon langage de prédilection. J’ai eu plusieurs projets de jeux vidéos mais je n’ai jamais eu la motivation d’en finir un seul, et ça ne m’intéresse plus comme avant.
Vers mes 12 ans j’ai eu une carte Arduino avec laquelle je n’ai jamais fait vraiment de projet et qui maintenant ne fonctionne plus
L’année dernière j’ai eu un RaspberryPi et je compte donc mettre l’assembleur dessus et l’utiliser pour programmer et upload les programmes de mon PC vers mon… PC ordinateur
Genèse et idée
ADKom signifie ADK pour Ardakaniz et Kom pour Com(puter), donc la série d’ordinateurs construient par moi, et A80, A pour l’architecture basée sur un accumulateur, et 80 pour la première version (0) 8-bits
Il y a quelques mois, j’ai découvert un YouTuber qui m’a fait découvrir l’électronique numérique: Ben Eater. Ce dernier a construit un ordinateur 8-bit et après de nombreuses demandes de personnes pour qu’il explique comment il a fait, il a décidé de le reconstruire entièrement en expliquant chaque parties distinctes.
J’ai regardé toutes ses vidéos, puis je me suis mis en tête que moi aussi je pourrais construire le mien, pour apprendre.
A la base je voulais faire un ordinateur qui est programmable en Brainf*ck . Puis des complications sur l’architecture sont arrivés, et puis je me suis dit qu’un "vrai" ordinateur serait plus intéressant (surtout sur le fait que programmer en BF c’est un peu limité et moins attrayant que de l’ASM, personnellement. Cependant, rien n’empêche d’en faire un interpréteur sur le résultat final).
J’ai donc commencé à l’architecture, car je ne compte pas recopier module par module celui de Ben Eater, ce serait un peu trop simple. Je voulais donc l’améliorer (sans pour autant rajouter trop de complexité pour que ça soit faisable) en rajoutant principalement des instructions et en améliorant l’ALU, celui de Ben Eater gèrant seulement l’addition/soustraction, je compte rajouter des comparaisons (<, ==) et des portes logiques (AND, OR) ).
Avec des très longs mois à architecturer et rearchitecturer, refaire, reréflechir, j’ai en trouvé d’autres comme celui-ci: nibbler. Au final, mon archi sera un mélange de celui de Ben, du site BigMessO’Wires et du livre The Elements Of Computing System
Objectifs
Apprendre. Et m’amuser et être fier de moi. Je suis conscient que une fois fini (et prions pour que je le finisse) cela ne servira pas à grand chose, mais au moins j’aurais appris énormément de choses et je pourrais me dire "J’ai construit un ordinateur à 16 ans \o/".
Avancement
Actuellement, il n’y a absolument rien de fait physiquement parlant .
L’architecture est enfin fixé après de nombreux jours de réflexion et de re-réflexion. C’est toujours ce que j’ai dis avant de trouver un truc trop limitant, ou mal pensé, et que je le change encore et encore.
Alors, à quelle allure je vais avancer ? Il n’y aura pas de rythme, le principal problème étant d’acheter les composants (que je n’ai pas)… Ben a indiqué qu’au final, son ordinateur lui aura couté entre \$150 et \$200, sachant que je veux lui apporter des améliorations, cela reviendra au final plus cher.
L’architecture
C’est un ordinateur à base d’accumulateur, c’est-à-dire que chaque opération utilise l’accumulateur pour le calcul (sauf dans certains cas) et remet le résultat dedans (en perdant l’ancienne valeur).
L’ALU est capable de faire des opérations bitwise not, or, and et nand, et du shifting (seulement sur l’accumulateur, que de 1 et que vers la gauche, donc c’est très limité mais ça va permettre entre autre d’utiliser des I2C)
Il y a trois IO: un write-only (pour un afficheur), un read-only (pour une entrée) et un qui peut faire les deux qui sont mappés à la fin de la RAM, leur adresse sont respectivement $FFD
, $FFE
et $FFF
Le langage Assembleur
Voilà à quoi il ressemble:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | mov #$ff, D mov #$0, A mov D, (A) loop inc.c (A), end mov #$fd, A mov D, ($f.A) mov #$0, A mov D, (A) pause end nop.npz end ; infinite loop |
Chaque instruction prend au minimum 2 octets: 1 où est codée la source, la destination, et un saut (On peut donc faire une opération normale et un saut dans la même instruction), un autre où est codé l’opération arithmétique (destiné à l’ALU donc) et un dernier falcultatif où sont stockés la valeur d’un adressage immédiat ou de l’offset
s1 s2 d1 d2 j1 j2 j3 j4
p o1 o2 o3 o4 o5 o6 o7
Avec s = source
, d = destination
, j = jump
, o = operation
et p = pause
.
Ce bit de pause
, comme son nom l’indique met en pause l’exécution du programme (L’assembleur transforme l’instruction pause en 1000 0000
)
Ces deux octets sont tous les deux stockés ensemble car la ROM du programme renvoie 16 bits. Cependant, les arguments sont dans deux cases mémoires différentes même si ils ne font que 8 bits, cela signifie donc que les 8 bits de poids fort seront inutilisés.
Les labels se déclarent simplement en tapant leur nom nomDuLabel
, et sont référencés tout aussi simplement
1 2 | loop inc.np loop |
Il y a quatre possibilités de jump:
- Si l’opération a provoqué une retenu, un overflow : carry -> c
- Si l’opération donne un résultat négatif : negative -> n
- Si l’opération donne 0 : zero -> z
- Et finalement, un peu à part, si l’opération donne un résultat positif qui vaut en fait (!n && !z): positive -> p
Il n’y a pas d’opération spécifique au saut, étant donné qu’il est codé avec les autres instructions. Si l’on ajoute à la fin d’une instruction normale (par exemple: sub.z #5, D, equal
), cela permet d’économiser un peu d’espace en ROM (et un peu de temps d’éxécution, puisque cela prend seulement 3 cycles d’horloge au lieu de 2*2). Si on ne peut pas pour X raison, il y a l’instruction nop
à la rescousse, qui ne modifie pas l’etat des registres mais qui permet de faire un saut quand même.
Le saut souhaité se spécifie à la suite de l’opération, après un point et l’adresse de saut est donné en tout dernier argument: op.jmp (arg1,) (arg2,) jumpArg
où jmp
sont les lettres correspondantes au type de saut. Le saut final correspondra au ’ou’ de ceux-là.
Par exemple, un nombre soit positif (p), soit négatif (n), c’est un nombre différent de 0, ou encore, un nombre sera toujours soit positif, soit négatif, soit égal à 0 (z), ce qui correspond donc au saut qui permet de tout le temps jump:
1 2 3 4 5 6 7 8 9 10 11 12 13 | mov #$0, A ; On part de 0 mov D, (A) loop inc (A) ; Et on incrémente mov D, (A) mov #42, D sub.np (A), D, loop ; Tant que c'est différent de 42 end nop.npz end ; infinite loop ` |
L’argument du saut peut être un nombre brut, ou venir du registre d’adressage A
.
Il y a aussi du préprocesseur qui va être mis en place à termes (du type define
, etc…).
Plus d’infos sur les instructions, j’ai fait un fichier de spécifactions ici
L’Assembleur
Deux logiciels sont compris dans une seule suite: L’assembleur et la VM
L’utilisation de l’assembleur est particulièrement simple: on lui donne un fichier asm d’entrée, et optionnellement un fichier de sortie (si aucun indiqué, out.bin
par défaut). L’argument -a
pour lui indiquer qu’on veut assembler et l’argument -e
pour lui indiquer qu’on veut émuler.
Lorsqu’il rencontre des erreurs, il nous donne le nom du fichier qu’on lui a donné, la ligne qui pose problème, et le problème en question.
TODO:
- Structure de base (✓)
- Opérations de base (✓)
- Sauts (❌)
- Labels (❌)
- Ajouter le reste des opérations (❌)
- Préprocesseur (define, reserve, etc…) (❌)
- Sûrement d’autres d’autres qui ne me viennent pas à l’esprit (❌)
La VM
J’ai commencé la programmation d’une VM pour pouvoir voir mes programmes fonctionner.
Il est codé dans la même application que l’assembleur, il suffit de lui rajouter l’option -vm
et il émulera le binaire.
Rien n’est fait pour l’instant, j’attends d’avoir fini de recoder l’assembleur en lui même.
TODO:
- Interprétation des opérations (❌)
- Interprétation des sauts (❌)
- Pouvoir voir le contenu des mémoires (❌)
- Ajouter les registres d’IO (❌)
Conclusion
Merci d’être venu à bout de cette présentation ! J’espère pouvoir avancer assez vite et finir ce projet pour ne pas laisser ce topic vide pendant 3 mois Trop tard…
A la base, je voulais attendre d’avoir les composants pour présenter mon projet, mais j’ai vu la FrenchiNES et ça m’a donné envie de vous en faire part dès maintenant, donc désolé de l’attente
Modules
- TODO
Links
- YT: Où je ferai des vidéos à propos des modules et expliquerai les différences avec ceux de Ben Eater.
- GitHub: Où je stocke tous les fichiers correspondant. Actuellement, il y a les schémas fait avec KiCAD (Registres, ProgramCounter, ALU), une description du langage assembleur ainsi que l’assembleur (qui inclu la VM).
Vidéos
Programmation d’une suite de Fibonacci puis émulation avec ma VM (obselète)