Getting started with MRISC32

This is a quick introduction to software development for the MRISC32 architecture.

MRISC32

The MRISC32 architecture is a novel 32-bit Vector/RISC instruction set architecture, designed to be efficient, powerful, forward looking and easy to work with. It is also open and completely free for anyone to use as they wish.

The compiler

For compiling programs there is an MRISC32 port of GCC + binutils + newlib, which is available for Linux, macOS and Windows. The latest version can be downloaded from the mrisc32-gnu-toolchain project home.

At the time of writing, the compiler is based on GCC 12.x (trunk) and contains support for:

  • C (with standard C library)
  • C++ (still limited support)
  • Assembly language
  • ELF linking, disassembly, etc

With the toolchain installed you can start compiling programs. Consider the following C program, square.c:

int square(int x) {
  return x * x;
}

It can be compiled using the following command:

mrisc32-elf-gcc -O2 -c square.c

This will produce an ELF object file, square.o, which you can disassemble using the objdump tool:

$ mrisc32-elf-objdump -d square.o
square.o:     file format elf32-mrisc32

Disassembly of section .text:

00000000 <square>:
   0:	00210227 	mul     r1, r1, r1
   4:	c3c00000 	ret

The last two lines are the MRISC32 assembly language implementation of the C function, square().

The first instruction (mul r1, r1, r1), multiplies the register r1 with itself, and stores the result in the register r1. The choice of registers come from the MRISC32 ABI that defines that the function argument (int x) is passed in register r1, and the function result is returned in register r1. The second instruction (ret) returns to the calling function.

The simulator

While compiling programs is fun, you also want to be able to run your programs. This is where the MRISC32 Simulator comes in. Like the toolchain, the simulator runs on Linux, macOS and Windows, and there are pre-built binaries that can be downloaded.

Hello world!

Let us start with a simple “Hello world!” C program, hello.c:

#include <stdio.h>

int main(void) {
  printf("Hello world!\n");
  return 0;
}

In order to enable simulator based console and file I/O etc, you need to pass -msim when linking your programs, which selects the simulator version of certain newlib routines (by default the GNU toolchain uses a platform agnostic version of newlib). Thus we can compile and link the program as follows:

mrisc32-elf-gcc -o hello.elf hello.c -msim

This produces the executable ELF binary hello.elf. However, the simulator does not know how to load ELF binaries (yet). We can run the ELF binary in the simulator like this:

$ mr32sim hello.elf
Hello world!

You can also pass the -v flag on the command line to get some more information about the program execution:

$ mr32sim -v hello.elf
Read ELF32 executable hello.elf into RAM @ 0x00000200
------------------------------------------------------------------------
Hello world!
------------------------------------------------------------------------
Exit code: 0
CPU instructions:
 Fetched instructions: 1497
 Vector loops:         100
 Total CPU cycles:     1593

Building and running DOOM

If you want to try something more advanced, you can try out the MRISC32 port of DOOM (building DOOM requires CMake and ninja):

git clone https://github.com/mbitsnbites/mc1-doom.git
cd mc1-doom/src
mkdir out
cd out
cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=../mc1-toolchain.cmake -DCMAKE_BUILD_TYPE=Release ..
ninja

This will produce the ELF binary src/out/mc1doom. In order to run the program you also need a DOOM game data file, and fortunately a link to the DOOM 1 shareware doom1.wad can be found at doomwiki.org. Download the wad file and place it in the src folder, and start the simulator by running the run.sh (or run.bat on Windows) script in the same folder:

./run.sh

If all is set up correctly, you should now be running the MRISC32 version of DOOM:

If you have a look at the run.sh script, you will see that it passes a few extra options to the simulator that enable the graphics mode of the simulator. Run mr32sim –help to get more information about the options.

To actually play the game, pass the -f option (for fullscreen) when starting the simulator. Keyboard input (WSAD, arrows, CTRL, etc) and mouse input should work as expected.

Where’s the hardware at?

(For the adventurous)

There is an open source VHDL implementation of the MRISC32 architecture, namely the MRISC32-A1 CPU, and there is also an FPGA computer called MC1 that is based on the MRISC32-A1 CPU.

While the MRISC32-A1 and the MC1 are not really ready for prime time yet, anyone with FPGA development experience should be able to get it up and running on a hobbyist class FPGA board.

With the still-in-early-development MC1-SDK it is even possible to create bootable SD card images that can be executed on the MC1 computer.

Be warned, though, that all of this requires some experience and perseverance, as the MC1 FPGA configuration and build process has not been streamlined yet.

Diving deeper

To get more familiar with the MRISC32 architecture, the MRISC32 project at GitHub is a good resource. Here are some more pointers:

You can also ask questions at the public MRISC32 discussion forums.

Leave a Reply

Your email address will not be published. Required fields are marked *