RISC-V ISA Simulator ====================== Author : Andrew Waterman, Yunsup Lee Date : June 19, 2011 Version : (under version control) About ------------- The RISC-V ISA Simulator implements a functional model of one or more RISC-V processors. Build Steps --------------- We assume that the RISCV environment variable is set to the RISC-V tools install path, and that the riscv-fesvr package is installed there. $ apt-get install device-tree-compiler $ mkdir build $ cd build $ ../configure --prefix=$RISCV --with-fesvr=$RISCV $ make $ [sudo] make install Compiling and Running a Simple C Program ------------------------------------------- Install spike (see Build Steps), riscv-gnu-toolchain, and riscv-pk. Write a short C program and name it hello.c. Then, compile it into a RISC-V ELF binary named hello: $ riscv64-unknown-elf-gcc -o hello hello.c Now you can simulate the program atop the proxy kernel: $ spike pk hello Simulating a New Instruction ------------------------------------ Adding an instruction to the simulator requires two steps: 1. Describe the instruction's functional behavior in the file riscv/insns/.h. Examine other instructions in that directory as a starting point. 2. Add the opcode and opcode mask to riscv/opcodes.h. Alternatively, add it to the riscv-opcodes package, and it will do so for you: $ cd ../riscv-opcodes $ vi opcodes // add a line for the new instruction $ make install 3. Rebuild the simulator. Interactive Debug Mode --------------------------- To invoke interactive debug mode, launch spike with -d: $ spike -d pk hello To see the contents of an integer register (0 is for core 0): : reg 0 a0 To see the contents of a floating point register: : fregs 0 ft0 or: : fregd 0 ft0 depending upon whether you wish to print the register as single- or double-precision. To see the contents of a memory location (physical address in hex): : mem 2020 To see the contents of memory with a virtual address (0 for core 0): : mem 0 2020 You can advance by one instruction by pressing . You can also execute until a desired equality is reached: : until pc 0 2020 (stop when pc=2020) : until mem 2020 50a9907311096993 (stop when mem[2020]=50a9907311096993) Alternatively, you can execute as long as an equality is true: : while mem 2020 50a9907311096993 You can continue execution indefinitely by: : r At any point during execution (even without -d), you can enter the interactive debug mode with `-`. To end the simulation from the debug prompt, press `-` or: : q Debugging With Gdb ------------------ An alternative to interactive debug mode is to attach using gdb. Because spike tries to be like real hardware, you also need OpenOCD to do that. OpenOCD doesn't currently know about address translation, so it's not possible to easily debug programs that are run under `pk`. We'll use the following test program: ``` $ cat rot13.c char text[] = "Vafgehpgvba frgf jnag gb or serr!"; // Don't use the stack, because sp isn't set up. volatile int wait = 1; int main() { while (wait) ; // Doesn't actually go on the stack, because there are lots of GPRs. int i = 0; while (text[i]) { char lower = text[i] | 32; if (lower >= 'a' && lower <= 'm') text[i] += 13; else if (lower > 'm' && lower <= 'z') text[i] -= 13; i++; } while (!wait) ; } $ cat spike.lds OUTPUT_ARCH( "riscv" ) SECTIONS { . = 0x10010000; .text : { *(.text) } .data : { *(.data) } } $ riscv64-unknown-elf-gcc -g -Og -o rot13-64.o -c rot13.c $ riscv64-unknown-elf-gcc -g -Og -T spike.lds -nostartfiles -o rot13-64 rot13-64.o ``` To debug this program, first run spike telling it to listen for OpenOCD: ``` $ spike --rbb-port=9824 -m0x10000000:0x20000 rot13-64 Listening for remote bitbang connection on port 9824. ``` In a separate shell run OpenOCD with the appropriate configuration file: ``` $ cat spike.cfg interface remote_bitbang remote_bitbang_host localhost remote_bitbang_port 9824 set _CHIPNAME riscv jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10e31913 set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME riscv -chain-position $_TARGETNAME gdb_report_data_abort enable init halt $ openocd -f spike.cfg Open On-Chip Debugger 0.10.0-dev-00002-gc3b344d (2017-06-08-12:14) ... riscv.cpu: target state: halted ``` In yet another shell, start your gdb debug session: ``` tnewsome@compy-vm:~/SiFive/spike-test$ riscv64-unknown-elf-gdb rot13-64 GNU gdb (GDB) 7.12.50.20170505-git Copyright (C) 2016 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=x86_64-pc-linux-gnu --target=riscv64-unknown-elf". Type "show configuration" for configuration details. For bug reporting instructions, please see: . Find the GDB manual and other documentation resources online at: . For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from rot13-64...done. (gdb) target remote localhost:3333 Remote debugging using localhost:3333 0x000000001001000a in main () at rot13.c:8 8 while (wait) (gdb) print wait $1 = 1 (gdb) print wait=0 $2 = 0 (gdb) print text $3 = "Vafgehpgvba frgf jnag gb or serr!" (gdb) b 23 Breakpoint 1 at 0x10010064: file rot13.c, line 23. (gdb) c Continuing. Breakpoint 1, main () at rot13.c:23 23 while (!wait) (gdb) print wait $4 = 0 (gdb) print text ... ```