Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/esdmr/mano-machine
Mano Machine implementation in SystemVerilog
https://github.com/esdmr/mano-machine
basic-computer computer-architecture mano-machine systemverilog
Last synced: about 1 month ago
JSON representation
Mano Machine implementation in SystemVerilog
- Host: GitHub
- URL: https://github.com/esdmr/mano-machine
- Owner: esdmr
- License: mit
- Created: 2023-12-22T17:03:57.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2024-05-14T15:37:06.000Z (8 months ago)
- Last Synced: 2024-05-15T04:45:28.699Z (8 months ago)
- Topics: basic-computer, computer-architecture, mano-machine, systemverilog
- Language: SystemVerilog
- Homepage:
- Size: 127 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Mano Machine implementation in SystemVerilog
For the *Computer Architecture* class, I created a project that simulates the
[Mano machine](https://en.wikipedia.org/wiki/Mano_machine). It consists of
synthesizable modules for the components that do not involve input/output, a
macro-based assembler, and a module that can run the simulation.## Requirements
To run the simulator along with the preloaded assembly program, you will need
the following tools:- [Python](https://www.python.org/) v3.12 or later
- [Icarus Verilog](https://steveicarus.github.io/iverilog/) v12.0 or laterTo run everything else, you will need the following tools too:
- [Node.JS](https://nodejs.org/) v18 or later
- [`tap-mocha-reporter`](https://www.npmjs.com/package/tap-mocha-reporter)
- C compiler such as [GCC](https://gcc.gnu.org/) to be used via `iverilog-vpi`
- Make, preferably [GNU Make](https://www.gnu.org/software/make/)
- [Verible](https://chipsalliance.github.io/verible/) `v0.0-3428-gcfcbb82b` or later
- [Verilator](https://verilator.org/) `v5.019` or later
- At least one of:
- Option A (recommended):
- [My fork of DigitalJS online](https://github.com/esdmr/digitaljs-online)
- [Yosys](https://yosyshq.net/yosys/) `v0.35` or later
- [cURL](https://curl.se/)
- [`xdg-open`](http://portland.freedesktop.org/doc/xdg-open.html)
- Option B:
- [VS Code](https://code.visualstudio.com/)
- [DigitalJS extension](https://marketplace.visualstudio.com/items?itemName=yuyichao.digitaljs)
- Option C:
- [DigitalJS online](http://digitaljs.tilk.eu/)## Usage
- Prepare the VPI modules:
`./sv.py make`.
- Simulate preloaded with the assembly program in
`src/program.asm.sv`:
`./sv.py run src/VirtualComputer.sv`.
- Synthesize to logic gates:
(A) `./sv.py synthesize --online http://localhost:15555 src/SOC.sv` or
(B) `./sv.py synthesize --vscode src/SOC.sv` or
(C) `./sv.py synthesize src/SOC.sv`.
- Translate to VHDL (not tested):
`./sv.py compile src/SOC.sv --type vhdl --out SOC.vhdl`.
- Run linter:
`./sv.py lint`.
- Run tests:
`./sv.py test`.
- Run the formatter:
`./sv.py format`.## Project structure
- `src`
- `Virtual*.sv`: non-synthesizable modules
- `/[a-z].*\.sv/`: non-module source files
- Anything else: synthesizable modules
- `test`
- `/[a-z].*\.sv/`: utility files
- Anything else: testbench modules
- `vpi`
- `*.c`: VPI source files for `iverilog`
- `Makefile`: configuration for Make
- `ckl`: C-like programming language which compiles to the Mano machine
- `sv.py`: Script which wraps almost any command that you will run
- `extended_instructions.py`: Script which generates new (and dare I say mostly
useless) instructions for the current CPU architecture.## The preamble
The files `src/preamble.sv` and `test/preamble.sv` contain macros which will be
loaded at the top of every file.An important macro from the preamble is `IMPORT`. Instead of wrapping each
module in `ifndef`-`define`, we will wrap the `include` which will import that
module. As long as no module is circularly importing itself, it is a more
elegant solution to importing a file only once and in order.In `test/preamble.sv`, the `IMPORT` macro will be redirected to the `src`
directory, so `IMPORT(RAM)` imports `src/RAM.sv` and not `test/RAM.sv`.
Additionally, `test/preamble.sv` includes some macros to assist in running
testbenches.## The assembler
We use SystemVerilog macros to implement the assembler. In a module which will
accept the assembler, you should implement the `_ASM_SET_MEMORY_` macro which
will be called with the bytes from the assembled program.Inside the module body, you will use the `ASM_DEFINE_PROGRAM` macro and pass the
program as its argument. For multiline programs, I recommend moving the content
of the argument into a macro. For very long programs, I recommend using `include`
and the `.asm.sv` suffix. (The formatter correctly indents the instructions with
this suffix.)Non-memory-reference instructions are available as `ASM_`.
Memory-reference instructions are available as
`ASM__`. See [`assembler.sv`](src/assembler.sv) for
more information.Labels can be created via `ASM_LABEL`. Some labels can be marked private, e.g.,
subroutine branches and variables. These can be defined via `ASM_SUBLABEL` and
are only accessible between two `ASM_LABEL`s (or the end of the program).You can set the assembler address via `ASM_ADDR` and `ASM_ADDR_REL`.
You can set raw data via `ASM_DATA`. If the data is the address of a label, you
can use `ASM_DATA_LABEL` and `ASM_DATA_SUBLABEL`. If the data is a string, you
can use `ASM_DATA_STR`. (It will not append a null character). Finally, you can
use `ASM_DATA_FILL` to initialize a span in the memory.There are some shortcuts available, such as `ASM_SUBROUTINE`, `ASM_CALL`,
`ASM_RETURN`, `ASM_ARG_SKIP`, `ASM_ARG_NEXT`, `ASM_SHR`, `ASM_SHL`, and
`ASM_ASR`. See [`assembler.sv`](src/assembler.sv) for more information.Finally, there is the `disassemble` task which will decode an instruction.
## The test library
There is an implementation of a [Test Anything Protocol
(TAP)](https://testanything.org/) producer inside `test/preamble.sv`. For every
test case, it will output a `ok` or `not ok` line to the stdout which will be
picked up by a tap consumer.There is a test runner implemented in Python in `sv.py`. You can use the `test`
sub-command to run some or all testbenches. If you are running this command via
a TTY and have `tap-mocha-reporter` installed, the output will be passed into
it.For asynchronous modules, you can use `TAP_TEST` and `TAP_CASE`. For synchronous
modules, you can also use `TAP_CASE_AT` and `TAP_CASE_AT_NEGEDGE`.See [`test/preamble.sv`](test/preamble.sv) for more information.
## The VPI module for IO
While SystemVerilog has `$fgetc`, the standard input is line-buffered, so it
cannot be used for the keyboard module. Additionally, `$fgetc` waits for user
input, blocking the simulation.To replace `$fgetc`, we will implement the necessary logic in C and load it into
the `iverilog` simulation. This is implemented inside `vpi/io.c`. It supports
both Windows (untested) and Linux. If you would like to avoid using this module
for some reason, you can pass the `--no-vpi` option to the `./sv.py run`
command.## The CKL programming language
Pronounced like “sickle”, it is a C-like programming language specifically for
the Mano Machine. It is currently a work in progress and also lacks many
optimizations.```c
// Top-level variable declaration
a;
// Top-level variable declaration with initializer
b = 123;// Forward declaration
add(a, b);// Function declaration
add(a, b) {
// Last expression is returned automatically.
a + b;
}// Special function declarations
$start() { /* … */ }
$isr() { /* … */ }io() {
// Asynchronous input
a = $input;
// Synchronous input
a = $input();// Asynchronous input
$output = a;
// Synchronous input
$output(a);// I/O flags
do; while (!$fgo);
do; while (!$fgi);// IEN flag
$ien = 1;
$ien = 0;// Address of the word immediately after the assembly program.
string = $post;// Inline assembly
asm("`ASM_ISZ_DL(%s)", a);
}// Also inline assembly
asm("`ASM_ADDR_REL(2)");
```