L2-specific metadataarray wrapper, hookups to tshrfile
This commit is contained in:
parent
bc3ef1011e
commit
0e39346a12
@ -43,6 +43,7 @@ case class L2CacheConfig(
|
||||
def rowoffbits = log2Up(rowbytes)
|
||||
def refillcycles = tl.dataBits/(rowbits)
|
||||
def statebits = log2Up(states)
|
||||
def nTSHRs = nReleaseTransactions + nAcquireTransactions
|
||||
|
||||
require(states > 0)
|
||||
require(isPow2(sets))
|
||||
@ -60,6 +61,16 @@ abstract trait L2CacheBundle extends Bundle {
|
||||
override def clone = this.getClass.getConstructors.head.newInstance(l2cacheconf).asInstanceOf[this.type]
|
||||
}
|
||||
|
||||
trait HasL2Id extends L2CacheBundle {
|
||||
val id = UInt(width = log2Up(l2cacheconf.nTSHRs))
|
||||
}
|
||||
|
||||
trait HasL2InternalRequestState extends L2CacheBundle {
|
||||
val tag_match = Bool()
|
||||
val old_meta = new L2MetaData
|
||||
val way_en = Bits(width = l2cacheconf.ways)
|
||||
}
|
||||
|
||||
abstract class ReplacementPolicy {
|
||||
def way: UInt
|
||||
def miss: Unit
|
||||
@ -80,20 +91,6 @@ abstract class MetaData(implicit val cacheconf: CacheConfig) extends CacheBundle
|
||||
val tag = Bits(width = cacheconf.tagbits)
|
||||
}
|
||||
|
||||
class L2MetaData(implicit val l2cacheconf: L2CacheConfig) extends MetaData
|
||||
with L2CacheBundle {
|
||||
val state = UInt(width = l2cacheconf.statebits)
|
||||
val sharers = Bits(width = l2cacheconf.tl.ln.nClients)
|
||||
}
|
||||
|
||||
/*
|
||||
class L3MetaData(implicit conf: L3CacheConfig) extends MetaData()(conf) {
|
||||
val cstate = UInt(width = cacheconf.cstatebits)
|
||||
val mstate = UInt(width = cacheconf.mstatebits)
|
||||
val sharers = Bits(width = cacheconf.tl.ln.nClients)
|
||||
}
|
||||
*/
|
||||
|
||||
class MetaReadReq(implicit val cacheconf: CacheConfig) extends CacheBundle {
|
||||
val idx = Bits(width = cacheconf.idxbits)
|
||||
}
|
||||
@ -137,49 +134,125 @@ class MetaDataArray[T <: MetaData](gen: () => T)(implicit conf: CacheConfig) ext
|
||||
io.write.ready := !rst
|
||||
}
|
||||
|
||||
class L2DataReadReq(implicit val l2cacheconf: L2CacheConfig) extends L2CacheBundle {
|
||||
object L2MetaData {
|
||||
def apply(tag: Bits, state: UInt, sharers: UInt)(implicit conf: L2CacheConfig) = {
|
||||
val meta = new L2MetaData
|
||||
meta.tag := tag
|
||||
meta.state := state
|
||||
meta.sharers := sharers
|
||||
meta
|
||||
}
|
||||
}
|
||||
class L2MetaData(implicit val l2cacheconf: L2CacheConfig) extends MetaData
|
||||
with L2CacheBundle {
|
||||
val state = UInt(width = l2cacheconf.statebits)
|
||||
val sharers = Bits(width = l2cacheconf.tl.ln.nClients)
|
||||
}
|
||||
|
||||
/*
|
||||
class L3MetaData(implicit conf: L3CacheConfig) extends MetaData()(conf) {
|
||||
val cstate = UInt(width = cacheconf.cstatebits)
|
||||
val mstate = UInt(width = cacheconf.mstatebits)
|
||||
val sharers = Bits(width = cacheconf.tl.ln.nClients)
|
||||
}
|
||||
*/
|
||||
|
||||
class L2MetaReadReq(implicit val l2cacheconf: L2CacheConfig) extends MetaReadReq
|
||||
with HasL2Id {
|
||||
val tag = Bits(width = l2cacheconf.tagbits)
|
||||
}
|
||||
|
||||
class L2MetaWriteReq(implicit val l2cacheconf: L2CacheConfig) extends MetaWriteReq[L2MetaData](new L2MetaData)
|
||||
with HasL2Id
|
||||
|
||||
class L2MetaResp(implicit val l2cacheconf: L2CacheConfig) extends L2CacheBundle
|
||||
with HasL2Id
|
||||
with HasL2InternalRequestState
|
||||
|
||||
class L2MetaDataArray(implicit conf: L2CacheConfig) extends Module {
|
||||
implicit val tl = conf.tl
|
||||
val io = new Bundle {
|
||||
val read = Decoupled(new L2MetaReadReq).flip
|
||||
val write = Decoupled(new L2MetaWriteReq).flip
|
||||
val resp = Valid(new L2MetaResp)
|
||||
}
|
||||
|
||||
val meta = Module(new MetaDataArray(() => L2MetaData(UInt(0), tl.co.newStateOnFlush, UInt(0))))
|
||||
meta.io.read <> io.read
|
||||
meta.io.write <> io.write
|
||||
|
||||
val s1_clk_en = Reg(next = io.read.fire())
|
||||
val s1_tag = RegEnable(io.read.bits.tag, io.read.valid)
|
||||
val s1_id = RegEnable(io.read.bits.id, io.read.valid)
|
||||
def wayMap[T <: Data](f: Int => T) = Vec((0 until conf.ways).map(f))
|
||||
val s1_tag_eq_way = wayMap((w: Int) => meta.io.resp(w).tag === s1_tag)
|
||||
val s1_tag_match_way = wayMap((w: Int) => s1_tag_eq_way(w) && tl.co.isValid(meta.io.resp(w).state)).toBits
|
||||
val s2_tag_match_way = RegEnable(s1_tag_match_way, s1_clk_en)
|
||||
val s2_tag_match = s2_tag_match_way.orR
|
||||
val s2_hit_state = Mux1H(s2_tag_match_way, wayMap((w: Int) => RegEnable(meta.io.resp(w).state, s1_clk_en)))
|
||||
val s2_hit_sharers = Mux1H(s2_tag_match_way, wayMap((w: Int) => RegEnable(meta.io.resp(w).sharers, s1_clk_en)))
|
||||
|
||||
val replacer = new RandomReplacement
|
||||
val s1_replaced_way_en = UIntToOH(replacer.way)
|
||||
val s2_replaced_way_en = UIntToOH(RegEnable(replacer.way, s1_clk_en))
|
||||
val s2_repl_meta = Mux1H(s2_replaced_way_en, wayMap((w: Int) =>
|
||||
RegEnable(meta.io.resp(w), s1_clk_en && s1_replaced_way_en(w))).toSeq)
|
||||
|
||||
io.resp.valid := Reg(next = s1_clk_en)
|
||||
io.resp.bits.id := RegEnable(s1_id, s1_clk_en)
|
||||
io.resp.bits.tag_match := s2_tag_match
|
||||
io.resp.bits.old_meta := Mux(s2_tag_match,
|
||||
L2MetaData(s2_repl_meta.tag, s2_hit_state, s2_hit_sharers),
|
||||
s2_repl_meta)
|
||||
io.resp.bits.way_en := Mux(s2_tag_match, s2_tag_match_way, s2_replaced_way_en)
|
||||
}
|
||||
|
||||
class L2DataReadReq(implicit val l2cacheconf: L2CacheConfig) extends L2CacheBundle
|
||||
with HasL2Id {
|
||||
val way_en = Bits(width = l2cacheconf.ways)
|
||||
val addr = Bits(width = l2cacheconf.tl.addrBits)
|
||||
}
|
||||
|
||||
class L2DataWriteReq(implicit conf: L2CacheConfig) extends L2DataReadReq()(conf) {
|
||||
val wmask = Bits(width = conf.tl.writeMaskBits)
|
||||
val data = Bits(width = conf.tl.dataBits)
|
||||
class L2DataWriteReq(implicit l2cacheconf: L2CacheConfig) extends L2DataReadReq {
|
||||
val wmask = Bits(width = l2cacheconf.tl.writeMaskBits)
|
||||
val data = Bits(width = l2cacheconf.tl.dataBits)
|
||||
}
|
||||
|
||||
class L2DataResp(implicit val l2cacheconf: L2CacheConfig) extends L2CacheBundle
|
||||
with HasL2Id {
|
||||
val data = Bits(width = l2cacheconf.tl.dataBits)
|
||||
}
|
||||
|
||||
class L2DataArray(implicit conf: L2CacheConfig) extends Module {
|
||||
val io = new Bundle {
|
||||
val read = Decoupled(new L2DataReadReq).flip
|
||||
val write = Decoupled(new L2DataWriteReq).flip
|
||||
val resp = Vec.fill(conf.ways){Bits(OUTPUT, conf.tl.dataBits)}
|
||||
val resp = Valid(new L2DataResp)
|
||||
}
|
||||
|
||||
val waddr = io.write.bits.addr
|
||||
val raddr = io.read.bits.addr
|
||||
val wmask = FillInterleaved(conf.wordbits, io.write.bits.wmask)
|
||||
for (w <- 0 until conf.ways) {
|
||||
val resp = (0 until conf.ways).map { w =>
|
||||
val array = Mem(Bits(width=conf.rowbits), conf.sets*conf.refillcycles, seqRead = true)
|
||||
when (io.write.bits.way_en(w) && io.write.valid) {
|
||||
array.write(waddr, io.write.bits.data, wmask)
|
||||
}
|
||||
io.resp(w) := array(RegEnable(raddr, io.read.bits.way_en(w) && io.read.valid))
|
||||
array(RegEnable(raddr, io.read.bits.way_en(w) && io.read.valid))
|
||||
}
|
||||
io.resp.valid := ShiftRegister(io.read.valid, 2)
|
||||
io.resp.bits.id := ShiftRegister(io.read.bits.id, 2)
|
||||
io.resp.bits.data := Mux1H(ShiftRegister(io.read.bits.way_en, 2), resp)
|
||||
|
||||
io.read.ready := Bool(true)
|
||||
io.write.ready := Bool(true)
|
||||
}
|
||||
|
||||
trait L2InternalRequestState extends L2CacheBundle {
|
||||
val tag_match = Bool()
|
||||
val old_meta = new L2MetaData
|
||||
val way_en = Bits(width = l2cacheconf.ways)
|
||||
}
|
||||
|
||||
class L2InternalAcquire(implicit val l2cacheconf: L2CacheConfig) extends Acquire()(l2cacheconf.tl)
|
||||
with L2InternalRequestState
|
||||
with HasL2InternalRequestState
|
||||
|
||||
class L2InternalRelease(implicit val l2cacheconf: L2CacheConfig) extends Release()(l2cacheconf.tl)
|
||||
with L2InternalRequestState
|
||||
with HasL2InternalRequestState
|
||||
|
||||
class InternalTileLinkIO(implicit val l2cacheconf: L2CacheConfig) extends L2CacheBundle {
|
||||
implicit val (tl, ln) = (l2cacheconf.tl, l2cacheconf.tl.ln)
|
||||
@ -194,23 +267,16 @@ class L2HellaCache(bankId: Int)(implicit conf: L2CacheConfig) extends CoherenceA
|
||||
implicit val (tl, ln, co) = (conf.tl, conf.tl.ln, conf.tl.co)
|
||||
|
||||
val tshrfile = Module(new TSHRFile(bankId))
|
||||
|
||||
// tags
|
||||
val meta = Module(new MetaDataArray(() => new L2MetaData))
|
||||
|
||||
// data
|
||||
val meta = Module(new L2MetaDataArray)
|
||||
val data = Module(new L2DataArray)
|
||||
|
||||
// replacement policy
|
||||
val replacer = new RandomReplacement
|
||||
/*
|
||||
val s1_replaced_way_en = UIntToOH(replacer.way)
|
||||
val s2_replaced_way_en = UIntToOH(RegEnable(replacer.way, s1_clk_en))
|
||||
val s2_repl_meta = Mux1H(s2_replaced_way_en, wayMap((w: Int) =>
|
||||
RegEnable(meta.io.resp(w), s1_clk_en && s1_replaced_way_en(w))).toSeq)
|
||||
*/
|
||||
|
||||
tshrfile.io.inner <> io.inner
|
||||
tshrfile.io.meta_read <> meta.io.read
|
||||
tshrfile.io.meta_write <> meta.io.write
|
||||
tshrfile.io.meta_resp <> meta.io.resp
|
||||
tshrfile.io.data_read <> data.io.read
|
||||
tshrfile.io.data_write <> data.io.write
|
||||
tshrfile.io.data_resp <> data.io.resp
|
||||
io.outer <> tshrfile.io.outer
|
||||
io.incoherent <> tshrfile.io.incoherent
|
||||
}
|
||||
@ -219,19 +285,31 @@ class L2HellaCache(bankId: Int)(implicit conf: L2CacheConfig) extends CoherenceA
|
||||
class TSHRFile(bankId: Int)(implicit conf: L2CacheConfig) extends Module {
|
||||
implicit val (tl, ln, co) = (conf.tl, conf.tl.ln, conf.tl.co)
|
||||
val io = new Bundle {
|
||||
val inner = (new InternalTileLinkIO).flip
|
||||
val inner = (new TileLinkIO).flip
|
||||
val outer = new UncachedTileLinkIO
|
||||
val incoherent = Vec.fill(ln.nClients){Bool()}.asInput
|
||||
val meta_read_req = Decoupled(new MetaReadReq)
|
||||
val meta_write_req = Decoupled(new MetaWriteReq(new L2MetaData))
|
||||
val data_read_req = Decoupled(new L2DataReadReq)
|
||||
val data_write_req = Decoupled(new L2DataWriteReq)
|
||||
val meta_read = Decoupled(new L2MetaReadReq)
|
||||
val meta_write = Decoupled(new L2MetaWriteReq)
|
||||
val meta_resp = Valid(new L2MetaResp).flip
|
||||
val data_read = Decoupled(new L2DataReadReq)
|
||||
val data_write = Decoupled(new L2DataWriteReq)
|
||||
val data_resp = Valid(new L2DataResp).flip
|
||||
}
|
||||
|
||||
// Wiring helper funcs
|
||||
def doOutputArbitration[T <: Data](out: DecoupledIO[T], ins: Seq[DecoupledIO[T]]) {
|
||||
val arb = Module(new RRArbiter(out.bits.clone, ins.size))
|
||||
out <> arb.io.out
|
||||
arb.io.in zip ins map { case (a, i) => a <> i }
|
||||
}
|
||||
|
||||
// Create TSHRs for outstanding transactions
|
||||
val nTrackers = conf.nReleaseTransactions + conf.nAcquireTransactions
|
||||
val trackerList = (0 until conf.nReleaseTransactions).map(id => Module(new L2VoluntaryReleaseTracker(id, bankId))) ++
|
||||
(conf.nReleaseTransactions until nTrackers).map(id => Module(new L2AcquireTracker(id, bankId)))
|
||||
val trackerList = (0 until conf.nReleaseTransactions).map { id =>
|
||||
Module(new L2VoluntaryReleaseTracker(id, bankId))
|
||||
} ++ (conf.nReleaseTransactions until nTrackers).map { id =>
|
||||
Module(new L2AcquireTracker(id, bankId))
|
||||
}
|
||||
|
||||
// Propagate incoherence flags
|
||||
trackerList.map(_.io.tile_incoherent := io.incoherent.toBits)
|
||||
@ -251,10 +329,11 @@ class TSHRFile(bankId: Int)(implicit conf: L2CacheConfig) extends Module {
|
||||
acquire.ready := trackerList.map(_.io.inner.acquire.ready).reduce(_||_) && !block_acquires
|
||||
alloc_arb.io.out.ready := acquire.valid && !block_acquires
|
||||
|
||||
// Handle probe request generation
|
||||
val probe_arb = Module(new Arbiter(new LogicalNetworkIO(new Probe), trackerList.size))
|
||||
io.inner.probe <> probe_arb.io.out
|
||||
probe_arb.io.in zip trackerList map { case (arb, t) => arb <> t.io.inner.probe }
|
||||
// Handle probe requests
|
||||
doOutputArbitration(io.inner.probe, trackerList.map(_.io.inner.probe))
|
||||
//val probe_arb = Module(new Arbiter(new LogicalNetworkIO(new Probe), trackerList.size))
|
||||
//io.inner.probe <> probe_arb.io.out
|
||||
//probe_arb.io.in zip trackerList map { case (arb, t) => arb <> t.io.inner.probe }
|
||||
|
||||
// Handle releases, which might be voluntary and might have data
|
||||
val release = io.inner.release
|
||||
@ -272,9 +351,10 @@ class TSHRFile(bankId: Int)(implicit conf: L2CacheConfig) extends Module {
|
||||
release.ready := Vec(trackerList.map(_.io.inner.release.ready)).read(release_idx) && !block_releases
|
||||
|
||||
// Reply to initial requestor
|
||||
val grant_arb = Module(new Arbiter(new LogicalNetworkIO(new Grant), trackerList.size))
|
||||
io.inner.grant <> grant_arb.io.out
|
||||
grant_arb.io.in zip trackerList map { case (arb, t) => arb <> t.io.inner.grant }
|
||||
doOutputArbitration(io.inner.grant, trackerList.map(_.io.inner.grant))
|
||||
//val grant_arb = Module(new Arbiter(new LogicalNetworkIO(new Grant), trackerList.size))
|
||||
//io.inner.grant <> grant_arb.io.out
|
||||
//grant_arb.io.in zip trackerList map { case (arb, t) => arb <> t.io.inner.grant }
|
||||
|
||||
// Free finished transactions
|
||||
val ack = io.inner.finish
|
||||
@ -282,21 +362,35 @@ class TSHRFile(bankId: Int)(implicit conf: L2CacheConfig) extends Module {
|
||||
trackerList.map(_.io.inner.finish.bits := ack.bits)
|
||||
ack.ready := Bool(true)
|
||||
|
||||
// Create an arbiter for the one memory port
|
||||
// Arbitrate for the outer memory port
|
||||
val outer_arb = Module(new UncachedTileLinkIOArbiterThatPassesId(trackerList.size))
|
||||
outer_arb.io.in zip trackerList map { case(arb, t) => arb <> t.io.outer }
|
||||
io.outer <> outer_arb.io.out
|
||||
|
||||
// Local memory
|
||||
doOutputArbitration(io.meta_read, trackerList.map(_.io.meta_read))
|
||||
doOutputArbitration(io.meta_write, trackerList.map(_.io.meta_write))
|
||||
doOutputArbitration(io.data_read, trackerList.map(_.io.data_read))
|
||||
doOutputArbitration(io.data_write, trackerList.map(_.io.data_write))
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
abstract class L2XactTracker()(implicit conf: L2CacheConfig) extends Module {
|
||||
implicit val (tl, ln, co) = (conf.tl, conf.tl.ln, conf.tl.co)
|
||||
val io = new Bundle {
|
||||
val inner = (new InternalTileLinkIO).flip
|
||||
val inner = (new TileLinkIO).flip
|
||||
val outer = new UncachedTileLinkIO
|
||||
val tile_incoherent = Bits(INPUT, ln.nClients)
|
||||
val has_acquire_conflict = Bool(OUTPUT)
|
||||
val has_release_conflict = Bool(OUTPUT)
|
||||
val meta_read = Decoupled(new L2MetaReadReq)
|
||||
val meta_write = Decoupled(new L2MetaWriteReq)
|
||||
val meta_resp = Valid(new L2MetaResp).flip
|
||||
val data_read = Decoupled(new L2DataReadReq)
|
||||
val data_write = Decoupled(new L2DataWriteReq)
|
||||
val data_resp = Valid(new L2DataResp).flip
|
||||
}
|
||||
|
||||
val c_acq = io.inner.acquire.bits
|
||||
|
Loading…
Reference in New Issue
Block a user