rv32gen is a basic "put together in a weekend" Risc-V 32bits Pseudo Random Instruction Generator.
rv32gen can be used to generate Risc-V test cases which can be used to find bugs in a Risc-V design and/or to execute code and functional coverage on simulators.
There are a few of these generators available on the web but they either use overly complicated UVM/SV frameworks or they don't constrain the branch/memory accesses.
The rv32gen program is very basic and consist of a single C and header file. I did not add a lot of options as it is easier to just hack the code to your requirements.
The program was developed to allow me to run code and functional coverage on my Risc-v design but interestingly it found a new bug even though it passes the Risc-v IMC compliance test and a bunch of compiled C tests.
What rv32gen generated was:
DIVU zero,s0,s1
this failed on my design in a spectacular way in that it managed to write to x0. It is unlikely this instruction will be in any of my embedded code but this might not always be the case.
The program generate pseudo random instructions including load/store and jumps. The load/store instructions are constrained to +/-2047 locations around a base address which can be specified on the command line (-sb). The jump/branch instructions are constrained to jump to a location a few instructions later or earlier in the test program.
- gcc compiler
gcc rv32gen.c -o rv32gen.exe
rv32gen -help
*** RV32GEN Ver 0.2 (c)2022 HT-LAB ***
Usage : genriscv <options> <output_filename>
Options:
-q : Quiet, must be specified first in the options list
-s <integer> : Set randomize seed, default seed=time()
-march <string> : Generate instructions for architecture, default to "IMC"
-ebreak : include ebreak opcodes, default excluded
-ecall : include ecall opcodes, default excluded
-ic <hex> : Instruction Count, default to 512 (2KByte)
-sb <hex> : Set load/store Base address, default to 0x1000
This will disable all output messages and is useful if rv32gen is used in a regression environment.
The default seed uses the current time(), if you want to have repeatable results then you can set the seed to a constant value using the -s option. Note that if you use the program in a regression environment without specifying the seed then the time between calling rv32gen must be larger than 1 seconds otherwise you will end up with the same testcase. The used seed is printed in the output source file.
# RV32GEN, ver 0,2
# march=imc
# ebreak is Excluded
# ecall is Excluded
# Seed used 1666167107
main: SUB t1,s2,zero # Start Pseudo Random Instruction Test
Not yet used but you can use it to generate just 32I (-march I) instructions, mul/div instructions 32M (-march M) or the default 32IM (-march IM).
For compressed "RVC" test cases simply assemble the generated code with:
<your riscv setup>-gcc -c -Os -mabi=ilp32 -march=rv32imc -ffreestanding -nostdlib ran0.S
gcc -march=rv32im | gcc -march=rv32imc |
---|---|
01a8a5b3 slt a1,a7,s10 |
01a8a5b3 slt a1,a7,s10 |
00001337 lui t1,0x1 |
----6305 lui t1,0x1 |
593c0c37 lui s8,0x593c0 |
593c0c37 lui s8,0x593c0 |
78831a03 lh s4,1928(t1) |
78831a03 lh s4,1928(t1) |
000016b7 lui a3,0x1 |
----6685 lui a3,0x1 |
0028bb33 sltu s6,a7,sp |
0028bb33 sltu s6,a7,sp |
ebc69523 sh t3,-342(a3) |
ebc69523 sh t3,-342(a3) |
6e793713 sltiu a4,s2,1767 |
6e793713 sltiu a4,s2,1767 |
00c0006f j 82e0 |
----a021 j 82a2 |
If you never want compressed code you can include the generated file in a wrapper with the ".option norvc" option.
.option norvc
.include ran0.S
By default ebreak\ecall (and efence) are not included in the generated code. If you specify -ebreak and/or -ecall then they will be included. Note the generated code always ends with an ebreak instruction.
Number of instruction to generate, defaults to 512 (2Kbyte).
Set the base address for load/store instructions. The generated load/store sequence first load the base address into a random register. It then issues a load/store with a random offset from -2027 to +2047.
rv32gen ran0.S -ic 0x1ff0 -s 1
# RV32GEN, ver 0.2
# march=imc
# ebreak is Excluded
# ecall is Excluded
# Seed used 1666167107
main: SUB t1,s2,zero # Start Pseudo Random Instruction Test
ORI s1,t0, 626
BGE s7,t1,jf0 # Test jump forwards
SLTI a2,ra,-1040
jf0: MUL s4,t4,a4
ORI a3,s6,-238
SLTIU s7,s9,-390
LUI t4,4096>>12 # Load/Store base address
SLL s7,s6,s3
LW t2,680(t4)
SLTIU s10,s6,-1116
SLTU s10,t4,t4
SRAI s9,s5,12
SLL a6,a0,t3
OR s0,gp,gp
SRLI s4,tp,28
LUI t5,4096>>12 # Load/Store base address
OR tp,t5,a2
LH ra,1362(t5)
LUI a2,4096>>12 # Load/Store base address
SLTI a4,s4,-2026
SH s6,-1034(a2)
AND s10,a7,a4
XORI t6,t1,-561
J jf1
jb1: LUI s11,0x18bc0
J js1
jf1: ADDI t5,s9,-924
BNE s11,a5,jb1 # Test jump backwards
js1: ORI t1,a0, 1874
LUI ra,4096>>12 # Load/Store base address
ADD a5,t5,t1
SB gp,-1481(ra)
SLTU s2,a6,t4
BEQ t5,a0,jf2 # Test jump forwards
MULHSU t6,a0,t6
...
...
jb679: MULHU s0,t3,ra
J js679
jf679: SLL s3,t0,s6
BLT a5,tp,jb679 # Test jump backwards
js679: MUL a2,a3,s11
ebreak # End of Test