Bare Metal RISC-V Angel Simulator

This week, I finally get the RISC-V Angel Simulator to run the C/C++ code compiled from the default RISC-V GNU compiler, which is specifically designed to compile files into ELF file that to be used with the RISC-V Spike and Proxy Kernel. I had verified that the bootloader extracted from proxy kernel is usable.

How Software Works

I really need to thank my supervisor in figuring that my problem during the findings for the solution of the necessity of proxy kernel. Yes, I do not understand how software works initially. As described in the link here, I finally understand why the RISC-V Angel code is actually storing the ELF file instruction and values into a JavaScript array. It is because it is allocating memory for the ELF file program, which is the RAM of the processor itself. Realizing that the bootloader is inserted correctly based on the result of it initialized, the memory allocation is done correctly in the elfload.js. I checked all the JavaScript memory arrays to ensure that the ELF file addresses and instructions are inserted correctly in the right array. And there are only 2 possibility left that could have gone wrong, the execution environment and the Instruction Set Architecture (ISA).

The RISC-V Angel Bug

Since the problem had persisted, I try to decode the instruction line by line, checking for register values and results. Initially, I noticed that there were 2 weird circumstances when tested with the printf() and iostream  library, which are the wrong value passed into the return address (ra) register causes the address to be loaded wrongly, and the redefinition of the memory arrays (RAM) which overwrites the default instruction value. After discussed with my supervisor, he urged me to decode the instruction line by line. As I proceed with it, I found that all the programs that worked properly without the printf() and iostream library, stores the memory in other addresses, which does not overwrite the instruction in the addresses that had been pre-allocated for the ELF file.

Thus, I saved the output log of the whole instructions that had been run for, and I trace the instruction one by one, I found that the AUIPC instruction might not be doing the right thing as stated in the ISA documentation. To prove that my thought would be correct, I compared the instructions from the log with the log I got from the Spike and proxy kernel. Using the command reg 0 gp from the RISC-V Spike, the instruction of AUIPC is found to be written wrongly. It should have been 0xFFFFFFFF instead of a 0xFFFFF000 in the extraction to Program Counter (PC). Since I am trying to run it in bare metal without showing anything, I changed the SCALL ISA as well, so that it will just operate as a NOP instruction. And everything works fine after these 2 modifications, which solved the issue of undefined error 0 previously. This also proven that the RISC-V Angel can actually run ELF file created, in bare metal mode, without system calls features in it.

A Simple Usage of GDB on other files

From my previous post, I mentioned that GDB is useful when debugging files, such as it could have the Step In, breakpoint and etc features. But the problem that I faced was gathering GDB information on other source file instead of the main source file. So what I did was, to compile the main source file into object file with the -c flag during compilation. And compile the file that I wanted with the -g flag. For example, riscv32-unknown-elf-g++ test.c main.o -g -o test -m32 This could gather the GDB information on the test.c source file instead of the main.c source file, which I found to be useful when debugging other source file.

Leave a Reply

Your email address will not be published. Required fields are marked *