A 32 bit RISC-V emulator made using a shader
Go to file
2022-11-25 23:09:11 +01:00
_Nix add Unity project 2021-08-17 09:52:24 +02:00
.github if you want ¯\_(ツ)_/¯ 2021-08-17 08:30:59 +00:00
bare_metal_test fixups and CSR memcpy test in bare_metal_test 2021-08-31 11:08:03 +02:00
buildroot-2022.02.1 update buildroot to 2022 2022-11-25 23:09:11 +01:00
elfy implement UART, CLINT, device tree, opensbi build 2021-06-03 22:45:13 +02:00
linux@f4e0f63196 update buildroot to 2022 2022-11-25 23:09:11 +01:00
mprv add micropython with riscv32 port 2021-08-17 09:49:37 +02:00
opensbi@7aa6c9aa96 update opensbi version and add optional performance patch 2021-08-17 09:43:14 +02:00
riscv32_beluga@85e04d1edb update buildroot to 2022 2022-11-25 23:09:11 +01:00
riscv-opcodes@7d1a0e3153 initial commit 2021-05-28 15:10:51 +02:00
riscv-rust@b4895fc56b support for all necessary CSRs, privilege modes, traps, atomics 2021-05-28 19:02:11 +02:00
riscv-tests@1b2c3ea84a implement UART, CLINT, device tree, opensbi build 2021-06-03 22:45:13 +02:00
rust_payload update rust_payload 2021-08-17 09:50:08 +02:00
rust_raytrace add rust_raytrace payload and image output 2021-10-14 20:14:51 +02:00
src add rust_raytrace payload and image output 2021-10-14 20:14:51 +02:00
tinypngout add rust_raytrace payload and image output 2021-10-14 20:14:51 +02:00
toimg add 'toimg' rust source, converts data to Unity textures 2021-08-17 09:45:29 +02:00
.gitignore add rust_raytrace payload and image output 2021-10-14 20:14:51 +02:00
.gitmodules update buildroot to 2022 2022-11-25 23:09:11 +01:00
buildroot-config update buildroot to 2022 2022-11-25 23:09:11 +01:00
dts.dts update device tree 2021-08-17 09:42:13 +02:00
instructions.txt initial commit 2021-05-28 15:10:51 +02:00
LICENSE Create LICENSE 2021-05-28 17:10:08 +00:00
linux-_pi_-patches-for-rvc.patch fixups and CSR memcpy test in bare_metal_test 2021-08-31 11:08:03 +02:00
linux.config add linux kernel, custom patches and update Makefile 2021-08-17 09:41:21 +02:00
Makefile add rust_raytrace payload and image output 2021-10-14 20:14:51 +02:00
opensbi-don-t-zero-BSS.patch update opensbi version and add optional performance patch 2021-08-17 09:43:14 +02:00
panic.jpg add image 2021-08-17 11:00:47 +02:00
parse_ins.pl initial commit 2021-05-28 15:10:51 +02:00
README.md add image 2021-08-17 11:00:47 +02:00
rust-target-rv32ima.patch update README for public release 2021-08-17 10:26:30 +02:00
test.sh fix riscv-tests and add flag for exit call 2021-08-17 09:36:49 +02:00

rvc - risc v in c / HLSL

An experimental 32-bit [0] RISC-V emulator written in plain C [1], with a focus on porting the result to a HLSL pixel shader.

The resulting HLSL (Unity CG) can be found in _Nix/, read on to learn more.

A version of this shader running in VRChat can be found in this world:
https://vrchat.com/home/world/wrld_8126d9ef-eba5-4d49-9867-9e3c4f0b290d

The C version was initially based on takahirox/riscv-rust (see for example instruction decoder generation using instructions.txt and parse_ins.pl), which is a great resource for learning about RISC-V in general, aside from the official specs of course.

Linux running in VRChat

[0] GPUs only really support 32-bit integer math (in the use-case I want to put this in anyway)
[1] The elf loader ('elfy') is written in Rust, because I was too lazy to do it myself in C (Rust uses the 'elf' crate) and it doesn't need porting anyway.

Cloning this repository

This repo makes heavy use of submodules, so make sure to use git clone --recursive on initial cloning (may take a long time) and run git submodule update --recursive after a new pull.

To build any of the code included, you will probably need the following:

  • A C compiler (gcc, clang)
  • A rust compiler
  • Perl 5
  • A device tree compiler (dtc)

C version specifics

Pay no mind to the somewhat weird style of C please, it is mostly because of the need to port to HLSL.

To build, remove the 'rvc' binary and 'src/main.o', then run 'make rvc' from the top level directory.

To run the riscv-tests, use test.sh. test.sh all --clean can be used to run the full supported test suite.

Shader specifics

The shader version is a direct port of the C one. It can be found as part of a Unity project in _Nix/.

This is not a drag-and-drop prefab by any means, it will require careful setup and integration into a world to be useful.

The biggest pitfall is probably the required Perl support. The shader code uses perlpp and a valid runtime environment (I recommend Strawberry Perl for Windows). See the file AutoImport.cs for more information, you will need to set a valid path in there. Technically, the already created *.h files can be used as-is, but you won't be able to meaningfully change any code without it.

The approach uses a Custom Render Texture and some (really messy) VRChat Udon scripts to manage the emulator during runtime. They will probably require fixing up for use in your own world.

The NixDebug.cs (Udon) script needs to be placed on a camera pointing at a camera loop reading in from the 'display' shader. This provides a translation layer between the 128bit-per-pixel integer texture used in the CRT and the Color(float, float, float, float) struct available in Unity/C#.

NixControl.cs is built with support for my Dial prefab in mind, but can be changed to support any other control input too of course.

Build instructions (for the various subprojects/payloads)

Toolchain/Initramfs

For both the target toolchain (riscv32-gnu-linux-) and the initramfs, buildroot is used - this is not a submodule, but an extracted and slightly modified version instead.

To build, run make buildroot-2021.05/build.marker in the top level directory. The toolchain will be made in buildroot-2021.05/output/host and the rootfs in buildroot-2021.05/output/images. This will take a long time.

Micropython

Enter the 'mprv' subdirectory. Run 'make'. Requires the toolchain to be built.

bare_metal_test

Enter the 'bare_metal_test' subdirectory. Run 'make'. Requires the toolchain to be built.

toimg

This tool is responsible for converting binary images (not ELF!) into texture files you can import into Unity, which can then be run by the shader version.

Enter the 'toimg' subdirectory. Run cargo build --release. Use ./target/release/toimg <binary> 2048 2048 to create an image file. The second '2048' specifies the height, which may be smaller than '2048'. On the first run, the program will display the optimal size to give for running a second time. This is not necessary, but will produce smaller images.

rust_payload

This is a test payload written in rust. It demonstrates the ability to run rust code natively on the emulator (both C and shader version). Build by running make rust_payload.bin in the top-level directory.

NOTE: This requires a custom rust toolchain, as the default one does not have a 'rv32ima' target, only 'rv32imac' which is not supported. A demonstrative patch for rustc can be found in rust-target-rv32ima.patch.

linux

To build the linux payload, run make linux_payload.bin in the top level directory. This requires the toolchain and initramfs to be built.

Why?

Because.

License

MIT. See LICENSE for more.