RISC-V source class riscv_asm_program_gen, the brain behind assembly instruction generator
By Shailesh Vasekar, VeriFast
Abstract
CHIPS Alliance has developed an open-source riscv-dv random instruction generator for RISC-V processor verification. This article focuses on the class riscv_asm_program_gen.sv and its various functions, which generate the complete RISC-V assembly program, which is then used to verify RISC-V IP. This class can also address any customization to RISC-V GPR or instruction.
Introduction
The open source https://github.com/chipsalliance/riscv-dv/tree/master defines the SV UVM-based class structure very helpful in the verification of RISC-V IP. The generated random test can be added directly to run with the design IP. The various sections of the ASM program, such as initialization routine, instruction section, data section, stack section, page table, interrupt and exception handling, etc., are generated with different functions in the riscv_asm_program_gen class itself.
First Thing First
First, the class riscv_instr_gen_config is randomized from the test riscv_instr_base_test.sv. This randomization decides the RISC-V extension we are running with, the privilege mode supported, the instruction count in the main and subprogram, whether the program must generate break instructions using variable no_ebreak, similarly no_dret, no_fence, no_wfi, and such configurations.
Many other such variables can be set to true or false based on DUT features and testbench stimulus generation requirements. The above snapshot lists very few of them.
Kick Start Function gen_program()
The function gen_program() is the main function to generate all sections of the program. Once it’s called from upper layer, it calls other function from the riscv_asm_program_gen one by one.
Then it calls function call get_directed_instr_stream(), selects the ratio of instruction generation from another function called add_directed_instr_stream().
riscv_asm_program_gen.sv(1552) @ 0: reporter [asm_gen] Adding directed instruction stream:riscv_jal_instr ratio: 30/1000
Next function call is to gen_program_header() and uses string array instr_stream to fill it up with header.
str[0] =.include “user_init.s” //example output
- The gen_program_header() function calls another function gen_section(“_start”, str); which inserts header instruction in the instr_stream.
- gen_program() then it calls init_gpr() function whose functionality to initialize general purpose registers with random value.
- Next generate_directed_instr_stream() functions get call which decides the ratio and insert directed instruction stream and randomizes the instruction as well. The function randomizes and selects which rs1, rs2 and rd to use based on instruction type. This will generate the asm program which has the instructions with various GPRs x0 to x31 used in all instructions the post_random() function of riscv_instr helps here.
- Then sequence riscv_instr_sequence which has function generate_instr_stream which has now all the stream of instruction available and uses convert2asm() function.
- There are also check for any illegal or HINT instructions ration is defined, if they are 0 then no illegal or HINT instruction is generated.
- From riscv_asm_program_gen main_program[hart].generate_instr_stream() is called which convert the instruction stream to the string format.
- There is any sub_program instruction to generate then function call to function insert_sub_program(sub_program[hart], instr_stream);
- Once the main and sub_program generation is done then host interface related instruction are added by gen_section function
str=write_tohost:
str= sw gp, tohost, t1
instr[0]=sw gp, tohost, t1
str=_exit:
- Then function push_gpr_to_kernel_stack() which pushes general purpose register to stack for trap handling. The riscv_asm_program uses gen_section() selects string for instruction str=mtvec_handler which has exception_hander and interrupt_handler defined.
Generated Program
The function gen_program() and group of functions defined in the same class together with riscv_ instruction_sequence and base test and other helper class generates full assembly language RISC-V program with random instructions, random GPR for each instruction with different patterns of instructions.
Summary of Generated Output
The `gen_program()` function and associated helpers work in concert with the `riscv_instruction_sequence`, base test classes, and various configuration helpers to produce a complete RISC-V assembly program. These programs feature randomized instructions and register selections suitable for robust IP verification.
Conclusion
The `riscv_asm_program_gen` class serves as a comprehensive utility to automate the generation of RISC-V assembly programs. Its modular function calls and rich configuration support make it a crucial component in the `riscv-dv` verification ecosystem.
Related Semiconductor IP
- 64 bit RISC-V Multicore Processor with 2048-bit VLEN and AMM
- RISC-V AI Acceleration Platform - Scalable, standards-aligned soft chiplet IP
- 32 bit RISC-V Multicore Processor with 256-bit VLEN and AMM
- All-In-One RISC-V NPU
- ISO26262 ASIL-B/D Compliant 32-bit RISC-V Core
Related White Papers
- IP vendors making leap from source code to silicon
- Commentary: Synopsys memory IP users seek RTL source code
- Successful Use of an Open Source Processor in a Commercial ASIC
- Open Source FlexRay Communication: Time Triggered OS and FlexRay Communication Middleware
Latest White Papers
- QiMeng: Fully Automated Hardware and Software Design for Processor Chip
- RISC-V source class riscv_asm_program_gen, the brain behind assembly instruction generator
- Concealable physical unclonable functions using vertical NAND flash memory
- Ramping Up Open-Source RISC-V Cores: Assessing the Energy Efficiency of Superscalar, Out-of-Order Execution
- Transition Fixes in 3nm Multi-Voltage SoC Design