{"id":21203172,"url":"https://github.com/esdmr/mano-machine","last_synced_at":"2026-02-06T00:32:53.142Z","repository":{"id":213926887,"uuid":"734804317","full_name":"esdmr/mano-machine","owner":"esdmr","description":"🖥️🤖 Mano Machine implementation in SystemVerilog","archived":false,"fork":false,"pushed_at":"2024-05-14T15:37:06.000Z","size":130,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-18T10:11:21.778Z","etag":null,"topics":["basic-computer","computer-architecture","mano-machine","systemverilog"],"latest_commit_sha":null,"homepage":"","language":"SystemVerilog","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/esdmr.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":"2023-12-22T17:03:57.000Z","updated_at":"2025-06-23T16:51:54.000Z","dependencies_parsed_at":"2024-11-20T20:24:38.945Z","dependency_job_id":"fe594d12-84cc-422d-b631-bc146eb4e1bb","html_url":"https://github.com/esdmr/mano-machine","commit_stats":null,"previous_names":["esdmr/mano-machine"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/esdmr/mano-machine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esdmr%2Fmano-machine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esdmr%2Fmano-machine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esdmr%2Fmano-machine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esdmr%2Fmano-machine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/esdmr","download_url":"https://codeload.github.com/esdmr/mano-machine/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esdmr%2Fmano-machine/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29140181,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T23:14:48.546Z","status":"ssl_error","status_checked_at":"2026-02-05T23:14:35.724Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["basic-computer","computer-architecture","mano-machine","systemverilog"],"created_at":"2024-11-20T20:21:47.695Z","updated_at":"2026-02-06T00:32:53.125Z","avatar_url":"https://github.com/esdmr.png","language":"SystemVerilog","readme":"# Mano Machine implementation in SystemVerilog\n\nFor the *Computer Architecture* class, I created a project that simulates the\n[Mano machine](https://en.wikipedia.org/wiki/Mano_machine). It consists of\nsynthesizable modules for the components that do not involve input/output, a\nmacro-based assembler, and a module that can run the simulation.\n\n## Requirements\n\nTo run the simulator along with the preloaded assembly program, you will need\nthe following tools:\n\n- [Python](https://www.python.org/) v3.12 or later\n- [Icarus Verilog](https://steveicarus.github.io/iverilog/) v12.0 or later\n\nTo run everything else, you will need the following tools too:\n\n- [Node.JS](https://nodejs.org/) v18 or later\n- [`tap-mocha-reporter`](https://www.npmjs.com/package/tap-mocha-reporter)\n- C compiler such as [GCC](https://gcc.gnu.org/) to be used via `iverilog-vpi`\n- Make, preferably [GNU Make](https://www.gnu.org/software/make/)\n- [Verible](https://chipsalliance.github.io/verible/) `v0.0-3428-gcfcbb82b` or later\n- [Verilator](https://verilator.org/) `v5.019` or later\n- At least one of:\n  - Option A (recommended):\n    - [My fork of DigitalJS online](https://github.com/esdmr/digitaljs-online)\n    - [Yosys](https://yosyshq.net/yosys/) `v0.35` or later\n    - [cURL](https://curl.se/)\n    - [`xdg-open`](http://portland.freedesktop.org/doc/xdg-open.html)\n  - Option B:\n    - [VS Code](https://code.visualstudio.com/)\n    - [DigitalJS extension](https://marketplace.visualstudio.com/items?itemName=yuyichao.digitaljs)\n  - Option C:\n    - [DigitalJS online](http://digitaljs.tilk.eu/)\n\n## Usage\n\n- Prepare the VPI modules:\n  `./sv.py make`.\n- Simulate preloaded with the assembly program in\n  `src/program.asm.sv`:\n  `./sv.py run src/VirtualComputer.sv`.\n- Synthesize to logic gates:\n  (A) `./sv.py synthesize --online http://localhost:15555 src/SOC.sv` or\n  (B) `./sv.py synthesize --vscode src/SOC.sv` or\n  (C) `./sv.py synthesize src/SOC.sv`.\n- Translate to VHDL (not tested):\n  `./sv.py compile src/SOC.sv --type vhdl --out SOC.vhdl`.\n- Run linter:\n  `./sv.py lint`.\n- Run tests:\n  `./sv.py test`.\n- Run the formatter:\n  `./sv.py format`.\n\n## Project structure\n\n- `src`\n  - `Virtual*.sv`: non-synthesizable modules\n  - `/[a-z].*\\.sv/`: non-module source files\n  - Anything else: synthesizable modules\n- `test`\n  - `/[a-z].*\\.sv/`: utility files\n  - Anything else: testbench modules\n- `vpi`\n  - `*.c`: VPI source files for `iverilog`\n  - `Makefile`: configuration for Make\n- `ckl`: C-like programming language which compiles to the Mano machine\n- `sv.py`: Script which wraps almost any command that you will run\n- `extended_instructions.py`: Script which generates new (and dare I say mostly\n  useless) instructions for the current CPU architecture.\n\n## The preamble\n\nThe files `src/preamble.sv` and `test/preamble.sv` contain macros which will be\nloaded at the top of every file.\n\nAn important macro from the preamble is `IMPORT`. Instead of wrapping each\nmodule in `ifndef`-`define`, we will wrap the `include` which will import that\nmodule. As long as no module is circularly importing itself, it is a more\nelegant solution to importing a file only once and in order.\n\nIn `test/preamble.sv`, the `IMPORT` macro will be redirected to the `src`\ndirectory, so `IMPORT(RAM)` imports `src/RAM.sv` and not `test/RAM.sv`.\nAdditionally, `test/preamble.sv` includes some macros to assist in running\ntestbenches.\n\n## The assembler\n\nWe use SystemVerilog macros to implement the assembler. In a module which will\naccept the assembler, you should implement the `_ASM_SET_MEMORY_` macro which\nwill be called with the bytes from the assembled program.\n\nInside the module body, you will use the `ASM_DEFINE_PROGRAM` macro and pass the\nprogram as its argument. For multiline programs, I recommend moving the content\nof the argument into a macro. For very long programs, I recommend using `include`\nand the `.asm.sv` suffix. (The formatter correctly indents the instructions with\nthis suffix.)\n\nNon-memory-reference instructions are available as `ASM_\u003cname\u003e`.\nMemory-reference instructions are available as\n`ASM_\u003cname\u003e_\u003cmode\u003e\u003coperand_type\u003e`. See [`assembler.sv`](src/assembler.sv) for\nmore information.\n\nLabels can be created via `ASM_LABEL`. Some labels can be marked private, e.g.,\nsubroutine branches and variables. These can be defined via `ASM_SUBLABEL` and\nare only accessible between two `ASM_LABEL`s (or the end of the program).\n\nYou can set the assembler address via `ASM_ADDR` and `ASM_ADDR_REL`.\n\nYou can set raw data via `ASM_DATA`. If the data is the address of a label, you\ncan use `ASM_DATA_LABEL` and `ASM_DATA_SUBLABEL`. If the data is a string, you\ncan use `ASM_DATA_STR`. (It will not append a null character). Finally, you can\nuse `ASM_DATA_FILL` to initialize a span in the memory.\n\nThere are some shortcuts available, such as `ASM_SUBROUTINE`, `ASM_CALL`,\n`ASM_RETURN`, `ASM_ARG_SKIP`, `ASM_ARG_NEXT`, `ASM_SHR`, `ASM_SHL`, and\n`ASM_ASR`.  See [`assembler.sv`](src/assembler.sv) for more information.\n\nFinally, there is the `disassemble` task which will decode an instruction.\n\n## The test library\n\nThere is an implementation of a [Test Anything Protocol\n(TAP)](https://testanything.org/) producer inside `test/preamble.sv`. For every\ntest case, it will output a `ok` or `not ok` line to the stdout which will be\npicked up by a tap consumer.\n\nThere is a test runner implemented in Python in `sv.py`. You can use the `test`\nsub-command to run some or all testbenches. If you are running this command via\na TTY and have `tap-mocha-reporter` installed, the output will be passed into\nit.\n\nFor asynchronous modules, you can use `TAP_TEST` and `TAP_CASE`. For synchronous\nmodules, you can also use `TAP_CASE_AT` and `TAP_CASE_AT_NEGEDGE`.\n\nSee [`test/preamble.sv`](test/preamble.sv) for more information.\n\n## The VPI module for IO\n\nWhile SystemVerilog has `$fgetc`, the standard input is line-buffered, so it\ncannot be used for the keyboard module. Additionally, `$fgetc` waits for user\ninput, blocking the simulation.\n\nTo replace `$fgetc`, we will implement the necessary logic in C and load it into\nthe `iverilog` simulation. This is implemented inside `vpi/io.c`. It supports\nboth Windows (untested) and Linux. If you would like to avoid using this module\nfor some reason, you can pass the `--no-vpi` option to the `./sv.py run`\ncommand.\n\n## The CKL programming language\n\nPronounced like “sickle”, it is a C-like programming language specifically for\nthe Mano Machine. It is currently a work in progress and also lacks many\noptimizations.\n\n```c\n// Top-level variable declaration\na;\n// Top-level variable declaration with initializer\nb = 123;\n\n// Forward declaration\nadd(a, b);\n\n// Function declaration\nadd(a, b) {\n  // Last expression is returned automatically.\n  a + b;\n}\n\n// Special function declarations\n$start() { /* … */ }\n$isr()   { /* … */ }\n\nio() {\n  // Asynchronous input\n  a = $input;\n  // Synchronous input\n  a = $input();\n\n  // Asynchronous input\n  $output = a;\n  // Synchronous input\n  $output(a);\n\n  // I/O flags\n  do; while (!$fgo);\n  do; while (!$fgi);\n\n  // IEN flag\n  $ien = 1;\n  $ien = 0;\n\n  // Address of the word immediately after the assembly program.\n  string = $post;\n\n  // Inline assembly\n  asm(\"`ASM_ISZ_DL(%s)\", a);\n}\n\n// Also inline assembly\nasm(\"`ASM_ADDR_REL(2)\");\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fesdmr%2Fmano-machine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fesdmr%2Fmano-machine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fesdmr%2Fmano-machine/lists"}