Code Block
Definition
In the RVVTS (RISC-V Vector Test Set) framework, a Code Block is a sequence of Code Fragments that forms an entity which can be executed on a RISC-V machine. A Code Fragment itself is an indivisible sequence of at least one assembler instruction implementing a specific operation — for example, a single RVV vector add instruction, or the multiple instructions needed to realize a bounded vector load/store operation together with the bounding logic. Code Blocks organize and handle assembler code used by RVVTS.
Construction and Lifecycle
Code Blocks can be:
- Created manually,
- Loaded from files, or
- Created automatically by the grammar-based Instruction Set Generator (ISG), or through Code Minimization performed by the framework.
The data structure provides methods to modify the contained code, retrieve sub-blocks, and save/load to/from files.
Role in Single Instruction Isolation with Code Minimization
The CodeErrMinRunner implements RVVTS's Single Instruction Isolation with Code Minimization technique and operates on Code Blocks. The pipeline proceeds in stages:
Initial comparison — A
CodeCompareRunnerruns the Code Block and compares the Machine State produced by the reference (Spike) against the Design Under Test (DUT). If a Machine State deviation occurs, the run is considered a fail, the failing Code Block is documented, and it is passed to Delta Code Reduction.Delta Code Reduction — Uses a binary-search algorithm (Algorithm 1) over Code Fragments. The algorithm maintains a
goodposition, abadposition, and atestposition; it executescodeblock.subpart(0, test)via aCodeCompareRunner, halves the search area depending on whether the run is a FAIL or PASS, and returns the position of the earliest single failing Code Fragment. The reduced Code Block consists of non-failing Code Fragments followed by a single failing Code Fragment at the end.Code Minimization — Splits the Code Block into two: the first contains all non-failing Code Fragments just before the failing fragment, and the second contains only the failing Code Fragment. A
CodeCheckRunnerexecutes the first block to extract the Machine State after execution of the non-failing fragments. The initialization code generated from this Machine State is combined with the second block (containing only the single failing fragment), yielding a minimized Code Block that contains only the Machine State initialization plus the single failing Code Fragment. Finally, aCodeCompareRunnerexecutes the minimized Code Block to obtain the final results.
The results of all runs, including the reduced and minimized Code Blocks, are documented for later analysis.
Role in Coverage-Guided Testset Generation
The CovGuidedTestsetGenerator generates dense Code Blocks with high functional coverage. Multiple independent instances can run in parallel to produce large test sets. Generation starts with an empty Code Block with zero functional coverage and alternates between two phases:
Extension phase — The ISG generates a new Code Fragment which is inserted at a random position in a copy of the current Code Block. The new Code Block is then instrumented, compiled, and executed by a
CodeCheckRunner, which returns a Machine State and a coverage value. Acceptance requires that (i) the Machine State must be valid, and (ii) the coverage of the new Code Block must be maintained or improved compared to the original Code Block. If either fails, the new Code Block is rejected and the original is used in the next iteration.Reduction phase — A random Code Fragment is removed from a copy of the current Code Block, and the resulting Code Block is executed via a
CodeCheckRunner. The coverage requirement differs here: the coverage must stay the same with respect to the original Code Block. If the requirements are met, the new Code Block is used for the next iteration.
Phase switching is determined by a configurable number of iterations for each phase, and the process can be stopped at any iteration by the program that instantiated the Runner (e.g., after a configured iteration/time limit or after reaching a certain coverage value).
Validity Requirements
Any generated Code Block must be compilable and executable. Additional requirements are configurable. At the time of writing, the only additional configurable property is a Boolean switch controlling whether the resulting Code Block is allowed to cause traps in the execution. This switch is crucial for generating test sets targeted for pure positive testing, and positive/negative testing.
Testset Execution
A variant of the CodeErrMinRunner, called the TestsetCodeErrMinRunner, is used to run pre-generated test sets. It takes a path and a file matching pattern as input, loads matching files as Code Blocks, and executes each as described above, collecting all obtained results.
Example: Test Set Statistics (Table 1)
The Valid Sequences (VS) test sets generated by CovGuidedTestsetGenerator contain:
- RV32: ~1.78 million Code Fragments, ~1.25 million RVV instructions, 30,500/31,894 functional coverage points (95.63%).
- RV64: ~1.69 million Code Fragments, ~1.21 million RVV instructions, 31,410/33,076 functional coverage points (94.96%).