# Minimal RISC-V core to boot Linux
> 吳哲郁
## Starting point
The codebase is derinved from [microxblue/rv32_linux](https://github.com/microxblue/rv32_linux).
## Environment Setup
### RISC-V GNU Toolchain
You could setup RISCV GNU toolchain by following the instruction in the [GitHub repository](https://github.com/riscv-collab/riscv-gnu-toolchain) or as the following.
1. Get the sources
```
$ git clone https://github.com/riscv/riscv-gnu-toolchain
```
2. Change to the cloned directory
```
$ cd riscv-bnu-toolchain
```
3. Configure the installed path, `march` and `mabi`
```
$ ./configure --prefix=/opt/riscv --with-arch=rv32ima_zicsr --with-abi=ilp32
```
4. Install the toolchain
```
$ make
```
5. Add toolchain path to PATH
```
$ echo `export PATH="/opt/riscv/bin:$PATH"` >> ~/.bashrc
$ source ~/.bashrc
```
### [Verilator](https://github.com/verilator/verilator)
> Verilator is a software programming tool which converts the hardware description language Verilog to a cycle-accurate behavioral model in the programming languages C++ or SystemC.
Verilator is an open source projects. With it, we can run RTL simulation for this project without needing to use a paid EDA tool.
To install Verilator, please follow the instructions on [the official website](https://verilator.org/guide/latest/install.html).
## Run Emulation
To boot linux on the emulator, please run the following commands:
1. Change to to project directory
```
$ cd rv32_linux
```
2. Run emulation
```
$ make emurun
```
If the emulation is successfully run, you will see the following boot log on the terminal
```
[ 0.000000] Linux version 6.10.0mini-rv32ima-00001-g9568811284f3-dirty (test@ubuntu) (riscv32-buildroot-linux-uclibc-gcc.br_real (Buildroot -g851edd24) 13.2.0, GNU ld (GNU Binutils) 2.40) #13 Sun Dec 15 11:06:43 PST 2024
[ 0.000000] Machine model: riscv-minimal-nommu,qemu
[ 0.000000] earlycon: uart8250 at MMIO32 0xffff0400 (options '1000000')
[ 0.000000] printk: legacy bootconsole [uart8250] enabled
[ 0.000000] Zone ranges:
[ 0.000000] Normal [mem 0x0000000080000000-0x0000000080fbffff]
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x0000000080000000-0x0000000080fbffff]
[ 0.000000] Initmem setup node 0 [mem 0x0000000080000000-0x0000000080fbffff]
[ 0.000000] riscv: base ISA extensions
[ 0.000000] riscv: ELF capabilities
[ 0.000000] Kernel command line: earlycon=uart8250,mmio32,0xffff0400,1000000 console=ttyS0
[ 0.000000] Dentry cache hash table entries: 2048 (order: 1, 8192 bytes, linear)
[ 0.000000] Inode-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 0.000000] Built 1 zonelists, mobility grouping off. Total pages: 4032
[ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[ 0.000000] Memory: 13440K/16128K available (1312K kernel code, 276K rwdata, 143K rodata, 673K init, 92K bss, 2688K reserved, 0K cma-reserved)
[ 0.000000] SLUB: HWalign=64, Order=0-1, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[ 0.000000] riscv-intc: 32 local interrupts mapped
[ 0.000000] clint: clint@11000000: timer running at 1000000 Hz
[ 0.000000] clocksource: clint_clocksource: mask: 0xffffffffffffffff max_cycles: 0x1d854df40, max_idle_ns: 3526361616960 ns
[ 0.000009] sched_clock: 64 bits at 1000kHz, resolution 1000ns, wraps every 2199023255500ns
[ 0.002063] Console: colour dummy device 80x25
[ 0.002589] Calibrating delay loop (skipped), value calculated using timer frequency.. 2.00 BogoMIPS (lpj=10000)
[ 0.003268] pid_max: default: 32768 minimum: 301
[ 0.004069] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 0.004621] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 0.016078] devtmpfs: initialized
[ 0.024529] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[ 0.025213] futex hash table entries: 256 (order: -1, 3072 bytes, linear)
[ 0.038745] clocksource: Switched to clocksource clint_clocksource
[ 0.109065] workingset: timestamp_bits=30 max_order=12 bucket_order=0
[ 0.336988] Serial: 8250/16550 driver, 1 ports, IRQ sharing disabled
[ 0.350913] of_serial ffff0400.uart: error -ENXIO: IRQ index 0 not found
[ 0.352841] printk: legacy console [ttyS0] disabled
[ 0.355949] ffff0400.uart: ttyS0 at MMIO 0xffff0400 (irq = 0, base_baud = 62500) is a 16550
[ 0.356768] printk: legacy console [ttyS0] enabled
[ 0.356768] printk: legacy console [ttyS0] enabled
[ 0.357477] printk: legacy bootconsole [uart8250] disabled
[ 0.357477] printk: legacy bootconsole [uart8250] disabled
[ 0.387672] clk: Disabling unused clocks
[ 0.394137] Freeing unused kernel image (initmem) memory: 668K
[ 0.394639] This architecture does not have kernel memory protection.
[ 0.395180] Run /init as init process
Welcome to mini-rv32ima Linux
Jan 1 00:00:00 login[21]: root login on 'console'
~ #
```
## Run RTL Simulation
To boot linux on the RTL simulation, please run the following commands:
1. Change to the project directory
```
$ cd rv32_linux
```
2. Build simulation firmware
```
$ make simfw
```
3. Change to simulation directory
```
$ cd Rv32Sim
```
4. Run the Verilator compilation process
```
$ make bld
```
5. Change to the project directory and run the simulation
```
$ cd ..
$ make simrun
```
## Reference
- [Verilator](https://en.wikipedia.org/wiki/Verilator)