What is RISC-V, anyway?
RISC-V (say “risk five”), a new computer architecture developed at UC Berkeley, aims to turn the world of computer architecture – and hopefully computing – on its head.
If you’re not familiar with RISC-V, you should read my announcement of SiFive’s first RISC-V silicon.
RISC-V support in muforth
I think RISC-V is amazing, and I want to see it succeed. To help in my small way – and to have some fun in the process! – I want muforth to support RISC-V.
What does this mean?
You could probably download and build the (rather big!) RISC-V toolchain and use it to build a copy of muforth for RISC-V. But since part of the “mission” of muforth is to do an end run around existing unwieldly toolchains, I think a more interesting approach is to use muforth as it was intended: as a cross-compiler.
What is involved?
As with any architecture, the steps to supporting RISC-V are something like this:
- write an assembler and disassembler
- write code to talk to the on-board debug
- write, or modify an existing, meta-compiler
With these three pieces it’s possible to:
- explore the chip’s memory, both by dumping hex contents and by disassembling them;
- write so-called “code” words: words written in RISC-V assembler
- write so-called “colon” words: high-level Forth words that are translated by the meta-compiler into some kind of executable form;
- do all these things interactively while connected to a debug target.
Status
As of muforth commit badd131afd1e it’s possible to do all these things! (See the getting started with RISC-V page for details.)
There are pieces missing, for sure. The meta-compiler is incomplete: while it’s possible to compile “user-mode” code, there is no way to write exception handlers. Generally, the current state of remote execution requires working demo code to run on the board after reset, before muforth can connect to it.
The kernel is also incomplete: it’s currently lacking multiplication and division words.
I decided, after long perseveration, to try doing an indirect-threaded code (ITC) Forth, even though ITC is not a great match for RISC architectures. On the plus side, ITC is very simple to implement. I was able in less than a day to tweak the MSP430 meta-compiler and kernel into being a RISC-V meta-compiler and kernel. I’d love to continue exploring implementations, but for the moment I’m going to stick with, and flesh out, the ITC implementation.
What’s missing?
I need to add documentation, support for the on-chip hardware (starting with equates describing the memory location of each chip register), a more complete kernel, and, ideally, multi-tasking capability. None of this is that hard; it just takes time.
Quirks, foibles, and difficulties
The only way to write to the on-board SPI flash on the SiFive board is via JTAG (via the on-board FTDI chip). Initially this has to be done using SiFive’s modified version of openocd; eventually I’d like to – somehow – do this directly from muforth.
What this means is that at the moment – and for the forseeable future – the only way to talk to the board – either to program the SPI flash or to write and test Forth code – is via openocd
. This isn’t as terrible as it seems; there is an easy way to get the RISC-V-capable openocd
.
RISC-V and SiFive documentation
I’ve compiled a page with lots of RISC-V resources.