# Lab2: RISC-V `RV32I[MA]` emulator with ELF support ## [rv32emu](https://github.com/sysprog21/rv32emu) * RISCV emulator for the RV32I architecture * based on [TinyEMU](https://bellard.org/tinyemu/) by Fabrice Bellard, check [Lab0: Web-based Emulators](https://hackmd.io/@sysprog/SJ7ht_MuS) * stripped down for RV32I only, all "gotos" removed, and fixed some bugs for the compliance test ## Sample Usage on Ubuntu Linux :::warning At present, we only verify on Ubuntu GNU/Linux. Please install Ubuntu Linux 20.04-LTS (or later) into your machine. It is fine with virtualization environments such as [VirtualBox](https://www.virtualbox.org/). ::: 1. Prepare GNU Toolchain for RISC-V. See [The xPack GNU RISC-V Embedded GCC](https://xpack.github.io/riscv-none-embed-gcc/) ```shell $ cd /tmp $ wget https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v8.2.0-3.1/xpack-riscv-none-embed-gcc-8.2.0-3.1-linux-x64.tgz $ tar zxvf xpack-riscv-none-embed-gcc-8.2.0-3.1-linux-x64.tgz $ cp -af xPacks/riscv-none-embed-gcc $HOME/ ``` 2. Configure `$PATH` ```shell $ cd $HOME/riscv-none-embed-gcc $ echo "export PATH=`pwd`/8.2.0-3.1/bin:$PATH" > setenv ``` Once step (1) and (2) are complete, you can simply update `$PATH` environment variable via: ```shell $ cd $HOME $ source riscv-none-embed-gcc/setenv ``` Check `$PATH` at the first time: ```shell $ riscv-none-embed-gcc -v ``` You shall be able to see the following messages: ``` gcc version 8.2.0 (xPack GNU RISC-V Embedded GCC, 64-bit) ``` 3. Fetch [rv32emu](https://github.com/sysprog21/rv32emu) and build from source ```shell $ git clone https://github.com/sysprog21/rv32emu $ cd rv32emu $ make ``` 4. Validate [rv32emu](https://github.com/sysprog21/rv32emu) ```shell $ make check ``` You shall see the following messages: ``` ./emu-rv32i test1 Hello RISC-V! >>> Execution time: 29144 ns >>> Instruction count: 62 (IPS=2127367) >>> Jumps: 14 (22.58%) - 0 forwards, 14 backwards >>> Branching T=13 (92.86%) F=1 (7.14%) ``` ## Using GNU Toolchain - [ ] [objdump](http://man7.org/linux/man-pages/man1/objdump.1.html) > `-d` : Display the assembler mnemonics for the machine instructions ```shell $ riscv-none-embed-objdump -d test1 ``` Expected output: ``` test1: file format elf32-littleriscv Disassembly of section .text: 00010054 <_start>: 10054: 000107b7 lui a5,0x10 10058: 07878793 addi a5,a5,120 # 10078 <_start+0x24> 1005c: 04800713 li a4,72 10060: 400026b7 lui a3,0x40002 10064: 00e68023 sb a4,0(a3) # 40002000 <__global_pointer$+0x3fff0778> 10068: 00178793 addi a5,a5,1 1006c: 0007c703 lbu a4,0(a5) 10070: fe071ae3 bnez a4,10064 <_start+0x10> 10074: 00008067 ret ``` - [ ] [readelf](http://man7.org/linux/man-pages/man1/readelf.1.html) > `-h` : Display the ELF file header ```shell $ riscv-none-embed-readelf -h test1 ``` Expected output: ``` ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: RISC-V Version: 0x1 Entry point address: 0x10054 Start of program headers: 52 (bytes into file) Start of section headers: 540 (bytes into file) Flags: 0x0 Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 1 Size of section headers: 40 (bytes) Number of section headers: 7 Section header string table index: 6 ``` - [ ] [size](http://man7.org/linux/man-pages/man1/size.1.html) > list the section sizes---and the total size---for each of the object or archive files objfile in its argument list. ```shell $ riscv-none-embed-size test1 ``` Expected output: ``` text data bss dec hex filename 52 0 0 52 34 test1 ``` ## Optional: Execute RTOS with RISC-V `RV32I[MA]` emulator * The [Zephyrâ„¢ Project](https://www.zephyrproject.org/) is a scalable real-time operating system (RTOS) supporting multiple hardware architectures, optimized for resource constrained devices, and built with safety and security in mind. * Zephyr Project is one of the [Linux Foundation Projects](https://www.linuxfoundation.org/projects/), but it is completely different from Linux kernel! You need newer versions of CMake, see [Kitware APT Repository](https://apt.kitware.com/) ```shell $ wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | sudo apt-key add - $ sudo apt-add-repository 'deb https://apt.kitware.com/ubuntu/ bionic main' $ sudo apt-get update $ sudo apt install cmake ``` :::info The above instructions are dedicated to Ubuntu Linux 18.04-LTS, and you might have to change for different versions. ::: Install device-tree-compiler (dtc): ```shell $ wget http://mirrors.kernel.org/ubuntu/pool/main/d/device-tree-compiler/device-tree-compiler_1.4.7-1_amd64.deb $ sudo dpkg -i device-tree-compiler_1.4.7-1_amd64.deb ``` Install ninja-build: ```shell $ sudo apt install ninja-build ``` Get Zephyr SDK and install ```shell $ cd /tmp $ wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.10.3/zephyr-sdk-0.10.3-setup.run $ sudo sh zephyr-sdk-0.10.3-setup.run ``` While the prompt `Enter target directory for SDK (default: /opt/zephyr-sdk/): ` appears, simply press enter. Then, configure after extracting. ```shell $ export ZEPHYR_TOOLCHAIN_VARIANT=zephyr $ export ZEPHYR_SDK_INSTALL_DIR="/opt/zephyr-sdk" ``` Build Zephyr RTOS from source ```shell $ cd $HOME/rv32emu $ git clone https://github.com/zephyrproject-rtos/zephyr $ cd zephyr $ pip3 install --user -r scripts/requirements.txt $ source zephyr-env.sh $ mkdir build-example $ cd build-example $ cmake -DBOARD=qemu_riscv32 ../samples/hello_world $ make ``` ## [Retro-V](https://gitlab.com/shaos/retro-v) * Retro-V is a SoftCPU in Verilog created by Shaos (completely from scratch) that implements RISC-V architecture RV32I (32-bit integer), but with 8-bit databus to resemble a retro 8-bit microprocessors suitable for building DIY computers around it * Retro-V is capable of passing RV32I compliance tests (now 98%), compatible with RTOS Zephyr.