diff --git a/config/rv64gc/config.vh b/config/rv64gc/config.vh index bb3e79659..04a674b47 100644 --- a/config/rv64gc/config.vh +++ b/config/rv64gc/config.vh @@ -41,7 +41,7 @@ localparam COUNTERS = 12'd32; localparam ZICNTR_SUPPORTED = 1; localparam ZIHPM_SUPPORTED = 1; localparam ZFH_SUPPORTED = 1; -localparam ZFA_SUPPORTED = 0; +localparam ZFA_SUPPORTED = 1; localparam SSTC_SUPPORTED = 1; localparam ZICBOM_SUPPORTED = 1; localparam ZICBOZ_SUPPORTED = 1; diff --git a/config/shared/config-shared.vh b/config/shared/config-shared.vh index 5dfb4b1ba..ba215785c 100644 --- a/config/shared/config-shared.vh +++ b/config/shared/config-shared.vh @@ -111,7 +111,7 @@ localparam LLEN = (($unsigned(FLEN)<$unsigned(XLEN)) ? ($unsigned(XLEN)) : ($uns localparam LOGCVTLEN = $unsigned($clog2(CVTLEN+1)); localparam NORMSHIFTSZ = (((CVTLEN+NF+1)>(DIVb + 1 +NF+1) & (CVTLEN+NF+1)>(3*NF+6)) ? (CVTLEN+NF+1) : ((DIVb + 1 +NF+1) > (3*NF+6) ? (DIVb + 1 +NF+1) : (3*NF+6))); localparam LOGNORMSHIFTSZ = ($clog2(NORMSHIFTSZ)); -localparam CORRSHIFTSZ = NORMSHIFTSZ-2; +localparam CORRSHIFTSZ = (((DIVMINb+1+NF) > (3*NF+4) ? (DIVMINb+1+NF) : (3*NF+4))); // max(DIVMINb+NF+1, 3*NF+4) // Disable spurious Verilator warnings diff --git a/sim/coverage-exclusions-rv64gc.do b/sim/coverage-exclusions-rv64gc.do index b9c20eead..d8e05c7d4 100644 --- a/sim/coverage-exclusions-rv64gc.do +++ b/sim/coverage-exclusions-rv64gc.do @@ -34,11 +34,24 @@ do GetLineNum.do # DH 4/22/23: Exclude all LZAs coverage exclude -srcfile lzc.sv +################# +# FPU Exclusions +################# # DH 4/22/23: FDIVSQRT can't go directly from done to busy again coverage exclude -scope /dut/core/fpu/fpu/fdivsqrt/fdivsqrtfsm -ftrans state DONE->BUSY # DH 4/22/23: The busy->idle transition only occurs if a FlushE occurs while the divider is busy. The flush is caused by a trap or return, # which won't happen while the divider is busy. coverage exclude -scope /dut/core/fpu/fpu/fdivsqrt/fdivsqrtfsm -ftrans state BUSY->IDLE +# All Memory-stage stalls have resolved by time fdivsqrt finishes regular operation in this configuration, so can't test StallM +coverage exclude -scope /dut/core/fpu/fpu/fdivsqrt/fdivsqrtfsm -linerange [GetLineNum ../src/fpu/fdivsqrt/fdivsqrtfsm.sv "exclusion-tag: fdivsqrtfsm stallm"] -item b 1 +coverage exclude -scope /dut/core/fpu/fpu/fdivsqrt/fdivsqrtfsm -linerange [GetLineNum ../src/fpu/fdivsqrt/fdivsqrtfsm.sv "exclusion-tag: fdivsqrtfsm stallm"] -item s 1 +# Division by zero never sets sticky/guard/overflow/round to cause inexact or underflow result, but check out of paranoia +coverage exclude -scope /dut/core/fpu/fpu/postprocess/flags -linerange [GetLineNum ../src/fpu/postproc/flags.sv "assign FpInexact"] -item e 1 -fecexprrow 15 +coverage exclude -scope /dut/core/fpu/fpu/postprocess/flags -linerange [GetLineNum ../src/fpu/postproc/flags.sv "assign Underflow"] -item e 1 -fecexprrow 22 + +################## +# Cache Exclusions +################## ### Exclude D$ states and logic for the I$ instance # This is cleaner than trying to set an I$-specific pragma in cachefsm.sv (which would exclude it for the D$ instance too) @@ -79,6 +92,7 @@ for {set i 0} {$i < $numcacheways} {incr i} { coverage exclude -scope /dut/core/ifu/bus/icache/icache/CacheWays[$i] -linerange [GetLineNum ../src/cache/cacheway.sv "exclusion-tag: icache SelectedWiteWordEn"] -item e 1 -fecexprrow 4 6 # below: flushD can't go high during an icache write b/c of pipeline stall coverage exclude -scope /dut/core/ifu/bus/icache/icache/CacheWays[$i] -linerange [GetLineNum ../src/cache/cacheway.sv "exclusion-tag: cache SetValidEN"] -item e 1 -fecexprrow 4 + coverage exclude -scope /dut/core/ifu/bus/icache/icache/CacheWays[$i] -linerange [GetLineNum ../src/cache/cacheway.sv "exclusion-tag: cache ClearValidEN"] -item e 1 -fecexprrow 4 } ## D$ Exclusions. @@ -94,6 +108,8 @@ for {set i 0} {$i < $numcacheways} {incr i} { # FlushStage=1 will never happen when SetValidWay=1 since a pipeline stall is asserted by the cache in the fetch stage, which happens before # going into the WRITE_LINE state (and asserting SetValidWay). No TrapM can fire and since StallW is high, a stallM caused by WFIStallM would not cause a flushW. coverage exclude -scope /dut/core/lsu/bus/dcache/dcache/CacheWays[$i] -linerange [GetLineNum ../src/cache/cacheway.sv "exclusion-tag: cache SetValidEN"] -item e 1 -fecexprrow 4 + coverage exclude -scope /dut/core/lsu/bus/dcache/dcache/CacheWays[$i] -linerange [GetLineNum ../src/cache/cacheway.sv "exclusion-tag: cache ClearValidEN"] -item e 1 -fecexprrow 4 +# Not right; other ways can get flushed and dirtied simultaneously coverage exclude -scope /dut/core/lsu/bus/dcache/dcache/CacheWays[$i] -linerange [GetLineNum ../src/cache/cacheway.sv "exclusion-tag: cache UpdateDirty"] -item c 1 -fecexprrow 6 } # D$ writeback, flush, write_line, or flush_writeback states can't be cancelled by a flush coverage exclude -scope /dut/core/lsu/bus/dcache/dcache/cachefsm -ftrans CurrState STATE_WRITEBACK->STATE_READY STATE_FLUSH->STATE_READY STATE_WRITE_LINE->STATE_READY STATE_FLUSH_WRITEBACK->STATE_READY @@ -224,6 +240,17 @@ coverage exclude -scope /dut/core/ifu/immu/immu -linerange $line-$line2 -item e coverage exclude -scope /dut/core/ifu/immu/immu -linerange $line-$line2 -item b 1 coverage exclude -scope /dut/core/ifu/immu/immu -linerange $line-$line2 -item s 1 +# IMMU never disables translations +coverage exclude -scope /dut/core/ifu/ifu/immu/immu/tlb/tlb/tlbcontrol -linerange [GetLineNum ../src/mmu/tlb/tlbcontrol.sv "assign Translate"] -item e 1 -fecexprrow 2 +coverage exclude -scope /dut/core/ifu/ifu/immu/immu/tlb/tlb/tlbcontrol -linerange [GetLineNum ../src/mmu/tlb/tlbcontrol.sv "assign UpdateDA"] -item e 1 -fecexprrow 5 +# never reaches this when ENVCFG_ADUE_1 because HPTW updates A bit first +coverage exclude -scope /dut/core/ifu/ifu/immu/immu/tlb/tlb/tlbcontrol -linerange [GetLineNum ../src/mmu/tlb/tlbcontrol.sv "assign PrePageFault"] -item e 1 -fecexprrow 18 + +# IMMU PMP does not support CBO instructions +coverage exclude -scope /dut/core/ifu/immu/immu/pmp/pmpchecker -linerange [GetLineNum ../src/mmu/pmpchecker.sv "exclusion-tag: immu-pmpcbom"] +coverage exclude -scope /dut/core/ifu/immu/immu/pmp/pmpchecker -linerange [GetLineNum ../src/mmu/pmpchecker.sv "exclusion-tag: immu-pmpcboz"] +coverage exclude -scope /dut/core/ifu/immu/immu/pmp/pmpchecker -linerange [GetLineNum ../src/mmu/pmpchecker.sv "exclusion-tag: immu-pmpcboaccess"] + # No irom set line [GetLineNum ../src/ifu/ifu.sv "~ITLBMissF & ~CacheableF & ~SelIROM"] coverage exclude -scope /dut/core/ifu -linerange $line-$line -item c 1 -feccondrow 6 @@ -258,5 +285,9 @@ coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmp/pmpchecker/pmp/pmpadrdecs[0] # EBU #################### -# Exclude EBU Beat Counter because it is only idle when bus has multicycle latency, but rv64gc has single cycle latency -coverage exclude -scope /core/ebu/ebu/ebufsmarb/BeatCounter +# Exclude EBU Beat Counter flop because it is only idle when bus has multicycle latency, but rv64gc has single cycle latency +coverage exclude -scope /dut/core/ebu/ebu/ebufsmarb/BeatCounter/cntrflop + + + + diff --git a/sim/imperas.ic b/sim/imperas.ic index b35166429..4cebcf526 100644 --- a/sim/imperas.ic +++ b/sim/imperas.ic @@ -11,6 +11,7 @@ --override cpu/mvendorid=0x602 --override cpu/marchid=0x24 --override refRoot/cpu/tvec_align=64 +--override refRoot/cpu/envcfg_mask=1 # bit manipulation --override cpu/add_Extensions=B @@ -21,6 +22,7 @@ --override cpu/Zcb=T --override cpu/Zicond=T --override cpu/Zfh=T +--override cpu/Zfa=T # Cache block operations --override cpu/Zicbom=T @@ -95,6 +97,7 @@ --callcommand refRoot/cpu/setPMA -lo 0x0010000000 -hi 0x0010000007 -attributes " rw-aA- 1--- " # UART0 error - 0x10000000 - 0x100000FF --callcommand refRoot/cpu/setPMA -lo 0x0010060000 -hi 0x00100600FF -attributes " rw-aA- --4- " # GPIO error - 0x10069000 - 0x100600FF --callcommand refRoot/cpu/setPMA -lo 0x0010040000 -hi 0x0010040FFF -attributes " rw-aA- --4- " # SPI error - 0x10040000 - 0x10040FFF +#--callcommand refRoot/cpu/setPMA -lo 0x0080000000 -hi 0x008FFFFFFF -attributes " rwxaA- 1248 " # UNCORE_RAM --callcommand refRoot/cpu/setPMA -lo 0x0080000000 -hi 0x008FFFFFFF -attributes " rwx--- 1248 " # UNCORE_RAM # Enable the Imperas instruction coverage diff --git a/src/cache/cacheway.sv b/src/cache/cacheway.sv index 3445067a0..d7a5ae34a 100644 --- a/src/cache/cacheway.sv +++ b/src/cache/cacheway.sv @@ -105,7 +105,7 @@ module cacheway import cvw::*; #(parameter cvw_t P, assign ClearDirtyWay = ClearDirty & SelData; assign SelectedWriteWordEn = (SetValidWay | SetDirtyWay) & ~FlushStage; // exclusion-tag: icache SelectedWiteWordEn assign SetValidEN = SetValidWay & ~FlushStage; // exclusion-tag: cache SetValidEN - assign ClearValidEN = ClearValidWay & ~FlushStage; // exclusion-tag: cache SetValidEN + assign ClearValidEN = ClearValidWay & ~FlushStage; // exclusion-tag: cache ClearValidEN // If writing the whole line set all write enables to 1, else only set the correct word. assign FinalByteMask = SetValidWay ? '1 : LineByteMask; // OR @@ -178,7 +178,7 @@ module cacheway import cvw::*; #(parameter cvw_t P, //if (reset) DirtyBits <= #1 {NUMLINES{1'b0}}; if(CacheEn) begin Dirty <= #1 DirtyBits[CacheSetTag]; - if((SetDirtyWay | ClearDirtyWay) & ~FlushStage) DirtyBits[CacheSetData] <= #1 SetDirtyWay; + if((SetDirtyWay | ClearDirtyWay) & ~FlushStage) DirtyBits[CacheSetData] <= #1 SetDirtyWay; // exclusion-tag: cache UpdateDirty end end end else assign Dirty = 1'b0; diff --git a/src/fpu/fcmp.sv b/src/fpu/fcmp.sv index e330f1fda..227676203 100755 --- a/src/fpu/fcmp.sv +++ b/src/fpu/fcmp.sv @@ -67,12 +67,13 @@ module fcmp import cvw::*; #(parameter cvw_t P) ( // LT/LE - signaling - sets invalid if NaN input // EQ - quiet - sets invalid if signaling NaN input always_comb begin - case (OpCtrl[2:0]) + casez (OpCtrl[2:0]) 3'b110: CmpNV = EitherSNaN; //min 3'b101: CmpNV = EitherSNaN; //max 3'b010: CmpNV = EitherSNaN; //equal - 3'b001: CmpNV = Zfa ? EitherSNaN : EitherNaN; // fltq / flt perform CompareQuietLess / CompareSignalingLess differing on when to set invalid - 3'b011: CmpNV = Zfa ? EitherSNaN : EitherNaN; // fleq / fle differ on when to set invalid + 3'b0?1: if (P.ZFA_SUPPORTED) + CmpNV = Zfa ? EitherSNaN : EitherNaN; // fltq,fleq / flt,fle perform CompareQuietLess / CompareSignalingLess differing on when to set invalid + else CmpNV = EitherNaN; // flt, fle default: CmpNV = 1'bx; endcase end diff --git a/src/fpu/fctrl.sv b/src/fpu/fctrl.sv index 6d5a91aa6..705a112d1 100755 --- a/src/fpu/fctrl.sv +++ b/src/fpu/fctrl.sv @@ -86,9 +86,8 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( assign Fmt = Funct7D[1:0]; assign Fmt2 = Rs2D[1:0]; // source format for fcvt fp->fp - assign SupportedFmt = (Fmt == 2'b00 | (Fmt == 2'b01 & P.D_SUPPORTED) | - (Fmt == 2'b10 & P.ZFH_SUPPORTED & {OpD[6:4], OpD[1:0]} != 5'b10011) | // fma not supported for Zfh - (Fmt == 2'b11 & P.Q_SUPPORTED)); + assign SupportedFmt = (Fmt == 2'b00 | (Fmt == 2'b01 & P.D_SUPPORTED) | + (Fmt == 2'b10 & P.ZFH_SUPPORTED) | (Fmt == 2'b11 & P.Q_SUPPORTED)); assign SupportedFmt2 = (Fmt2 == 2'b00 | (Fmt2 == 2'b01 & P.D_SUPPORTED) | (Fmt2 == 2'b10 & P.ZFH_SUPPORTED) | (Fmt2 == 2'b11 & P.Q_SUPPORTED)); diff --git a/src/fpu/fdivsqrt/fdivsqrtfsm.sv b/src/fpu/fdivsqrt/fdivsqrtfsm.sv index 862d53b25..cd890ed87 100644 --- a/src/fpu/fdivsqrt/fdivsqrtfsm.sv +++ b/src/fpu/fdivsqrt/fdivsqrtfsm.sv @@ -70,8 +70,8 @@ module fdivsqrtfsm import cvw::*; #(parameter cvw_t P) ( end else if (state == BUSY) begin if (step == 1 | WZeroE) state <= #1 DONE; // finished steps or terminate early on zero residual step <= step - 1; - end else if (state == DONE) begin - if (StallM) state <= #1 DONE; + end else if (state == DONE) begin // Can't still be stalled in configs tested, but keep this check for paranoia + if (StallM) state <= #1 DONE; // exclusion-tag: fdivsqrtfsm stallm else state <= #1 IDLE; end end diff --git a/src/fpu/postproc/cvtshiftcalc.sv b/src/fpu/postproc/cvtshiftcalc.sv index ff3d29b90..77b8543fd 100644 --- a/src/fpu/postproc/cvtshiftcalc.sv +++ b/src/fpu/postproc/cvtshiftcalc.sv @@ -98,6 +98,6 @@ module cvtshiftcalc import cvw::*; #(parameter cvw_t P) ( // determine if the result underflows ??? -> fp // - if the first 1 is shifted out of the result then the result underflows // - can't underflow an integer to fp conversions - assign CvtResUf = ($signed(CvtCe) < $signed({{P.NE-$clog2(P.NF){1'b1}}, ResNegNF}))&~XZero&~IntToFp; + assign CvtResUf = ($signed(CvtCe) < $signed({{P.NE-$clog2(P.NF){1'b1}}, ResNegNF}))&~XZero; // dh &~IntToFp not necessary because integer to float conversion never underflows endmodule diff --git a/src/fpu/postproc/flags.sv b/src/fpu/postproc/flags.sv index 50d9bf229..40fe887ca 100644 --- a/src/fpu/postproc/flags.sv +++ b/src/fpu/postproc/flags.sv @@ -148,8 +148,7 @@ module flags import cvw::*; #(parameter cvw_t P) ( // Set Inexact flag if the result is diffrent from what would be outputed given infinite precision // - Don't set the underflow flag if an underflowed res isn't outputed assign FpInexact = (Sticky|Guard|Overflow|Round)&~(InfIn|NaNIn|DivByZero|Invalid); - //assign FpInexact = (Sticky|Guard|Overflow|Round)&~(InfIn|NaNIn|DivByZero|Invalid|XZero); - + // if the res is too small to be represented and not 0 // | and if the res is not invalid (outside the integer bounds) // | | diff --git a/src/fpu/postproc/fmashiftcalc.sv b/src/fpu/postproc/fmashiftcalc.sv index 0a8ac3035..b13b6d3da 100644 --- a/src/fpu/postproc/fmashiftcalc.sv +++ b/src/fpu/postproc/fmashiftcalc.sv @@ -101,9 +101,9 @@ module fmashiftcalc import cvw::*; #(parameter cvw_t P) ( assign Sum2GEFL = $signed(PreNormSumExp) >= $signed((P.NE+2)'(-P.NF2-2+P.BIAS-P.BIAS2)) | ~|PreNormSumExp; always_comb begin case (Fmt) - P.FMT: FmaPreResultSubnorm = Sum0LEZ & Sum0GEFL & ~FmaSZero; - P.FMT1: FmaPreResultSubnorm = Sum1LEZ & Sum1GEFL & ~FmaSZero; - P.FMT2: FmaPreResultSubnorm = Sum2LEZ & Sum2GEFL & ~FmaSZero; + P.FMT: FmaPreResultSubnorm = Sum0LEZ & Sum0GEFL; // & ~FmaSZero; // checking sum is not zero is harmless but turns out to be unnecessary + P.FMT1: FmaPreResultSubnorm = Sum1LEZ & Sum1GEFL; // & ~FmaSZero; + P.FMT2: FmaPreResultSubnorm = Sum2LEZ & Sum2GEFL; // & ~FmaSZero; default: FmaPreResultSubnorm = 1'bx; endcase end diff --git a/src/fpu/postproc/round.sv b/src/fpu/postproc/round.sv index 460786135..445f563d9 100644 --- a/src/fpu/postproc/round.sv +++ b/src/fpu/postproc/round.sv @@ -68,6 +68,7 @@ module round import cvw::*; #(parameter cvw_t P) ( logic CalcPlus1; // calculated plus1 logic FpPlus1; // do you add one to the fp result logic [P.FLEN:0] RoundAdd; // how much to add to the result + logic CvtToInt; // Convert to integer operation // what position is XLEN in? // options: @@ -111,6 +112,7 @@ module round import cvw::*; #(parameter cvw_t P) ( // determine what format the final result is in: int or fp assign IntRes = ToInt; assign FpRes = ~IntRes; + assign CvtToInt = ToInt; // under current encodings, CvtOp always is 1 when ToInt is selected, so leave it out // sticky bit calculation if (P.FPSIZES == 1) begin @@ -244,9 +246,9 @@ module round import cvw::*; #(parameter cvw_t P) ( endcase end - assign Guard = ToInt&CvtOp ? Mf[P.CORRSHIFTSZ-P.XLEN-1] : FpGuard; - assign LsbRes = ToInt&CvtOp ? Mf[P.CORRSHIFTSZ-P.XLEN] : FpLsbRes; - assign Round = ToInt&CvtOp ? Mf[P.CORRSHIFTSZ-P.XLEN-2] : FpRound; + assign Guard = CvtToInt ? Mf[P.CORRSHIFTSZ-P.XLEN-1] : FpGuard; + assign LsbRes = CvtToInt ? Mf[P.CORRSHIFTSZ-P.XLEN] : FpLsbRes; + assign Round = CvtToInt ? Mf[P.CORRSHIFTSZ-P.XLEN-2] : FpRound; always_comb begin // Determine if you add 1 @@ -272,7 +274,7 @@ module round import cvw::*; #(parameter cvw_t P) ( // If an answer is exact don't round assign Plus1 = CalcPlus1 & (Sticky|Round|Guard); - assign FpPlus1 = Plus1&~(ToInt&CvtOp); + assign FpPlus1 = Plus1&~(CvtToInt); assign UfPlus1 = UfCalcPlus1 & (Sticky|Round); // place Plus1 into the proper position for the format diff --git a/src/fpu/postproc/shiftcorrection.sv b/src/fpu/postproc/shiftcorrection.sv index 1da3556d8..f5860b42d 100644 --- a/src/fpu/postproc/shiftcorrection.sv +++ b/src/fpu/postproc/shiftcorrection.sv @@ -44,7 +44,7 @@ module shiftcorrection import cvw::*; #(parameter cvw_t P) ( output logic [P.NE+1:0] Ue // corrected exponent for divider ); - logic [P.CORRSHIFTSZ-1:0] CorrSumShifted; // the shifted sum after LZA correction + logic [3*P.NF+3:0] CorrSumShifted; // the shifted sum after LZA correction logic [P.CORRSHIFTSZ-1:0] CorrQm0, CorrQm1; // portions of Shifted to select for CorrQmShifted logic [P.CORRSHIFTSZ-1:0] CorrQmShifted; // the shifted divsqrt result after one bit shift logic ResSubnorm; // is the result Subnormal @@ -68,7 +68,7 @@ module shiftcorrection import cvw::*; #(parameter cvw_t P) ( // if the result of the divider was calculated to be subnormal, then the result was correctly normalized, so select the top shifted bits always_comb - if(FmaOp) Mf = {CorrSumShifted}; + if(FmaOp) Mf = {CorrSumShifted, {P.CORRSHIFTSZ-(3*P.NF+4){1'b0}}}; else if (DivOp&~DivResSubnorm) Mf = CorrQmShifted; else Mf = Shifted[P.NORMSHIFTSZ-1:P.NORMSHIFTSZ-P.CORRSHIFTSZ]; diff --git a/src/fpu/postproc/specialcase.sv b/src/fpu/postproc/specialcase.sv index 76784e4a1..ba30daaf2 100644 --- a/src/fpu/postproc/specialcase.sv +++ b/src/fpu/postproc/specialcase.sv @@ -342,7 +342,7 @@ module specialcase import cvw::*; #(parameter cvw_t P) ( else OfIntRes2 = OfIntRes; if (Zfa) Int64Res = {{(P.XLEN-32){CvtNegRes[P.XLEN-1]}}, CvtNegRes[31:0]}; else Int64Res = CvtNegRes[P.XLEN-1:0]; - if (Zfa) SelCvtOfRes = InfIn | NaNIn; // fcvtmod.w.d only overflows to 0 on NaN or Infinity + if (Zfa) SelCvtOfRes = InfIn | NaNIn | (CvtCe > 32 + 52); // fcvtmod.w.d only overflows to 0 on NaN or Infinity, or if the shift is so large that only zeros are left else SelCvtOfRes = IntInvalid; // regular fcvt gives an overflow if out of range end else diff --git a/src/mmu/pmpchecker.sv b/src/mmu/pmpchecker.sv index ef8c42aac..97cc6a18d 100644 --- a/src/mmu/pmpchecker.sv +++ b/src/mmu/pmpchecker.sv @@ -70,13 +70,13 @@ module pmpchecker import cvw::*; #(parameter cvw_t P) ( priorityonehot #(P.PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches. // Only enforce PMP checking for S and U modes or in Machine mode when L bit is set in selected region - assign EnforcePMP = (PrivilegeModeW != P.M_MODE) | (|(L & FirstMatch)); // *** switch to this logic when PMP is initialized for non-machine mode + assign EnforcePMP = (PrivilegeModeW != P.M_MODE) | (|(L & FirstMatch)); - assign PMPCBOMAccessFault = EnforcePMP & (|CMOpM[2:0]) & ~|((R|W) & FirstMatch) ; - assign PMPCBOZAccessFault = EnforcePMP & CMOpM[3] & ~|(W & FirstMatch) ; - assign PMPCMOAccessFault = PMPCBOZAccessFault | PMPCBOMAccessFault; + assign PMPCBOMAccessFault = EnforcePMP & (|CMOpM[2:0]) & ~|((R|W) & FirstMatch) ; // exclusion-tag: immu-pmpcbom + assign PMPCBOZAccessFault = EnforcePMP & CMOpM[3] & ~|(W & FirstMatch) ; // exclusion-tag: immu-pmpcboz + assign PMPCMOAccessFault = PMPCBOZAccessFault | PMPCBOMAccessFault; // exclusion-tag: immu-pmpcboaccess assign PMPInstrAccessFaultF = EnforcePMP & ExecuteAccessF & ~|(X & FirstMatch) ; - assign PMPStoreAmoAccessFaultM = (EnforcePMP & WriteAccessM & ~|(W & FirstMatch)) | PMPCMOAccessFault; + assign PMPStoreAmoAccessFaultM = (EnforcePMP & WriteAccessM & ~|(W & FirstMatch)) | PMPCMOAccessFault; // exclusion-tag: immu-pmpstoreamoaccessfault assign PMPLoadAccessFaultM = EnforcePMP & ReadAccessM & ~|(R & FirstMatch) ; endmodule diff --git a/testbench/tests.vh b/testbench/tests.vh index fecf4ebc9..efb0e6788 100644 --- a/testbench/tests.vh +++ b/testbench/tests.vh @@ -67,6 +67,7 @@ string tvpaths[] = '{ "pmpcfg1", "pmpcfg2", "pmppriority", + "pmpcbo", "pmpadrdecs" }; diff --git a/tests/coverage/Makefile b/tests/coverage/Makefile index 2f6002efc..676e77855 100644 --- a/tests/coverage/Makefile +++ b/tests/coverage/Makefile @@ -17,7 +17,7 @@ all: $(OBJECTS) # Change many things if bit width isn't 64 %.elf: $(SRCDIR)/%.$(SEXT) WALLY-init-lib.h Makefile - riscv64-unknown-elf-gcc -g -o $@ -march=rv64gqc_zba_zbb_zbc_zbs_zfh_zicboz_zicbop_zicbom -mabi=lp64 -mcmodel=medany \ + riscv64-unknown-elf-gcc -g -o $@ -march=rv64gqc_zfa_zba_zbb_zbc_zbs_zfh_zicboz_zicbop_zicbom -mabi=lp64 -mcmodel=medany \ -nostartfiles -T../../examples/link/link.ld $< riscv64-unknown-elf-objdump -S $@ > $@.objdump riscv64-unknown-elf-elf2hex --bit-width 64 --input $@ --output $@.memfile diff --git a/tests/coverage/WALLY-init-lib.h b/tests/coverage/WALLY-init-lib.h index 55bfcf4e5..fdf9be6cf 100644 --- a/tests/coverage/WALLY-init-lib.h +++ b/tests/coverage/WALLY-init-lib.h @@ -24,6 +24,8 @@ //////////////////////////////////////////////////////////////////////////////////////////////// // load code to initalize stack, handle interrupts, terminate +// The PMP tests are sensitive to the exact addresses in this code, so unfortunately +// modifying anything breaks those tests. .section .text.init .global rvtest_entry_point @@ -36,7 +38,11 @@ rvtest_entry_point: csrw mtvec, t0 # Initialize MTVEC to trap_handler csrw mideleg, zero # Don't delegate interrupts csrw medeleg, zero # Don't delegate exceptions +# li t0, -1 # set mtimecmp to biggest number so it doesnt interrupt again +# li t1, 0x02004000 # MTIMECMP in CLINT +# sd t0, 0(t1) li t0, 0x80 +# li t0, 0x00 csrw mie, t0 # Enable machine timer interrupt la t0, topoftrapstack csrw mscratch, t0 # MSCRATCH holds trap stack pointer diff --git a/tests/coverage/ebu.S b/tests/coverage/ebu.S index 8c69f9d11..c6be8e4ef 100644 --- a/tests/coverage/ebu.S +++ b/tests/coverage/ebu.S @@ -1,7 +1,7 @@ /////////////////////////////////////////// // ebu.S // -// Written: David_Harris@hmc.edu 23 March 2023 +// Written: David_Harris@hmc.edu 21 January 2024 // // Purpose: Test coverage for EBU // @@ -24,22 +24,289 @@ //////////////////////////////////////////////////////////////////////////////////////////////// // load code to initalize stack, handle interrupts, terminate + #include "WALLY-init-lib.h" +# run-elf.bash find this in project description main: + li t5, 0x1 + slli t5, t5, 62 + ori t5, t5, 0xF0 + csrs menvcfg, t5 # menvcfg.PBMTE = 1, CBZE, CBCFE, CBIE all 1 - # Test clz with all bits being 0 - li t0, 0 - clz t1, t0 - li t0, -1 - clz t1, t0 - li t0, 1 - clz t1, t0 + # Page table root address at 0x80010000; SV48 + li t5, 0x9000000000080010 + csrw satp, t5 - # Test forwarding from store conditional - lr.w t0, 0(a0) - sc.w t0, a1, 0(a0) - addi t0, t0, 1 + # sfence.vma x0, x0 + # switch to supervisor mode + li a0, 1 + ecall + + # + +# Tricky case to cover. I$ miss concurrent with DTLB miss. HPTW has to hit the first +# access in the cache and miss a later one. Trigger this by doing a load that touches +# a page not in the DTLB but where the top-level PTE is already there. Has to happen +# near the end of the 16-instruction I$ line. +# +# Condition Coverage for instance /core/ebu/ebu/ebufsmarb -- +# +# File ../src/ebu/ebufsmarb.sv +#----------------Focused Condition View------------------- +#Line 72 Item 1 ((HREADY & FinalBeatD) & (LSUReq ~& IFUReq)) +#Condition totals: 2 of 4 input terms covered = 50.00% +# +# Input Term Covered Reason for no coverage Hint +# ----------- -------- ----------------------- -------------- +# HREADY Y +# FinalBeatD Y +# LSUReq N '_1' not hit Hit '_1' +# IFUReq N No hits Hit '_0' and '_1' +# +# Rows: Hits FEC Target Non-masking condition(s) +# --------- --------- -------------------- ------------------------- +# Row 1: 2 HREADY_0 ((LSUReq ~& IFUReq) && FinalBeatD) +# Row 2: 14 HREADY_1 ((LSUReq ~& IFUReq) && FinalBeatD) +# Row 3: 1 FinalBeatD_0 ((LSUReq ~& IFUReq) && HREADY) +# Row 4: 14 FinalBeatD_1 ((LSUReq ~& IFUReq) && HREADY) +# Row 5: 14 LSUReq_0 ((HREADY & FinalBeatD) && IFUReq) +# Row 6: ***0*** LSUReq_1 ((HREADY & FinalBeatD) && IFUReq) +# Row 7: ***0*** IFUReq_0 ((HREADY & FinalBeatD) && LSUReq) +# Row 8: ***0*** IFUReq_1 ((HREADY & FinalBeatD) && LSUReq) + + + li a0, 0x80000000 + li a1, 0x80A00000 + j label1 + +.align 6 # start on multiple of 64 bytes / 16 instruction cache line +label1: + addi t2, t3, 0x100 # occupy part of cache line + sfence.vma # flush tlb + lw t0, 0x234(a0) # load to get an entry in the DTLB accessing top-level PTE + addi t2, t3, 0x103 # occupy part of cache line + addi t2, t3, 0x104 # occupy part of cache line + addi t2, t3, 0x105 # occupy part of cache line + addi t2, t3, 0x106 # occupy part of cache line + addi t2, t3, 0x107 # occupy part of cache line + addi t2, t3, 0x108 # occupy part of cache line + addi t2, t3, 0x109 # occupy part of cache line + addi t2, t3, 0x10A # occupy part of cache line + lw t0, 0x234(a1) # trigger DTLB miss + addi t2, t3, 0x10C # occupy part of cache line + addi t2, t3, 0x10D # occupy part of cache line + addi t2, t3, 0x10E # occupy part of cache line + addi t2, t3, 0x10F # occupy part of cache line + +# next multiple of 16 + addi t2, t3, 0x100 # occupy part of cache line + sfence.vma # flush tlb + lw t0, 0x334(a0) # load to get an entry in the DTLB accessing top-level PTE + addi t2, t3, 0x103 # occupy part of cache line + addi t2, t3, 0x104 # occupy part of cache line + addi t2, t3, 0x105 # occupy part of cache line + addi t2, t3, 0x106 # occupy part of cache line + addi t2, t3, 0x107 # occupy part of cache line + addi t2, t3, 0x108 # occupy part of cache line + addi t2, t3, 0x109 # occupy part of cache line + addi t2, t3, 0x10A # occupy part of cache line + addi t2, t3, 0x10B # occupy part of cache line + lw t0, 0x334(a1) # trigger DTLB miss + addi t2, t3, 0x10D # occupy part of cache line + addi t2, t3, 0x10E # occupy part of cache line + addi t2, t3, 0x10F # occupy part of cache line + +# next multiple of 16 + addi t2, t3, 0x100 # occupy part of cache line + sfence.vma # flush tlb + lw t0, 0x434(a0) # load to get an entry in the DTLB accessing top-level PTE + addi t2, t3, 0x103 # occupy part of cache line + addi t2, t3, 0x104 # occupy part of cache line + addi t2, t3, 0x105 # occupy part of cache line + addi t2, t3, 0x106 # occupy part of cache line + addi t2, t3, 0x107 # occupy part of cache line + addi t2, t3, 0x108 # occupy part of cache line + addi t2, t3, 0x109 # occupy part of cache line + addi t2, t3, 0x10A # occupy part of cache line + addi t2, t3, 0x10B # occupy part of cache line + addi t2, t3, 0x10C # occupy part of cache line + lw t0, 0x434(a1) # trigger DTLB miss + addi t2, t3, 0x10E # occupy part of cache line + addi t2, t3, 0x10F # occupy part of cache line + +# next multiple of 16 + addi t2, t3, 0x100 # occupy part of cache line + sfence.vma # flush tlb + lw t0, 0x534(a0) # load to get an entry in the DTLB accessing top-level PTE + addi t2, t3, 0x103 # occupy part of cache line + addi t2, t3, 0x104 # occupy part of cache line + addi t2, t3, 0x105 # occupy part of cache line + addi t2, t3, 0x106 # occupy part of cache line + addi t2, t3, 0x107 # occupy part of cache line + addi t2, t3, 0x108 # occupy part of cache line + addi t2, t3, 0x109 # occupy part of cache line + addi t2, t3, 0x10A # occupy part of cache line + addi t2, t3, 0x10B # occupy part of cache line + addi t2, t3, 0x10C # occupy part of cache line + addi t2, t3, 0x10D # occupy part of cache line + lw t0, 0x534(a1) # trigger DTLB miss + addi t2, t3, 0x10F # occupy part of cache line + + # wrap up + li a0, 3 # switch back to machine mode because code at 0x80000000 may not have clean page table entry + ecall j done + + +.data + +.align 16 +# root Page table situated at 0x80010000 +pagetable: + .8byte 0x200044C1 # 0x00000000-0x80_00000000: PTE at 0x80011000 C1 dirty, accessed, valid + .8byte 0x00000000000010CF # misaligned terapage at 0x80_00000000 + +# next page table at 0x80011000 +.align 12 + .8byte 0x00000000000010CF # misaligned gigapage at 0x00000000 + .8byte 0x00000000200058C1 # PTE for pages at 0x40000000 + .8byte 0x00000000200048C1 # gigapage at 0x80000000 pointing to 0x80120000 + + +# Next page table at 0x80012000 for gigapage at 0x80000000 +.align 12 + .8byte 0x0000000020004CC1 # for VA starting at 80000000 (pointer to NAPOT 64 KiB pages) + .8byte 0x0000000020014CCF # for VA starting at 80200000 (misaligned megapage) + .8byte 0x00000000200050C1 # for VA starting at 80400000 (bad PBMT pages) + .8byte 0x4000000020004CC1 # for VA starting at 80600000 (bad entry: nonleaf PTE can't have PBMT != 0) + .8byte 0x00000000200054C1 # for VA starting at 80800000 (testing rwx permissiosn with cbom/cboz) + .8byte 0x00000000200058C1 # for VA starting at 80A00000 (pointer to NAPOT 64 KiB pages like at 80000000) + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + .8byte 0x0000000020004CC1 + +# Leaf page table at 0x80013000 with NAPOT pages +.align 12 + #80000000 + .8byte 0xA0000000200020CF + .8byte 0xA0000000200020CF + .8byte 0xA0000000200020CF + .8byte 0xA0000000200020CF + + .8byte 0xA0000000200020CF + .8byte 0xA0000000200020CF + .8byte 0xA0000000200020CF + .8byte 0xA0000000200020CF + + .8byte 0xA0000000200020CF + .8byte 0xA0000000200020CF + .8byte 0xA0000000200020CF + .8byte 0xA0000000200020CF + + .8byte 0xA0000000200020CF + .8byte 0xA0000000200020CF + .8byte 0xA0000000200020CF + .8byte 0xA0000000200020CF + + .8byte 0x80000000200060CF + .8byte 0x80000000200060CF + .8byte 0x80000000200060CF + .8byte 0x80000000200060CF + + .8byte 0x80000000200060CF + .8byte 0x80000000200060CF + .8byte 0x80000000200060CF + .8byte 0x80000000200060CF + + .8byte 0x80000000200060CF + .8byte 0x80000000200060CF + .8byte 0x80000000200060CF + .8byte 0x80000000200060CF + + .8byte 0x80000000200060CF + .8byte 0x80000000200060CF + .8byte 0x80000000200060CF + .8byte 0x80000000200060CF + + .8byte 0x800000002000A0CF + .8byte 0x800000002000A0CF + .8byte 0x800000002000A0CF + .8byte 0x800000002000A0CF + + .8byte 0x800000002000A0CF + .8byte 0x800000002000A0CF + .8byte 0x800000002000A0CF + .8byte 0x800000002000A0CF + + .8byte 0x800000002000A0CF + .8byte 0x800000002000A0CF + .8byte 0x800000002000A0CF + .8byte 0x800000002000A0CF + + .8byte 0x800000002000A0CF + .8byte 0x800000002000A0CF + .8byte 0x800000002000A0CF + .8byte 0x800000002000A0CF + + .8byte 0x800000002000E0CF + .8byte 0x800000002000E0CF + .8byte 0x800000002000E0CF + .8byte 0x800000002000E0CF + + .8byte 0x800000002000E0CF + .8byte 0x800000002000E0CF + +# Leaf page table at 0x80014000 with PBMT pages +.align 12 + #80400000 + .8byte 0x60000000200020CF # reserved entry + +# Leaf page table at 0x80015000 with various permissions for testing CBOM and CBOZ +.align 12 + #80800000 + .8byte 0x00000000200000CF # valid rwx for VA 80800000 + .8byte 0x00000000200000CB # valid r x for VA 80801000 + .8byte 0x00000000200000C3 # valid r for VA 80802000 + .8byte 0x00000000200000C9 # valid x for VA 80803000 + .8byte 0x00000000200000CD # valid wx for VA 80804000 (illegal combination, but used to test tlbcontrol) + .8byte 0x000000002000000F # valid rwx for VA 80805000 for covering ITLB translate and UpdateDA + .8byte 0x20000000200000CF # PBMT=1 for VA 80806000 for covering ITLB BadPBMT + +# Leaf page table at 0x80016000 with NAPOT pages +.align 12 + .8byte 0xA0000000200020CF + .8byte 0xA0000000200020CF + .8byte 0xA0000000200020CF + .8byte 0xA0000000200020CF diff --git a/tests/coverage/fpu.S b/tests/coverage/fpu.S index 29ad9b418..0e3fd80d7 100644 --- a/tests/coverage/fpu.S +++ b/tests/coverage/fpu.S @@ -139,7 +139,7 @@ main: .word 0xc5000007 // Attempting to toggle (Op7 != 7) to 0 on line 97 in fctrl, not sure what instruction this works out to .word 0xe0101053 // toggling (Rs2D == 0) to 0 on line 139 in fctrl. Illegal Intsr (like fclass but incorrect rs2) .word 0xe0100053 // toggling (Rs2D == 0) to 0 on line 141 in fctrl. Illegal Intsr (like fmv but incorrect rs2) - .word 0x40500053 // toggling (Rs2D[4:2] == 0) to 0 on line 145 in fctrl. + .word 0x40D00053 // toggling (Rs2D[4:2] == 0) to 0 on line 145 in fctrl. .word 0x40300053 // toggling SupportFmt2 to 0 on line 145 in fctrl. .word 0x42100053 // toggling (Rs2D[1:0] != 1) to 0 on line 147 in fctrl. Illegal Instr .word 0xf0100053 // toggling (Rs2D == 0) to 0 on line 143 in fctrl. Illegal Instr @@ -155,6 +155,39 @@ main: .word 0xF0007053 // illegal fmv (bad Funct3) .word 0x43007053 // illegal fcvt.d.* (bad Rs2D) .word 0x42207053 // illegal fcvt.d.* (bad Rs2D[1]) + .word 0xD5F00053 // illegal fcvt.h.* (bad Rs2D) + .word 0xC5F00053 // illegal fcvt.*.h (bad Rs2D) + .word 0x04000043 // illegal fmadd.h (h not supported) + + // Test divide by zero with rounding mode toward zero + li t0, 1 + csrw frm, t0 // set rounding mode = 1 + li t0, 0x3f800000 + fcvt.s.w ft1, t0 + fcvt.s.w ft2, zero + fdiv.s ft3, ft1, ft2 + +/* These didn't make a difference + + // Test subtraction of identical denormalized numbers with to exercise FmaPreResultSubnorm logic with FmaSZero + li t0, 0xFFFFFFFF00000001 + fmv.w.x ft1, t0 // smallest denorm + fsub.s ft1, ft1, ft1 // difference = 0 + + li t0, 0x0000000000000001 + fmv.d.x ft1, t0 // smallest denorm + fsub.d ft1, ft1, ft1 // difference = 0 + + // Test subtraction of identical denormalized numbers with to exercise FmaPreResultSubnorm logic with FmaSZero + li t0, 0xFFFFFFFF00100001 + fmv.w.x ft1, t0 // almost largest denorm + fsub.s ft1, ft1, ft1 // difference = 0 + + li t0, 0x0001000000000001 + fmv.d.x ft1, t0 // smallest denorm + fsub.d ft1, ft1, ft1 // difference = 0 + +*/ # Test floating point convert to integer and using result fcvt.w.s t0, f0 diff --git a/tests/coverage/lsu.S b/tests/coverage/lsu.S index c50b79eb7..9ccb32aa8 100644 --- a/tests/coverage/lsu.S +++ b/tests/coverage/lsu.S @@ -30,4 +30,7 @@ main: sfence.vma x0, x0 // sfence.vma to assert TLBFlush + li a0, 0x80000001 # misaligned address + amoadd.w t0, a0, (a0) # amo access to misaligned address + j done \ No newline at end of file diff --git a/tests/coverage/pmpcbo.S b/tests/coverage/pmpcbo.S new file mode 100644 index 000000000..2e7eab642 --- /dev/null +++ b/tests/coverage/pmpcbo.S @@ -0,0 +1,31 @@ +// pmpcbo.S +// David_Harris@hmc.edu 1/21/24 +// Cover PMP checks of cache management instructions + +#include "WALLY-init-lib.h" +main: + + # set up PMP so user and supervisor mode can access partial address space + li t0, 0x080F; +# li t0, 0x0808; + csrw pmpcfg0, t0 # configure PMP0 to TOR RWX and PMP1 to TOR no access + li t0, 0x2003FFFF + li t1, 0xFFFFFFFF + csrw pmpaddr0, t0 # configure PMP0 top of range to 0x800FFFFF to allow all 32-bit addresses + csrw pmpaddr1, t1 # configure PMP1 top of range to 0xFFFFFFFF to prohibit accesses above + + # enable cbo instructions + li t0, 0xF0 + csrw menvcfg, t0 + csrw senvcfg, t0 + + # switch to supervisor mode + li a0, 1 + ecall + + # cbo instructions to PMP-forbidded address + li a0, 0x81000000 # forbidden address + cbo.zero (a0) + cbo.inval (a0) + + j done \ No newline at end of file diff --git a/tests/coverage/tlbmisc.S b/tests/coverage/tlbmisc.S index 67971dd06..db1435008 100644 --- a/tests/coverage/tlbmisc.S +++ b/tests/coverage/tlbmisc.S @@ -62,15 +62,32 @@ main: jalr ra, t0 # jump to misaligned gigapage li t0, 0x80200000 jalr ra, t0 # jump to misaligned megapage + li t0, 0x7FFFFFFF80000000 - # exercise ebufsmarb (not yet providing coverage 1/1/24 DH & RT) - li t0, 0x80000000 - lw t1, 0(t0) # fetch from an address to warm up tlb entries - li t0, 0x80A00000 - lw t1, 0(t0) # trigger TLB miss on a non-first entry - jal backandforth + + jalr ra, t0 # jump to page with UpperBitsUnequal + li t0, 0x0000000080C00000 + jalr ra, t0 # jump to page with bad reserved bits 60:54 in PTE + + # test with ENVCFG_ADUE = 1: switch to machine mode, set ADUE, access page with A=0, clear ADUE, + li a0, 3 + ecall # switch to machine mode + li t0, 1 + slli t0, t0, 61 + csrs menvcfg, t0 # set menvcfg.ADUE + li a0, 1 + ecall # switch back to supervisor mode + li t0, 0x0000000080E00000 + jalr ra, t0 # jump to page without accessed bit yet set + li a0, 3 + ecall # switch to machine mode + li t0, 1 + slli t0, t0, 61 + csrc menvcfg, t0 # clear menvcfg.ADUE + li a0, 1 + ecall # switch back to supervisor mode - # exercise malformed PBMT pages + # exercise malformed PBMT pages # page has PBMT = 3 (reserved) li t0, 0x80400000 @@ -97,7 +114,7 @@ main: li t0, 1 ecall # switch back to supervisor mode li t0, 0x80806000 - jalr ra, t0 # jump to page to exercise ITLB with PBMT !=0 when ENVCFG_BPMTE=0 + jalr ra, t0 # jump to page to exercise ITLB with PBMT !=0 when ENVCFG_PMTE=0 # change back to default trap handler after checking everything that might cause an instruction page fault jal changetodefaulthandler @@ -154,6 +171,8 @@ main: li a0, 1 ecall + + # wrap up li a0, 3 # switch back to machine mode because code at 0x80000000 may not have clean page table entry ecall @@ -229,8 +248,8 @@ pagetable: .8byte 0x4000000020004CC1 # for VA starting at 80600000 (bad entry: nonleaf PTE can't have PBMT != 0) .8byte 0x00000000200054C1 # for VA starting at 80800000 (testing rwx permissiosn with cbom/cboz) .8byte 0x0000000020004CC1 # for VA starting at 80A00000 (pointer to NAPOT 64 KiB pages like at 80000000) - .8byte 0x0000000020004CC1 - .8byte 0x0000000020004CC1 + .8byte 0x0F00000020004CCF # for VA starting at 80C00000 (bad reserved field in bits 60:54) + .8byte 0x000000002000000F # for VA starting at 80E00000 (not dirty or accessed) .8byte 0x0000000020004CC1 .8byte 0x0000000020004CC1 .8byte 0x0000000020004CC1