4. Simulating the Core¶
The Chromite repository also contains a simple test-soc for the purpose of simulating applications and verifying the core.
To create a verilated executable follow the steps in Section 3 and then run the following command:
$ make link_verilator_elf
This will generate a bin
folder containing the verilated chromite_core
executable. This can be used
for simulation as described in Section 4.
Please note that the bram-based memory in the test-bench can only hold upto 32MB of code. Thus the elf2hex arguments will need to applied accordingly.
Note
The elf2hex program is available from the modified spike application.
Note
The size of the BRAM Memory can be changed by changing the configuration bsc_compile_options.test_memory_size in the configuration YAML.
4.1. BootRom Content¶
By default, on system-reset the core will always jump to 0x1000
which is mapped to the bootrom.
The bootrom is initialized using the file boot.mem
. The bootrom after a few instructions
causes a re-direction jump to address 0x80000000
where the application program is expected to be.
It is thus required that all programs are linked with text-section begining at 0x80000000
.
The rest of the boot-rom holds a dummy device-tree-string information.
To boot.mem
file is generated in the bin
folder using the following command:
$ make generate_boot_files
Tip
You can skip executing the bootrom by changing the reset_pc field in the configuration
YAML. However, the verilated executable will still require a dummy boot.mem
file to initiate
simulation
4.1.1. Verilated Executable¶
We use verilator to simulate the core and the test-soc described above. In order to generate the verilated executable do the following (you can skip this is you have already followed the steps so far)
$ cd chromite
$ python -m configure.main -ispec sample_config/default.yaml
$ make -j<jobs> generate_verilog
$ make link_verilator_elf generate_boot_files
The above should result in following files in the bin
folder:
chromite_core
boot.mem
4.1.2. Executing User Programs¶
Let’s assume the software program that you would like to simulate on the core is called
prog.elf
(compiled using standard riscv-gcc).
In order to run this elf on the chromite verilated executable you can do the following:
$ ./chromite_core +elf=<path to prog.elf>
Note
Since the boot code in the bootrom implicitly jumps to 0x80000000
the programs
should also be compiled at 0x80000000
.
4.2. Hello World¶
To run hello-world first ensure the verilated executable is available in the bin folder (use steps mentionedin in Section 4.1.1. After which run the following:
$ make hello
Hello World
4.3. Dhrystone¶
To run dhrystone first ensure the verilated executable is available in the bin folder (use steps mentionedin in Section 4.1.1. After which run the following:
$ make dhrystone ITERATIONS=10000
Microseconds for one run through Dhrystone: 10.0
Dhrystones per Second: 98448.0
Note
The above numbers are obtained by using the samples/rv64imacsu/* config files which have been configured for high performance. The performance numbers will change based on the config used to generate the core instance.
4.4. CoreMarks¶
To run coremarks first ensure the verilated executable is available in the bin folder (use steps mentionedin in Section 4.1.1. After which run the following:
$ make coremarks ITERATIONS=35
2K performance run parameters for coremark.
CoreMark Size : 666
Total ticks : 12323206
Total time (secs): 12
Iterations/Sec : 2
Iterations : 35
Compiler version : riscv64-unknown-elf-9.2.0
Compiler flags : -mcmodel=medany -DCUSTOM -DPERFORMANCE_RUN=1 -DMAIN_HAS_NOARGC=1 \
-DHAS_STDIO -DHAS_PRINTF -DHAS_TIME_H -DUSE_CLOCK -DHAS_FLOAT=0 \
-DITERATIONS=35 -O3 -fno-common -funroll-loops -finline-functions \
-fselective-scheduling -falign-functions=16 -falign-jumps=4 \
-falign-loops=4 -finline-limit=1000 -nostartfiles -nostdlib \
-ffast-math -fno-builtin-printf -march=rv64imafdc -mexplicit-relocs
Memory location : STACK
seedcrc : 0xe9f5
[0]crclist : 0xe714
[0]crcmatrix : 0x1fd7
[0]crcstate : 0x8e3a
[0]crcfinal : 0xcf56
Correct operation validated. See README.md for run and reporting rules.
Note
The above numbers are obtained by using the samples/default.yaml config file which has been configured for high performance. The performance numbers will change based on the config used to generate the core instance.
4.4.1. Notes on Simulation¶
4.5. Support for PutChar¶
The test-soc for simulation contains a simple uart. The putchar
function for the same is available
HERE.
This has to be used in the printf functions. The output of the putchar
is captured in a separate
file app_log during simulation.
4.6. Simulation Arguments (plusargs)¶
./chromite_core +elf=<elf-path> +rtldump
: if the core has been configured withtrace_dump: true
, then artl.dump
file is created which shows the log of instruction execution. Each line in the file has the following format:<privilege-mode> <program-counter> <instruction> <register-updated> <register value>
To enable printing of debug statements from the bluespec code, one can pass custom logger arguments to the simulation binary as follows
./chromite_core +elf=<elf-path> +fullverbose
: prints all the logger statements across all modules and all levels of verbosity./chromite_core +elf=<elf-path> +mstage1 +l0
: prints all the logger statements within module stage1 which are at verbosity level 0../chromite_core +elf=<elf-path> +mstage2 +mstage4 +l0 +l3
: prints all the logger statements within modules stage2 and stage4 which are at verbosity levels 0 and 3 only.
To print the cycle difference between 2 consecutive instruction commits you can use
+instr_latency along with rtldump to appen this in the rtl.dump file itself.
To exit the simulation when a self-loop is encountered use +halt_selfloop with the compiled binary
An
app_log
file is also created which captures the output of the uart, typically used in theputchar
function in C/C++ codes as mentioned above.
4.7. Connect to GDB in Simulation¶
A debugger implementation following the riscv-debug-draft-014 has been integrated with the core.
This can be instantiated in the design by configuring with: debugger_support: true
Perform the following steps to connect to the core executable with a gdb terminal. This assumes you have installed openocd and is available as part of you $PATH variable.
Modify the sample_config/default.yaml
to enable: debugger_support and open_ocd.
Generate a new executable with this config to support jtag remote-bitbang in the
test-bench
$ python -m configure.main -ispec sample_config/default.yaml
$ make gdb # generate executable with open-ocd vpi enabled in the test-bench
Simulate the RTL In a new terminal do the following:
$ cd chromite/bin/ $ ./chromite_core +elf=<elf-path> > /dev/null
Connect to OpenOCD Open a new terminal and type the following:
$ cd chromite/test_soc/gdb_setup/ $ openocd -f shakti_ocd.cfg
Connect to GDB Open yet another terminal and type the following:
$ cd chromite/test_soc/gdb_setup $ riscv64-unknown-elf-gdb -x gdb.script
In this window you can now perform gdb commands like : set $pc, i r, etc
To reset the SoC via the debugger you can execute the following within the gdb shell:
$ monitor reset halt
$ monitor gdb_sync
$ stepi
$ i r
Note
The above will not reset memories like the BRAM Memory.