aboutsummaryrefslogtreecommitdiff
#### Warning! This README has not been updated! I have finished and successfully defended the thesis since then. ####

## About
This repository shall contain the the code for 'Laboratory station based on
programmable logic device for WebAssembly execution evaluation' developed as my
engineering thesis at AGH University of Science and Technology in Cracov,
Poland.

The project utilizes Verilog HDL. Icarus Verilog Simulator is used for
simulation and test benches, while Yosys, arachne-pnr/nextpnr and icestorm are
the tools chosen for synthesis, p&r and bitstream generation for Olimex's
iCE40HX8K-EVB FPGA.

## Technical choices
I'm using one of few FPGAs with fully libre toolchain. SystemVerilog and VHDL
are not yet (officially) supported in Yosys, so I'm using Verilog2005.

I'm writing my own stack machine CPU for the job. Another option would be to
run an existing register-based CPU (picorv32?) on the FPGA and interpret Wasm
on it. Despite my thesis' topis is broad anough it would allow that, I didn't
go this way, because:
 - there'd be nothing innovative in this approach,
 - I'd end up mostly copying other's code, ending up with a copy-paster's
   thesis...

I'm using Wishbone pipelined interconnect for CPU and other components.

WebAsm binary format was not designed for direct execution, so I'm instead
creating a minimal stack machine, that would allow almost 1:1 translation of
Wasm code to it's own instruction format. I still think it's possible to make
a CPU, that would execute Wasm directly - it's just matter of a bit more
effort.

The stack machine is and will be limited. That's why some more complex Wasm
instructions (e.g. 64-bit operations, maybe float operations) have to be
replaced with calls to software routines.

The goal is to write some minimal "bootloader", that would translate Wasm
to my stack machine's instructions on-device.

The SPI chip on iCE40HX8K-EVB is 2MB big. The configuration stored on it is
below 137KB. I'm going to use the remaining memory to store the actual Wasm
code for execution.

The initial booting code will be preloaded to embedded RAM (iCE40HX8K has such
feature and Yosys supports it).

I'm using VGA (640x480@60Hz) with self-created text mode for communicating to
the outside. UART is also planned.

I wrote an assembly for my stack machine (tclasm.tcl). The actual assembly
instructions are expressed in terms of tcl command executions, so we could call
it pseudo-assembly. Before embracing tcl, I needed a way to express memory
reads and writes for some test benches and created a simple macroassembly
(include/macroasm.vh). I probably should have used tcl from the beginning...

Everything is done through some (quite sophisticated) Makefiles.

## Project structure
 - Makefile - needs no explaination...
 - Makefile.config - included by Makefile and Makefile.test, defines variables,
   		     makes it easy to, e.g., change the compiler command
 - Makefile.util - also included by Makefile and Makefile.test - defines things,
   		   that didn't semantically fit into Makefile.config
 - design/ - Verilog sources, that will get synthesized for FPGA (+some other
   	     files like initial memory contents)
 - models/ - Verilog modules used in testing
 - tests/ - benches, each in its own subdirectory, with a Makefile including
   	    Makefile.test
 - tclasm.tcl - implementation of simple assembly in terms of tcl commands
 - include/ - Verilog header files for inclusion
 - tools/ - small C programs
 - COPYING - 0BSD license
 - README.txt - You're reading it

## Project status
I'm a huge bit delayed with the work (should have had a working prototype in
June...), but I'm working on it.

I had a previous approach to the problem in July. Work was going extremely
slowly and I felt, that my code was really bad. This is also because I haven't
had any serious hardware design experience before. Now, I started anew. My
current approach is less CISCy. I'm also doing everything in the simulator,
with test benches for every module and plans to get it to run on the FPGA once
the design is able to display something through VGA. That's different from my
previous approach, where I was trying to make something run on the board and
then write tests for it. I'm now determined to use Wishbone, because I believe
it helps me keep the design clean.

My stack machine is currently able to do some operations like memory accesses,
addition and unsigned division, jumps, but it's not yet ready to have most of
Wasm translated to it. At the beginning of September I changed the design and
instruction format and rewrote the stack machine. The current one can be
considered my third approach :p

### Thoughts
It's indeed an interesting project, but from practical point of view - it's
still going to be more efficient to JIT-compile Wasm on a register-based
architecture... Perhaps it'd be more useful to optimize an exisiting processor
(OpenRISC, OpenSPARC, RiscV) for that?
> 2023-12-17daemon: Fix my own whitespace errors.Tobias Geerinckx-Rice This follows up on commit d993ed43b2bae8717437aa27d9d33fd223a6411f and was entirely predictable. The noise, sorry for it. Change-Id: I8ddb8cfe33db3864949f6589cc091616a90ebc5b 2023-12-10daemon: Sacrifice builders on OOM.Tobias Geerinckx-Rice * nix/libstore/build.cc (DerivationGoal::runChild): Maximise our OOM score adjustment. Change-Id: I418c763b499ca16e1ffe3c6033319112b9744f51 2023-12-11daemon: Implement ‘substitute-urls’ RPC.Ludovic Courtès * nix/libstore/worker-protocol.hh (PROTOCOL_VERSION): Bump. (WorkerOp): Add ‘wopSubstituteURLs’. * nix/nix-daemon/nix-daemon.cc (performOp): Implement it. * guix/store.scm (%protocol-version): Bump. (operation-id): Add ‘substitute-urls’. (substitute-urls): New procedure. * tests/store.scm ("substitute-urls, default") ("substitute-urls, client-specified URLs") ("substitute-urls, disabled"): New tests. Change-Id: I2c0119500c3a1eecfa5ebf32463ffb0f173161de 2023-12-04daemon: Simplify “empty status” substitute error message.Ludovic Courtès * nix/libstore/build.cc (SubstitutionGoal::finished): Don’t show what the empty status looks like. Change-Id: Ie898432aeb047aff3d59024de6ed6d18f68903c4 2023-09-24Revert "build: Add missing guix-gc.timer file to binary tarball."Tobias Geerinckx-Rice This reverts commit 69f6edc1a8596d2cb4c67e0435d35633af6f3cbc. The intention is good, but nodist_systemdservice_DATA are meant to be disposable artefacts generated from corresponding ‘.in’ files. etc/guix-gc.timer doesn't fit that description, breaking builds: $ make clean && make … make[2]: *** No rule to make target 'etc/guix-gc.timer', needed by 'all-am'. Stop. 2023-09-26daemon: Add “git-download” built-in builder.Ludovic Courtès The new builder makes it possible to break cycles that occurs when the fixed-output derivation for the source of a dependency of ‘git’ would itself depend on ‘git’. * guix/scripts/perform-download.scm (perform-git-download): New procedure. (perform-download): Move fixed-output derivation check to… (guix-perform-download): … here. Invoke ‘perform-download’ or ‘perform-git-download’ depending on what ‘derivation-builder’ returns. * nix/libstore/builtins.cc (builtins): Add “git-download”. * tests/derivations.scm ("built-in-builders"): Update. ("'git-download' built-in builder") ("'git-download' built-in builder, invalid hash") ("'git-download' built-in builder, invalid commit") ("'git-download' built-in builder, not found"): New tests. 2023-09-09daemon: Fix build with GCC 13.Sören Tempel The sqlite.hh file uses fixed-width integer types from stdint.h. As such, it needs to include <cstdint>. Without this include, the file doesn't compile successfully with GCC13. See: https://gcc.gnu.org/gcc-13/porting_to.html#header-dep-changes * nix/libstore/sqlite.hh: include <cstdint> Signed-off-by: Sören Tempel <soeren@soeren-tempel.net> Signed-off-by: Ludovic Courtès <ludo@gnu.org> 2023-08-31build: Add missing guix-gc.timer file to binary tarball.Maxim Cournoyer Partially fixes <https://issues.guix.gnu.org/65117>. * nix/local.mk (nodist_systemdservice_DATA): Add etc/guix-gc.timer. 2023-01-09daemon: Improve error message for wrong hash sizes.Ludovic Courtès * nix/libutil/hash.cc (parseHash): Show the hash algorithm name and expected size in the error message. * tests/derivations.scm ("fixed-output derivation, invalid hash size"): New test. 2022-12-18daemon: Make "opening file" error messages distinguishable.Ludovic Courtès * nix/libstore/build.cc (DerivationGoal::openLogFile): Customize "opening file" error message. * nix/libutil/hash.cc (hashFile): Likewise. * nix/libutil/util.cc (readFile, writeFile): Likewise. 2022-10-17Revert "nix: Guard against removing temporary roots of living processes."Ludovic Courtès This reverts commit bb0beaecdee1a2315a1269b1746d238c8ab0e699. This change broke a number of tests that assumed the previous behavior. 2022-10-07nix: Guard against removing temporary roots of living processes.Ludovic Courtès Fixes <https://issues.guix.gnu.org/25018>. * nix/libstore/gc.cc (readTempRoots): Add a check to guard against removing the temporary roots of a living process. Signed-off-by: Maxim Cournoyer <maxim.cournoyer@gmail.com>