mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-03 02:05:21 +00:00
Merge branch 'main' of https://github.com/openhwgroup/cvw
This commit is contained in:
commit
cbc44a68ab
@ -246,6 +246,30 @@ coverage exclude -scope /dut/core/ifu/ifu/immu/immu/tlb/tlb/tlbcontrol -linerang
|
|||||||
# never reaches this when ENVCFG_ADUE_1 because HPTW updates A bit first
|
# 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
|
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
|
||||||
|
|
||||||
|
###############
|
||||||
|
# HPTW exclusions
|
||||||
|
###############
|
||||||
|
|
||||||
|
# RV64GC HPTW never starts at L1_ADR
|
||||||
|
set line [GetLineNum ../src/mmu/hptw.sv "InitialWalkerState == L1_ADR"]
|
||||||
|
coverage exclude -scope /dut/core/lsu/lsu/hptw/hptw -linerange $line-$line -item c 1 -feccondrow 2
|
||||||
|
|
||||||
|
# Never possible to get a page fault when neither reading nor writing
|
||||||
|
set line [GetLineNum ../src/mmu/hptw.sv "assign HPTWLoadPageFault"]
|
||||||
|
coverage exclude -scope /dut/core/lsu/lsu/hptw/hptw -linerange $line-$line -item e 1 -fecexprrow 7
|
||||||
|
|
||||||
|
# Never possible to get a store page fault from an ITLB walk
|
||||||
|
set line [GetLineNum ../src/mmu/hptw.sv "assign HPTWStoreAmoPageFault"]
|
||||||
|
coverage exclude -scope /dut/core/lsu/lsu/hptw/hptw -linerange $line-$line -item e 1 -fecexprrow 3
|
||||||
|
|
||||||
|
# Never possible to get Access = 0 on a nonleaf PTE with no OtherPageFault (because InvalidRead/Write will be 1 on the nonleaf)
|
||||||
|
set line [GetLineNum ../src/mmu/hptw.sv "assign HPTWUpdateDA"]
|
||||||
|
coverage exclude -scope /dut/core/lsu/lsu/hptw/hptw -linerange $line-$line -item e 1 -fecexprrow 3
|
||||||
|
|
||||||
|
###############
|
||||||
|
# Other exclusions
|
||||||
|
###############
|
||||||
|
|
||||||
# IMMU PMP does not support CBO instructions
|
# 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-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-pmpcboz"]
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
--override cpu/mvendorid=0x602
|
--override cpu/mvendorid=0x602
|
||||||
--override cpu/marchid=0x24
|
--override cpu/marchid=0x24
|
||||||
--override refRoot/cpu/tvec_align=64
|
--override refRoot/cpu/tvec_align=64
|
||||||
--override refRoot/cpu/envcfg_mask=1
|
--override refRoot/cpu/envcfg_mask=1 # dh 1/26/24 this should be deleted when ImperasDV is updated to allow envcfg.FIOM to be written
|
||||||
|
|
||||||
# bit manipulation
|
# bit manipulation
|
||||||
--override cpu/add_Extensions=B
|
--override cpu/add_Extensions=B
|
||||||
|
@ -93,7 +93,6 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic [P.PA_BITS-1:0] HPTWReadAdr;
|
logic [P.PA_BITS-1:0] HPTWReadAdr;
|
||||||
logic SelHPTWAdr;
|
logic SelHPTWAdr;
|
||||||
logic [P.XLEN+1:0] HPTWAdrExt;
|
logic [P.XLEN+1:0] HPTWAdrExt;
|
||||||
logic ITLBMissOrUpdateDAF;
|
|
||||||
logic DTLBMissOrUpdateDAM;
|
logic DTLBMissOrUpdateDAM;
|
||||||
logic LSUAccessFaultM;
|
logic LSUAccessFaultM;
|
||||||
logic [P.PA_BITS-1:0] HPTWAdr;
|
logic [P.PA_BITS-1:0] HPTWAdr;
|
||||||
@ -113,12 +112,12 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
|||||||
// map hptw access faults onto either the original LSU load/store fault or instruction access fault
|
// map hptw access faults onto either the original LSU load/store fault or instruction access fault
|
||||||
assign LSUAccessFaultM = LSULoadAccessFaultM | LSUStoreAmoAccessFaultM;
|
assign LSUAccessFaultM = LSULoadAccessFaultM | LSUStoreAmoAccessFaultM;
|
||||||
assign HPTWFaultM = LSUAccessFaultM | PBMTFaultM;
|
assign HPTWFaultM = LSUAccessFaultM | PBMTFaultM;
|
||||||
assign HPTWLoadAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[1] & ~MemRWM[0];
|
assign HPTWLoadAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[1] & ~MemRWM[0];
|
||||||
assign HPTWStoreAmoAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[0];
|
assign HPTWStoreAmoAccessFault = LSUAccessFaultM & DTLBWalk & MemRWM[0];
|
||||||
assign HPTWInstrAccessFault = LSUAccessFaultM & ~DTLBWalk;
|
assign HPTWInstrAccessFault = LSUAccessFaultM & ~DTLBWalk;
|
||||||
assign HPTWLoadPageFault = PBMTFaultM & DTLBWalk & MemRWM[1] & ~MemRWM[0];
|
assign HPTWLoadPageFault = PBMTFaultM & DTLBWalk & MemRWM[1] & ~MemRWM[0];
|
||||||
assign HPTWStoreAmoPageFault = PBMTFaultM & DTLBWalk & MemRWM[0];
|
assign HPTWStoreAmoPageFault = PBMTFaultM & DTLBWalk & MemRWM[0];
|
||||||
assign HPTWInstrPageFault = PBMTFaultM & ~DTLBWalk;
|
assign HPTWInstrPageFault = PBMTFaultM & ~DTLBWalk;
|
||||||
|
|
||||||
flopr #(7) HPTWAccesFaultReg(clk, reset, {TakeHPTWFault, HPTWLoadAccessFault, HPTWStoreAmoAccessFault, HPTWInstrAccessFault,
|
flopr #(7) HPTWAccesFaultReg(clk, reset, {TakeHPTWFault, HPTWLoadAccessFault, HPTWStoreAmoAccessFault, HPTWInstrAccessFault,
|
||||||
HPTWLoadPageFault, HPTWStoreAmoPageFault, HPTWInstrPageFault},
|
HPTWLoadPageFault, HPTWStoreAmoPageFault, HPTWInstrPageFault},
|
||||||
@ -127,17 +126,18 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
assign TakeHPTWFault = WalkerState != IDLE;
|
assign TakeHPTWFault = WalkerState != IDLE;
|
||||||
|
|
||||||
assign LoadAccessFaultM = TakeHPTWFault ? HPTWLoadAccessFaultDelay : LSULoadAccessFaultM;
|
// Improve timing by taking HPTW faults off critical path because these are multicycle operations anyway
|
||||||
|
assign LoadAccessFaultM = TakeHPTWFault ? HPTWLoadAccessFaultDelay : LSULoadAccessFaultM;
|
||||||
assign StoreAmoAccessFaultM = TakeHPTWFault ? HPTWStoreAmoAccessFaultDelay : LSUStoreAmoAccessFaultM;
|
assign StoreAmoAccessFaultM = TakeHPTWFault ? HPTWStoreAmoAccessFaultDelay : LSUStoreAmoAccessFaultM;
|
||||||
assign HPTWInstrAccessFaultF = TakeHPTWFault ? HPTWInstrAccessFaultDelay : 1'b0;
|
assign HPTWInstrAccessFaultF = TakeHPTWFault ? HPTWInstrAccessFaultDelay : 1'b0;
|
||||||
assign LoadPageFaultM = TakeHPTWFault ? HPTWLoadPageFaultDelay : LSULoadPageFaultM;
|
assign LoadPageFaultM = TakeHPTWFault ? HPTWLoadPageFaultDelay : LSULoadPageFaultM;
|
||||||
assign StoreAmoPageFaultM = TakeHPTWFault ? HPTWStoreAmoPageFaultDelay : LSUStoreAmoPageFaultM;
|
assign StoreAmoPageFaultM = TakeHPTWFault ? HPTWStoreAmoPageFaultDelay : LSUStoreAmoPageFaultM;
|
||||||
assign HPTWInstrPageFaultF = TakeHPTWFault ? HPTWInstrPageFaultDelay : 1'b0;
|
assign HPTWInstrPageFaultF = TakeHPTWFault ? HPTWInstrPageFaultDelay : 1'b0;
|
||||||
|
|
||||||
// Extract bits from CSRs and inputs
|
// Extract bits from CSRs and inputs
|
||||||
assign SvMode = SATP_REGW[P.XLEN-1:P.XLEN-P.SVMODE_BITS];
|
assign SvMode = SATP_REGW[P.XLEN-1:P.XLEN-P.SVMODE_BITS];
|
||||||
assign BasePageTablePPN = SATP_REGW[P.PPN_BITS-1:0];
|
assign BasePageTablePPN = SATP_REGW[P.PPN_BITS-1:0];
|
||||||
assign TLBMiss = (DTLBMissOrUpdateDAM | ITLBMissOrUpdateDAF);
|
assign TLBMiss = (DTLBMissOrUpdateDAM | ITLBMissF);
|
||||||
|
|
||||||
// Determine which address to translate
|
// Determine which address to translate
|
||||||
mux2 #(P.XLEN) vadrmux(PCSpillF, IEUAdrExtM[P.XLEN-1:0], DTLBWalk, TranslationVAdr);
|
mux2 #(P.XLEN) vadrmux(PCSpillF, IEUAdrExtM[P.XLEN-1:0], DTLBWalk, TranslationVAdr);
|
||||||
@ -203,7 +203,7 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
|||||||
// memory access. If there is the PTE needs to be updated seting Access
|
// memory access. If there is the PTE needs to be updated seting Access
|
||||||
// and possibly also Dirty. Dirty is set if the operation is a store/amo.
|
// and possibly also Dirty. Dirty is set if the operation is a store/amo.
|
||||||
// However any other fault should not cause the update, and updates are in software when ENVCFG_ADUE = 0
|
// However any other fault should not cause the update, and updates are in software when ENVCFG_ADUE = 0
|
||||||
assign HPTWUpdateDA = ValidLeafPTE & (~Accessed | SetDirty) & ENVCFG_ADUE & ~OtherPageFault;
|
assign HPTWUpdateDA = ValidLeafPTE & (~Accessed | SetDirty) & ENVCFG_ADUE & ~OtherPageFault;
|
||||||
|
|
||||||
assign HPTWRW[0] = (WalkerState == UPDATE_PTE); // HPTWRW[0] will always be 0 if ADUE = 0 because HPTWUpdateDA will be 0 so WalkerState never is UPDATE_PTE
|
assign HPTWRW[0] = (WalkerState == UPDATE_PTE); // HPTWRW[0] will always be 0 if ADUE = 0 because HPTWUpdateDA will be 0 so WalkerState never is UPDATE_PTE
|
||||||
assign UpdatePTE = (WalkerState == LEAF) & HPTWUpdateDA; // UpdatePTE will always be 0 if ADUE = 0 because HPTWUpdateDA will be 0
|
assign UpdatePTE = (WalkerState == LEAF) & HPTWUpdateDA; // UpdatePTE will always be 0 if ADUE = 0 because HPTWUpdateDA will be 0
|
||||||
@ -283,7 +283,7 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
|||||||
flopenl #(.TYPE(statetype)) WalkerStateReg(clk, reset | FlushW, 1'b1, NextWalkerState, IDLE, WalkerState);
|
flopenl #(.TYPE(statetype)) WalkerStateReg(clk, reset | FlushW, 1'b1, NextWalkerState, IDLE, WalkerState);
|
||||||
always_comb
|
always_comb
|
||||||
case (WalkerState)
|
case (WalkerState)
|
||||||
IDLE: if (TLBMiss & ~DCacheBusStallM) NextWalkerState = InitialWalkerState;
|
IDLE: if (TLBMiss) NextWalkerState = InitialWalkerState;
|
||||||
else NextWalkerState = IDLE;
|
else NextWalkerState = IDLE;
|
||||||
L3_ADR: NextWalkerState = L3_RD; // first access in SV48
|
L3_ADR: NextWalkerState = L3_RD; // first access in SV48
|
||||||
L3_RD: if (DCacheBusStallM) NextWalkerState = L3_RD;
|
L3_RD: if (DCacheBusStallM) NextWalkerState = L3_RD;
|
||||||
@ -294,7 +294,7 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
|||||||
L2_RD: if (DCacheBusStallM) NextWalkerState = L2_RD;
|
L2_RD: if (DCacheBusStallM) NextWalkerState = L2_RD;
|
||||||
else if(HPTWFaultM) NextWalkerState = FAULT;
|
else if(HPTWFaultM) NextWalkerState = FAULT;
|
||||||
else NextWalkerState = L1_ADR;
|
else NextWalkerState = L1_ADR;
|
||||||
L1_ADR: if (InitialWalkerState == L1_ADR | ValidNonLeafPTE) NextWalkerState = L1_RD; // first access in SV32
|
L1_ADR: if (InitialWalkerState == L1_ADR | ValidNonLeafPTE) NextWalkerState = L1_RD; // first access in SV32
|
||||||
else NextWalkerState = LEAF;
|
else NextWalkerState = LEAF;
|
||||||
L1_RD: if (DCacheBusStallM) NextWalkerState = L1_RD;
|
L1_RD: if (DCacheBusStallM) NextWalkerState = L1_RD;
|
||||||
else if(HPTWFaultM) NextWalkerState = FAULT;
|
else if(HPTWFaultM) NextWalkerState = FAULT;
|
||||||
@ -320,9 +320,8 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
|||||||
// The FSM directly transistions to IDLE to ready for the next operation when the delayed version will not be high.
|
// The FSM directly transistions to IDLE to ready for the next operation when the delayed version will not be high.
|
||||||
|
|
||||||
assign HPTWAccessFaultDelay = HPTWLoadAccessFaultDelay | HPTWStoreAmoAccessFaultDelay | HPTWInstrAccessFaultDelay;
|
assign HPTWAccessFaultDelay = HPTWLoadAccessFaultDelay | HPTWStoreAmoAccessFaultDelay | HPTWInstrAccessFaultDelay;
|
||||||
assign HPTWStall = (WalkerState != IDLE & WalkerState != FAULT) | (WalkerState == IDLE & TLBMiss);
|
assign HPTWStall = (WalkerState != IDLE & WalkerState != FAULT) | (WalkerState == IDLE & TLBMiss);
|
||||||
|
|
||||||
assign ITLBMissOrUpdateDAF = ITLBMissF | (P.SVADU_SUPPORTED & InstrUpdateDAF);
|
|
||||||
assign DTLBMissOrUpdateDAM = DTLBMissM | (P.SVADU_SUPPORTED & DataUpdateDAM);
|
assign DTLBMissOrUpdateDAM = DTLBMissM | (P.SVADU_SUPPORTED & DataUpdateDAM);
|
||||||
|
|
||||||
// HTPW address/data/control muxing
|
// HTPW address/data/control muxing
|
||||||
|
@ -123,6 +123,27 @@ main:
|
|||||||
li t0, 0x80806000
|
li t0, 0x80806000
|
||||||
jalr ra, t0 # jump to page to exercise ITLB with PBMT !=0 when ENVCFG_PMTE=0
|
jalr ra, t0 # jump to page to exercise ITLB with PBMT !=0 when ENVCFG_PMTE=0
|
||||||
|
|
||||||
|
# Load and AMO operation on page table entry that causes access fault
|
||||||
|
li t0, 0x81000000
|
||||||
|
lw t1, 0(t0)
|
||||||
|
sfence.vma
|
||||||
|
amoadd.w t0, t0, 0(t0)
|
||||||
|
|
||||||
|
# Access fault on top level PTE
|
||||||
|
li t0, 0x1000000000
|
||||||
|
lw t1, 0(t0)
|
||||||
|
|
||||||
|
# Access fault on megapage
|
||||||
|
li t0, 0x81400000
|
||||||
|
lw t1, 0(t0)
|
||||||
|
|
||||||
|
# AMO operation on page table entry that causes page fault due to malformed PBMT
|
||||||
|
li t0, 0x81200000
|
||||||
|
jalr t0 # Attempt to fetch instruction from address causing faulty page walk
|
||||||
|
lw t1, 0(t0)
|
||||||
|
sfence.vma
|
||||||
|
amoadd.w t0, t0, 0(t0)
|
||||||
|
|
||||||
# change back to default trap handler after checking everything that might cause an instruction page fault
|
# change back to default trap handler after checking everything that might cause an instruction page fault
|
||||||
jal changetodefaulthandler
|
jal changetodefaulthandler
|
||||||
|
|
||||||
@ -178,8 +199,6 @@ main:
|
|||||||
li a0, 1
|
li a0, 1
|
||||||
ecall
|
ecall
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# wrap up
|
# wrap up
|
||||||
li a0, 3 # switch back to machine mode because code at 0x80000000 may not have clean page table entry
|
li a0, 3 # switch back to machine mode because code at 0x80000000 may not have clean page table entry
|
||||||
ecall
|
ecall
|
||||||
@ -237,32 +256,30 @@ ipf:
|
|||||||
.align 16
|
.align 16
|
||||||
# root Page table situated at 0x80010000
|
# root Page table situated at 0x80010000
|
||||||
pagetable:
|
pagetable:
|
||||||
.8byte 0x200044C1 # 0x00000000-0x80_00000000: PTE at 0x80011000 C1 dirty, accessed, valid
|
.8byte 0x200044C1 # 0x00000000-0x7F_FFFFFFFF: PTE at 0x80011000 C1 dirty, accessed, valid
|
||||||
.8byte 0x00000000000010CF # misaligned terapage at 0x80_00000000
|
.8byte 0x00000000000010CF # misaligned terapage at 0x80_00000000
|
||||||
|
.8byte 0x00000000000000CF # access fault terapage at 0x100_00000000
|
||||||
|
|
||||||
# next page table at 0x80011000
|
# next page table at 0x80011000
|
||||||
.align 12
|
.align 12
|
||||||
.8byte 0x00000000000010CF # misaligned gigapage at 0x00000000
|
.8byte 0x00000000000010CF # misaligned gigapage at 0x00000000
|
||||||
.8byte 0x00000000200058C1 # PTE for pages at 0x40000000
|
.8byte 0x00000000200058C1 # PTE for pages at 0x40000000 pointing to 0x80150000
|
||||||
.8byte 0x00000000200048C1 # gigapage at 0x80000000 pointing to 0x80120000
|
.8byte 0x00000000200048C1 # gigapage at 0x80000000 pointing to 0x80120000
|
||||||
|
|
||||||
|
|
||||||
# Next page table at 0x80012000 for gigapage at 0x80000000
|
# Next page table at 0x80012000 for gigapage at 0x80000000
|
||||||
.align 12
|
.align 12
|
||||||
.8byte 0x0000000020004CC1 # for VA starting at 80000000 (pointer to NAPOT 64 KiB pages)
|
.8byte 0x0000000020004CC1 # for VA starting at 80000000 (pointer to NAPOT 64 KiB pages Page table at 80013000)
|
||||||
.8byte 0x0000000020014CCF # for VA starting at 80200000 (misaligned megapage)
|
.8byte 0x0000000020014CCF # for VA starting at 80200000 (misaligned megapage)
|
||||||
.8byte 0x00000000200050C1 # for VA starting at 80400000 (bad PBMT pages)
|
.8byte 0x00000000200050C1 # for VA starting at 80400000 (bad PBMT pages page table at 0x80014000)
|
||||||
.8byte 0x4000000020004CC1 # for VA starting at 80600000 (bad entry: nonleaf PTE can't have PBMT != 0)
|
.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 0x00000000200054C1 # for VA starting at 80800000 (testing rwx permissiosn with cbom/cboz . page table at 0x80015000)
|
||||||
.8byte 0x0000000020004CC1 # for VA starting at 80A00000 (pointer to NAPOT 64 KiB pages like at 80000000)
|
.8byte 0x0000000020004CC1 # for VA starting at 80A00000 (pointer to NAPOT 64 KiB pages like at 80000000. page table at 0x80013000)
|
||||||
.8byte 0x0F00000020004CCF # for VA starting at 80C00000 (bad reserved field in bits 60:54)
|
.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 0x000000002000000F # for VA starting at 80E00000 (megapage not dirty or accessed)
|
||||||
.8byte 0x0000000020004CC1
|
.8byte 0x0000000000004CC1 # for VA starting at 81000000 (nonleaf pointing to unimplemented memory causes access fault)
|
||||||
.8byte 0x0000000020004CC1
|
.8byte 0x4000000020004CC1 # for VA starting at 81200000 (nonleaf with PBMT nonzero causes page fault)
|
||||||
.8byte 0x0000000020004CC1
|
.8byte 0x00000000000000CF # for VA starting at 81400000 (megapage with access fault)
|
||||||
.8byte 0x0000000020004CC1
|
|
||||||
.8byte 0x0000000020004CC1
|
|
||||||
.8byte 0x0000000020004CC1
|
|
||||||
.8byte 0x0000000020004CC1
|
.8byte 0x0000000020004CC1
|
||||||
.8byte 0x0000000020004CC1
|
.8byte 0x0000000020004CC1
|
||||||
.8byte 0x0000000020004CC1
|
.8byte 0x0000000020004CC1
|
||||||
@ -288,7 +305,7 @@ pagetable:
|
|||||||
.8byte 0x0000000020004CC1
|
.8byte 0x0000000020004CC1
|
||||||
.8byte 0x0000000020004CC1
|
.8byte 0x0000000020004CC1
|
||||||
|
|
||||||
# Leaf page table at 0x80013000 with NAPOT pages
|
# Leaf page table at 0x80013000 with 64 KiB NAPOT pages
|
||||||
.align 12
|
.align 12
|
||||||
#80000000
|
#80000000
|
||||||
.8byte 0xA0000000200020CF
|
.8byte 0xA0000000200020CF
|
||||||
|
Loading…
Reference in New Issue
Block a user