Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions sim/questa/coverage-exclusions-rv64gc.do
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,9 @@ set line [GetLineNum ${SRC}/mmu/pmpchecker.sv "EnforcePMP & ExecuteAccessF"]
coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmp/pmpchecker -linerange $line-$line -item e 1 -fecexprrow 1,2,4,5,6
set line [GetLineNum ${SRC}/mmu/pmpchecker.sv "EnforcePMP & ExecuteAccessF"]
coverage exclude -scope /dut/core/ifu/immu/immu/pmp/pmpchecker -linerange $line-$line -item e 1 -fecexprrow 3
## A single data access is never simultaneously read and write, so WriteAccessM=1 can never occur
## while the ReadAccessM-qualified load-access-fault term is evaluated (PMPLoadAccessFaultM, row 2).
set line [GetLineNum ${SRC}/mmu/pmpchecker.sv "EnforcePMP & ReadAccessM"]
Comment thread
davidharrishmc marked this conversation as resolved.
Outdated


## The IFU has ReadAccess = WriteAccess = 0 and ExecuteAccess = 1 hardwired, so exclude alternatives
Expand Down Expand Up @@ -412,10 +415,6 @@ coverage exclude -scope /dut/core/lsu/hptw/hptw -linerange $line-$line -item e 1
set line [GetLineNum ${SRC}/mmu/hptw.sv "assign HPTWUpdateDA"]
coverage exclude -scope /dut/core/lsu/hptw/hptw -linerange $line-$line -item e 1 -fecexprrow 3

# NOTE: the hptw instance is at /dut/core/lsu/hptw/hptw (single lsu). The four exclusions above use a
# stale /dut/core/lsu/hptw/hptw path that no longer resolves (silent no-ops) -- left untouched here;
# the two exclusions below use the correct path.

# UPDATE_PTE never self-loops on a cache-bus stall: the PTE being A/D-updated was just read during the
# same uninterrupted walk (LSU stalled, line cannot be evicted), so it is resident/writable in the D$ and
# the UPDATE_PTE store hits. DCacheBusStallM therefore cannot assert in UPDATE_PTE, so the
Expand Down
22 changes: 21 additions & 1 deletion src/mmu/hptw.sv
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ module hptw import cvw::*; #(parameter cvw_t P) (
logic ValidPTE, LeafPTE, ValidLeafPTE, ValidNonLeafPTE;
logic StartWalk;
logic TLBMissOrUpdateDA;
logic ITLBMissReady;
logic MStageMemPending;
logic PRegEn;
logic [2:0] NextPageType;
logic [P.SVMODE_BITS-1:0] SvMode;
Expand Down Expand Up @@ -143,7 +145,25 @@ module hptw import cvw::*; #(parameter cvw_t P) (
// Extract bits from CSRs and inputs
assign SvMode = SATP_REGW[P.XLEN-1:P.XLEN-P.SVMODE_BITS];
assign BasePageTablePPN = SATP_REGW[P.PPN_BITS-1:0];
assign TLBMissOrUpdateDA = DTLBMissOrUpdateDAM | ITLBMissOrUpdateAF;
// Defer servicing an instruction-side (ITLB) miss while a committed M-stage data access
// (load/store/AMO/CMO) is still present. At IDLE, SelHPTW=0 so DCacheBusStallM reflects the LSU
// data op (not an HPTW access). Two hazards motivate the deferral:
// (#1538) Starting the walk while the data op's cache/bus access is mid-flight would seize the
// data cache and drop a committed store. Covered by ~DCacheBusStallM.
// (#1766) Even after the data op has *hit* in the cache (DCacheBusStallM low), the load's read
// data is only valid combinationally while the access still owns the cache. If the
// pipeline is stalled for another reason (here HPTWStall itself, from the pending ITLB
// miss) the load is held in M; starting the walk now re-points the cache SRAMs at the
// PTE sets and the load captures stale data when it finally retires. Covered by
// ~MStageMemPending: hold the walk until the data op leaves the M stage (MemRWM/CMOpM
// deassert), then start the walk against an idle cache.
// This cannot deadlock: the data op's retirement never depends on the (younger) instruction-fetch
// walk, so it drains through the normal LSU stall and the walk starts once it leaves M. Because
// TLBMissOrUpdateDA is low while deferred, HPTWStall is also low for the ITLB miss, so the HPTW
// does not freeze the pipeline against the data op. DTLB misses are never deferred.
assign MStageMemPending = (|MemRWM) | (|CMOpM);
assign ITLBMissReady = ITLBMissOrUpdateAF & ~DCacheBusStallM & ~MStageMemPending;
assign TLBMissOrUpdateDA = DTLBMissOrUpdateDAM | ITLBMissReady;

// Determine which address to translate
mux2 #(P.XLEN) vadrmux(PCSpillF, IEUAdrExtM[P.XLEN-1:0], DTLBWalk, TranslationVAdr);
Expand Down