Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds test generation support for the experimental Zibi RISC-V extension, which defines two new branch instructions (beqi and bnei) that compare a register against a compact 5-bit immediate.
Changes:
- Adds a new
BIinstruction type formatter, a new coverpoint generator for cross-product of rs1/cimm edges, and extendscp_offsetandcp_imm_edgesto support the BI type. - Adds the
Zibi.csvtestplan, new coverage templates (sample_BI.sv,cr_rs1_cimm_edges_offset.sv,cp_imm_edges_5bit_u_n0.sv), and new trace/disassembler support for BEQI/BNEI. - Adds
imm_5bitedge values toIMMEDIATE_EDGESand newcimmfield toRISCV_trace_dataandRISCV_instruction_base.
Reviewed changes
Copilot reviewed 7 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
testplans/Zibi.csv |
Testplan defining coverpoints for beqi and bnei |
generators/testgen/src/testgen/formatters/types/bi_type.py |
New BI instruction type formatter |
generators/testgen/src/testgen/data/edges.py |
Adds 5-bit unsigned immediate edge values |
generators/testgen/src/testgen/coverpoints/special/cr_rs1_cimm_edges_offset.py |
New cross-product coverpoint generator for rs1 edges × cimm edges × branch direction |
generators/testgen/src/testgen/coverpoints/special/cp_offset.py |
Extends cp_offset to support BI type; has a bug with missing immval in backward branch emission |
generators/testgen/src/testgen/coverpoints/cp_imm_edges.py |
Adds 5-bit unsigned immediate edge support; misleading comment |
generators/coverage/templates/sample_BI.sv |
Coverage sampling template for BI type |
generators/coverage/templates/cr_rs1_cimm_edges_offset.sv |
Cross-coverage template |
generators/coverage/templates/cp_imm_edges_5bit_u_n0.sv |
Empty — missing coverpoint definition |
framework/src/act/fcov/disassemble.svh |
Adds BEQI/BNEI disassembly; uses undefined constants BEQI/BNEI |
framework/src/act/fcov/coverage/RISCV_trace_data.svh |
Adds cimm field to trace data |
framework/src/act/fcov/coverage/RISCV_instruction_base.svh |
Adds add_cimm() method |
| ################################## | ||
| # cr_rs1_cimm_edges_offset.py | ||
| # | ||
| # tjc.challenger1024@jmail.com Mar 2026 |
There was a problem hiding this comment.
The email address tjc.challenger1024@jmail.com appears to be a typo — it says jmail.com instead of gmail.com.
| BEQI: $sformat(decoded, "beqi %s, %0d, %0d", rs1, cimm5, immBType); | ||
| BNEI: $sformat(decoded, "bnei %s, %0d, %0d", rs1, cimm5, immBType); |
There was a problem hiding this comment.
The BEQI and BNEI constants used in the casez statement are not defined anywhere in the decode packages (RISCV_decode_pkg.svh or RISCV_imported_decode_pkg.svh). All other instructions in the casez (e.g., BEQ, BNE, EBREAK, etc.) have corresponding localparam entries. Without these definitions, the SystemVerilog will fail to compile because BEQI and BNEI are undefined identifiers. The opcode bit patterns for beqi and bnei need to be added to RISCV_decode_pkg.svh or RISCV_imported_decode_pkg.svh.
| elif instr_type == "BI": | ||
| assert params.rs1 is not None and params.immval is not None | ||
| if instr_name == "beqi": | ||
| test_lines.append(f"LI(x{params.rs1}, {params.immval}) # setup for taken branch") | ||
| else: # bnei | ||
| val = params.immval + 1 if params.immval != 31 else params.immval - 1 | ||
| test_lines.append(f"LI(x{params.rs1}, {val}) # setup for taken branch") |
There was a problem hiding this comment.
The backward branch instruction generated for BI type is missing the immediate operand. Line 55 (unchanged context) uses f"2: {instr_name} x{params.rs1}, {f'x{params.rs2},' if params.rs2 is not None else ''} 1b # backward branch". For BI type, params.rs2 is None, so this generates beqi x{rs1}, 1b rather than the correct beqi x{rs1}, {params.immval}, 1b. The elif instr_type == "BI" branch added here must also handle the branch instruction emission on line 55, or line 55 needs to be updated to include params.immval for the BI type.
| elif coverpoint.endswith("_5bit"): | ||
| edges_imm = IMMEDIATE_EDGES.imm_5bit | ||
| elif coverpoint.endswith("_5bit_u_n0"): | ||
| edges_imm = IMMEDIATE_EDGES.imm_5bit[1:] # exclude imm=0, add imm=-1 for Zibi extension |
There was a problem hiding this comment.
The comment on line 33 says "exclude imm=0, add imm=-1 for Zibi extension", but the code only slices IMMEDIATE_EDGES.imm_5bit[1:] which simply excludes 0. No -1 value is ever added. If cimm=0 is supposed to encode -1 per the Zibi spec (as reflected in disassemble.svh line 59 where cimm5 = (instr[24:20] == 0) ? -1 : instr[24:20]), the comment is misleading. Either the comment should be corrected to just say "exclude imm=0", or a -1 entry should actually be added to test the special cimm=0 encoding.
davidharrishmc
left a comment
There was a problem hiding this comment.
Exciting to see this first PR for a new extension in ACT4. Thank you for contributing!
A few things I'm trying to follow, and I'm sure @jordancarlin will have feedback too.
| @@ -0,0 +1,3 @@ | |||
| cr_rs1_cimm_edges_offset : cross cp_rs1_edges,cp_imm_edges_5bit_u_n0,cp_offset iff (ins.trap == 0 ) { | |||
There was a problem hiding this comment.
The cp_imm_edges_5bit_u_n0.sv file is showing up empty for me during review. Either it wasn't committed properly or Github is doing something wonky on my viewer.
I'd like to check the case of 0 becoming -1 is in the coverpoint.
| "0: # destination for backwards branch that is never taken", | ||
| f"{instr_name} x{params.rs1}, {params.immval}, 3f # forward branch, if taken", | ||
| "1: # goes here if not taken", | ||
| f"{instr_name} x{params.rs1}, {params.immval}, 0b # backward branch, never taken", |
There was a problem hiding this comment.
If there is a bug in the implementation and this branch is taken, it looks like the test may infinite loop. Can this be modified to set a signature (which will mismatch the reference model) and keep going?
| "j 4f # done with test", | ||
| "3: # goes here during forward branch if taken", | ||
| f"{instr_name} x{params.rs1}, {params.immval}, 2b # backward branch, definitely taken", | ||
| "4: # done with test", |
There was a problem hiding this comment.
Put another sigupd here in case the branch that should have been taken didn't get taken.
| elif coverpoint.endswith("_5bit"): | ||
| edges_imm = IMMEDIATE_EDGES.imm_5bit | ||
| elif coverpoint.endswith("_5bit_u_n0"): | ||
| edges_imm = IMMEDIATE_EDGES.imm_5bit[1:] # exclude imm=0, add imm=-1 for Zibi extension |
There was a problem hiding this comment.
I'm having trouble following how the effective immediate of -1 is generated. There is a draft spec below, which I think is backward (should it say immediate negative one is represented as zero)? Is this code excluding that case?
Zibi extension encodes all 5-bit immediate as positive number, with the exception of immediate zero, which is represented as negative one
https://github.com/riscv/zibi/blob/main/src/zibi.adoc
Add tests for the experimental extension Zibi.
Link: https://github.com/riscv/zibi/issues/2