未验证 提交 5b7ef044 编写于 作者: L Lemover 提交者: GitHub

pmp: add static pmp check that stored in tlb entries (#1366)

* memblock: regnext ptw's resp

* pmp: timing optimization from tlb.sram.ppn to pmp, add static pmp check

long latency: tlb's sram may be slow to gen ppn, ppn to pmp may be
long latency.
Solution: add static pmp check.

Fatal problem: pmp grain is smalled than TLB pages(4KB, 2MB, 1GB)
Solution: increase pmp'grain to 4K, for 4K entries, pre-check pmp and
store the result into tlb storage. For super pages, still dynamic check
that translation and check.

* pmp: change pmp grain to 4KB, change pma relative init config

* bump ready-to-run, update nemu so for pmp grain

* bump ready-to-run, update nemu so for pmp grain again

  update pmp unit test. The old test assumes that pmp grain is less than 512bit.
上级 bd1f1bf3
Subproject commit 383fc68ae7d7e53445c4114130dedb25d54f9369
Subproject commit 379f6a2009b2719436d55e80895680dcc8ed139d
......@@ -127,6 +127,7 @@ class MinimalConfig(n: Int = 1) extends Config(
normalReplacer = Some("setplru"),
superNWays = 4,
normalAsVictim = true,
partialStaticPMP = true,
outReplace = true
),
sttlbParameters = TLBParameters(
......@@ -137,6 +138,7 @@ class MinimalConfig(n: Int = 1) extends Config(
normalReplacer = Some("setplru"),
normalAsVictim = true,
superNWays = 4,
partialStaticPMP = true,
outReplace = true
),
btlbParameters = TLBParameters(
......
......@@ -29,10 +29,10 @@ case class PMParameters
NumPMP: Int = 16,
NumPMA: Int = 16,
PlatformGrain: Int = log2Ceil(512/8), // 512 bits
PlatformGrain: Int = log2Ceil(4*1024), // 4KB, a normal page
mmpma: MMPMAConfig = MMPMAConfig(
address = 0x38021000,
mask = 0x1ff,
mask = 0xfff,
lgMaxSize = 3,
sameCycle = true,
num = 2
......
......@@ -184,6 +184,7 @@ case class XSCoreParameters
superNWays = 8,
normalAsVictim = true,
outReplace = true,
partialStaticPMP = true,
saveLevel = true
),
sttlbParameters: TLBParameters = TLBParameters(
......@@ -195,6 +196,7 @@ case class XSCoreParameters
superNWays = 8,
normalAsVictim = true,
outReplace = true,
partialStaticPMP = true,
saveLevel = true
),
refillBothTlb: Boolean = false,
......
......@@ -183,19 +183,28 @@ class MemBlockImp(outer: MemBlock) extends LazyModuleImp(outer)
}
val dtlb = dtlb_ld ++ dtlb_st
val ptw_resp_next = RegEnable(io.ptw.resp.bits, io.ptw.resp.valid)
val ptw_resp_v = RegNext(io.ptw.resp.valid && !(sfence.valid && tlbcsr.satp.changed), init = false.B)
io.ptw.resp.ready := true.B
(dtlb_ld.map(_.ptw.req) ++ dtlb_st.map(_.ptw.req)).zipWithIndex.map{ case (tlb, i) =>
tlb(0) <> io.ptw.req(i)
val vector_hit = if (refillBothTlb) Cat(ptw_resp_next.vector).orR
else if (i < exuParameters.LduCnt) Cat(ptw_resp_next.vector.take(exuParameters.LduCnt)).orR
else Cat(ptw_resp_next.vector.drop(exuParameters.LduCnt)).orR
io.ptw.req(i).valid := tlb(0).valid && !(ptw_resp_v && vector_hit &&
ptw_resp_next.data.entry.hit(tlb(0).bits.vpn, tlbcsr.satp.asid, allType = true, ignoreAsid = true))
}
dtlb_ld.map(_.ptw.resp.bits := io.ptw.resp.bits.data)
dtlb_st.map(_.ptw.resp.bits := io.ptw.resp.bits.data)
dtlb_ld.map(_.ptw.resp.bits := ptw_resp_next.data)
dtlb_st.map(_.ptw.resp.bits := ptw_resp_next.data)
if (refillBothTlb) {
dtlb_ld.map(_.ptw.resp.valid := io.ptw.resp.valid && Cat(io.ptw.resp.bits.vector).orR)
dtlb_st.map(_.ptw.resp.valid := io.ptw.resp.valid && Cat(io.ptw.resp.bits.vector).orR)
dtlb_ld.map(_.ptw.resp.valid := ptw_resp_v && Cat(ptw_resp_next.vector).orR)
dtlb_st.map(_.ptw.resp.valid := ptw_resp_v && Cat(ptw_resp_next.vector).orR)
} else {
dtlb_ld.map(_.ptw.resp.valid := io.ptw.resp.valid && Cat(io.ptw.resp.bits.vector.take(exuParameters.LduCnt)).orR)
dtlb_st.map(_.ptw.resp.valid := io.ptw.resp.valid && Cat(io.ptw.resp.bits.vector.drop(exuParameters.LduCnt)).orR)
dtlb_ld.map(_.ptw.resp.valid := ptw_resp_v && Cat(ptw_resp_next.vector.take(exuParameters.LduCnt)).orR)
dtlb_st.map(_.ptw.resp.valid := ptw_resp_v && Cat(ptw_resp_next.vector.drop(exuParameters.LduCnt)).orR)
}
io.ptw.resp.ready := true.B
// pmp
val pmp = Module(new PMP())
......@@ -206,6 +215,12 @@ class MemBlockImp(outer: MemBlock) extends LazyModuleImp(outer)
p.apply(tlbcsr.priv.dmode, pmp.io.pmp, pmp.io.pma, d)
require(p.req.bits.size.getWidth == d.bits.size.getWidth)
}
val pmp_check_ptw = Module(new PMPCheckerv2(lgMaxSize = 3, sameCycle = false, leaveHitMux = true))
pmp_check_ptw.io.apply(tlbcsr.priv.dmode, pmp.io.pmp, pmp.io.pma, io.ptw.resp.valid,
Cat(io.ptw.resp.bits.data.entry.ppn, 0.U(12.W)).asUInt)
dtlb_ld.map(_.ptw_replenish := pmp_check_ptw.io.resp)
dtlb_st.map(_.ptw_replenish := pmp_check_ptw.io.resp)
val tdata = Reg(Vec(6, new MatchTriggerIO))
val tEnable = RegInit(VecInit(Seq.fill(6)(false.B)))
val en = csrCtrl.trigger_enable
......
......@@ -107,12 +107,12 @@ trait PMAMethod extends PMAConst {
MemMap("h00_3800_0000", "h00_3800_FFFF", "h0", "CLINT", "RW"),
MemMap("h00_3801_0000", "h00_3801_FFFF", "h0", "BEU", "RW"),
MemMap("h00_3802_0000", "h00_3802_0FFF", "h0", "DebugModule", "RWX"),
MemMap("h00_3802_1000", "h00_3802_11FF", "h0", "MMPMA", "RW"),
MemMap("h00_3802_1200", "h00_3900_0FFF", "h0", "Reserved", ""),
MemMap("h00_3900_1000", "h00_3900_103F", "h0", "Core_reset", "RW"),
MemMap("h00_3900_1020", "h00_39FF_FFFF", "h0", "Reserved", ""),
MemMap("h00_3A00_0000", "h00_3A00_003F", "h0", "PLL0", "RW),
MemMap('h00_3A00_0020", "h00_3BFF_FFFF", "h0", "Reserved", ""),
MemMap("h00_3802_1000", "h00_3802_1FFF", "h0", "MMPMA", "RW"),
MemMap("h00_3802_2000", "h00_3900_0FFF", "h0", "Reserved", ""),
MemMap("h00_3900_1000", "h00_3900_1FFF", "h0", "Core_reset", "RW"),
MemMap("h00_3900_2000", "h00_39FF_FFFF", "h0", "Reserved", ""),
MemMap("h00_3A00_0000", "h00_3A00_0FFF", "h0", "PLL0", "RW),
MemMap('h00_3A00_1000", "h00_3BFF_FFFF", "h0", "Reserved", ""),
MemMap("h00_3C00_0000", "h00_3FFF_FFFF", "h0", "PLIC", "RW"),
MemMap("h00_4000_0000", "h00_7FFF_FFFF", "h0", "PCIe", "RW"),
MemMap("h00_8000_0000", "h0F_FFFF_FFFF", "h0", "DDR", "RWXIDSA"),
......@@ -154,7 +154,7 @@ trait PMAMethod extends PMAConst {
cfg(idx).a := 1.U
idx = idx - 1
addr(idx) := shift_addr(0x3A000040)
addr(idx) := shift_addr(0x3A001000)
cfg(idx).a := 1.U; cfg(idx).r := true.B; cfg(idx).w := true.B
idx = idx - 1
......@@ -162,7 +162,7 @@ trait PMAMethod extends PMAConst {
cfg(idx).a := 1.U
idx = idx - 1
addr(idx) := shift_addr(0x39001040)
addr(idx) := shift_addr(0x39002000)
cfg(idx).a := 1.U; cfg(idx).r := true.B; cfg(idx).w := true.B
idx = idx - 1
......@@ -170,7 +170,7 @@ trait PMAMethod extends PMAConst {
cfg(idx).a := 1.U
idx = idx - 1
addr(idx) := shift_addr(0x38021200)
addr(idx) := shift_addr(0x38022000)
cfg(idx).a := 1.U; cfg(idx).r := true.B; cfg(idx).w := true.B
idx = idx - 1
......
......@@ -465,6 +465,30 @@ class PMPCheckIO(lgMaxSize: Int)(implicit p: Parameters) extends PMPBundle {
override def cloneType: this.type = (new PMPCheckIO(lgMaxSize)).asInstanceOf[this.type]
}
class PMPCheckv2IO(lgMaxSize: Int)(implicit p: Parameters) extends PMPBundle {
val check_env = Input(new PMPCheckerEnv())
val req = Flipped(Valid(new PMPReqBundle(lgMaxSize))) // usage: assign the valid to fire signal
val resp = Output(new PMPConfig())
def apply(mode: UInt, pmp: Vec[PMPEntry], pma: Vec[PMPEntry], req: Valid[PMPReqBundle]) = {
check_env.apply(mode, pmp, pma)
this.req := req
resp
}
def req_apply(valid: Bool, addr: UInt): Unit = {
this.req.valid := valid
this.req.bits.apply(addr)
}
def apply(mode: UInt, pmp: Vec[PMPEntry], pma: Vec[PMPEntry], valid: Bool, addr: UInt) = {
check_env.apply(mode, pmp, pma)
req_apply(valid, addr)
resp
}
override def cloneType: this.type = (new PMPCheckv2IO(lgMaxSize)).asInstanceOf[this.type]
}
@chiselName
class PMPChecker
(
......@@ -493,4 +517,44 @@ class PMPChecker
} else {
io.resp := RegEnable(resp, io.req.valid)
}
}
/* get config with check */
@chiselName
class PMPCheckerv2
(
lgMaxSize: Int = 3,
sameCycle: Boolean = false,
leaveHitMux: Boolean = false
)(implicit p: Parameters) extends PMPModule
with PMPCheckMethod
with PMACheckMethod
{
require(!(leaveHitMux && sameCycle))
val io = IO(new PMPCheckv2IO(lgMaxSize))
val req = io.req.bits
val res_pmp = pmp_match_res(leaveHitMux, io.req.valid)(req.addr, req.size, io.check_env.pmp, io.check_env.mode, lgMaxSize)
val res_pma = pma_match_res(leaveHitMux, io.req.valid)(req.addr, req.size, io.check_env.pma, io.check_env.mode, lgMaxSize)
val resp = and(res_pmp, res_pma)
if (sameCycle || leaveHitMux) {
io.resp := resp
} else {
io.resp := RegEnable(resp, io.req.valid)
}
def and(pmp: PMPEntry, pma: PMPEntry): PMPConfig = {
val tmp_res = Wire(new PMPConfig)
tmp_res.l := DontCare
tmp_res.a := DontCare
tmp_res.r := pmp.cfg.r && pma.cfg.r
tmp_res.w := pmp.cfg.w && pma.cfg.w
tmp_res.x := pmp.cfg.x && pma.cfg.x
tmp_res.c := pma.cfg.c
tmp_res.atomic := pma.cfg.atomic
tmp_res
}
}
\ No newline at end of file
......@@ -25,7 +25,8 @@ import xiangshan.backend.rob.RobPtr
import xiangshan.backend.fu.util.HasCSRConst
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
import freechips.rocketchip.tilelink._
import xiangshan.backend.fu.PMPReqBundle
import xiangshan.backend.fu.{PMPReqBundle, PMPConfig}
abstract class TlbBundle(implicit p: Parameters) extends XSBundle with HasTlbConst
abstract class TlbModule(implicit p: Parameters) extends XSModule with HasTlbConst
......@@ -50,6 +51,22 @@ class PtePermBundle(implicit p: Parameters) extends TlbBundle {
}
}
class TlbPMBundle(implicit p: Parameters) extends TlbBundle {
val r = Bool()
val w = Bool()
val x = Bool()
val c = Bool()
val atomic = Bool()
def assign_ap(pm: PMPConfig) = {
r := pm.r
w := pm.w
x := pm.x
c := pm.c
atomic := pm.atomic
}
}
class TlbPermBundle(implicit p: Parameters) extends TlbBundle {
val pf = Bool() // NOTE: if this is true, just raise pf
val af = Bool() // NOTE: if this is true, just raise af
......@@ -62,8 +79,11 @@ class TlbPermBundle(implicit p: Parameters) extends TlbBundle {
val w = Bool()
val r = Bool()
val pm = new TlbPMBundle
override def toPrintable: Printable = {
p"pf:${pf} af:${af} d:${d} a:${a} g:${g} u:${u} x:${x} w:${w} r:${r}"
p"pf:${pf} af:${af} d:${d} a:${a} g:${g} u:${u} x:${x} w:${w} r:${r} " +
p"pm:${pm}"
}
}
......@@ -191,7 +211,7 @@ class TlbEntry(pageNormal: Boolean, pageSuper: Boolean)(implicit p: Parameters)
))
}
def apply(item: PtwResp, asid: UInt): TlbEntry = {
def apply(item: PtwResp, asid: UInt, pm: PMPConfig): TlbEntry = {
this.tag := {if (pageNormal) item.entry.tag else item.entry.tag(vpnLen-1, vpnnLen)}
this.asid := asid
val inner_level = item.entry.level.getOrElse(0.U)
......@@ -211,6 +231,8 @@ class TlbEntry(pageNormal: Boolean, pageSuper: Boolean)(implicit p: Parameters)
this.perm.w := ptePerm.w
this.perm.r := ptePerm.r
this.perm.pm.assign_ap(pm)
this
}
......@@ -271,6 +293,7 @@ class TlbStorageIO(nSets: Int, nWays: Int, ports: Int)(implicit p: Parameters) e
val w = Flipped(ValidIO(new Bundle {
val wayIdx = Output(UInt(log2Up(nWays).W))
val data = Output(new PtwResp)
val data_replenish = Output(new PMPConfig)
}))
val victim = new Bundle {
val out = ValidIO(Output(new Bundle {
......@@ -291,10 +314,11 @@ class TlbStorageIO(nSets: Int, nWays: Int, ports: Int)(implicit p: Parameters) e
(this.r.resp_hit_sameCycle(i), this.r.resp(i).bits.hit, this.r.resp(i).bits.ppn, this.r.resp(i).bits.perm)
}
def w_apply(valid: Bool, wayIdx: UInt, data: PtwResp): Unit = {
def w_apply(valid: Bool, wayIdx: UInt, data: PtwResp, data_replenish: PMPConfig): Unit = {
this.w.valid := valid
this.w.bits.wayIdx := wayIdx
this.w.bits.data := data
this.w.bits.data_replenish := data_replenish
}
override def cloneType: this.type = new TlbStorageIO(nSets, nWays, ports).asInstanceOf[this.type]
......@@ -364,6 +388,7 @@ class TlbResp(implicit p: Parameters) extends TlbBundle {
val pf = new TlbExceptionBundle()
val af = new TlbExceptionBundle()
}
val static_pm = Output(Valid(Bool())) // valid for static, bits for mmio result from normal entries
val ptwBack = Output(Bool()) // when ptw back, wake up replay rs's state
override def toPrintable: Printable = {
......@@ -401,6 +426,7 @@ class TlbIO(Width: Int, q: TLBParameters)(implicit p: Parameters) extends
MMUIOBaseBundle {
val requestor = Vec(Width, Flipped(new TlbRequestIO))
val ptw = new TlbPtwIO(Width)
val ptw_replenish = Input(new PMPConfig())
val replace = if (q.outReplace) Flipped(new TlbReplaceIO(Width, q)) else null
val pmp = Vec(Width, ValidIO(new PMPReqBundle()))
......
......@@ -43,6 +43,7 @@ case class TLBParameters
normalAsVictim: Boolean = false, // when get replace from fa, store it into sram
outReplace: Boolean = false,
shouldBlock: Boolean = false, // only for perf, not support for io
partialStaticPMP: Boolean = false, // partila static pmp result stored in entries
saveLevel: Boolean = false
)
......
......@@ -146,8 +146,12 @@ class TLB(Width: Int, q: TLBParameters)(implicit p: Parameters) extends TlbModul
resp(i).bits.fast_miss := fast_miss
resp(i).bits.ptwBack := io.ptw.resp.fire()
// for timing optimization, pmp check is divided into dynamic and static
// dynamic: superpage (or full-connected reg entries) -> check pmp when translation done
// static: 4K pages (or sram entries) -> check pmp with pre-checked results
val pmp_paddr = Mux(vmEnable, Cat(super_ppn, offReg), if (!q.sameCycle) RegNext(vaddr) else vaddr)
pmp(i).valid := resp(i).valid
pmp(i).bits.addr := resp(i).bits.paddr
pmp(i).bits.addr := pmp_paddr
pmp(i).bits.size := sizeReg
pmp(i).bits.cmd := cmdReg
......@@ -169,9 +173,14 @@ class TLB(Width: Int, q: TLBParameters)(implicit p: Parameters) extends TlbModul
// but ptw may also have access fault, then af happens, the translation is wrong.
// In this case, pf has lower priority than af
resp(i).bits.excp.af.ld := af && TlbCmd.isRead(cmdReg) && fault_valid
resp(i).bits.excp.af.st := af && TlbCmd.isWrite(cmdReg) && fault_valid
resp(i).bits.excp.af.instr := af && TlbCmd.isExec(cmdReg) && fault_valid
val spm = normal_perm.pm // static physical memory protection or attribute
val spm_v = !super_hit && vmEnable && q.partialStaticPMP.B // static pm valid; do not use normal_hit, it's too long.
// for tlb without sram, tlb will miss, pm should be ignored outsize
resp(i).bits.excp.af.ld := (af || (spm_v && !spm.r)) && TlbCmd.isRead(cmdReg) && fault_valid
resp(i).bits.excp.af.st := (af || (spm_v && !spm.w)) && TlbCmd.isWrite(cmdReg) && fault_valid
resp(i).bits.excp.af.instr := (af || (spm_v && !spm.x)) && TlbCmd.isExec(cmdReg) && fault_valid
resp(i).bits.static_pm.valid := spm_v && fault_valid // ls/st unit should use this mmio, not the result from pmp
resp(i).bits.static_pm.bits := !spm.c
(hit, miss, validReg)
}
......@@ -218,13 +227,15 @@ class TLB(Width: Int, q: TLBParameters)(implicit p: Parameters) extends TlbModul
valid = { if (q.normalAsVictim) false.B
else refill && ptw.resp.bits.entry.level.get === 2.U },
wayIdx = normal_refill_idx,
data = ptw.resp.bits
data = ptw.resp.bits,
data_replenish = io.ptw_replenish
)
superPage.w_apply(
valid = { if (q.normalAsVictim) refill
else refill && ptw.resp.bits.entry.level.get =/= 2.U },
wayIdx = super_refill_idx,
data = ptw.resp.bits
data = ptw.resp.bits,
data_replenish = io.ptw_replenish
)
// if sameCycle, just req.valid
......@@ -381,6 +392,7 @@ object TLB {
in(i).resp.bits := tlb.io.requestor(i).resp.bits
tlb.io.requestor(i).resp.ready := in(i).resp.ready
}
tlb.io.ptw_replenish <> DontCare // itlb only use reg, so no static pmp/pma
}
tlb.io.ptw
}
......
......@@ -80,7 +80,7 @@ class TLBFA(
when (io.w.valid) {
v(io.w.bits.wayIdx) := true.B
entries(io.w.bits.wayIdx).apply(io.w.bits.data, io.csr.satp.asid)
entries(io.w.bits.wayIdx).apply(io.w.bits.data, io.csr.satp.asid, io.w.bits.data_replenish)
}
val refill_vpn_reg = RegNext(io.w.bits.data.entry.tag)
......@@ -213,8 +213,12 @@ class TLBSA(
entries.io.w.apply(
valid = io.w.valid || io.victim.in.valid,
setIdx = Mux(io.w.valid, get_set_idx(io.w.bits.data.entry.tag, nSets), get_set_idx(io.victim.in.bits.entry.tag, nSets)),
data = Mux(io.w.valid, (Wire(new TlbEntry(normalPage, superPage)).apply(io.w.bits.data, io.csr.satp.asid)), io.victim.in.bits.entry),
setIdx = Mux(io.w.valid,
get_set_idx(io.w.bits.data.entry.tag, nSets),
get_set_idx(io.victim.in.bits.entry.tag, nSets)),
data = Mux(io.w.valid,
(Wire(new TlbEntry(normalPage, superPage)).apply(io.w.bits.data, io.csr.satp.asid, io.w.bits.data_replenish)),
io.victim.in.bits.entry),
waymask = UIntToOH(io.w.bits.wayIdx)
)
}
......
......@@ -277,16 +277,25 @@ class LoadUnit_S2(implicit p: Parameters) extends XSModule with HasLoadHelper {
val loadViolationQueryResp = Flipped(Valid(new LoadViolationQueryResp))
val csrCtrl = Flipped(new CustomCSRCtrlIO)
val sentFastUop = Input(Bool())
val static_pm = Input(Valid(Bool())) // valid for static, bits for mmio
})
val pmp = WireInit(io.pmpResp)
when (io.static_pm.valid) {
pmp.ld := false.B
pmp.st := false.B
pmp.instr := false.B
pmp.mmio := io.static_pm.bits
}
val s2_is_prefetch = io.in.bits.isSoftPrefetch
val excep = WireInit(io.in.bits.uop.cf.exceptionVec)
excep(loadAccessFault) := io.in.bits.uop.cf.exceptionVec(loadAccessFault) || io.pmpResp.ld
excep(loadAccessFault) := io.in.bits.uop.cf.exceptionVec(loadAccessFault) || pmp.ld
when (s2_is_prefetch) {
excep := 0.U.asTypeOf(excep.cloneType)
}
val s2_exception = ExceptionNO.selectByFu(io.out.bits.uop.cf.exceptionVec, lduCfg).asUInt.orR
val actually_mmio = io.pmpResp.mmio
val actually_mmio = pmp.mmio
val s2_uop = io.in.bits.uop
val s2_mask = io.in.bits.mask
val s2_paddr = io.in.bits.paddr
......@@ -302,7 +311,7 @@ class LoadUnit_S2(implicit p: Parameters) extends XSModule with HasLoadHelper {
val s2_forward_fail = io.lsq.matchInvalid || io.sbuffer.matchInvalid
// assert(!s2_forward_fail)
io.dcache_kill := false.B // move pmp resp kill to outside
io.dcache_kill := pmp.ld || pmp.mmio // false.B // move pmp resp kill to outside
io.dcacheResp.ready := true.B
val dcacheShouldResp = !(s2_tlb_miss || s2_exception || s2_mmio || s2_is_prefetch)
assert(!(io.in.valid && (dcacheShouldResp && !io.dcacheResp.valid)), "DCache response got lost")
......@@ -496,9 +505,10 @@ class LoadUnit(implicit p: Parameters) extends XSModule with HasLoadHelper with
PipelineConnect(load_s1.io.out, load_s2.io.in, true.B, load_s1.io.out.bits.uop.robIdx.needFlush(io.redirect))
io.dcache.s2_kill := load_s2.io.dcache_kill || (io.pmp.ld || io.pmp.mmio) // to kill mmio resp which are redirected
io.dcache.s2_kill := load_s2.io.dcache_kill // to kill mmio resp which are redirected
load_s2.io.dcacheResp <> io.dcache.resp
load_s2.io.pmpResp <> io.pmp
load_s2.io.static_pm := RegNext(io.tlb.resp.bits.static_pm)
load_s2.io.lsq.forwardData <> io.lsq.forward.forwardData
load_s2.io.lsq.forwardMask <> io.lsq.forward.forwardMask
load_s2.io.lsq.forwardMaskFast <> io.lsq.forward.forwardMaskFast // should not be used in load_s2
......
......@@ -153,16 +153,24 @@ class StoreUnit_S2(implicit p: Parameters) extends XSModule {
val io = IO(new Bundle() {
val in = Flipped(Decoupled(new LsPipelineBundle))
val pmpResp = Flipped(new PMPRespBundle)
val static_pm = Input(Valid(Bool()))
val out = Decoupled(new LsPipelineBundle)
})
val pmp = WireInit(io.pmpResp)
when (io.static_pm.valid) {
pmp.ld := false.B
pmp.st := false.B
pmp.instr := false.B
pmp.mmio := io.static_pm.bits
}
val s2_exception = ExceptionNO.selectByFu(io.out.bits.uop.cf.exceptionVec, staCfg).asUInt.orR
val is_mmio = io.in.bits.mmio || io.pmpResp.mmio
val is_mmio = io.in.bits.mmio || pmp.mmio
io.in.ready := true.B
io.out.bits := io.in.bits
io.out.bits.mmio := is_mmio && !s2_exception
io.out.bits.uop.cf.exceptionVec(storeAccessFault) := io.in.bits.uop.cf.exceptionVec(storeAccessFault) || io.pmpResp.st
io.out.bits.uop.cf.exceptionVec(storeAccessFault) := io.in.bits.uop.cf.exceptionVec(storeAccessFault) || pmp.st
io.out.valid := io.in.valid && (!is_mmio || s2_exception)
}
......@@ -221,6 +229,7 @@ class StoreUnit(implicit p: Parameters) extends XSModule {
PipelineConnect(store_s1.io.out, store_s2.io.in, true.B, store_s1.io.out.bits.uop.robIdx.needFlush(io.redirect))
store_s2.io.pmpResp <> io.pmp
store_s2.io.static_pm := RegNext(io.tlb.resp.bits.static_pm)
io.lsq_replenish := store_s2.io.out.bits // mmio and exception
PipelineConnect(store_s2.io.out, store_s3.io.in, true.B, store_s2.io.out.bits.uop.robIdx.needFlush(io.redirect))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册