Skip to content

Commit

Permalink
Add Reading a CSR in C
Browse files Browse the repository at this point in the history
  • Loading branch information
Dolu1990 committed Jan 7, 2025
1 parent 5f51859 commit 6c6a1e5
Showing 1 changed file with 66 additions and 0 deletions.
66 changes: 66 additions & 0 deletions source/VexiiRiscv/Tutorial/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -683,3 +683,69 @@ This should now print 10 times "hello world" on your terminal
[info] hello world
[info] hello world
Reading a CSR
----------------

In the CPU, there is the mcycle CSR which is a hardware counter which increment every clock cycles.
Let's say we want to print its value 10 times.

Reading a CSR (Control Status Register) in assembly is straight forward (ex : csrr x1, mstatus). But to do that in C, you need to wrap it a bit.


.. code-block:: c
#include <sim.h>
void main(){
for(int i=0;i<10;i++) {
int value;
asm volatile ("csrr %0, mcycle": "=r" (value));
sim_puthex(value);
sim_putchar('\n');
}
}
Here are a few explenations :

- **asm** : To start specifying some assembly inside some C code
- **volatile** : To ensure GCC do not optimize away the given assembly code (not realy necessary in our case)
- **"csrr %0, mcycle"** : Read the mcycle CSR and write its value into %0, %0 refering to the value variable
- **"=r" (value)** : Define a write only output operand binded to the C "value" variable

I will not go more into the details of the GCC asm("") syntax, as i'm not good at it and it is quite complicated.

Hopefully, there is the riscv.h header you can include, which wrap all of those asm("") commands into easy to use macros :

.. code-block:: c
#include <sim.h>
#include <riscv.h>
void main(){
for(int i=0;i<10;i++) {
sim_puthex(csr_read(mcycle));
sim_putchar('\n');
}
}
Then, running it via :

sbt "Test/runMain vexiiriscv.tester.TestBench --with-rvm --allow-bypass-from=0 --load-elf helloworld/build/helloworld.elf --trace-all --no-probe --debug-privileged --no-rvls-check --performance-counters=0"

Will print the following in the terminal

.. code-block::
[info] [Progress] Start VexiiRiscv test simulation with seed 2
[info] 00000094
[info] 000000a6
[info] 000000b8
[info] 000000ca
[info] 000000dc
[info] 000000ee
[info] 00000100
[info] 00000112
[info] 00000124
[info] 00000136
Note, we added the --performance-counters=0 VexiiRiscv argument, as the mcycle isn't implemented otherwise.
The RISC-V architecture specifies various 64 bits counters which aren't cheap in FPGA, so VexiiRiscv do not implement them by default.

0 comments on commit 6c6a1e5

Please sign in to comment.