From a799c8bdd998945d66466a740dcf7b24eee69e69 Mon Sep 17 00:00:00 2001 From: Corey Hickson Date: Thu, 13 Mar 2025 04:52:24 -0700 Subject: [PATCH 1/6] 100% fctrl code coverage --- src/fpu/fctrl.sv | 4 ++-- tests/coverage/fpu.S | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/fpu/fctrl.sv b/src/fpu/fctrl.sv index 2b8dbc411..597cdd25f 100755 --- a/src/fpu/fctrl.sv +++ b/src/fpu/fctrl.sv @@ -154,7 +154,7 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( 7'b11100??: if (Funct3D == 3'b001 & Rs2D == 5'b00000) ControlsD = `FCTRLW'b0_1_10_00_000_0_0_0_0_0; // fclass else if (Funct3D == 3'b000 & Rs2D == 5'b00000) begin - if (Fmt[1:0] == 2'b00 | Fmt[1:0] == 2'b10 | (P.XLEN == 64 & Fmt[1:0] == 2'b01)) + if (~(P.XLEN != 64 & Fmt[1:0] == 2'b01)) ControlsD = `FCTRLW'b0_1_11_00_000_0_0_0_0_0; // fmv.x.w/d/h fp to int register (double only in RV64) end else if (P.ZFA_SUPPORTED & P.XLEN == 32 & P.D_SUPPORTED & Funct7D[1:0] == 2'b01 & Funct3D == 3'b000 & Rs2D == 5'b00001) ControlsD = `FCTRLW'b0_1_11_00_000_0_0_0_1_0; // fmvh.x.d (Zfa) @@ -164,7 +164,7 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( ControlsD = `FCTRLW'b0_1_11_00_000_0_0_0_1_0; // fmvh.x.q (Zfa) // coverage on 7'b11110??: if (Funct3D == 3'b000 & Rs2D == 5'b00000) begin - if (Fmt[1:0] == 2'b00 | Fmt[1:0] == 2'b10 | (P.XLEN == 64 & Fmt[1:0] == 2'b01)) + if (~(P.XLEN != 64 & Fmt[1:0] == 2'b01)) ControlsD = `FCTRLW'b1_0_00_00_011_0_0_0_0_0; // fmv.w/d/h.x int to fp reg (double only in RV64) end else if (P.ZFA_SUPPORTED & Funct3D == 3'b000 & Rs2D == 5'b00001) ControlsD = `FCTRLW'b1_0_00_00_111_0_0_0_1_0; // fli (Zfa) diff --git a/tests/coverage/fpu.S b/tests/coverage/fpu.S index 760898306..66f5b021e 100644 --- a/tests/coverage/fpu.S +++ b/tests/coverage/fpu.S @@ -154,6 +154,15 @@ main: fdiv.s ft2, ft1, ft0 # should get interrupted, triggering a flush csrci mstatus, 0b1000 # disable interrupts with mstatus.MIE + // fcrtl: unsupported rm with dyn rounding + csrrwi t0, frm, 0b111 # save previous rm, set frm csr to 111 (unsupported) + fadd.s f0, f0, f0, dyn # try to use unsupported rounding mode in csr + csrrwi x0, frm, 0b110 # set frm csr to 110 (unsupported) + fadd.s f0, f0, f0, dyn # try to use unsupported rounding mode in csr + csrrwi x0, frm, 0b101 # set frm csr to 101 (unsupported) + fadd.s f0, f0, f0, dyn # try to use unsupported rounding mode in csr + csrrw x0, frm, t0 # restore previous rm + # Completing branch coverage in fctrl.sv .word 0x38007553 // Testing the all False case for 119 - funct7 under, op = 101 0011 .word 0x40000053 // Line 145 All False Test case - illegal instruction? From 64a741c0b75eadd3c4feba823f43fd478a14c9a4 Mon Sep 17 00:00:00 2001 From: Corey Hickson Date: Wed, 2 Apr 2025 02:06:46 -0700 Subject: [PATCH 2/6] Restored previous RTL with coverage exclusion --- src/fpu/fctrl.sv | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/fpu/fctrl.sv b/src/fpu/fctrl.sv index 597cdd25f..01fac7de6 100755 --- a/src/fpu/fctrl.sv +++ b/src/fpu/fctrl.sv @@ -154,8 +154,11 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( 7'b11100??: if (Funct3D == 3'b001 & Rs2D == 5'b00000) ControlsD = `FCTRLW'b0_1_10_00_000_0_0_0_0_0; // fclass else if (Funct3D == 3'b000 & Rs2D == 5'b00000) begin - if (~(P.XLEN != 64 & Fmt[1:0] == 2'b01)) + // coverage off + // without Q support, the FMT field is guaranteed to match one of these three, so this line cannot be fully covered + if (Fmt[1:0] == 2'b00 | Fmt[1:0] == 2'b10 | (P.XLEN == 64 & Fmt[1:0] == 2'b01)) ControlsD = `FCTRLW'b0_1_11_00_000_0_0_0_0_0; // fmv.x.w/d/h fp to int register (double only in RV64) + // coverage on end else if (P.ZFA_SUPPORTED & P.XLEN == 32 & P.D_SUPPORTED & Funct7D[1:0] == 2'b01 & Funct3D == 3'b000 & Rs2D == 5'b00001) ControlsD = `FCTRLW'b0_1_11_00_000_0_0_0_1_0; // fmvh.x.d (Zfa) // Q not supported in RV64GC @@ -164,8 +167,11 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( ControlsD = `FCTRLW'b0_1_11_00_000_0_0_0_1_0; // fmvh.x.q (Zfa) // coverage on 7'b11110??: if (Funct3D == 3'b000 & Rs2D == 5'b00000) begin - if (~(P.XLEN != 64 & Fmt[1:0] == 2'b01)) + // coverage off + // without Q support, the FMT field is guaranteed to match one of these three, so this line cannot be fully covered + if (Fmt[1:0] == 2'b00 | Fmt[1:0] == 2'b10 | (P.XLEN == 64 & Fmt[1:0] == 2'b01)) ControlsD = `FCTRLW'b1_0_00_00_011_0_0_0_0_0; // fmv.w/d/h.x int to fp reg (double only in RV64) + // coverage on end else if (P.ZFA_SUPPORTED & Funct3D == 3'b000 & Rs2D == 5'b00001) ControlsD = `FCTRLW'b1_0_00_00_111_0_0_0_1_0; // fli (Zfa) 7'b0100000: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b00) From e6b3b3cec5d2b68d2c2815611fe8162cd158ef86 Mon Sep 17 00:00:00 2001 From: Corey Hickson Date: Wed, 2 Apr 2025 02:07:58 -0700 Subject: [PATCH 3/6] Code coverage exclusions for signals related to StallFCause --- src/hazard/hazard.sv | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/hazard/hazard.sv b/src/hazard/hazard.sv index 63b31001c..44faf3349 100644 --- a/src/hazard/hazard.sv +++ b/src/hazard/hazard.sv @@ -101,13 +101,19 @@ module hazard ( assign StallW = StallWCause; // detect the first stage that is not stalled + // coverage off + // StallD = StallF so LatestUnstalledD is necessarily 0 assign LatestUnstalledD = ~StallD & StallF; + // coverage on assign LatestUnstalledE = ~StallE & StallD; assign LatestUnstalledM = ~StallM & StallE; assign LatestUnstalledW = ~StallW & StallM; // Each stage flushes if the previous stage is the last one stalled (for cause) or the system has reason to flush + // coverage off + // LatestUnstalledD is always 0 assign FlushD = LatestUnstalledD | FlushDCause; + // coverage on assign FlushE = LatestUnstalledE | FlushECause; assign FlushM = LatestUnstalledM | FlushMCause; assign FlushW = LatestUnstalledW | FlushWCause; From cc8a5b152fa727bb9edc9863085fdeb4ccb1db4a Mon Sep 17 00:00:00 2001 From: Corey Hickson Date: Wed, 2 Apr 2025 18:06:19 -0700 Subject: [PATCH 4/6] exclude only impossible scenarios rather than whole line --- sim/questa/coverage-exclusions-rv64gc.do | 3 +++ src/fpu/fctrl.sv | 10 ++-------- tests/coverage/fpu.S | 9 --------- 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/sim/questa/coverage-exclusions-rv64gc.do b/sim/questa/coverage-exclusions-rv64gc.do index 146660eb7..77c52dfc5 100644 --- a/sim/questa/coverage-exclusions-rv64gc.do +++ b/sim/questa/coverage-exclusions-rv64gc.do @@ -55,6 +55,9 @@ coverage exclude -scope /dut/core/fpu/fpu/postprocess/flags -linerange [GetLineN coverage exclude -scope /dut/core/fpu/fpu/postprocess/flags -linerange [GetLineNum ${SRC}/fpu/postproc/flags.sv "assign Underflow"] -item e 1 -fecexprrow 22 # Convert int to fp will never underflow coverage exclude -scope /dut/core/fpu/fpu/postprocess/cvtshiftcalc -linerange [GetLineNum ${SRC}/fpu/postproc/cvtshiftcalc.sv "assign CvtResUf"] -item e 1 -fecexprrow 4 +# without Q support, the FMT field is guaranteed to be 00, 01, or 10 +coverage exclude -scope /dut/core/fpu/fpu/fctrl -linerange [GetLineNum ${SRC}/fpu/fctrl.sv "fmv int to fp"] -item 1 3 5 +coverage exclude -scope /dut/core/fpu/fpu/fctrl -linerange [GetLineNum ${SRC}/fpu/fctrl.sv "fmv fp to int"] -item 1 3 5 ################## # Cache Exclusions diff --git a/src/fpu/fctrl.sv b/src/fpu/fctrl.sv index 01fac7de6..805d56857 100755 --- a/src/fpu/fctrl.sv +++ b/src/fpu/fctrl.sv @@ -154,11 +154,8 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( 7'b11100??: if (Funct3D == 3'b001 & Rs2D == 5'b00000) ControlsD = `FCTRLW'b0_1_10_00_000_0_0_0_0_0; // fclass else if (Funct3D == 3'b000 & Rs2D == 5'b00000) begin - // coverage off - // without Q support, the FMT field is guaranteed to match one of these three, so this line cannot be fully covered - if (Fmt[1:0] == 2'b00 | Fmt[1:0] == 2'b10 | (P.XLEN == 64 & Fmt[1:0] == 2'b01)) + if (Fmt[1:0] == 2'b00 | Fmt[1:0] == 2'b10 | (P.XLEN == 64 & Fmt[1:0] == 2'b01)) // coverage-tag: fmv fp to int ControlsD = `FCTRLW'b0_1_11_00_000_0_0_0_0_0; // fmv.x.w/d/h fp to int register (double only in RV64) - // coverage on end else if (P.ZFA_SUPPORTED & P.XLEN == 32 & P.D_SUPPORTED & Funct7D[1:0] == 2'b01 & Funct3D == 3'b000 & Rs2D == 5'b00001) ControlsD = `FCTRLW'b0_1_11_00_000_0_0_0_1_0; // fmvh.x.d (Zfa) // Q not supported in RV64GC @@ -167,11 +164,8 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( ControlsD = `FCTRLW'b0_1_11_00_000_0_0_0_1_0; // fmvh.x.q (Zfa) // coverage on 7'b11110??: if (Funct3D == 3'b000 & Rs2D == 5'b00000) begin - // coverage off - // without Q support, the FMT field is guaranteed to match one of these three, so this line cannot be fully covered - if (Fmt[1:0] == 2'b00 | Fmt[1:0] == 2'b10 | (P.XLEN == 64 & Fmt[1:0] == 2'b01)) + if (Fmt[1:0] == 2'b00 | Fmt[1:0] == 2'b10 | (P.XLEN == 64 & Fmt[1:0] == 2'b01)) // coverage-tag: fmv int to fp ControlsD = `FCTRLW'b1_0_00_00_011_0_0_0_0_0; // fmv.w/d/h.x int to fp reg (double only in RV64) - // coverage on end else if (P.ZFA_SUPPORTED & Funct3D == 3'b000 & Rs2D == 5'b00001) ControlsD = `FCTRLW'b1_0_00_00_111_0_0_0_1_0; // fli (Zfa) 7'b0100000: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b00) diff --git a/tests/coverage/fpu.S b/tests/coverage/fpu.S index 66f5b021e..760898306 100644 --- a/tests/coverage/fpu.S +++ b/tests/coverage/fpu.S @@ -154,15 +154,6 @@ main: fdiv.s ft2, ft1, ft0 # should get interrupted, triggering a flush csrci mstatus, 0b1000 # disable interrupts with mstatus.MIE - // fcrtl: unsupported rm with dyn rounding - csrrwi t0, frm, 0b111 # save previous rm, set frm csr to 111 (unsupported) - fadd.s f0, f0, f0, dyn # try to use unsupported rounding mode in csr - csrrwi x0, frm, 0b110 # set frm csr to 110 (unsupported) - fadd.s f0, f0, f0, dyn # try to use unsupported rounding mode in csr - csrrwi x0, frm, 0b101 # set frm csr to 101 (unsupported) - fadd.s f0, f0, f0, dyn # try to use unsupported rounding mode in csr - csrrw x0, frm, t0 # restore previous rm - # Completing branch coverage in fctrl.sv .word 0x38007553 // Testing the all False case for 119 - funct7 under, op = 101 0011 .word 0x40000053 // Line 145 All False Test case - illegal instruction? From a9ec44746e1dcfa4e62550b9ac4a10b6bb1d24fd Mon Sep 17 00:00:00 2001 From: Corey Hickson Date: Wed, 2 Apr 2025 23:50:34 -0700 Subject: [PATCH 5/6] Change LatestUnstalledD exclusion to only impossible scenarios --- sim/questa/coverage-exclusions-rv64gc.do | 3 +++ src/hazard/hazard.sv | 6 ++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/sim/questa/coverage-exclusions-rv64gc.do b/sim/questa/coverage-exclusions-rv64gc.do index 77c52dfc5..1c952ade8 100644 --- a/sim/questa/coverage-exclusions-rv64gc.do +++ b/sim/questa/coverage-exclusions-rv64gc.do @@ -409,6 +409,9 @@ coverage exclude -srcfile priorityonehot.sv coverage exclude -scope /dut/core/ifu/immu/immu/pmp/pmpchecker/pmp/pmpadrdecs[0] -linerange [GetLineNum ${SRC}/mmu/pmpadrdec.sv "exclusion-tag: PAgePMPAdrIn"] -item e 1 -fecexprrow 1 coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmp/pmpchecker/pmp/pmpadrdecs[0] -linerange [GetLineNum ${SRC}/mmu/pmpadrdec.sv "exclusion-tag: PAgePMPAdrIn"] -item e 1 -fecexprrow 1 +# StallD always equals StallF so LatestUnstalledD is always 0 +coverage exclude -scope /dut/core/hzu -linerange [GetLineNum ${SRC}/hazard/hazard.sv "StallD always equals StallF"] -item 1 4 + #################### # Privileged #################### diff --git a/src/hazard/hazard.sv b/src/hazard/hazard.sv index 44faf3349..18dbc2e70 100644 --- a/src/hazard/hazard.sv +++ b/src/hazard/hazard.sv @@ -101,10 +101,8 @@ module hazard ( assign StallW = StallWCause; // detect the first stage that is not stalled - // coverage off - // StallD = StallF so LatestUnstalledD is necessarily 0 - assign LatestUnstalledD = ~StallD & StallF; - // coverage on + + assign LatestUnstalledD = ~StallD & StallF; // coverage tag: StallD always equals StallF assign LatestUnstalledE = ~StallE & StallD; assign LatestUnstalledM = ~StallM & StallE; assign LatestUnstalledW = ~StallW & StallM; From b86026abbe746bcc0d0f61f3edb2224b2deb0a49 Mon Sep 17 00:00:00 2001 From: Corey Hickson Date: Thu, 3 Apr 2025 10:16:54 -0700 Subject: [PATCH 6/6] Fixed FlushD exclusion --- sim/questa/coverage-exclusions-rv64gc.do | 1 + src/hazard/hazard.sv | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/sim/questa/coverage-exclusions-rv64gc.do b/sim/questa/coverage-exclusions-rv64gc.do index 1c952ade8..64241e01c 100644 --- a/sim/questa/coverage-exclusions-rv64gc.do +++ b/sim/questa/coverage-exclusions-rv64gc.do @@ -411,6 +411,7 @@ coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmp/pmpchecker/pmp/pmpadrdecs[0] # StallD always equals StallF so LatestUnstalledD is always 0 coverage exclude -scope /dut/core/hzu -linerange [GetLineNum ${SRC}/hazard/hazard.sv "StallD always equals StallF"] -item 1 4 +coverage exclude -scope /dut/core/hzu -linerange [GetLineNum ${SRC}/hazard/hazard.sv "coverage tag: LatestUnstalledD always 0"] -item e 1 -fecexprrow 2 #################### # Privileged diff --git a/src/hazard/hazard.sv b/src/hazard/hazard.sv index 18dbc2e70..c15ff208f 100644 --- a/src/hazard/hazard.sv +++ b/src/hazard/hazard.sv @@ -108,10 +108,7 @@ module hazard ( assign LatestUnstalledW = ~StallW & StallM; // Each stage flushes if the previous stage is the last one stalled (for cause) or the system has reason to flush - // coverage off - // LatestUnstalledD is always 0 - assign FlushD = LatestUnstalledD | FlushDCause; - // coverage on + assign FlushD = LatestUnstalledD | FlushDCause; // coverage tag: LatestUnstalledD always 0 assign FlushE = LatestUnstalledE | FlushECause; assign FlushM = LatestUnstalledM | FlushMCause; assign FlushW = LatestUnstalledW | FlushWCause;