Conversation
coverpoints/priv/ZicsrH_coverage.svh
Outdated
| } | ||
|
|
||
| // M-mode CSRs should be inaccessible from HS-mode (expect illegal instruction) | ||
| cp_mhcsr_inaccessible_hs: cross priv_mode_s, mhcsrname, csrop { |
There was a problem hiding this comment.
should there be another cross with an illegal instruction exception?
coverpoints/priv/ZicsrH_coverage.svh
Outdated
| cp_vscsr_virtualfault_vs: cross priv_mode_s, vscsrname, csrop; // V=1, S-mode | ||
|
|
||
| // U-mode: All H-extension CSRs should be inaccessible | ||
| cp_hcsr_inaccessible_u: cross priv_mode_u, mhcsrname, csrop; |
There was a problem hiding this comment.
might need to cross these with an illegal instruction exception
davidharrishmc
left a comment
There was a problem hiding this comment.
@AnonymousVikram there is still a lot that needs to clean up on this PR. I've done a partial review. When it is ready, turn off draft and let me know that it is ready to review.
coverpoints/priv/ZicsrH_coverage.svh
Outdated
| cp_vscsr_access_m: cross priv_mode_m, vscsrname, csrop, write_pattern; | ||
|
|
||
| // HS-mode access to HS and VS CSRs | ||
| cp_hscsr_access_hs: cross priv_mode_s, hscsrname, csrop, write_pattern { |
There was a problem hiding this comment.
How do we know we are in hs mode, not vs mode?
coverpoints/priv/ZicsrH_coverage.svh
Outdated
| // Covergroup for H-extension CSR access testing | ||
| covergroup ZicsrH_csr_access_cg with function sample(ins_t ins); | ||
| option.per_instance = 0; | ||
| `include "coverage/RISCV_coverage_standard_coverpoints.svh" |
There was a problem hiding this comment.
I don't see this file in riscv-arch-test act4 branch.
coverpoints/priv/ZicsrH_coverage.svh
Outdated
| ignore_bins not_hs = binsof(priv_mode_s) intersect {2'b00, 2'b11}; // Only S-mode (HS) | ||
| } | ||
| cp_vscsr_access_hs: cross priv_mode_s, vscsrname, csrop, write_pattern { | ||
| ignore_bins not_hs = binsof(priv_mode_s) intersect {2'b00, 2'b11}; |
There was a problem hiding this comment.
Same queries as above. These apply many places.
coverpoints/priv/ZicsrH_coverage.svh
Outdated
| } | ||
|
|
||
| // M-mode CSRs should be inaccessible from HS-mode (expect illegal instruction) | ||
| cp_mhcsr_inaccessible_hs: cross priv_mode_s, mhcsrname, csrop, exception { |
There was a problem hiding this comment.
Exception is not needed here. Exception is an expected outcome, not an input condition.
There was a problem hiding this comment.
Applies many places.
coverpoints/priv/ZicsrH_coverage.svh
Outdated
| // M-mode CSRs should be inaccessible from HS-mode (expect illegal instruction) | ||
| cp_mhcsr_inaccessible_hs: cross priv_mode_s, mhcsrname, csrop, exception { | ||
| ignore_bins not_hs = binsof(priv_mode_s) intersect {2'b00, 2'b11}; | ||
| ignore_bins no_trap = binsof(exception) intersect {0}; |
coverpoints/priv/ZicsrH_coverage.svh
Outdated
| } | ||
|
|
||
| // VS-mode: HS and VS CSRs should cause virtual instruction fault | ||
| cp_hscsr_virtualfault_vs: cross priv_mode_s, hscsrname, csrop; // V=1, S-mode |
There was a problem hiding this comment.
This should be vs mode, not priv_mode_s.
There was a problem hiding this comment.
The coverpoint is named cp_hcsr_virtualinstructionfault
coverpoints/priv/ZicsrH_coverage.svh
Outdated
| cp_vscsr_virtualfault_vs: cross priv_mode_s, vscsrname, csrop; // V=1, S-mode | ||
|
|
||
| // U-mode: All H-extension CSRs should be inaccessible | ||
| cp_hcsr_inaccessible_u: cross priv_mode_u, mhcsrname, csrop, exception { |
There was a problem hiding this comment.
I think this should be mhcsr rather than hcsr.
There was a problem hiding this comment.
Distinguish u and vu modes.
There was a problem hiding this comment.
Pull request overview
This PR adds functional coverage infrastructure for the RISC-V Hypervisor extension (ZicsrH), introducing comprehensive coverage points for hypervisor CSRs and privileged instructions.
- Adds coverage groups for H-extension CSR access patterns, bit-walking tests, and replica testing
- Implements coverage for privilege mode interactions (M, HS, VS, U, VU modes)
- Covers hypervisor-specific behaviors like TVM/VTVM traps, virtual instruction faults, and special CSR fields
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| coverpoints/priv/ZicsrH_coverage_init.svh | Initializes all ZicsrH coverage group instances with appropriate names |
| coverpoints/priv/ZicsrH_coverage.svh | Defines 9 comprehensive coverage groups for H-extension CSRs, privilege modes, traps, and hypervisor instructions |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // VTVM trap in VS-mode accessing satp | ||
| cp_vtvm_vs: cross priv_mode_s, csr_tvm, csrop, mstatus_tvm, hstatus_v_bit { | ||
| ignore_bins not_satp = binsof(csr_tvm) intersect {12'h680}; // Only satp for VTVM | ||
| ignore_bins not_vs = binsof(hstatus_v_bit) intersect {hstatus_v_bit.hs_mode}; | ||
| } |
There was a problem hiding this comment.
The VTVM cross coverage appears to have incorrect filtering logic. Line 578 uses ignore_bins to exclude hgatp (12'h680) from the VTVM test, but the comment on line 576 states "VTVM trap in VS-mode accessing satp". However, according to the RISC-V privileged specification, VTVM controls traps for SATP accesses from VS-mode, so the filtering is correct. But the cross coverage is using mstatus_tvm which controls TVM, not VTVM. VTVM is a separate bit in hstatus. This coverpoint should check hstatus.VTVM instead of mstatus.TVM for the VS-mode case.
coverpoints/priv/ZicsrH_coverage.svh
Outdated
| // VS-mode (hstatus.V=1): HS CSRs should cause virtual instruction fault | ||
| cp_hscsr_virtualinstructionfault_vs: cross priv_mode_s, hscsrname, csrop, hstatus_v_bit, exception { | ||
| ignore_bins not_vs_mode = binsof(hstatus_v_bit) intersect {hstatus_v_bit.hs_mode}; // Exclude HS mode (hstatus.V=0) | ||
| ignore_bins no_virtual_instr_fault_trap = binsof(exception) intersect {0}; // Expect a trap (virtual instruction fault) | ||
| } | ||
| // VS-mode (hstatus.V=1): VS CSRs should cause virtual instruction fault |
There was a problem hiding this comment.
The comment on line 159 appears to be redundant or incorrectly placed. Line 154 already has a comment describing "VS-mode (hstatus.V=1): HS CSRs should cause virtual instruction fault", and line 159 repeats "VS-mode (hstatus.V=1): VS CSRs should cause virtual instruction fault". However, this is describing a different coverpoint (cp_vscsr_virtualinstructionfault_vs vs cp_hscsr_virtualinstructionfault_vs), so while not incorrect, the duplicate phrasing on consecutive lines reduces clarity. Consider condensing these comments or making them more distinct.
| // VS-mode (hstatus.V=1): HS CSRs should cause virtual instruction fault | |
| cp_hscsr_virtualinstructionfault_vs: cross priv_mode_s, hscsrname, csrop, hstatus_v_bit, exception { | |
| ignore_bins not_vs_mode = binsof(hstatus_v_bit) intersect {hstatus_v_bit.hs_mode}; // Exclude HS mode (hstatus.V=0) | |
| ignore_bins no_virtual_instr_fault_trap = binsof(exception) intersect {0}; // Expect a trap (virtual instruction fault) | |
| } | |
| // VS-mode (hstatus.V=1): VS CSRs should cause virtual instruction fault | |
| // In VS-mode (hstatus.V=1), accesses to HS CSRs (cp_hscsr_virtualinstructionfault_vs) should cause a virtual instruction fault | |
| cp_hscsr_virtualinstructionfault_vs: cross priv_mode_s, hscsrname, csrop, hstatus_v_bit, exception { | |
| ignore_bins not_vs_mode = binsof(hstatus_v_bit) intersect {hstatus_v_bit.hs_mode}; // Exclude HS mode (hstatus.V=0) | |
| ignore_bins no_virtual_instr_fault_trap = binsof(exception) intersect {0}; // Expect a trap (virtual instruction fault) | |
| } | |
| // In VS-mode (hstatus.V=1), accesses to VS CSRs (cp_vscsr_virtualinstructionfault_vs) should cause a virtual instruction fault |
| ZicsrH_vsstatus_cg = new(); ZicsrH_vsstatus_cg.set_inst_name("obj_ZicsrH_vsstatus"); | ||
| ZicsrH_tvm_cg = new(); ZicsrH_tvm_cg.set_inst_name("obj_ZicsrH_tvm"); | ||
| ZicsrH_mtval_cg = new(); ZicsrH_mtval_cg.set_inst_name("obj_ZicsrH_mtval"); | ||
| ZicsrH_hprivinst_cg = new(); ZicsrH_hprivinst_cg.set_inst_name("obj_ZicsrH_hprivinst"); |
There was a problem hiding this comment.
Inconsistent spacing in the initialization statements. Lines 13-16 have proper alignment with consistent spacing before set_inst_name, but lines 17-21 have inconsistent spacing (some have more spaces, some fewer). For better readability and maintainability, all lines should use consistent alignment.
| ZicsrH_vsstatus_cg = new(); ZicsrH_vsstatus_cg.set_inst_name("obj_ZicsrH_vsstatus"); | |
| ZicsrH_tvm_cg = new(); ZicsrH_tvm_cg.set_inst_name("obj_ZicsrH_tvm"); | |
| ZicsrH_mtval_cg = new(); ZicsrH_mtval_cg.set_inst_name("obj_ZicsrH_mtval"); | |
| ZicsrH_hprivinst_cg = new(); ZicsrH_hprivinst_cg.set_inst_name("obj_ZicsrH_hprivinst"); | |
| ZicsrH_vsstatus_cg = new(); ZicsrH_vsstatus_cg.set_inst_name("obj_ZicsrH_vsstatus"); | |
| ZicsrH_tvm_cg = new(); ZicsrH_tvm_cg.set_inst_name("obj_ZicsrH_tvm"); | |
| ZicsrH_mtval_cg = new(); ZicsrH_mtval_cg.set_inst_name("obj_ZicsrH_mtval"); | |
| ZicsrH_hprivinst_cg = new(); ZicsrH_hprivinst_cg.set_inst_name("obj_ZicsrH_hprivinst"); |
| cp_vsstatus_sd: coverpoint ins.current.rs1_val[XLEN-1] { | ||
| } | ||
|
|
||
| // FS field [14:13] | ||
| cp_vsstatus_fs: coverpoint ins.current.rs1_val[14:13] { | ||
| } | ||
|
|
||
| // VS field [10:9] | ||
| cp_vsstatus_vs: coverpoint ins.current.rs1_val[10:9] { | ||
| } | ||
|
|
||
| // XS field [16:15] - read-only, reflects extension state | ||
| cp_vsstatus_xs: coverpoint ins.current.rs1_val[16:15] { |
There was a problem hiding this comment.
The coverpoints include both cp_vsstatus_sd, cp_vsstatus_fs, cp_vsstatus_vs, and cp_vsstatus_xs but these are defined without any bins. Empty coverpoints without bins will capture all possible values, which may not be the intended behavior. Consider adding explicit bins to define the specific values or states that should be covered for each field.
| cp_vsstatus_sd: coverpoint ins.current.rs1_val[XLEN-1] { | |
| } | |
| // FS field [14:13] | |
| cp_vsstatus_fs: coverpoint ins.current.rs1_val[14:13] { | |
| } | |
| // VS field [10:9] | |
| cp_vsstatus_vs: coverpoint ins.current.rs1_val[10:9] { | |
| } | |
| // XS field [16:15] - read-only, reflects extension state | |
| cp_vsstatus_xs: coverpoint ins.current.rs1_val[16:15] { | |
| cp_vsstatus_sd: coverpoint ins.current.rs1_val[XLEN-1] { | |
| bins sd_0 = {0}; | |
| bins sd_1 = {1}; | |
| } | |
| // FS field [14:13] | |
| cp_vsstatus_fs: coverpoint ins.current.rs1_val[14:13] { | |
| bins fs_off = {2'b00}; | |
| bins fs_initial = {2'b01}; | |
| bins fs_clean = {2'b10}; | |
| bins fs_dirty = {2'b11}; | |
| } | |
| // VS field [10:9] | |
| cp_vsstatus_vs: coverpoint ins.current.rs1_val[10:9] { | |
| bins vs_0 = {2'b00}; | |
| bins vs_1 = {2'b01}; | |
| bins vs_2 = {2'b10}; | |
| bins vs_3 = {2'b11}; | |
| } | |
| // XS field [16:15] - read-only, reflects extension state | |
| cp_vsstatus_xs: coverpoint ins.current.rs1_val[16:15] { | |
| bins xs_all_clean = {2'b00}; | |
| bins xs_initial = {2'b01}; | |
| bins xs_clean = {2'b10}; | |
| bins xs_dirty = {2'b11}; |
| ignore_bins not_hs = binsof(priv_mode_s) intersect {2'b00, 2'b11}; | ||
| } | ||
|
|
||
| cp_hfence_m: cross priv_mode_m, hfence; | ||
| cp_hfence_hs: cross priv_mode_s, hfence { | ||
| ignore_bins not_hs = binsof(priv_mode_s) intersect {2'b00, 2'b11}; |
There was a problem hiding this comment.
The cross coverage cp_hv_loadstore_hs and cp_hfence_hs use ignore_bins to filter priv_mode_s values, but the filtering logic intersects with hardcoded values {2'b00, 2'b11}. This assumes specific encodings for privilege modes. Consider using named bins (e.g., priv_mode_s.u_mode, priv_mode_s.m_mode) for clarity and to ensure the ignore_bins correctly excludes non-HS modes. This would make the code more maintainable and less prone to errors if privilege mode encodings change.
| ignore_bins not_hs = binsof(priv_mode_s) intersect {2'b00, 2'b11}; | |
| } | |
| cp_hfence_m: cross priv_mode_m, hfence; | |
| cp_hfence_hs: cross priv_mode_s, hfence { | |
| ignore_bins not_hs = binsof(priv_mode_s) intersect {2'b00, 2'b11}; | |
| ignore_bins not_hs = binsof(priv_mode_s) intersect {priv_mode_s.u_mode, priv_mode_s.m_mode}; | |
| } | |
| cp_hfence_m: cross priv_mode_m, hfence; | |
| cp_hfence_hs: cross priv_mode_s, hfence { | |
| ignore_bins not_hs = binsof(priv_mode_s) intersect {priv_mode_s.u_mode, priv_mode_s.m_mode}; |
| hfence: coverpoint ins.current.insn { | ||
| bins hfence_vvma = {32'h22000073}; // rs1=x0, rs2=x0 | ||
| bins hfence_gvma = {32'h62000073}; // rs1=x0, rs2=x0 |
There was a problem hiding this comment.
The hfence coverpoint bins are defined with specific full 32-bit instruction encodings (e.g., 32'h22000073, 32'h62000073) which only match when rs1=x0 and rs2=x0. However, HFENCE.VVMA and HFENCE.GVMA instructions can have non-zero rs1 and rs2 operands to specify address ranges and ASIDs/VMIDs. This coverage will miss testing these instructions with different operand values. Consider using wildcard bins to cover the full range of valid operand combinations.
| hfence: coverpoint ins.current.insn { | |
| bins hfence_vvma = {32'h22000073}; // rs1=x0, rs2=x0 | |
| bins hfence_gvma = {32'h62000073}; // rs1=x0, rs2=x0 | |
| // HFENCE instructions: match all valid rs1/rs2 combinations | |
| hfence: coverpoint ins.current.insn { | |
| wildcard bins hfence_vvma = {32'b00100010??????????00000001110011}; // HFENCE.VVMA: opcode=SYSTEM, funct7=0x22, funct3=0, rs1/rs2=any | |
| wildcard bins hfence_gvma = {32'b01100010??????????00000001110011}; // HFENCE.GVMA: opcode=SYSTEM, funct7=0x62, funct3=0, rs1/rs2=any |
|
@AnonymousVikram there is still a lot to do here. We seem to have a disconnect because you seem to think it is done. Let's communicate more over Slack or f2f. Please reply to the comments with "DONE" when you feel they are done. Same with comments from Copilot. |
Description
Related Issues
Ratified/Unratified Extensions
List Extensions
Reference Model Used
Mandatory Checklist:
Optional Checklist: