Tighten PMAs for LR/SC and misaligned accesses
- LR/SC on cacheable memory only (not even scratchpad) - No misaligned accesses on regions with get/put-effects
This commit is contained in:
parent
74a7838de0
commit
c366007a0d
@ -105,6 +105,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
|
|||||||
// address translation
|
// address translation
|
||||||
val tlb = Module(new TLB(log2Ceil(coreDataBytes), nTLBEntries))
|
val tlb = Module(new TLB(log2Ceil(coreDataBytes), nTLBEntries))
|
||||||
io.ptw <> tlb.io.ptw
|
io.ptw <> tlb.io.ptw
|
||||||
|
io.cpu.xcpt := tlb.io.resp
|
||||||
tlb.io.req.valid := s1_valid && !io.cpu.s1_kill && (s1_readwrite || s1_sfence)
|
tlb.io.req.valid := s1_valid && !io.cpu.s1_kill && (s1_readwrite || s1_sfence)
|
||||||
tlb.io.req.bits.sfence.valid := s1_sfence
|
tlb.io.req.bits.sfence.valid := s1_sfence
|
||||||
tlb.io.req.bits.sfence.bits.rs1 := s1_req.typ(0)
|
tlb.io.req.bits.sfence.bits.rs1 := s1_req.typ(0)
|
||||||
@ -187,16 +188,9 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
|
|||||||
assert( !(s3_valid && s3_uncached) )
|
assert( !(s3_valid && s3_uncached) )
|
||||||
}
|
}
|
||||||
|
|
||||||
// exceptions
|
|
||||||
io.cpu.xcpt := tlb.io.resp
|
|
||||||
if (usingDataScratchpad) {
|
|
||||||
val no_xcpt = s1_req.phys /* slave port */ && s1_hit_state.isValid()
|
|
||||||
when (no_xcpt) { io.cpu.xcpt := 0.U.asTypeOf(io.cpu.xcpt) }
|
|
||||||
}
|
|
||||||
|
|
||||||
// load reservations
|
// load reservations
|
||||||
val s2_lr = Bool(usingAtomics) && s2_req.cmd === M_XLR
|
val s2_lr = Bool(usingAtomics && !usingDataScratchpad) && s2_req.cmd === M_XLR
|
||||||
val s2_sc = Bool(usingAtomics) && s2_req.cmd === M_XSC
|
val s2_sc = Bool(usingAtomics && !usingDataScratchpad) && s2_req.cmd === M_XSC
|
||||||
val lrscCount = Reg(init=UInt(0))
|
val lrscCount = Reg(init=UInt(0))
|
||||||
val lrscValid = lrscCount > lrscBackoff
|
val lrscValid = lrscCount > lrscBackoff
|
||||||
val lrscAddr = Reg(UInt())
|
val lrscAddr = Reg(UInt())
|
||||||
@ -208,6 +202,16 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
|
|||||||
when (lrscCount > 0) { lrscCount := lrscCount - 1 }
|
when (lrscCount > 0) { lrscCount := lrscCount - 1 }
|
||||||
when ((s2_valid_masked && lrscCount > 0) || io.cpu.invalidate_lr) { lrscCount := 0 }
|
when ((s2_valid_masked && lrscCount > 0) || io.cpu.invalidate_lr) { lrscCount := 0 }
|
||||||
|
|
||||||
|
if (usingDataScratchpad) {
|
||||||
|
require(!usingVM) // therefore, req.phys means this is a slave-port access
|
||||||
|
val s1_isSlavePortAccess = s1_req.phys
|
||||||
|
when (s1_isSlavePortAccess) {
|
||||||
|
assert(!s1_valid || s1_hit_state.isValid())
|
||||||
|
io.cpu.xcpt := 0.U.asTypeOf(io.cpu.xcpt)
|
||||||
|
}
|
||||||
|
assert(!(s2_valid_masked && s2_req.cmd.isOneOf(M_XLR, M_XSC)))
|
||||||
|
}
|
||||||
|
|
||||||
// pending store buffer
|
// pending store buffer
|
||||||
val pstore1_cmd = RegEnable(s1_req.cmd, s1_valid_not_nacked && s1_write)
|
val pstore1_cmd = RegEnable(s1_req.cmd, s1_valid_not_nacked && s1_write)
|
||||||
val pstore1_typ = RegEnable(s1_req.typ, s1_valid_not_nacked && s1_write)
|
val pstore1_typ = RegEnable(s1_req.typ, s1_valid_not_nacked && s1_write)
|
||||||
|
@ -73,6 +73,7 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters
|
|||||||
val pr = Bool()
|
val pr = Bool()
|
||||||
val pal = Bool() // AMO logical
|
val pal = Bool() // AMO logical
|
||||||
val paa = Bool() // AMO arithmetic
|
val paa = Bool() // AMO arithmetic
|
||||||
|
val eff = Bool() // get/put effects
|
||||||
val c = Bool()
|
val c = Bool()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,6 +117,7 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters
|
|||||||
val prot_al = fastCheck(_.supportsLogical) || cacheable
|
val prot_al = fastCheck(_.supportsLogical) || cacheable
|
||||||
val prot_aa = fastCheck(_.supportsArithmetic) || cacheable
|
val prot_aa = fastCheck(_.supportsArithmetic) || cacheable
|
||||||
val prot_x = fastCheck(_.executable) && pmp.io.x
|
val prot_x = fastCheck(_.executable) && pmp.io.x
|
||||||
|
val prot_eff = fastCheck(Seq(RegionType.PUT_EFFECTS, RegionType.GET_EFFECTS) contains _.regionType)
|
||||||
val isSpecial = !(io.ptw.resp.bits.homogeneous || io.ptw.resp.bits.ae)
|
val isSpecial = !(io.ptw.resp.bits.homogeneous || io.ptw.resp.bits.ae)
|
||||||
|
|
||||||
val lookup_tag = Cat(io.ptw.ptbr.asid, vpn(vpnBits-1,0))
|
val lookup_tag = Cat(io.ptw.ptbr.asid, vpn(vpnBits-1,0))
|
||||||
@ -160,6 +162,7 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters
|
|||||||
newEntry.px := prot_x && !io.ptw.resp.bits.ae
|
newEntry.px := prot_x && !io.ptw.resp.bits.ae
|
||||||
newEntry.pal := prot_al
|
newEntry.pal := prot_al
|
||||||
newEntry.paa := prot_aa
|
newEntry.paa := prot_aa
|
||||||
|
newEntry.eff := prot_eff
|
||||||
|
|
||||||
valid := valid | UIntToOH(waddr)
|
valid := valid | UIntToOH(waddr)
|
||||||
reg_entries(waddr) := newEntry.asUInt
|
reg_entries(waddr) := newEntry.asUInt
|
||||||
@ -177,13 +180,15 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters
|
|||||||
val px_array = Cat(Fill(2, prot_x), entries.init.map(_.px).asUInt)
|
val px_array = Cat(Fill(2, prot_x), entries.init.map(_.px).asUInt)
|
||||||
val paa_array = Cat(Fill(2, prot_aa), entries.init.map(_.paa).asUInt)
|
val paa_array = Cat(Fill(2, prot_aa), entries.init.map(_.paa).asUInt)
|
||||||
val pal_array = Cat(Fill(2, prot_al), entries.init.map(_.pal).asUInt)
|
val pal_array = Cat(Fill(2, prot_al), entries.init.map(_.pal).asUInt)
|
||||||
|
val eff_array = Cat(Fill(2, prot_eff), entries.init.map(_.eff).asUInt)
|
||||||
val c_array = Cat(Fill(2, cacheable), entries.init.map(_.c).asUInt)
|
val c_array = Cat(Fill(2, cacheable), entries.init.map(_.c).asUInt)
|
||||||
val ae_st_array = ~pw_array | Mux(isAMOLogical(io.req.bits.cmd), ~pal_array, 0.U) | Mux(isAMOArithmetic(io.req.bits.cmd), ~paa_array, 0.U)
|
val ae_st_array = ~pw_array | Mux(isAMOLogical(io.req.bits.cmd), ~pal_array, 0.U) | Mux(isAMOArithmetic(io.req.bits.cmd), ~paa_array, 0.U)
|
||||||
|
|
||||||
val misaligned = (io.req.bits.vaddr & (UIntToOH(io.req.bits.size) - 1)).orR
|
val misaligned = (io.req.bits.vaddr & (UIntToOH(io.req.bits.size) - 1)).orR
|
||||||
val bad_va =
|
val ae = misaligned || Bool(usingAtomics) && !io.resp.cacheable && io.req.bits.cmd.isOneOf(M_XLR, M_XSC)
|
||||||
if (vpnBits == vpnBitsExtended) Bool(false)
|
val bad_va = vm_enabled &&
|
||||||
else vpn(vpnBits) =/= vpn(vpnBits-1)
|
(if (vpnBits == vpnBitsExtended) Bool(false)
|
||||||
|
else vpn(vpnBits) =/= vpn(vpnBits-1))
|
||||||
val tlb_hit = hits(totalEntries-1, 0).orR
|
val tlb_hit = hits(totalEntries-1, 0).orR
|
||||||
val tlb_miss = vm_enabled && !bad_va && !tlb_hit && !io.req.bits.sfence.valid
|
val tlb_miss = vm_enabled && !bad_va && !tlb_hit && !io.req.bits.sfence.valid
|
||||||
|
|
||||||
@ -202,11 +207,11 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters
|
|||||||
io.resp.pf.ld := (bad_va || (~r_array & hits).orR) && isRead(io.req.bits.cmd)
|
io.resp.pf.ld := (bad_va || (~r_array & hits).orR) && isRead(io.req.bits.cmd)
|
||||||
io.resp.pf.st := (bad_va || (~w_array & hits).orR) && isWrite(io.req.bits.cmd)
|
io.resp.pf.st := (bad_va || (~w_array & hits).orR) && isWrite(io.req.bits.cmd)
|
||||||
io.resp.pf.inst := bad_va || (~x_array & hits).orR
|
io.resp.pf.inst := bad_va || (~x_array & hits).orR
|
||||||
io.resp.ae.ld := (~pr_array & hits).orR && isRead(io.req.bits.cmd)
|
io.resp.ae.ld := ((~pr_array & hits).orR || ae) && isRead(io.req.bits.cmd)
|
||||||
io.resp.ae.st := (ae_st_array & hits).orR && isWrite(io.req.bits.cmd)
|
io.resp.ae.st := ((ae_st_array & hits).orR || ae) && isWrite(io.req.bits.cmd)
|
||||||
io.resp.ae.inst := (~px_array & hits).orR
|
io.resp.ae.inst := (~px_array & hits).orR
|
||||||
io.resp.ma.ld := misaligned && isRead(io.req.bits.cmd)
|
io.resp.ma.ld := (~eff_array & hits).orR && misaligned && isRead(io.req.bits.cmd)
|
||||||
io.resp.ma.st := misaligned && isWrite(io.req.bits.cmd)
|
io.resp.ma.st := (~eff_array & hits).orR && misaligned && isWrite(io.req.bits.cmd)
|
||||||
io.resp.ma.inst := false // this is up to the pipeline to figure out
|
io.resp.ma.inst := false // this is up to the pipeline to figure out
|
||||||
io.resp.cacheable := (c_array & hits).orR
|
io.resp.cacheable := (c_array & hits).orR
|
||||||
io.resp.miss := do_refill || tlb_miss || multipleHits
|
io.resp.miss := do_refill || tlb_miss || multipleHits
|
||||||
|
Loading…
Reference in New Issue
Block a user