未验证 提交 5854c1ed 编写于 作者: L Lemover 提交者: GitHub

l2tlb: mem access now takes 512 bits, 8 ptes (#973)

* mmu: wrap l2tlb's param withL2TLBParameters

* mmu.l2tlb: add param blockBytes: 64, 8 ptes

* mmu.l2tlb: set l2tlb cache size to l2:256, l3:4096

* mmu.l2tlb: add config print

* mmu.l2tlb: fix bug of resp data indices choosen and opt coding style
上级 605f31fc
......@@ -30,6 +30,7 @@ import xiangshan.backend.dispatch.DispatchParameters
import xiangshan.backend.exu.ExuParameters
import xiangshan.cache.{DCacheParameters, ICacheParameters, L1plusCacheParameters}
import xiangshan.cache.prefetch.{BOPParameters, L1plusPrefetcherParameters, L2PrefetcherParameters, StreamPrefetchParameters}
import xiangshan.cache.mmu.{L2TLBParameters}
import device.{XSDebugModuleParams, EnableJtag}
class DefaultConfig(n: Int) extends Config((site, here, up) => {
......@@ -108,10 +109,15 @@ class MinimalConfig(n: Int = 1) extends Config(
EnableLoop = false,
TlbEntrySize = 32,
TlbSPEntrySize = 4,
PtwL1EntrySize = 2,
PtwL2EntrySize = 64,
PtwL3EntrySize = 128,
PtwSPEntrySize = 2,
l2tlbParameters = L2TLBParameters(
l1Size = 4,
l2nSets = 4,
l2nWays = 4,
l3nSets = 4,
l3nWays = 8,
spSize = 2,
missQueueSize = 8
),
useFakeL2Cache = true, // disable L2 Cache
)),
L3Size = 256 * 1024, // 256KB L3 Cache
......
......@@ -25,6 +25,7 @@ import xiangshan.backend.fu.fpu._
import xiangshan.backend.dispatch.DispatchParameters
import xiangshan.cache.{DCacheParameters, ICacheParameters, L1plusCacheParameters}
import xiangshan.cache.prefetch.{BOPParameters, L1plusPrefetcherParameters, L2PrefetcherParameters, StreamPrefetchParameters}
import xiangshan.cache.mmu.{L2TLBParameters}
import freechips.rocketchip.diplomacy.AddressSet
case object XSCoreParamsKey extends Field[XSCoreParameters]
......@@ -105,11 +106,7 @@ case class XSCoreParameters
RefillSize: Int = 512,
TlbEntrySize: Int = 32,
TlbSPEntrySize: Int = 4,
PtwL3EntrySize: Int = 4096, //(512 * 8) or 512
PtwSPEntrySize: Int = 16,
PtwL1EntrySize: Int = 16,
PtwL2EntrySize: Int = 256, //(256 * 8)
PtwMissQueueSize: Int = 8,
l2tlbParameters: L2TLBParameters = L2TLBParameters(),
NumPerfCounters: Int = 16,
icacheParameters: ICacheParameters = ICacheParameters(
tagECC = Some("parity"),
......@@ -241,11 +238,7 @@ trait HasXSParameter {
val DTLBWidth = coreParams.LoadPipelineWidth + coreParams.StorePipelineWidth
val TlbEntrySize = coreParams.TlbEntrySize
val TlbSPEntrySize = coreParams.TlbSPEntrySize
val PtwL3EntrySize = coreParams.PtwL3EntrySize
val PtwSPEntrySize = coreParams.PtwSPEntrySize
val PtwL1EntrySize = coreParams.PtwL1EntrySize
val PtwL2EntrySize = coreParams.PtwL2EntrySize
val PtwMissQueueSize = coreParams.PtwMissQueueSize
val l2tlbParams = coreParams.l2tlbParameters
val NumPerfCounters = coreParams.NumPerfCounters
val instBytes = if (HasCExtension) 2 else 4
......@@ -311,8 +304,8 @@ trait HasXSParameter {
blockBytes = L2BlockSize,
nEntries = dcacheParameters.nMissEntries * 2 // TODO: this is too large
),
)
)
// load violation predict
val ResetTimeMax2Pow = 20 //1078576
val ResetTimeMin2Pow = 10 //1024
......
......@@ -348,7 +348,7 @@ class XSCoreImp(outer: XSCoreBase) extends LazyModuleImp(outer)
val dtlbRepeater = if (usePTWRepeater) {
Module(new PTWRepeater(LoadPipelineWidth + StorePipelineWidth))
} else {
Module(new PTWFilter(LoadPipelineWidth + StorePipelineWidth, PtwMissQueueSize))
Module(new PTWFilter(LoadPipelineWidth + StorePipelineWidth, l2tlbParams.missQueueSize))
}
itlbRepeater.io.tlb <> frontend.io.ptw
dtlbRepeater.io.tlb <> memBlock.io.ptw
......
......@@ -370,7 +370,7 @@ class PtwEntries(num: Int, tagLen: Int, level: Int, hasPerm: Boolean)(implicit p
def genEntries(vpn: UInt, data: UInt, levelUInt: UInt) = {
require((data.getWidth / XLEN) == num,
"input data length must be multiple of pte length")
s"input data length must be multiple of pte length: data.length:${data.getWidth} num:${num}")
val ps = Wire(new PtwEntries(num, tagLen, level, hasPerm))
ps.tag := tagClip(vpn)
......@@ -405,6 +405,14 @@ class PtwResp(implicit p: Parameters) extends PtwBundle {
val entry = new PtwEntry(tagLen = vpnLen, hasPerm = true, hasLevel = true)
val pf = Bool()
def apply(pf: Bool, level: UInt, pte: PteBundle, vpn: UInt) = {
this.entry.level.map(_ := level)
this.entry.tag := vpn
this.entry.perm.map(_ := pte.getPerm())
this.entry.ppn := pte.ppn
this.pf := pf
}
override def toPrintable: Printable = {
p"entry:${entry} pf:${pf}"
}
......
......@@ -25,6 +25,32 @@ import utils._
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
import freechips.rocketchip.tilelink._
case class L2TLBParameters
(
name: String = "l2tlb",
// l1
l1Size: Int = 16,
l1Associative: String = "fa",
l1Replacer: Option[String] = Some("plru"),
// l2
l2nSets: Int = 8,
l2nWays: Int = 4,
l2Replacer: Option[String] = Some("setplru"),
// l3
l3nSets: Int = 64,
l3nWays: Int = 8,
l3Replacer: Option[String] = Some("setplru"),
// sp
spSize: Int = 16,
spReplacer: Option[String] = Some("plru"),
// miss queue
missQueueSize: Int = 8,
// sram
sramSinglePort: Boolean = true,
// way size
blockBytes: Int = 64
)
trait HasTlbConst extends HasXSParameter {
val Level = 3
......@@ -70,48 +96,40 @@ trait HasTlbConst extends HasXSParameter {
trait HasPtwConst extends HasTlbConst with MemoryOpConstants{
val PtwWidth = 2
val MemBandWidth = 256 // TODO: change to IO bandwidth param
val SramSinglePort = true // NOTE: ptwl2, ptwl3 sram single port or not
val sramSinglePort = true // NOTE: ptwl2, ptwl3 sram single port or not
val blockBits = l2tlbParams.blockBytes * 8
val bPtwWidth = log2Up(PtwWidth)
// ptwl1: fully-associated
val PtwL1TagLen = vpnnLen
val ptwl1Replacer = Some("plru")
/* +-------+----------+-------------+
* | Tag | SetIdx | SectorIdx |
* +-------+----------+-------------+
*/
// ptwl2: 8-way group-associated
val PtwL2WayNum = 8
val PtwL2WaySize = PtwL2EntrySize / PtwL2WayNum
val PtwL2SectorSize = MemBandWidth/XLEN
val PtwL2LineSize = PtwL2SectorSize * PtwL2WayNum
val PtwL2LineNum = PtwL2EntrySize / PtwL2LineSize
val PtwL2IdxLen = log2Up(PtwL2WaySize)
val l2tlbParams.l2nWays = l2tlbParams.l2nWays
val PtwL2SetNum = l2tlbParams.l2nSets
val PtwL2SectorSize = blockBits /XLEN
val PtwL2IdxLen = log2Up(PtwL2SetNum * PtwL2SectorSize)
val PtwL2SectorIdxLen = log2Up(PtwL2SectorSize)
val PtwL2SetIdxLen = log2Up(PtwL2LineNum)
val PtwL2SetIdxLen = log2Up(PtwL2SetNum)
val PtwL2TagLen = vpnnLen * 2 - PtwL2IdxLen
val ptwl2Replacer = Some("setplru")
// ptwl3: 16-way group-associated
val PtwL3WayNum = 8
val PtwL3WaySize = PtwL3EntrySize / PtwL3WayNum
val PtwL3SectorSize = MemBandWidth / XLEN
val PtwL3LineSize = PtwL3SectorSize * PtwL3WayNum
val PtwL3LineNum = PtwL3EntrySize / PtwL3LineSize
val PtwL3IdxLen = log2Up(PtwL3WaySize)
val l2tlbParams.l3nWays = l2tlbParams.l3nWays
val PtwL3SetNum = l2tlbParams.l3nSets
val PtwL3SectorSize = blockBits / XLEN
val PtwL3IdxLen = log2Up(PtwL3SetNum * PtwL3SectorSize)
val PtwL3SectorIdxLen = log2Up(PtwL3SectorSize)
val PtwL3SetIdxLen = log2Up(PtwL3LineNum)
val PtwL3SetIdxLen = log2Up(PtwL3SetNum)
val PtwL3TagLen = vpnnLen * 3 - PtwL3IdxLen
val ptwl3Replacer = Some("setplru")
// super page, including 1GB and 2MB page
val SPTagLen = vpnnLen * 2
val spReplacer = Some("plru")
val MSHRSize = PtwMissQueueSize
val MSHRSize = l2tlbParams.missQueueSize
def genPtwL2Idx(vpn: UInt) = {
(vpn(vpnLen - 1, vpnnLen))(PtwL2IdxLen - 1, 0)
......
......@@ -39,7 +39,6 @@ class PTW()(implicit p: Parameters) extends LazyModule {
class PTWImp(outer: PTW)(implicit p: Parameters) extends PtwModule(outer) {
val (mem, edge) = outer.node.out.head
require(mem.d.bits.data.getWidth == l1BusDataWidth, "PTW: tilelink width does not match")
val io = IO(new PtwIO)
val difftestIO = IO(new Bundle() {
......@@ -100,11 +99,6 @@ class PTWImp(outer: PTW)(implicit p: Parameters) extends PtwModule(outer) {
cache.io.req.bits.vpn := arb2.io.out.bits.vpn
cache.io.req.bits.source := arb2.io.out.bits.source
cache.io.req.bits.isReplay := arb2.io.chosen === 0.U
cache.io.refill.valid := mem.d.valid
cache.io.refill.bits.ptes := mem.d.bits.data
cache.io.refill.bits.vpn := fsm.io.refill.vpn
cache.io.refill.bits.level := fsm.io.refill.level
cache.io.refill.bits.memAddr := fsm.io.refill.memAddr
cache.io.sfence := sfence
cache.io.refuseRefill := fsm.io.sfenceLatch
cache.io.resp.ready := Mux(cache.io.resp.bits.hit, true.B, missQueue.io.in.ready || fsm.io.req.ready)
......@@ -121,24 +115,44 @@ class PTWImp(outer: PTW)(implicit p: Parameters) extends PtwModule(outer) {
fsm.io.req.bits.l2Hit := cache.io.resp.bits.toFsm.l2Hit
fsm.io.req.bits.ppn := cache.io.resp.bits.toFsm.ppn
fsm.io.req.bits.vpn := cache.io.resp.bits.vpn
fsm.io.mem.req.ready := mem.a.ready
fsm.io.mem.resp.valid := mem.d.valid
fsm.io.mem.resp.bits.data := mem.d.bits.data
fsm.io.csr := csr
fsm.io.sfence := sfence
fsm.io.resp.ready := MuxLookup(fsm.io.resp.bits.source, false.B,
(0 until PtwWidth).map(i => i.U -> outArb(i).in(1).ready))
// mem
val memRead = edge.Get(
fromSource = 0.U/*id*/,
// toAddress = memAddr(log2Up(CacheLineSize / 2 / 8) - 1, 0),
toAddress = Cat(fsm.io.mem.req.bits.addr(PAddrBits - 1, log2Up(l1BusDataWidth/8)), 0.U(log2Up(l1BusDataWidth/8).W)),
lgSize = log2Up(l1BusDataWidth/8).U
toAddress = Cat(fsm.io.mem.req.bits.addr(PAddrBits - 1, log2Up(l2tlbParams.blockBytes)), 0.U(log2Up(l2tlbParams.blockBytes).W)),
lgSize = log2Up(l2tlbParams.blockBytes).U
)._2
mem.a.bits := memRead
mem.a.valid := fsm.io.mem.req.valid
mem.d.ready := true.B
val refill_data = Reg(Vec(blockBits / l1BusDataWidth, UInt(l1BusDataWidth.W)))
val refill_helper = edge.firstlastHelper(mem.d.bits, mem.d.fire())
val refill_valid = RegNext(refill_helper._3)
when (mem.d.valid) {
refill_data(refill_helper._4) := mem.d.bits.data
}
def get_part(data: Vec[UInt], index: UInt): UInt = {
val inner_data = data.asTypeOf(Vec(data.getWidth / XLEN, UInt(XLEN.W)))
inner_data(index)
}
val req_addr_low = fsm.io.mem.req.bits.addr(log2Up(l2tlbParams.blockBytes)-1, log2Up(XLEN/8))
fsm.io.mem.req.ready := mem.a.ready
fsm.io.mem.resp.valid := refill_valid
fsm.io.mem.resp.bits := get_part(refill_data, req_addr_low)
cache.io.refill.valid := refill_valid
cache.io.refill.bits.ptes := refill_data.asUInt
cache.io.refill.bits.vpn := fsm.io.refill.vpn
cache.io.refill.bits.level := fsm.io.refill.level
cache.io.refill.bits.memAddr := fsm.io.refill.memAddr
for (i <- 0 until PtwWidth) {
outArb(i).in(0).valid := cache.io.resp.valid && cache.io.resp.bits.hit && cache.io.resp.bits.source===i.U
outArb(i).in(0).bits.entry := cache.io.resp.bits.toTlb
......@@ -170,6 +184,9 @@ class PTWImp(outer: PTW)(implicit p: Parameters) extends PtwModule(outer) {
XSPerfAccumulate(s"req_blocked_by_mq", arb1.io.out.valid && missQueue.io.out.valid)
XSPerfAccumulate(s"replay_again", cache.io.resp.valid && !cache.io.resp.bits.hit && cache.io.resp.bits.isReplay && !fsm.io.req.ready)
XSPerfAccumulate(s"into_fsm_no_replay", cache.io.resp.valid && !cache.io.resp.bits.hit && !cache.io.resp.bits.isReplay && fsm.io.req.ready)
// print configs
println(s"${l2tlbParams.name}: one ptw, miss queue size ${l2tlbParams.missQueueSize} l1:${l2tlbParams.l1Size} fa l2: nSets ${l2tlbParams.l2nSets} nWays ${l2tlbParams.l2nWays} l3: ${l2tlbParams.l3nSets} nWays ${l2tlbParams.l3nWays} blockBytes:${l2tlbParams.blockBytes}")
}
class PTEHelper() extends BlackBox {
......
......@@ -49,7 +49,7 @@ class PtwCacheIO()(implicit p: Parameters) extends PtwBundle {
val toTlb = new PtwEntry(tagLen = vpnLen, hasPerm = true, hasLevel = true)
})
val refill = Flipped(ValidIO(new Bundle {
val ptes = UInt(MemBandWidth.W)
val ptes = UInt(blockBits.W)
val vpn = UInt(vpnLen.W)
val level = UInt(log2Up(Level).W)
val memAddr = Input(UInt(PAddrBits.W))
......@@ -77,67 +77,67 @@ class PtwCache()(implicit p: Parameters) extends XSModule with HasPtwConst {
// when miss queue is full, please to block itlb and dtlb input
// when refill, refuce to accept new req
val rwHarzad = if (SramSinglePort) io.refill.valid else false.B
val rwHarzad = if (sramSinglePort) io.refill.valid else false.B
io.req.ready := !rwHarzad && (second_ready || io.req.bits.isReplay)
// NOTE: when write, don't ready, whe
// when replay, just come in, out make sure resp.fire()
// l1: level 0 non-leaf pte
val l1 = Reg(Vec(PtwL1EntrySize, new PtwEntry(tagLen = PtwL1TagLen)))
val l1v = RegInit(0.U(PtwL1EntrySize.W))
val l1g = Reg(UInt(PtwL1EntrySize.W))
val l1 = Reg(Vec(l2tlbParams.l1Size, new PtwEntry(tagLen = PtwL1TagLen)))
val l1v = RegInit(0.U(l2tlbParams.l1Size.W))
val l1g = Reg(UInt(l2tlbParams.l1Size.W))
// l2: level 1 non-leaf pte
val l2 = Module(new SRAMTemplate(
new PtwEntries(num = PtwL2SectorSize, tagLen = PtwL2TagLen, level = 1, hasPerm = false),
set = PtwL2LineNum,
way = PtwL2WayNum,
singlePort = SramSinglePort
set = l2tlbParams.l2nSets,
way = l2tlbParams.l2nWays,
singlePort = sramSinglePort
))
val l2v = RegInit(0.U((PtwL2LineNum * PtwL2WayNum).W))
val l2g = Reg(UInt((PtwL2LineNum * PtwL2WayNum).W))
val l2v = RegInit(0.U((l2tlbParams.l2nSets * l2tlbParams.l2nWays).W))
val l2g = Reg(UInt((l2tlbParams.l2nSets * l2tlbParams.l2nWays).W))
def getl2vSet(vpn: UInt) = {
require(log2Up(PtwL2WayNum) == log2Down(PtwL2WayNum))
require(log2Up(l2tlbParams.l2nWays) == log2Down(l2tlbParams.l2nWays))
val set = genPtwL2SetIdx(vpn)
require(set.getWidth == log2Up(PtwL2LineNum))
val l2vVec = l2v.asTypeOf(Vec(PtwL2LineNum, UInt(PtwL2WayNum.W)))
require(set.getWidth == log2Up(l2tlbParams.l2nSets))
val l2vVec = l2v.asTypeOf(Vec(l2tlbParams.l2nSets, UInt(l2tlbParams.l2nWays.W)))
l2vVec(set)
}
// l3: level 2 leaf pte of 4KB pages
val l3 = Module(new SRAMTemplate(
new PtwEntries(num = PtwL3SectorSize, tagLen = PtwL3TagLen, level = 2, hasPerm = true),
set = PtwL3LineNum,
way = PtwL3WayNum,
singlePort = SramSinglePort
set = l2tlbParams.l3nSets,
way = l2tlbParams.l3nWays,
singlePort = sramSinglePort
))
val l3v = RegInit(0.U((PtwL3LineNum * PtwL3WayNum).W))
val l3g = Reg(UInt((PtwL3LineNum * PtwL3WayNum).W))
val l3v = RegInit(0.U((l2tlbParams.l3nSets * l2tlbParams.l3nWays).W))
val l3g = Reg(UInt((l2tlbParams.l3nSets * l2tlbParams.l3nWays).W))
def getl3vSet(vpn: UInt) = {
require(log2Up(PtwL3WayNum) == log2Down(PtwL3WayNum))
require(log2Up(l2tlbParams.l3nWays) == log2Down(l2tlbParams.l3nWays))
val set = genPtwL3SetIdx(vpn)
require(set.getWidth == log2Up(PtwL3LineNum))
val l3vVec = l3v.asTypeOf(Vec(PtwL3LineNum, UInt(PtwL3WayNum.W)))
require(set.getWidth == log2Up(l2tlbParams.l3nSets))
val l3vVec = l3v.asTypeOf(Vec(l2tlbParams.l3nSets, UInt(l2tlbParams.l3nWays.W)))
l3vVec(set)
}
// sp: level 0/1 leaf pte of 1GB/2MB super pages
val sp = Reg(Vec(PtwSPEntrySize, new PtwEntry(tagLen = SPTagLen, hasPerm = true, hasLevel = true)))
val spv = RegInit(0.U(PtwSPEntrySize.W))
val spg = Reg(UInt(PtwSPEntrySize.W))
val sp = Reg(Vec(l2tlbParams.spSize, new PtwEntry(tagLen = SPTagLen, hasPerm = true, hasLevel = true)))
val spv = RegInit(0.U(l2tlbParams.spSize.W))
val spg = Reg(UInt(l2tlbParams.spSize.W))
// Access Perf
val l1AccessPerf = Wire(Vec(PtwL1EntrySize, Bool()))
val l2AccessPerf = Wire(Vec(PtwL2WayNum, Bool()))
val l3AccessPerf = Wire(Vec(PtwL3WayNum, Bool()))
val spAccessPerf = Wire(Vec(PtwSPEntrySize, Bool()))
val l1AccessPerf = Wire(Vec(l2tlbParams.l1Size, Bool()))
val l2AccessPerf = Wire(Vec(l2tlbParams.l2nWays, Bool()))
val l3AccessPerf = Wire(Vec(l2tlbParams.l3nWays, Bool()))
val spAccessPerf = Wire(Vec(l2tlbParams.spSize, Bool()))
l1AccessPerf.map(_ := false.B)
l2AccessPerf.map(_ := false.B)
l3AccessPerf.map(_ := false.B)
spAccessPerf.map(_ := false.B)
// l1
val ptwl1replace = ReplacementPolicy.fromString(ptwl1Replacer, PtwL1EntrySize)
val ptwl1replace = ReplacementPolicy.fromString(l2tlbParams.l1Replacer, l2tlbParams.l1Size)
val (l1Hit, l1HitPPN) = {
val hitVecT = l1.zipWithIndex.map { case (e, i) => e.hit(first_req.vpn) && l1v(i) }
val hitVec = hitVecT.map(RegEnable(_, first_fire))
......@@ -147,7 +147,7 @@ class PtwCache()(implicit p: Parameters) extends XSModule with HasPtwConst {
when (hit) { ptwl1replace.access(OHToUInt(hitVec)) }
l1AccessPerf.zip(hitVec).map{ case (l, h) => l := h && RegNext(first_fire)}
for (i <- 0 until PtwL1EntrySize) {
for (i <- 0 until l2tlbParams.l1Size) {
XSDebug(first_fire, p"[l1] l1(${i.U}) ${l1(i)} hit:${l1(i).hit(first_req.vpn)}\n")
}
XSDebug(first_fire, p"[l1] l1v:${Binary(l1v)} hitVecT:${Binary(VecInit(hitVecT).asUInt)}\n")
......@@ -160,7 +160,7 @@ class PtwCache()(implicit p: Parameters) extends XSModule with HasPtwConst {
}
// l2
val ptwl2replace = ReplacementPolicy.fromString(ptwl2Replacer,PtwL2WayNum,PtwL2LineNum)
val ptwl2replace = ReplacementPolicy.fromString(l2tlbParams.l2Replacer,l2tlbParams.l2nWays,l2tlbParams.l2nSets)
val (l2Hit, l2HitPPN) = {
val ridx = genPtwL2SetIdx(first_req.vpn)
val vidx = RegEnable(VecInit(getl2vSet(first_req.vpn).asBools), first_fire)
......@@ -171,7 +171,7 @@ class PtwCache()(implicit p: Parameters) extends XSModule with HasPtwConst {
val hitVec = VecInit(ramDatas.zip(vidx).map { case (wayData, v) => wayData.hit(second_req.vpn) && v })
val hitWayData = ParallelPriorityMux(hitVec zip ramDatas)
val hit = ParallelOR(hitVec) && second_valid
val hitWay = ParallelPriorityMux(hitVec zip (0 until PtwL2WayNum).map(_.U))
val hitWay = ParallelPriorityMux(hitVec zip (0 until l2tlbParams.l2nWays).map(_.U))
ridx.suggestName(s"l2_ridx")
vidx.suggestName(s"l2_vidx")
......@@ -184,7 +184,7 @@ class PtwCache()(implicit p: Parameters) extends XSModule with HasPtwConst {
l2AccessPerf.zip(hitVec).map{ case (l, h) => l := h && RegNext(first_fire) }
XSDebug(first_fire, p"[l2] ridx:0x${Hexadecimal(ridx)}\n")
for (i <- 0 until PtwL2WayNum) {
for (i <- 0 until l2tlbParams.l2nWays) {
XSDebug(RegNext(first_fire), p"[l2] ramDatas(${i.U}) ${ramDatas(i)} l2v:${vidx(i)} hit:${ramDatas(i).hit(second_req.vpn)}\n")
}
XSDebug(second_valid, p"[l2] l2Hit:${hit} l2HitPPN:0x${Hexadecimal(hitWayData.ppns(genPtwL2SectorIdx(second_req.vpn)))} hitVec:${Binary(hitVec.asUInt)} hitWay:${hitWay} vidx:${Binary(vidx.asUInt)}\n")
......@@ -193,7 +193,7 @@ class PtwCache()(implicit p: Parameters) extends XSModule with HasPtwConst {
}
// l3
val ptwl3replace = ReplacementPolicy.fromString(ptwl3Replacer,PtwL3WayNum,PtwL3LineNum)
val ptwl3replace = ReplacementPolicy.fromString(l2tlbParams.l3Replacer,l2tlbParams.l3nWays,l2tlbParams.l3nSets)
val (l3Hit, l3HitData) = {
val ridx = genPtwL3SetIdx(first_req.vpn)
val vidx = RegEnable(VecInit(getl3vSet(first_req.vpn).asBools), first_fire)
......@@ -203,13 +203,13 @@ class PtwCache()(implicit p: Parameters) extends XSModule with HasPtwConst {
val hitVec = VecInit(ramDatas.zip(vidx).map{ case (wayData, v) => wayData.hit(second_req.vpn) && v })
val hitWayData = ParallelPriorityMux(hitVec zip ramDatas)
val hit = ParallelOR(hitVec) && second_valid
val hitWay = ParallelPriorityMux(hitVec zip (0 until PtwL3WayNum).map(_.U))
val hitWay = ParallelPriorityMux(hitVec zip (0 until l2tlbParams.l3nWays).map(_.U))
when (hit) { ptwl3replace.access(genPtwL3SetIdx(second_req.vpn), hitWay) }
l3AccessPerf.zip(hitVec).map{ case (l, h) => l := h && RegNext(first_fire) }
XSDebug(first_fire, p"[l3] ridx:0x${Hexadecimal(ridx)}\n")
for (i <- 0 until PtwL3WayNum) {
for (i <- 0 until l2tlbParams.l3nWays) {
XSDebug(RegNext(first_fire), p"[l3] ramDatas(${i.U}) ${ramDatas(i)} l3v:${vidx(i)} hit:${ramDatas(i).hit(second_req.vpn)}\n")
}
XSDebug(second_valid, p"[l3] l3Hit:${hit} l3HitData:${hitWayData} hitVec:${Binary(hitVec.asUInt)} hitWay:${hitWay} vidx:${Binary(vidx.asUInt)}\n")
......@@ -226,7 +226,7 @@ class PtwCache()(implicit p: Parameters) extends XSModule with HasPtwConst {
val l3HitPerm = l3HitData.perms.getOrElse(0.U.asTypeOf(Vec(PtwL3SectorSize, new PtePermBundle)))(genPtwL3SectorIdx(second_req.vpn))
// super page
val spreplace = ReplacementPolicy.fromString(spReplacer, PtwSPEntrySize)
val spreplace = ReplacementPolicy.fromString(l2tlbParams.spReplacer, l2tlbParams.spSize)
val (spHit, spHitData) = {
val hitVecT = sp.zipWithIndex.map { case (e, i) => e.hit(first_req.vpn) && spv(i) }
val hitVec = hitVecT.map(RegEnable(_, first_fire))
......@@ -236,7 +236,7 @@ class PtwCache()(implicit p: Parameters) extends XSModule with HasPtwConst {
when (hit) { spreplace.access(OHToUInt(hitVec)) }
spAccessPerf.zip(hitVec).map{ case (s, h) => s := h && RegNext(first_fire) }
for (i <- 0 until PtwSPEntrySize) {
for (i <- 0 until l2tlbParams.spSize) {
XSDebug(first_fire, p"[sp] sp(${i.U}) ${sp(i)} hit:${sp(i).hit(first_req.vpn)} spv:${spv(i)}\n")
}
XSDebug(second_valid, p"[sp] spHit:${hit} spHitData:${hitData} hitVec:${Binary(VecInit(hitVec).asUInt)}\n")
......@@ -270,10 +270,10 @@ class PtwCache()(implicit p: Parameters) extends XSModule with HasPtwConst {
assert(!(l3Hit && spHit), "normal page and super page both hit")
// refill Perf
val l1RefillPerf = Wire(Vec(PtwL1EntrySize, Bool()))
val l2RefillPerf = Wire(Vec(PtwL2WayNum, Bool()))
val l3RefillPerf = Wire(Vec(PtwL3WayNum, Bool()))
val spRefillPerf = Wire(Vec(PtwSPEntrySize, Bool()))
val l1RefillPerf = Wire(Vec(l2tlbParams.l1Size, Bool()))
val l2RefillPerf = Wire(Vec(l2tlbParams.l2nWays, Bool()))
val l3RefillPerf = Wire(Vec(l2tlbParams.l3nWays, Bool()))
val spRefillPerf = Wire(Vec(l2tlbParams.spSize, Bool()))
l1RefillPerf.map(_ := false.B)
l2RefillPerf.map(_ := false.B)
l3RefillPerf.map(_ := false.B)
......@@ -285,15 +285,20 @@ class PtwCache()(implicit p: Parameters) extends XSModule with HasPtwConst {
l2.io.w.req.valid := false.B
l3.io.w.req.valid := false.B
def get_part(data: UInt, index: UInt): UInt = {
val inner_data = data.asTypeOf(Vec(data.getWidth / XLEN, UInt(XLEN.W)))
inner_data(index)
}
val memRdata = refill.ptes
val memSelData = memRdata.asTypeOf(Vec(MemBandWidth/XLEN, UInt(XLEN.W)))(refill.memAddr(log2Up(l1BusDataWidth/8) - 1, log2Up(XLEN/8)))
val memPtes = (0 until PtwL3SectorSize).map(i => memRdata((i+1)*XLEN-1, i*XLEN).asTypeOf(new PteBundle))
val memSelData = get_part(memRdata, refill.memAddr(log2Up(l2tlbParams.blockBytes)-1, log2Up(XLEN/8)))
val memPtes = (0 until (l2tlbParams.blockBytes/(XLEN/8))).map(i => memRdata((i+1)*XLEN-1, i*XLEN).asTypeOf(new PteBundle))
val memPte = memSelData.asTypeOf(new PteBundle)
// TODO: handle sfenceLatch outsize
when (io.refill.valid && !memPte.isPf(refill.level) && !(sfence.valid || refuseRefill)) {
when (refill.level === 0.U && !memPte.isLeaf()) {
// val refillIdx = LFSR64()(log2Up(PtwL1EntrySize)-1,0) // TODO: may be LRU
// val refillIdx = LFSR64()(log2Up(l2tlbParams.l1Size)-1,0) // TODO: may be LRU
val refillIdx = replaceWrapper(l1v, ptwl1replace.way)
refillIdx.suggestName(s"PtwL1RefillIdx")
val rfOH = UIntToOH(refillIdx)
......@@ -302,7 +307,7 @@ class PtwCache()(implicit p: Parameters) extends XSModule with HasPtwConst {
l1v := l1v | rfOH
l1g := (l1g & ~rfOH) | Mux(memPte.perm.g, rfOH, 0.U)
for (i <- 0 until PtwL1EntrySize) {
for (i <- 0 until l2tlbParams.l1Size) {
l1RefillPerf(i) := i.U === refillIdx
}
......@@ -330,7 +335,7 @@ class PtwCache()(implicit p: Parameters) extends XSModule with HasPtwConst {
l2v := l2v | rfvOH
l2g := l2g & ~rfvOH | Mux(Cat(memPtes.map(_.perm.g)).andR, rfvOH, 0.U)
for (i <- 0 until PtwL2WayNum) {
for (i <- 0 until l2tlbParams.l2nWays) {
l2RefillPerf(i) := i.U === victimWay
}
......@@ -365,7 +370,7 @@ class PtwCache()(implicit p: Parameters) extends XSModule with HasPtwConst {
l3v := l3v | rfvOH
l3g := l3g & ~rfvOH | Mux(Cat(memPtes.map(_.perm.g)).andR, rfvOH, 0.U)
for (i <- 0 until PtwL3WayNum) {
for (i <- 0 until l2tlbParams.l3nWays) {
l3RefillPerf(i) := i.U === victimWay
}
......@@ -384,14 +389,14 @@ class PtwCache()(implicit p: Parameters) extends XSModule with HasPtwConst {
}
when ((refill.level === 0.U || refill.level === 1.U) && memPte.isLeaf()) {
val refillIdx = spreplace.way// LFSR64()(log2Up(PtwSPEntrySize)-1,0) // TODO: may be LRU
val refillIdx = spreplace.way// LFSR64()(log2Up(l2tlbParams.spSize)-1,0) // TODO: may be LRU
val rfOH = UIntToOH(refillIdx)
sp(refillIdx).refill(refill.vpn, memSelData, refill.level)
spreplace.access(refillIdx)
spv := spv | rfOH
spg := spg & ~rfOH | Mux(memPte.perm.g, rfOH, 0.U)
for (i <- 0 until PtwSPEntrySize) {
for (i <- 0 until l2tlbParams.spSize) {
spRefillPerf(i) := i.U === refillIdx
}
......@@ -422,8 +427,8 @@ class PtwCache()(implicit p: Parameters) extends XSModule with HasPtwConst {
} .otherwise {
// val flushMask = UIntToOH(genTlbL2Idx(sfence.bits.addr(sfence.bits.addr.getWidth-1, offLen)))
val flushSetIdxOH = UIntToOH(genPtwL3SetIdx(sfence.bits.addr(sfence.bits.addr.getWidth-1, offLen)))
// val flushMask = VecInit(flushSetIdxOH.asBools.map(Fill(PtwL3WayNum, _.asUInt))).asUInt
val flushMask = VecInit(flushSetIdxOH.asBools.map { a => Fill(PtwL3WayNum, a.asUInt) }).asUInt
// val flushMask = VecInit(flushSetIdxOH.asBools.map(Fill(l2tlbParams.l3nWays, _.asUInt))).asUInt
val flushMask = VecInit(flushSetIdxOH.asBools.map { a => Fill(l2tlbParams.l3nWays, a.asUInt) }).asUInt
flushSetIdxOH.suggestName(s"sfence_nrs1_flushSetIdxOH")
flushMask.suggestName(s"sfence_nrs1_flushMask")
when (sfence.bits.rs2) {
......
......@@ -44,9 +44,7 @@ class PtwFsmIO()(implicit p: Parameters) extends PtwBundle {
val req = DecoupledIO(new Bundle {
val addr = UInt(PAddrBits.W)
})
val resp = Flipped(ValidIO(new Bundle {
val data = UInt(MemBandWidth.W)
}))
val resp = Flipped(ValidIO(UInt(XLEN.W)))
}
val csr = Input(new TlbCsrBundle)
......@@ -78,10 +76,7 @@ class PtwFsm()(implicit p: Parameters) extends XSModule with HasPtwConst {
val l1Hit = Reg(Bool())
val l2Hit = Reg(Bool())
val memRdata = mem.resp.bits.data
val memSelData = memRdata.asTypeOf(Vec(MemBandWidth/XLEN, UInt(XLEN.W)))(memAddrReg(log2Up(l1BusDataWidth/8) - 1, log2Up(XLEN/8)))
val memPtes = (0 until PtwL3SectorSize).map(i => memRdata((i+1)*XLEN-1, i*XLEN).asTypeOf(new PteBundle))
val memPte = memSelData.asTypeOf(new PteBundle)
val memPte = mem.resp.bits.asTypeOf(new PteBundle().cloneType)
val memPteReg = RegEnable(memPte, mem.resp.fire())
val notFound = WireInit(false.B)
......@@ -136,17 +131,17 @@ class PtwFsm()(implicit p: Parameters) extends XSModule with HasPtwConst {
}
val finish = mem.resp.fire() && (memPte.isLeaf() || memPte.isPf(level) || level === 2.U)
val resp = Reg(io.resp.bits.cloneType)
val resp_pf = Reg(Bool())
val resp_level = Reg(UInt(2.W))
val resp_pte = Reg(new PteBundle())
when (finish && !sfenceLatch) {
resp.source := RegEnable(io.req.bits.source, io.req.fire())
resp.resp.pf := level === 3.U || notFound
resp.resp.entry.tag := vpn
resp.resp.entry.ppn := memPte.ppn
resp.resp.entry.perm.map(_ := memPte.getPerm())
resp.resp.entry.level.map(_ := level)
resp_pf := level === 3.U || notFound
resp_level := level
resp_pte := memPte
}
io.resp.valid := state === s_resp
io.resp.bits := resp
io.resp.bits.source := RegEnable(io.req.bits.source, io.req.fire())
io.resp.bits.resp.apply(resp_pf, resp_level, resp_pte, vpn)
io.req.ready := state === s_idle
val l1addr = MakeAddr(satp.ppn, getVpnn(vpn, 2))
......@@ -173,4 +168,4 @@ class PtwFsm()(implicit p: Parameters) extends XSModule with HasPtwConst {
XSPerfAccumulate("mem_count", mem.req.fire())
XSPerfAccumulate("mem_cycle", BoolStopWatch(mem.req.fire, mem.resp.fire(), true))
XSPerfAccumulate("mem_blocked", mem.req.valid && !mem.req.ready)
}
\ No newline at end of file
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册