{"id":16334985,"url":"https://github.com/ncfavier/marvin","last_synced_at":"2025-05-16T09:30:42.559Z","repository":{"id":66325183,"uuid":"301118052","full_name":"ncfavier/marvin","owner":"ncfavier","description":"Microprocessor simulator for the digital electronics project at ENS","archived":false,"fork":false,"pushed_at":"2020-10-04T14:26:24.000Z","size":1691,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-17T20:26:40.791Z","etag":null,"topics":["digital-circuits","microprocessor","simulator"],"latest_commit_sha":null,"homepage":"","language":"OCaml","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ncfavier.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-04T11:57:24.000Z","updated_at":"2020-10-04T14:57:26.000Z","dependencies_parsed_at":"2023-03-10T23:49:27.895Z","dependency_job_id":null,"html_url":"https://github.com/ncfavier/marvin","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ncfavier%2Fmarvin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ncfavier%2Fmarvin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ncfavier%2Fmarvin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ncfavier%2Fmarvin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ncfavier","download_url":"https://codeload.github.com/ncfavier/marvin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254504664,"owners_count":22082070,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["digital-circuits","microprocessor","simulator"],"created_at":"2024-10-10T23:39:47.591Z","updated_at":"2025-05-16T09:30:42.538Z","avatar_url":"https://github.com/ncfavier.png","language":"OCaml","funding_links":[],"categories":[],"sub_categories":[],"readme":"# marvin\n\nCe projet est réalisé en Haskell (GHC 8.6.5), et dépend des bibliothèques `base`, `containers`, `array`, `mtl`, `megaparsec` et `time`.\n\nIl contient les modules suivants :\n\n- `Netlist` : définition et parsage des netlists ;\n- `Simulator` : simulateur de netlists ;\n- `Dialog` (exécutable `dialog`) : interface « dialogue » du simulateur : lit les variables d'entrée au clavier et affiche les variables de sortie ;\n- `Clock` (exécutable `clock`) : interface « horloge » du simulateur : ne lit aucune variable, affiche l'heure et la date dans un format lisible, gère l'initialisation et la synchronisation ;\n- `Assembler` (exécutable `assembler`) : compile un programme assembleur vers une image RAM chargeable par le simulateur.\n\n## Simulateur\n\n    dialog [-n STEPS] NETLIST\n\nLa ROM et la RAM sont représentées comme des tableaux de booléens, afin de ne pas privilégier une taille de mot donnée.\n\nLes entiers sont interprétés et stockés de manière gros-boutiste.\n\nOn maintient un environnement associant une valeur à chaque variable de la netlist (initialement zéro).\n\nLa netlist n'est pas supposée triée : si une variable `a` dépend d'une variable `b`, on calculera `b` avant `a`. À chaque étape, on calcule uniquement les variables suivantes (et leurs dépendances) :\n\n- les variables d'entrée ;\n- les variables de sortie ;\n- les variables `x` apparaissant dans une équation de la forme `... = REG x` ;\n- les variables `x` apparaissant dans une équation de la forme `x = RAM ...`.\n\nCela permet de ne pas calculer les variables non utilisées, et je conjecture que c'est suffisant pour effectuer tous les effets de bord.\n\nLa RAM (resp. la ROM) est initialisée avec le contenu de l'image `ram.img` (resp. `rom.img`) si elle existe, et complétée par des zéros.\n\nLe format pour les images RAM/ROM est le suivant :\n\n- un entier par ligne ;\n- le premier entier est la taille de mot `n` ;\n- le deuxième entier est la taille `m` de l'image en mots ;\n- le reste interprété comme une suite de mots de `n` bits, concaténés et éventuellement complétés pour atteindre `m` mots.\n\n## Microprocesseur\n\nLe microprocesseur manipule des mots de **42 bits**. Il comporte une ALU, une RAM, une ROM, ainsi que les registres `A`, `B`, `C`, `D` et `PC` (compteur d'instruction).\n\nChaque instruction occupe exactement trois emplacements mémoire : un *opcode* et deux opérandes (optionnelles).\n\nLes différentes parties du microprocesseur sont orchestrées par divers signaux de contrôle, chacun correspondant à un bit de l'opcode en cours d'exécution.\n\nLes instructions suivantes sont disponibles :\n\n- `mov` : déplace une opérande vers l'autre ;\n- `add`, `sub` : addition, soustraction ;\n- `mul`, `div`, `mod` : multiplication, division, modulo ;\n- `not`, `and`, `or`, `xor` : opérations logiques ;\n- `test` : met la destination à 0 si la source vaut 0, à 1 sinon ;\n- `jmp` : saut ;\n- `jz`, `je`, `jnz`, `jne`, `jl`, `jnl`, `jge`, `jg`, `jng`, `jle` : sauts conditionnels par rapport au registre `A`.\n\nLes opérations arithmétiques et logiques prennent une opérande source et une opérande destination, et placent le résultat dans l'opérande destination.\n\nLes opérandes peuvent faire référence à un entier immédiat, un registre, ou un emplacement mémoire ; le type d'opérande est codé sur les deux bits de poids faible. Les deux opérandes ne peuvent pas faire référence à la mémoire en même temps.\n\nLe microprocesseur est écrit en minijazz (`proc.mj`), et compilé vers la netlist `proc.net`.\n\nIl dépend d'une version légèrement modifiée de minijazz (fournie dans le dépôt) : le type des fonctions `reg` et `mux` permet de les utiliser avec des signaux de taille quelconque.\n\n## Assembleur\n\n    assembler FILE\n\nL'assembleur permet de compiler depuis un langage assembleur vers une image RAM contenant un programme exécutable par le microprocesseur.\n\nIl supporte trois types d'instructions :\n\n- les affectations : `x = v` ;\n- les étiquettes : `label:` ;\n- les instructions machine : `ins [op1 [op2]]`.\n\nLes opérandes sont de la forme :\n\n- registre : `%a` ;\n- mémoire : `*42`, `*foo` ;\n- immédiat : `42`, `foo`.\n\nL'image est écrite sur la sortie standard. La taille de l'image produite est fixée à 2048 mots.\n\n## Horloge\n\n    clock [OPTIONS...] NETLIST\n      -a           --async          run in async mode\n      -i TIMEDATE  --init=TIMEDATE  initial timedate\n\nL'option `-a` permet d'ignorer l'horloge système et de faire tourner l'horloge le plus rapidement possible ; l'option `-i` permet d'initialiser l'horloge à un instant donné (format `%Y-%m-%d %H:%M:%S`).\n\nCertains emplacements en mémoire sont utilisés pour l'entrée-sortie :\n\n- les adresses 1024 - 1029 contiennent les secondes, minutes, heures, jours, mois et années ;\n- l'adresse 1030 est mise à 1 en mode synchrone, à 0 sinon ;\n- l'adresse 1031 sert à la synchronisation : le simulateur ajoute 1 à cet emplacement pour chaque seconde écoulée.\n\nLe programme assembleur de l'horloge se trouve dans `clock.asm`, et doit être compilé vers `ram.img`. La ROM n'est pas utilisée.\n\nL'horloge tient compte des années bissextiles.\n\n## TL;DR\n\nLa cible `runclock` du Makefile fourni permet de tout compiler et de lancer l'horloge en mode synchrone.\n\nLa variable `async` peut être définie pour activer le mode asynchrone (`make runclock async=1`).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fncfavier%2Fmarvin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fncfavier%2Fmarvin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fncfavier%2Fmarvin/lists"}