Skip to content
STIMSMITH

RISC-V Assembly Program Generation

Concept WIKI v2 · 5/27/2026

RISC-V assembly program generation in RISCV-DV produces bare-metal RISC-V assembly programs, or in some modes executable memory-loadable dumps, for RISC-V processor and model verification. The flow is configurable through randomized generator configuration and command-line parameters, constructs main and optional sub-program instruction streams, inserts directed streams for sequenced scenarios, emits program sections such as initialization, data, stack, page-table, and trap-handling code, and converts randomized instruction streams into assembly text.

Overview

RISC-V assembly program generation, as described for RISCV-DV, is the process of producing a complete bare-metal RISC-V assembly language test program for processor verification. The generated program can be compiled and executed on a RISC-V processor core or model. RISCV-DV can also generate an executable dump that may be loaded directly into memory for simulation or emulation; in the SystemVerilog version, this dump is represented as ASCII text because SystemVerilog does not provide native binary-data processing support. [1]

In the RISCV-DV implementation, the riscv_asm_program_gen.sv class is the central SystemVerilog/UVM component responsible for generating the full assembly program. The generated ASM program includes sections such as initialization, instruction, data, stack, page table, interrupt handling, and exception handling, with those sections produced by functions in riscv_asm_program_gen. [2]

Configuration and customization

Generation is parameterized before the assembly program is emitted. The riscv_instr_gen_config class is randomized from riscv_instr_base_test.sv; this configuration determines items such as the RISC-V extension being used, supported privilege mode, instruction counts in the main program and sub-programs, and whether specific instruction classes are suppressed through controls such as no_ebreak, no_dret, no_fence, and no_wfi. [2]

RISCV-DV is also customizable through command-line options. Examples include the requested number of sub-programs and ratios of instruction-stream categories. In the simplest mode, the generator can emit millions of disparate random instructions into a single main function. When a sub-program count is provided, it randomly divides the requested total instruction count across sub-programs and stitches the resulting call stack using suitable function-call control flow. [1]

gen_program() flow

The gen_program() function is the main entry point for generating all sections of the program. After being called from an upper layer, it invokes other riscv_asm_program_gen functions in sequence. The documented flow includes:

  1. Selecting directed instruction streams by calling get_directed_instr_stream() and applying ratios through add_directed_instr_stream().
  2. Calling gen_program_header() to populate the instr_stream string array with program-header content, such as an include of user_init.s.
  3. Using gen_section("_start", str) to insert header/start instructions into the instruction stream.
  4. Calling init_gpr() to initialize general-purpose registers with random values.
  5. Calling generate_directed_instr_stream() to choose stream ratios, insert directed streams, and randomize instruction operands such as rs1, rs2, and rd according to instruction type.
  6. Using riscv_instr_sequence.generate_instr_stream() and convert2asm() to convert available instruction streams into assembly form.
  7. Checking illegal-instruction and HINT-instruction ratios; if those ratios are zero, those instruction categories are not generated.
  8. Calling main_program[hart].generate_instr_stream() to convert the main instruction stream into string format.
  9. Calling insert_sub_program(sub_program[hart], instr_stream) when sub-program instructions are generated.
  10. Adding host-interface related instructions through gen_section, including a write_tohost section with sw gp, tohost, t1 and an _exit label.
  11. Calling push_gpr_to_kernel_stack() to push general-purpose registers to the stack for trap handling, and using an mtvec_handler section containing exception-handler and interrupt-handler definitions. [2] [3]

Together with riscv_instruction_sequence, base-test classes, and helper configuration classes, gen_program() produces a complete RISC-V assembly program with randomized instructions, randomized GPR usage, and different instruction patterns for verification stimulus. [3]

Directed streams and sequencing

Not all instructions are useful or safe when generated in isolation. For example, an unconstrained jalr can jump near program exit and skip most executable test code, enter an infinite loop, or jump outside the generated program scope. To handle such cases, RISCV-DV groups execution use cases into directed streams, including loop sequences, load/store hazards, and numeric computation exceptions. Instructions in a directed stream are constrained together so that they form a meaningful execution scenario. [1]

The directed streams are generated, randomized, and inserted randomly into an initial dump of non-directed randomized instructions. During insertion, RISCV-DV avoids inserting one directed stream inside another already-injected directed stream. Near the end of generation, RISCV-DV revisits the merged instruction stream, examines embedded jump instructions, and annotates target locations with appropriate labels. [1]

Generated output

The generated output is intended as verification stimulus for RISC-V IP. The output program contains randomized instructions and register selections, can be integrated into a design-IP verification run, and includes support sections such as host-interface code and trap-handling support. [2] [3]

Profiling relevance

Because RISCV-DV is highly parameterized, the runtime of its components varies significantly depending on the parameters selected by the user. The cited DVCon paper describes profiling support using a uvm_trace method that records wall-clock timing around code sections, allowing generator performance to be analyzed before optimization. [1]

LINKED ENTITIES

1 links

CITATIONS

9 sources
9 citations
[1] RISCV-DV outputs a bare-metal RISC-V assembly program, can also generate an executable memory-loadable dump, and the SystemVerilog version outputs ASCII instead of native binary data. [PDF] Crafting a Million Instructions/Sec RISCV-DV - DVCon Proceedings
[2] `riscv_asm_program_gen.sv` is the RISCV-DV class responsible for generating complete RISC-V assembly programs and their major sections. RISC-V source class riscv_asm_program_gen, the brain behind ...
[3] `riscv_instr_gen_config` randomization controls extensions, privilege mode, instruction counts, and suppression controls such as `no_ebreak`, `no_dret`, `no_fence`, and `no_wfi`. RISC-V source class riscv_asm_program_gen, the brain behind ...
[4] RISCV-DV generation is customizable through command-line options including sub-program counts and instruction-stream ratios; it can emit random instructions into a main function or divide them across sub-programs with function-call control flow. [PDF] Crafting a Million Instructions/Sec RISCV-DV - DVCon Proceedings
[5] `gen_program()` invokes helper functions to generate headers, initialize GPRs, generate directed streams, convert instruction streams to assembly, insert sub-programs, add host-interface code, and prepare trap-handling support. RISC-V source class riscv_asm_program_gen, the brain behind ...
[6] RISCV-DV uses directed streams for sequenced execution scenarios such as loop sequences, load/store hazards, and numeric computation exceptions, and avoids unsafe unconstrained jumps such as problematic `jalr` placement. [PDF] Crafting a Million Instructions/Sec RISCV-DV - DVCon Proceedings
[7] Directed streams are generated, randomized, inserted into non-directed randomized instructions without nesting inside already-inserted directed streams, and jump targets are labeled near the end of generation. [PDF] Crafting a Million Instructions/Sec RISCV-DV - DVCon Proceedings
[8] The generated program contains randomized instructions and GPR selections suitable for RISC-V IP verification. RISC-V source class riscv_asm_program_gen, the brain behind ...
[9] RISCV-DV runtime varies with selected parameters, and `uvm_trace` can be used to record wall-clock timing around code regions for profiling. [PDF] Crafting a Million Instructions/Sec RISCV-DV - DVCon Proceedings

VERSION HISTORY

v2 · 5/27/2026 · gpt-5.5 (current)
v1 · 5/26/2026 · gpt-5.5