2022-11-27 03:13:00 -05:00
# riscv_emufun (mini-rv32ima)
2022-10-27 18:14:37 -07:00
2022-11-29 15:06:00 -08:00
Click below for the YouTube video introducing this project:
2022-11-29 15:06:09 -08:00
2022-12-05 14:31:21 -08:00
[](https://www.youtube.com/watch?v=YT5vB3UqU_E) [](https://www.youtube.com/watch?v=uZMNK17VCMU)
2022-11-28 21:12:54 -08:00
2022-11-27 04:43:55 -05:00
## What
2022-11-27 02:36:32 -05:00
2022-11-27 04:43:55 -05:00
mini-rv32ima is a single-file-header, [mini-rv32ima.h ](https://github.com/cnlohr/riscv_emufun/blob/master/mini-rv32ima/mini-rv32ima.h ), in the [STB Style library ](https://github.com/nothings/stb ) that:
2022-12-12 16:25:03 -08:00
* Implements a RISC-V **rv32ima/Zifencei†+Zicsr ** (and partial su), with CLINT and MMIO.
2022-11-27 03:05:03 -05:00
* Is about **400 lines ** of actual code.
* Has **no dependencies ** , not even libc.
2022-11-27 03:13:00 -05:00
* Is **easily extensible ** . So you can easily add CSRs, instructions, MMIO, etc!
2022-11-27 03:05:03 -05:00
* Is pretty **performant ** . (~450 coremark on my laptop, about 1/2 the speed of QEMU)
* Is human-readable and in **basic C ** code.
* Is "**incomplete**" in that it didn't implement the tons of the spec that Linux doesn't (and you shouldn't) use.
2022-11-30 04:58:59 +01:00
* Is trivially **embeddable ** in applications.
2022-11-27 02:47:22 -05:00
It has a [demo wrapper ](https://github.com/cnlohr/riscv_emufun/blob/master/mini-rv32ima/mini-rv32ima.c ) that:
* Implements a CLI, SYSCON, UART, DTB and Kernel image loading.
2022-11-27 03:05:03 -05:00
* And it only around **250 lines ** of code, itself.
* Compiles down to a * * ~18kB executable** and only relies on libc.
2022-11-27 02:36:32 -05:00
2022-12-12 16:25:21 -08:00
†: Zifence+RV32A are stubbed. So, tweaks will need to be made if you want to emulate a multiprocessor system with this emulator.
2022-12-12 16:25:03 -08:00
2022-11-27 02:36:32 -05:00
Just see the `mini-rv32ima` folder.
It's "fully functional" now in that I can run Linux, apps, etc. Compile flat binaries and drop them in an image.
2022-11-27 04:43:55 -05:00
## Why
2022-12-07 23:09:39 +02:00
I'm working on a really really simple C Risc-V emulator. So simple it doesn't even have an MMU (Memory Management Unit). I have a few goals, they include:
2022-11-27 04:43:55 -05:00
* Furthering RV32-NOMMU work to improve Linux support for RV32-NOMMU. (Imagine if we could run Linux on the $1 ESP32-C3)
* Learning more about RV32 and writing emulators.
* Being further inspired by @pimaker 's amazing work on [Running Linux in a Pixel Shader ](https://blog.pimaker.at/texts/rvc1/ ) and having the sneaking suspicion performance could be even better!
* Hoping to port it to some weird places.
* Understand the * most simplistic * system you can run Linux on and trying to push that boundary.
2022-12-20 22:18:26 +07:00
* Continue to include my [education of people about assembly language ](https://www.youtube.com/watch?v=Gelf0AyVGy4 ).
2022-11-27 04:43:55 -05:00
## How
2022-11-28 03:21:19 -05:00
Windows instructions (Just playing with the image)
2022-11-27 02:36:32 -05:00
* Clone this repo.
2022-11-28 03:21:19 -05:00
* Install or have TinyCC. [Powershell Installer ](https://github.com/cntools/Install-TCC ) or [Regular Windows Installer ](https://github.com/cnlohr/tinycc-win64-installer/releases/tag/v0_0.9.27 )
* Run `winrun.ps` in the `windows` folder.
2022-12-04 18:12:15 -08:00
WSL (For full toolchain and image build:
* You will need to remove all spaces from your path i.e. `export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/mnt/c/Windows/system32:/snap/bin` and continue the instructions. P.S. What in the world was Windows thinking, putting a space between "Program" and "Files"??!?
2022-11-28 03:21:19 -05:00
Linux instructions (both):
* Clone this repo.
* Install `git build-essential` and/or whatever other requirements are in place for [buildroot ](https://buildroot.org/ ).
2022-11-27 08:07:46 -05:00
* `make testdlimage`
2022-11-27 07:42:18 -05:00
* It automatically downloads the image (~1MB) and runs the emulator.
* Should be up and running in about 2.5s depending on internet speed.
2022-11-27 02:36:32 -05:00
2022-11-28 03:21:19 -05:00
You can do in-depth work on Linux by:
* `make everything`
If you want to play with the bare metal system, see below, or if you have the toolchain installed, just:
* `make testbare`
2022-11-27 02:36:32 -05:00
2022-12-05 14:30:16 -08:00
If you just want to play emdoom, and use the prebuilt image:
* On Windows, run `windows\winrundoom.ps1`
* On Linux, `cd mini-rv32ima` , and type `make testdoom`
2022-11-27 03:13:00 -05:00
## Questions?
* Why not rv64?
* Because then I can't run it as easily in a pixel shader if I ever hope to.
* Can I add an MMU?
2022-11-30 13:38:28 -05:00
* Yes. It actually probably wouldn't be too difficult.
2022-11-27 03:13:00 -05:00
* Should I add an MMU?
* No. It is important to further support for nommu systems to empower minimal Risc-V designs!
Everything else: Contact us on my Discord: https://discord.com/invite/CCeyWyZ
2022-11-14 04:04:51 -05:00
2024-04-28 01:54:21 -07:00
## How do I use this in my own project?
You shoud not need to modify `mini-rv32ima.h` , but instead, use `mini-rv32ima.c` as a template for what you are trying to do in your own project.
You can override all functionality by defining the following macros. Here are examples of what `mini-rv32ima.c` does with them. You can see the definition of the functions, or augment their definitions, by altering `mini-rv32ima.c` .
2024-04-28 01:55:35 -07:00
| Macro | Definition / Comment |
2024-04-28 01:55:49 -07:00
| --- | --- |
2024-04-28 01:55:35 -07:00
| `MINIRV32WARN( x... )` | `printf( x );` <br> Warnings emitted from mini-rv32ima.h |
| `MINIRV32_DECORATE` | `static` <br> How to decorate the functions. |
| `MINI_RV32_RAM_SIZE` | `ram_amt` <br> A variable, how big is system RAM? |
| `MINIRV32_IMPLEMENTATION` | If using mini-rv32ima.h, need to define this. |
| `MINIRV32_POSTEXEC( pc, ir, retval )` | `{ if( retval > 0 ) { if( fail_on_all_faults ) { printf( "FAULT\n" ); return 3; } else retval = HandleException( ir, retval ); } }` <br> If you want to execute something every time slice. |
| `MINIRV32_HANDLE_MEM_STORE_CONTROL( addy, val )` | `if( HandleControlStore( addy, val ) ) return val;` <br> Called on non-RAM memory access. |
| `MINIRV32_HANDLE_MEM_LOAD_CONTROL( addy, rval )` | `rval = HandleControlLoad( addy );` <br> Called on non-RAM memory access return a value. |
| `MINIRV32_OTHERCSR_WRITE( csrno, value )` | `HandleOtherCSRWrite( image, csrno, value );` <br> You can use CSRs for control requests. |
| `MINIRV32_OTHERCSR_READ( csrno, value )` | `value = HandleOtherCSRRead( image, csrno );` <br> You can use CSRs for control requests. |
2024-04-28 01:54:21 -07:00
2022-11-27 04:52:10 -05:00
## Hopeful goals?
2022-11-27 04:41:58 -05:00
* Further drive down needed features to run Linux.
* Remove need for RV32A extension on systems with only one CPU.
* Support for relocatable ELF executables.
* Add support for an unreal UART. One that's **much ** simpler than the current 8250 driver.
* Maybe run this in a pixelshader too!
2022-11-27 04:52:10 -05:00
* Get opensbi working with this.
2022-11-27 04:41:58 -05:00
* Be able to "embed" rv32 emulators in random projects.
2022-11-27 06:54:37 -05:00
* Can I use early console to be a full system console?
* Can I increase the maximum contiguous memory allocatable?
2022-10-27 18:14:37 -07:00
2022-11-27 04:58:45 -05:00
## Special Thanks
* For @regymm and their [patches to buildroot ](https://github.com/regymm/buildroot ) and help!
* callout: Regymm's [quazisoc project ](https://github.com/regymm/quasiSoC/ ).
* Buildroot (For being so helpful).
* @vowstar and their team working on [k210-linux-nommu ](https://github.com/vowstar/k210-linux-nommu ).
* This [guide ](https://jborza.com/emulation/2020/04/09/riscv-environment.html )
* [rvcodecjs ](https://luplab.gitlab.io/rvcodecjs/ ) I probably went through over 1,000 codes here.
2023-05-04 15:33:34 -07:00
* @splinedrive from the [KianV RISC-V noMMU SoC ](https://github.com/splinedrive/kianRiscV/tree/master/linux_socs/kianv_harris_mcycle_edition?s=09 ) project.
2022-11-27 07:38:36 -05:00
## More details
If you want to build the kernel yourself:
* `make everything`
* About 20 minutes. (Or 4+ hours if you're on [Windows Subsytem for Linux 2 ](https://github.com/microsoft/WSL/issues/4197 ))
* And you should be dropped into a Linux busybox shell with some little tools that were compiled here.
2022-12-05 14:34:16 -08:00
## Emdoom notes
* Emdoom building is in the `experiments/emdoom` folder
* You * MUST * build your kernel with `MAX_ORDER` set to >12 in `buildroot/output/build/linux-5.19/include/linux/mmzone.h` if you are building your own image.
* You CAN use the pre-existing image that is described above.
* On Windows, it will be very slow. Not sure why.
2022-11-17 04:27:32 -05:00
2022-11-27 04:58:45 -05:00
If you want to use bare metal to build your binaries so you don't need buildroot, you can use the rv64 gcc in 32-bit mode built into Ubuntu 20.04 and up.
2022-11-21 07:08:31 -05:00
```
2022-11-27 04:58:45 -05:00
sudo apt-get install gcc-multilib gcc-riscv64-unknown-elf make
2022-11-21 07:08:31 -05:00
```
2022-11-14 02:45:05 -05:00
2022-11-28 04:25:59 -05:00
## Links
* "Hackaday Supercon 2022: Charles Lohr - Assembly in 2022: Yes! We Still Use it and Here's Why" : https://www.youtube.com/watch?v=Gelf0AyVGy4
2022-11-28 03:21:19 -05:00
## Attic
2022-11-27 04:52:10 -05:00
2022-11-23 06:17:26 -05:00
2022-11-28 03:21:19 -05:00
## General notes:
* https://github.com/cnlohr/riscv_emufun/commit/2f09cdeb378dc0215c07eb63f5a6fb43dbbf1871#diff -b48ccd795ae9aced07d022bf010bf9376232c4d78210c3113d90a8d349c59b3dL440
2022-11-27 04:50:33 -05:00
2022-11-27 05:01:22 -05:00
(These things don't currently work)
### Building Tests
(This does not work, now)
```
cd riscv-tests
export CROSS_COMPILE=riscv64-linux-gnu-
export PLATFORM_RISCV_XLEN=32
CC=riscv64-linux-gnu-gcc ./configure
make XLEN=32 RISCV_PREFIX=riscv64-unknown-elf- RISCV_GCC_OPTS="-g -O1 -march=rv32imaf -mabi=ilp32f -I/usr/include"
```
### Building OpenSBI
(This does not currently work!)
```
cd opensbi
export CROSS_COMPILE=riscv64-unknown-elf-
export PLATFORM_RISCV_XLEN=32
make
```
2022-11-27 06:54:37 -05:00
### Extra links
* Clear outline of CSRs: https://five-embeddev.com/riscv-isa-manual/latest/priv-csrs.html
2022-12-09 11:12:13 -08:00
* Fonts used in videos: https://audiolink.dev/
2022-12-04 04:56:01 -05:00
### Using custom build
Where yminpatch is the patch from the mailing list.
```
rm -rf buildroot
git clone git://git.buildroot.net/buildroot
cd buildroot
git am < ../yminpatch.txt
make qemu_riscv32_nommu_virt_defconfig
make
# Or use our configs.
```
Note: For emdoom you will need to modify include/linux/mmzone.h and change MAX_ORDER to 13.
2023-03-25 09:20:48 -04:00
### Buildroot Notes
Add this:
https://github.com/cnlohr/buildroot/pull/1/commits/bc890f74354e7e2f2b1cf7715f6ef334ff6ed1b2
Use this:
https://github.com/cnlohr/buildroot/commit/e97714621bfae535d947817e98956b112eb80a75