This program was developed for my 2024 Capstone project. The goal behind the development of a CPU emulator was to learn more about computer architecture methodologies including instruction encoding, decoding, execution, and memory management. RISC-V was chosen as the architecture of study due to its open-source design and rise in popularity in modern chip design.
The scope of this project focuses on the implementation of all RV32i instructions.
- The foundation of my program came from a developer project repo of a 64i implementation (along with many additional extensions). My project modified this code to conform to the RV32I Base Integer Instruction Set, Version 2.0 documentation.
Tutorial Page Written By the Author
- Additional tools and references used to understand and develop a RISC-V system.
Reference Card For 32i Instructions
RISC-V 32i Instruction Breakdown
Series of Lectures Breaking Down the ISA
Great Slideshow From Berkeley About the Different Instruction Formats
RISC-V Toolchain GCC Options (-mabi, -march)
Link Options (-Wl & -nostdlib)
- Extra links to forums that helped me better understand how to use the RISC-V toolchain, write assembly, and configure my tools.
Using LUI and ADDI to Load 32-bit Constants
Demonstration of Using objdump tool and more
A Manual For RISC-V ASM Programming
Stopping Toolchain From Building Compressed (16-bit) Instructions
GitHub Issue Discussing New Standards 32i ISA
To build and run the emulator, clone the repo and do the following:
make
./main <binary.bin> [-d]-d Dump the contents of all 32 32-bit registers after each executed instruction.
Single instruction binary.bin files live in ./isa_tests/single/bin/
Cross compiled C Program binaries live in ./isa_tests/cprog/bin/
To run the Python scripts that build the binaries, object files, and assembly (only for c programs), you'll need access to the riscv-gnu-toolchain cross-compiler.
If you choose to compile the tools yourself, follow the toolchain's instructions and run the following:
./configure --prefix=/opt/riscv --with-arch=rv32g --with-abi=ilp32d
makeTotal build time took me around 2 hours using an OrbStack Ubuntu VM.
You can download a prebuilt 32i version of the toolchain here. Be sure to untar it in /opt/riscv/ and run export PATH=$PATH:/opt/riscv/bin/ to add the tools to your path.
- However, this set of tools cannot produce working binaries from C programs due to how newlib functions. If you wish to compile them anyway, be sure to remove the -nostdlib option in the build_cprog.py script.
Testing was primarily done through self-verification using a RISC-V Interpreter developed by Cornell University.
I originally wanted to use the riscv-tests repository but faced issues with the configuration of the toolchain. For future developments, I'll adjust my program and tools to take advantage of the test suite.
Future developments of this project will seek to implement the Zicsr Standard Extension so that I can use the riscv-tests repo to perform more official testing and, additionally, add support to all of the classical extensions: M, A, F, D, and C.