Merge branch 'dse'
Conflicts: src/main/scala/htif.scala src/main/scala/llc.scala
This commit is contained in:
commit
5e26b4ab66
@ -1,75 +1,38 @@
|
||||
package uncore
|
||||
import Chisel._
|
||||
|
||||
trait CacheConfig {
|
||||
def sets: Int
|
||||
def ways: Int
|
||||
def tl: TileLinkConfiguration
|
||||
def as: AddressSpaceConfiguration
|
||||
def dm: Boolean
|
||||
def states: Int
|
||||
def lines: Int
|
||||
def tagbits: Int
|
||||
def idxbits: Int
|
||||
def offbits: Int
|
||||
def untagbits: Int
|
||||
def rowbits: Int
|
||||
case object CacheName extends Field[String]
|
||||
case object NSets extends Field[Int]
|
||||
case object NWays extends Field[Int]
|
||||
case object BlockOffBits extends Field[Int]
|
||||
case object RowBits extends Field[Int]
|
||||
case object WordBits extends Field[Int]
|
||||
case object Replacer extends Field[() => ReplacementPolicy]
|
||||
|
||||
abstract trait CacheParameters extends UsesParameters {
|
||||
val paddrBits = params(PAddrBits)
|
||||
val vaddrBits = params(VAddrBits)
|
||||
val pgIdxBits = params(PgIdxBits)
|
||||
val nSets = params(NSets)
|
||||
val blockOffBits = params(BlockOffBits)
|
||||
val idxBits = log2Up(nSets)
|
||||
val untagBits = blockOffBits + idxBits
|
||||
val tagBits = paddrBits - untagBits
|
||||
val nWays = params(NWays)
|
||||
val wayBits = log2Up(nWays)
|
||||
val isDM = nWays == 1
|
||||
val wordBits = params(WordBits)
|
||||
val wordBytes = wordBits/8
|
||||
val wordOffBits = log2Up(wordBytes)
|
||||
val rowBits = params(RowBits)
|
||||
val rowWords = rowBits/wordBits
|
||||
val rowBytes = rowBits/8
|
||||
val rowOffBits = log2Up(rowBytes)
|
||||
val refillCycles = params(TLDataBits)/rowBits
|
||||
}
|
||||
|
||||
case class L2CacheConfig(
|
||||
val sets: Int, val ways: Int,
|
||||
val nrpq: Int, val nsdq: Int,
|
||||
val nReleaseTransactions: Int,
|
||||
val nAcquireTransactions: Int,
|
||||
val tl: TileLinkConfiguration,
|
||||
val as: AddressSpaceConfiguration)
|
||||
extends CoherenceAgentConfiguration
|
||||
with CacheConfig
|
||||
{
|
||||
def states = tl.co.nMasterStates
|
||||
def lines = sets*ways
|
||||
def dm = ways == 1
|
||||
def offbits = 0
|
||||
def lineaddrbits = tl.addrBits
|
||||
def idxbits = log2Up(sets)
|
||||
def waybits = log2Up(ways)
|
||||
def untagbits = offbits + idxbits
|
||||
def tagbits = lineaddrbits - idxbits
|
||||
def wordbits = 64
|
||||
def wordbytes = wordbits/8
|
||||
def wordoffbits = log2Up(wordbytes)
|
||||
def rowbits = tl.dataBits
|
||||
def rowbytes = rowbits/8
|
||||
def rowoffbits = log2Up(rowbytes)
|
||||
def refillcycles = tl.dataBits/(rowbits)
|
||||
def statebits = log2Up(states)
|
||||
def nTSHRs = nReleaseTransactions + nAcquireTransactions
|
||||
|
||||
require(states > 0)
|
||||
require(isPow2(sets))
|
||||
require(isPow2(ways)) // TODO: relax this
|
||||
require(refillcycles == 1) //TODO: relax this?
|
||||
}
|
||||
|
||||
abstract trait CacheBundle extends Bundle {
|
||||
implicit val cacheconf: CacheConfig
|
||||
override def clone = this.getClass.getConstructors.head.newInstance(cacheconf).asInstanceOf[this.type]
|
||||
}
|
||||
|
||||
abstract trait L2CacheBundle extends Bundle {
|
||||
implicit val l2cacheconf: L2CacheConfig
|
||||
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 CacheBundle extends Bundle with CacheParameters
|
||||
abstract class CacheModule extends Module with CacheParameters
|
||||
|
||||
abstract class ReplacementPolicy {
|
||||
def way: UInt
|
||||
@ -77,54 +40,53 @@ abstract class ReplacementPolicy {
|
||||
def hit: Unit
|
||||
}
|
||||
|
||||
class RandomReplacement(implicit val cacheconf: CacheConfig) extends ReplacementPolicy {
|
||||
class RandomReplacement(ways: Int) extends ReplacementPolicy {
|
||||
private val replace = Bool()
|
||||
replace := Bool(false)
|
||||
val lfsr = LFSR16(replace)
|
||||
|
||||
def way = if(cacheconf.dm) UInt(0) else lfsr(log2Up(cacheconf.ways)-1,0)
|
||||
def way = if(ways == 1) UInt(0) else lfsr(log2Up(ways)-1,0)
|
||||
def miss = replace := Bool(true)
|
||||
def hit = {}
|
||||
}
|
||||
|
||||
abstract class Metadata(implicit val cacheconf: CacheConfig) extends CacheBundle {
|
||||
val tag = Bits(width = cacheconf.tagbits)
|
||||
abstract class Metadata extends CacheBundle {
|
||||
val tag = Bits(width = tagBits)
|
||||
val coh: CoherenceMetadata
|
||||
}
|
||||
|
||||
class MetaReadReq(implicit val cacheconf: CacheConfig) extends CacheBundle {
|
||||
val idx = Bits(width = cacheconf.idxbits)
|
||||
class MetaReadReq extends CacheBundle {
|
||||
val idx = Bits(width = idxBits)
|
||||
}
|
||||
|
||||
class MetaWriteReq[T <: Metadata](gen: T)(implicit conf: CacheConfig) extends MetaReadReq {
|
||||
val way_en = Bits(width = conf.ways)
|
||||
class MetaWriteReq[T <: Metadata](gen: T) extends MetaReadReq {
|
||||
val way_en = Bits(width = nWays)
|
||||
val data = gen.clone
|
||||
override def clone = new MetaWriteReq(gen)(conf).asInstanceOf[this.type]
|
||||
override def clone = new MetaWriteReq(gen).asInstanceOf[this.type]
|
||||
}
|
||||
|
||||
class MetadataArray[T <: Metadata](makeRstVal: () => T)(implicit conf: CacheConfig) extends Module {
|
||||
implicit val tl = conf.tl
|
||||
class MetadataArray[T <: Metadata](makeRstVal: () => T) extends CacheModule {
|
||||
val rstVal = makeRstVal()
|
||||
val io = new Bundle {
|
||||
val read = Decoupled(new MetaReadReq).flip
|
||||
val write = Decoupled(new MetaWriteReq(rstVal.clone)).flip
|
||||
val resp = Vec.fill(conf.ways){rstVal.clone.asOutput}
|
||||
val resp = Vec.fill(nWays){rstVal.clone.asOutput}
|
||||
}
|
||||
val metabits = rstVal.getWidth
|
||||
val rst_cnt = Reg(init=UInt(0, log2Up(conf.sets+1)))
|
||||
val rst = rst_cnt < UInt(conf.sets)
|
||||
val rst_cnt = Reg(init=UInt(0, log2Up(nSets+1)))
|
||||
val rst = rst_cnt < UInt(nSets)
|
||||
val waddr = Mux(rst, rst_cnt, io.write.bits.idx)
|
||||
val wdata = Mux(rst, rstVal, io.write.bits.data).toBits
|
||||
val wmask = Mux(rst, SInt(-1), io.write.bits.way_en)
|
||||
when (rst) { rst_cnt := rst_cnt+UInt(1) }
|
||||
|
||||
val tag_arr = Mem(UInt(width = metabits*conf.ways), conf.sets, seqRead = true)
|
||||
val tag_arr = Mem(UInt(width = metabits*nWays), nSets, seqRead = true)
|
||||
when (rst || io.write.valid) {
|
||||
tag_arr.write(waddr, Fill(conf.ways, wdata), FillInterleaved(metabits, wmask))
|
||||
tag_arr.write(waddr, Fill(nWays, wdata), FillInterleaved(metabits, wmask))
|
||||
}
|
||||
|
||||
val tags = tag_arr(RegEnable(io.read.bits.idx, io.read.valid))
|
||||
for (w <- 0 until conf.ways) {
|
||||
for (w <- 0 until nWays) {
|
||||
val m = tags(metabits*(w+1)-1, metabits*w)
|
||||
io.resp(w) := rstVal.clone.fromBits(m)
|
||||
}
|
||||
@ -133,62 +95,68 @@ class MetadataArray[T <: Metadata](makeRstVal: () => T)(implicit conf: CacheConf
|
||||
io.write.ready := !rst
|
||||
}
|
||||
|
||||
abstract trait L2HellaCacheParameters extends CacheParameters
|
||||
with CoherenceAgentParameters
|
||||
|
||||
abstract class L2HellaCacheBundle extends Bundle with L2HellaCacheParameters
|
||||
abstract class L2HellaCacheModule extends Module with L2HellaCacheParameters
|
||||
|
||||
trait HasL2Id extends Bundle with CoherenceAgentParameters {
|
||||
val id = UInt(width = log2Up(nTransactors))
|
||||
}
|
||||
|
||||
trait HasL2InternalRequestState extends L2HellaCacheBundle {
|
||||
val tag_match = Bool()
|
||||
val old_meta = new L2Metadata
|
||||
val way_en = Bits(width = nWays)
|
||||
}
|
||||
|
||||
object L2Metadata {
|
||||
def apply(tag: Bits, coh: MasterMetadata)(implicit conf: L2CacheConfig) = {
|
||||
def apply(tag: Bits, coh: MasterMetadata) = {
|
||||
val meta = new L2Metadata
|
||||
meta.tag := tag
|
||||
meta.coh := coh
|
||||
meta
|
||||
}
|
||||
}
|
||||
class L2Metadata(implicit val l2cacheconf: L2CacheConfig) extends Metadata
|
||||
with L2CacheBundle {
|
||||
val coh = l2cacheconf.tl.co.masterMetadataOnFlush.clone
|
||||
class L2Metadata extends Metadata with L2HellaCacheParameters {
|
||||
val coh = co.masterMetadataOnFlush.clone
|
||||
}
|
||||
|
||||
/*
|
||||
class L3Metadata(implicit conf: L3CacheConfig) extends Metadata
|
||||
with L3CacheBundle {
|
||||
val coh = MixedMetaData(conf.innerTL.co, conf.outerTL.co) ?
|
||||
}
|
||||
*/
|
||||
|
||||
class L2MetaReadReq(implicit val l2cacheconf: L2CacheConfig) extends MetaReadReq
|
||||
with HasL2Id {
|
||||
val tag = Bits(width = l2cacheconf.tagbits)
|
||||
class L2MetaReadReq extends MetaReadReq with HasL2Id {
|
||||
val tag = Bits(width = tagBits)
|
||||
}
|
||||
|
||||
class L2MetaWriteReq(implicit val l2cacheconf: L2CacheConfig) extends MetaWriteReq[L2Metadata](new L2Metadata)
|
||||
class L2MetaWriteReq extends MetaWriteReq[L2Metadata](new L2Metadata)
|
||||
with HasL2Id
|
||||
|
||||
class L2MetaResp(implicit val l2cacheconf: L2CacheConfig) extends L2CacheBundle
|
||||
class L2MetaResp extends L2HellaCacheBundle
|
||||
with HasL2Id
|
||||
with HasL2InternalRequestState
|
||||
|
||||
class L2MetadataArray(implicit conf: L2CacheConfig) extends Module {
|
||||
implicit val tl = conf.tl
|
||||
class L2MetadataArray extends L2HellaCacheModule {
|
||||
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.masterMetadataOnFlush)))
|
||||
val meta = Module(new MetadataArray(() => L2Metadata(UInt(0), co.masterMetadataOnFlush)))
|
||||
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))
|
||||
def wayMap[T <: Data](f: Int => T) = Vec((0 until nWays).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).coh)).toBits
|
||||
val s1_tag_match_way = wayMap((w: Int) => s1_tag_eq_way(w) && co.isValid(meta.io.resp(w).coh)).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_coh = Mux1H(s2_tag_match_way, wayMap((w: Int) => RegEnable(meta.io.resp(w).coh, s1_clk_en)))
|
||||
//val s2_hit = s2_tag_match && tl.co.isHit(s2_req.cmd, s2_hit_state) && s2_hit_state === tl.co.newStateOnHit(s2_req.cmd, s2_hit_state)
|
||||
|
||||
val replacer = new RandomReplacement
|
||||
val replacer = params(Replacer)()
|
||||
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) =>
|
||||
@ -203,23 +171,21 @@ class L2MetadataArray(implicit conf: L2CacheConfig) extends Module {
|
||||
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 L2DataReadReq extends L2HellaCacheBundle with HasL2Id {
|
||||
val way_en = Bits(width = nWays)
|
||||
val addr = Bits(width = params(TLAddrBits))
|
||||
}
|
||||
|
||||
class L2DataWriteReq(implicit l2cacheconf: L2CacheConfig) extends L2DataReadReq {
|
||||
val wmask = Bits(width = l2cacheconf.tl.writeMaskBits)
|
||||
val data = Bits(width = l2cacheconf.tl.dataBits)
|
||||
class L2DataWriteReq extends L2DataReadReq {
|
||||
val wmask = Bits(width = params(TLWriteMaskBits))
|
||||
val data = Bits(width = params(TLDataBits))
|
||||
}
|
||||
|
||||
class L2DataResp(implicit val l2cacheconf: L2CacheConfig) extends L2CacheBundle
|
||||
with HasL2Id {
|
||||
val data = Bits(width = l2cacheconf.tl.dataBits)
|
||||
class L2DataResp extends Bundle with HasL2Id {
|
||||
val data = Bits(width = params(TLDataBits))
|
||||
}
|
||||
|
||||
class L2DataArray(implicit conf: L2CacheConfig) extends Module {
|
||||
class L2DataArray extends L2HellaCacheModule {
|
||||
val io = new Bundle {
|
||||
val read = Decoupled(new L2DataReadReq).flip
|
||||
val write = Decoupled(new L2DataWriteReq).flip
|
||||
@ -228,9 +194,9 @@ class L2DataArray(implicit conf: L2CacheConfig) extends Module {
|
||||
|
||||
val waddr = io.write.bits.addr
|
||||
val raddr = io.read.bits.addr
|
||||
val wmask = FillInterleaved(conf.wordbits, io.write.bits.wmask)
|
||||
val resp = (0 until conf.ways).map { w =>
|
||||
val array = Mem(Bits(width=conf.rowbits), conf.sets*conf.refillcycles, seqRead = true)
|
||||
val wmask = FillInterleaved(wordBits, io.write.bits.wmask)
|
||||
val resp = (0 until nWays).map { w =>
|
||||
val array = Mem(Bits(width=params(RowBits)), nSets*refillCycles, seqRead = true)
|
||||
when (io.write.bits.way_en(w) && io.write.valid) {
|
||||
array.write(waddr, io.write.bits.data, wmask)
|
||||
}
|
||||
@ -244,23 +210,11 @@ class L2DataArray(implicit conf: L2CacheConfig) extends Module {
|
||||
io.write.ready := Bool(true)
|
||||
}
|
||||
|
||||
class L2InternalAcquire(implicit val l2cacheconf: L2CacheConfig) extends Acquire()(l2cacheconf.tl)
|
||||
with HasL2InternalRequestState
|
||||
class L2HellaCache(bankId: Int) extends CoherenceAgent with L2HellaCacheParameters {
|
||||
|
||||
class L2InternalRelease(implicit val l2cacheconf: L2CacheConfig) extends Release()(l2cacheconf.tl)
|
||||
with HasL2InternalRequestState
|
||||
|
||||
class InternalTileLinkIO(implicit val l2cacheconf: L2CacheConfig) extends L2CacheBundle {
|
||||
implicit val (tl, ln) = (l2cacheconf.tl, l2cacheconf.tl.ln)
|
||||
val acquire = new DecoupledIO(new LogicalNetworkIO(new L2InternalAcquire))
|
||||
val probe = new DecoupledIO(new LogicalNetworkIO(new Probe)).flip
|
||||
val release = new DecoupledIO(new LogicalNetworkIO(new L2InternalRelease))
|
||||
val grant = new DecoupledIO(new LogicalNetworkIO(new Grant)).flip
|
||||
val finish = new DecoupledIO(new LogicalNetworkIO(new Finish))
|
||||
}
|
||||
|
||||
class L2HellaCache(bankId: Int)(implicit conf: L2CacheConfig) extends CoherenceAgent {
|
||||
implicit val (tl, ln, co) = (conf.tl, conf.tl.ln, conf.tl.co)
|
||||
require(isPow2(nSets))
|
||||
require(isPow2(nWays))
|
||||
require(refillCycles == 1)
|
||||
|
||||
val tshrfile = Module(new TSHRFile(bankId))
|
||||
val meta = Module(new L2MetadataArray)
|
||||
@ -278,12 +232,11 @@ 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)
|
||||
class TSHRFile(bankId: Int) extends L2HellaCacheModule {
|
||||
val io = new Bundle {
|
||||
val inner = (new TileLinkIO).flip
|
||||
val outer = new UncachedTileLinkIO
|
||||
val incoherent = Vec.fill(ln.nClients){Bool()}.asInput
|
||||
val incoherent = Vec.fill(nClients){Bool()}.asInput
|
||||
val meta_read = Decoupled(new L2MetaReadReq)
|
||||
val meta_write = Decoupled(new L2MetaWriteReq)
|
||||
val meta_resp = Valid(new L2MetaResp).flip
|
||||
@ -305,10 +258,9 @@ class TSHRFile(bankId: Int)(implicit conf: L2CacheConfig) extends Module {
|
||||
}
|
||||
|
||||
// Create TSHRs for outstanding transactions
|
||||
val nTrackers = conf.nReleaseTransactions + conf.nAcquireTransactions
|
||||
val trackerList = (0 until conf.nReleaseTransactions).map { id =>
|
||||
val trackerList = (0 until nReleaseTransactors).map { id =>
|
||||
Module(new L2VoluntaryReleaseTracker(id, bankId))
|
||||
} ++ (conf.nReleaseTransactions until nTrackers).map { id =>
|
||||
} ++ (nReleaseTransactors until nTransactors).map { id =>
|
||||
Module(new L2AcquireTracker(id, bankId))
|
||||
}
|
||||
|
||||
@ -373,12 +325,11 @@ class TSHRFile(bankId: Int)(implicit conf: L2CacheConfig) extends Module {
|
||||
}
|
||||
|
||||
|
||||
abstract class L2XactTracker()(implicit conf: L2CacheConfig) extends Module {
|
||||
implicit val (tl, ln, co) = (conf.tl, conf.tl.ln, conf.tl.co)
|
||||
abstract class L2XactTracker extends L2HellaCacheModule {
|
||||
val io = new Bundle {
|
||||
val inner = (new TileLinkIO).flip
|
||||
val outer = new UncachedTileLinkIO
|
||||
val tile_incoherent = Bits(INPUT, ln.nClients)
|
||||
val tile_incoherent = Bits(INPUT, nClients)
|
||||
val has_acquire_conflict = Bool(OUTPUT)
|
||||
val has_release_conflict = Bool(OUTPUT)
|
||||
val meta_read = Decoupled(new L2MetaReadReq)
|
||||
@ -397,11 +348,11 @@ abstract class L2XactTracker()(implicit conf: L2CacheConfig) extends Module {
|
||||
|
||||
}
|
||||
|
||||
class L2VoluntaryReleaseTracker(trackerId: Int, bankId: Int)(implicit conf: L2CacheConfig) extends L2XactTracker()(conf) {
|
||||
class L2VoluntaryReleaseTracker(trackerId: Int, bankId: Int) extends L2XactTracker {
|
||||
val s_idle :: s_mem :: s_ack :: s_busy :: Nil = Enum(UInt(), 4)
|
||||
val state = Reg(init=s_idle)
|
||||
val xact = Reg{ new Release }
|
||||
val init_client_id = Reg(init=UInt(0, width = log2Up(ln.nClients)))
|
||||
val init_client_id = Reg(init=UInt(0, width = log2Up(nClients)))
|
||||
val new_meta = Reg(new L2Metadata)
|
||||
val incoming_rel = io.inner.release.bits
|
||||
|
||||
@ -460,16 +411,16 @@ Mux(co.messageHasData(xact), s_mem, s_ack)
|
||||
}
|
||||
}
|
||||
|
||||
class L2AcquireTracker(trackerId: Int, bankId: Int)(implicit conf: L2CacheConfig) extends L2XactTracker()(conf) {
|
||||
class L2AcquireTracker(trackerId: Int, bankId: Int) extends L2XactTracker {
|
||||
val s_idle :: s_probe :: s_mem_read :: s_mem_write :: s_make_grant :: s_busy :: Nil = Enum(UInt(), 6)
|
||||
val state = Reg(init=s_idle)
|
||||
val xact = Reg{ new Acquire }
|
||||
val init_client_id = Reg(init=UInt(0, width = log2Up(ln.nClients)))
|
||||
val init_client_id = Reg(init=UInt(0, width = log2Up(nClients)))
|
||||
//TODO: Will need id reg for merged release xacts
|
||||
|
||||
val init_sharer_cnt = Reg(init=UInt(0, width = log2Up(ln.nClients)))
|
||||
val release_count = if (ln.nClients == 1) UInt(0) else Reg(init=UInt(0, width = log2Up(ln.nClients)))
|
||||
val probe_flags = Reg(init=Bits(0, width = ln.nClients))
|
||||
val init_sharer_cnt = Reg(init=UInt(0, width = log2Up(nClients)))
|
||||
val release_count = if(nClients == 1) UInt(0) else Reg(init=UInt(0, width = log2Up(nClients)))
|
||||
val probe_flags = Reg(init=Bits(0, width = nClients))
|
||||
val curr_p_id = PriorityEncoder(probe_flags)
|
||||
|
||||
val pending_outer_write = co.messageHasData(xact)
|
||||
@ -480,12 +431,12 @@ class L2AcquireTracker(trackerId: Int, bankId: Int)(implicit conf: L2CacheConfig
|
||||
xact.addr, UInt(trackerId), c_rel.payload.data)
|
||||
val outer_read = Acquire(co.getUncachedReadAcquireType, xact.addr, UInt(trackerId))
|
||||
|
||||
val probe_initial_flags = Bits(width = ln.nClients)
|
||||
val probe_initial_flags = Bits(width = nClients)
|
||||
probe_initial_flags := Bits(0)
|
||||
if (ln.nClients > 1) {
|
||||
if (nClients > 1) {
|
||||
// issue self-probes for uncached read xacts to facilitate I$ coherence
|
||||
val probe_self = Bool(true) //co.needsSelfProbe(io.inner.acquire.bits.payload)
|
||||
val myflag = Mux(probe_self, Bits(0), UIntToOH(c_acq.header.src(log2Up(ln.nClients)-1,0)))
|
||||
val myflag = Mux(probe_self, Bits(0), UIntToOH(c_acq.header.src(log2Up(nClients)-1,0)))
|
||||
probe_initial_flags := ~(io.tile_incoherent | myflag)
|
||||
}
|
||||
|
||||
@ -501,7 +452,7 @@ class L2AcquireTracker(trackerId: Int, bankId: Int)(implicit conf: L2CacheConfig
|
||||
io.inner.probe.valid := Bool(false)
|
||||
io.inner.probe.bits.header.src := UInt(bankId)
|
||||
io.inner.probe.bits.header.dst := curr_p_id
|
||||
io.inner.probe.bits.payload := Probe(co.getProbeType(xact.a_type, conf.tl.co.masterMetadataOnFlush),
|
||||
io.inner.probe.bits.payload := Probe(co.getProbeType(xact.a_type, co.masterMetadataOnFlush),
|
||||
xact.addr,
|
||||
UInt(trackerId))
|
||||
|
||||
@ -525,9 +476,9 @@ class L2AcquireTracker(trackerId: Int, bankId: Int)(implicit conf: L2CacheConfig
|
||||
when( io.inner.acquire.valid ) {
|
||||
xact := c_acq.payload
|
||||
init_client_id := c_acq.header.src
|
||||
init_sharer_cnt := UInt(ln.nClients) // TODO: Broadcast only
|
||||
init_sharer_cnt := UInt(nClients) // TODO: Broadcast only
|
||||
probe_flags := probe_initial_flags
|
||||
if(ln.nClients > 1) {
|
||||
if(nClients > 1) {
|
||||
release_count := PopCount(probe_initial_flags)
|
||||
state := Mux(probe_initial_flags.orR, s_probe,
|
||||
Mux(needs_outer_write, s_mem_write,
|
||||
@ -550,7 +501,7 @@ class L2AcquireTracker(trackerId: Int, bankId: Int)(implicit conf: L2CacheConfig
|
||||
io.outer.acquire.bits.payload := outer_write_rel
|
||||
when(io.outer.acquire.ready) {
|
||||
io.inner.release.ready := Bool(true)
|
||||
if(ln.nClients > 1) release_count := release_count - UInt(1)
|
||||
if(nClients > 1) release_count := release_count - UInt(1)
|
||||
when(release_count === UInt(1)) {
|
||||
state := Mux(pending_outer_write, s_mem_write,
|
||||
Mux(pending_outer_read, s_mem_read, s_make_grant))
|
||||
@ -558,7 +509,7 @@ class L2AcquireTracker(trackerId: Int, bankId: Int)(implicit conf: L2CacheConfig
|
||||
}
|
||||
} .otherwise {
|
||||
io.inner.release.ready := Bool(true)
|
||||
if(ln.nClients > 1) release_count := release_count - UInt(1)
|
||||
if(nClients > 1) release_count := release_count - UInt(1)
|
||||
when(release_count === UInt(1)) {
|
||||
state := Mux(pending_outer_write, s_mem_write,
|
||||
Mux(pending_outer_read, s_mem_read, s_make_grant))
|
||||
|
@ -4,7 +4,23 @@ import Chisel._
|
||||
import Node._
|
||||
import uncore._
|
||||
|
||||
class HostIO(val w: Int) extends Bundle
|
||||
case object HTIFWidth extends Field[Int]
|
||||
case object HTIFNSCR extends Field[Int]
|
||||
case object HTIFOffsetBits extends Field[Int]
|
||||
case object HTIFNCores extends Field[Int]
|
||||
|
||||
abstract trait HTIFParameters extends UsesParameters {
|
||||
val dataBits = params(TLDataBits)
|
||||
val co = params(TLCoherence)
|
||||
val w = params(HTIFWidth)
|
||||
val nSCR = params(HTIFNSCR)
|
||||
val offsetBits = params(HTIFOffsetBits)
|
||||
val nCores = params(HTIFNCores)
|
||||
}
|
||||
|
||||
abstract class HTIFBundle extends Bundle with HTIFParameters
|
||||
|
||||
class HostIO extends HTIFBundle
|
||||
{
|
||||
val clk = Bool(OUTPUT)
|
||||
val clk_edge = Bool(OUTPUT)
|
||||
@ -20,43 +36,40 @@ class PCRReq extends Bundle
|
||||
val data = Bits(width = 64)
|
||||
}
|
||||
|
||||
class HTIFIO(ntiles: Int) extends Bundle
|
||||
{
|
||||
class HTIFIO extends HTIFBundle {
|
||||
val reset = Bool(INPUT)
|
||||
val id = UInt(INPUT, log2Up(ntiles))
|
||||
val id = UInt(INPUT, log2Up(nCores))
|
||||
val pcr_req = Decoupled(new PCRReq).flip
|
||||
val pcr_rep = Decoupled(Bits(width = 64))
|
||||
val ipi_req = Decoupled(Bits(width = log2Up(ntiles)))
|
||||
val ipi_req = Decoupled(Bits(width = log2Up(nCores)))
|
||||
val ipi_rep = Decoupled(Bool()).flip
|
||||
val debug_stats_pcr = Bool(OUTPUT)
|
||||
// wired directly to stats register
|
||||
// expected to be used to quickly indicate to testbench to do logging b/c in 'interesting' work
|
||||
}
|
||||
|
||||
class SCRIO(n: Int) extends Bundle
|
||||
{
|
||||
val rdata = Vec.fill(n){Bits(INPUT, 64)}
|
||||
class SCRIO extends HTIFBundle {
|
||||
val rdata = Vec.fill(nSCR){Bits(INPUT, 64)}
|
||||
val wen = Bool(OUTPUT)
|
||||
val waddr = UInt(OUTPUT, log2Up(n))
|
||||
val waddr = UInt(OUTPUT, log2Up(nSCR))
|
||||
val wdata = Bits(OUTPUT, 64)
|
||||
}
|
||||
|
||||
class HTIF(w: Int, pcr_RESET: Int, nSCR: Int, offsetBits: Int)(implicit conf: TileLinkConfiguration) extends Module
|
||||
{
|
||||
implicit val (ln, co) = (conf.ln, conf.co)
|
||||
val nTiles = ln.nClients-1 // This HTIF is itself a TileLink client
|
||||
val io = new Bundle {
|
||||
val host = new HostIO(w)
|
||||
val cpu = Vec.fill(nTiles){new HTIFIO(nTiles).flip}
|
||||
class HTIFModuleIO extends HTIFBundle {
|
||||
val host = new HostIO
|
||||
val cpu = Vec.fill(nCores){new HTIFIO}.flip
|
||||
val mem = new TileLinkIO
|
||||
val scr = new SCRIO(nSCR)
|
||||
val scr = new SCRIO
|
||||
}
|
||||
|
||||
class HTIF(pcr_RESET: Int) extends Module with HTIFParameters {
|
||||
val io = new HTIFModuleIO
|
||||
|
||||
io.host.debug_stats_pcr := io.cpu.map(_.debug_stats_pcr).reduce(_||_)
|
||||
// system is 'interesting' if any tile is 'interesting'
|
||||
|
||||
val short_request_bits = 64
|
||||
val long_request_bits = short_request_bits + conf.dataBits
|
||||
val long_request_bits = short_request_bits + dataBits
|
||||
require(short_request_bits % w == 0)
|
||||
|
||||
val rx_count_w = 13 + log2Up(64) - log2Up(w) // data size field is 12 bits
|
||||
@ -92,7 +105,7 @@ class HTIF(w: Int, pcr_RESET: Int, nSCR: Int, offsetBits: Int)(implicit conf: Ti
|
||||
val cmd_readmem :: cmd_writemem :: cmd_readcr :: cmd_writecr :: cmd_ack :: cmd_nack :: Nil = Enum(UInt(), 6)
|
||||
|
||||
val pcr_addr = addr(io.cpu(0).pcr_req.bits.addr.getWidth-1, 0)
|
||||
val pcr_coreid = addr(log2Up(nTiles)-1+20+1,20)
|
||||
val pcr_coreid = addr(log2Up(nCores)-1+20+1,20)
|
||||
val pcr_wdata = packet_ram(0)
|
||||
|
||||
val bad_mem_packet = size(offsetBits-1-3,0).orR || addr(offsetBits-1-3,0).orR
|
||||
@ -114,13 +127,13 @@ class HTIF(w: Int, pcr_RESET: Int, nSCR: Int, offsetBits: Int)(implicit conf: Ti
|
||||
|
||||
val mem_acked = Reg(init=Bool(false))
|
||||
val mem_gxid = Reg(Bits())
|
||||
val mem_gsrc = Reg(UInt(width = conf.ln.idBits))
|
||||
val mem_gsrc = Reg(UInt())
|
||||
val mem_needs_ack = Reg(Bool())
|
||||
when (io.mem.grant.valid) {
|
||||
mem_acked := Bool(true)
|
||||
mem_gxid := io.mem.grant.bits.payload.master_xact_id
|
||||
mem_gsrc := io.mem.grant.bits.header.src
|
||||
mem_needs_ack := conf.co.requiresAckForGrant(io.mem.grant.bits.payload.g_type)
|
||||
mem_needs_ack := co.requiresAckForGrant(io.mem.grant.bits.payload.g_type)
|
||||
}
|
||||
io.mem.grant.ready := Bool(true)
|
||||
|
||||
@ -168,8 +181,8 @@ class HTIF(w: Int, pcr_RESET: Int, nSCR: Int, offsetBits: Int)(implicit conf: Ti
|
||||
}
|
||||
|
||||
var mem_req_data: Bits = null
|
||||
for (i <- 0 until conf.dataBits/short_request_bits) {
|
||||
val idx = UInt(i, log2Up(conf.dataBits/short_request_bits))
|
||||
for (i <- 0 until dataBits/short_request_bits) {
|
||||
val idx = UInt(i, log2Up(dataBits/short_request_bits))
|
||||
when (state === state_mem_rresp && io.mem.grant.valid) {
|
||||
packet_ram(idx) := io.mem.grant.bits.payload.data((i+1)*short_request_bits-1, i*short_request_bits)
|
||||
}
|
||||
@ -184,7 +197,7 @@ class HTIF(w: Int, pcr_RESET: Int, nSCR: Int, offsetBits: Int)(implicit conf: Ti
|
||||
acq_q.io.deq.ready := io.mem.acquire.ready
|
||||
io.mem.acquire.bits.payload := acq_q.io.deq.bits
|
||||
io.mem.acquire.bits.payload.data := mem_req_data
|
||||
io.mem.acquire.bits.header.src := UInt(conf.ln.nClients) // By convention HTIF is the client with the largest id
|
||||
io.mem.acquire.bits.header.src := UInt(params(LNClients)) // By convention HTIF is the client with the largest id
|
||||
io.mem.acquire.bits.header.dst := UInt(0) // DNC; Overwritten outside module
|
||||
io.mem.finish.valid := (state === state_mem_finish) && mem_needs_ack
|
||||
io.mem.finish.bits.payload.master_xact_id := mem_gxid
|
||||
@ -194,7 +207,7 @@ class HTIF(w: Int, pcr_RESET: Int, nSCR: Int, offsetBits: Int)(implicit conf: Ti
|
||||
|
||||
val pcr_reset = UInt(pcr_RESET)(pcr_addr.getWidth-1,0)
|
||||
val pcrReadData = Reg(Bits(width = io.cpu(0).pcr_rep.bits.getWidth))
|
||||
for (i <- 0 until nTiles) {
|
||||
for (i <- 0 until nCores) {
|
||||
val my_reset = Reg(init=Bool(true))
|
||||
val my_ipi = Reg(init=Bool(false))
|
||||
|
||||
@ -211,7 +224,7 @@ class HTIF(w: Int, pcr_RESET: Int, nSCR: Int, offsetBits: Int)(implicit conf: Ti
|
||||
}
|
||||
cpu.ipi_rep.valid := my_ipi
|
||||
cpu.ipi_req.ready := Bool(true)
|
||||
for (j <- 0 until nTiles) {
|
||||
for (j <- 0 until nCores) {
|
||||
when (io.cpu(j).ipi_req.valid && io.cpu(j).ipi_req.bits === UInt(i)) {
|
||||
my_ipi := Bool(true)
|
||||
}
|
||||
@ -239,8 +252,8 @@ class HTIF(w: Int, pcr_RESET: Int, nSCR: Int, offsetBits: Int)(implicit conf: Ti
|
||||
val scr_rdata = Vec.fill(io.scr.rdata.size){Bits(width = 64)}
|
||||
for (i <- 0 until scr_rdata.size)
|
||||
scr_rdata(i) := io.scr.rdata(i)
|
||||
scr_rdata(0) := UInt(nTiles)
|
||||
scr_rdata(1) := UInt((BigInt(conf.dataBits/8) << acq_q.io.enq.bits.addr.getWidth) >> 20)
|
||||
scr_rdata(0) := UInt(nCores)
|
||||
scr_rdata(1) := UInt((BigInt(dataBits/8) << acq_q.io.enq.bits.addr.getWidth) >> 20)
|
||||
|
||||
io.scr.wen := Bool(false)
|
||||
io.scr.wdata := pcr_wdata
|
||||
|
@ -77,26 +77,26 @@ class BigMem[T <: Data](n: Int, preLatency: Int, postLatency: Int, leaf: Mem[UIn
|
||||
io.rdata := Mux1H(rdataSel, rdataDeep)
|
||||
}
|
||||
|
||||
class LLCDataReq(ways: Int)(implicit conf: MemoryIFConfiguration) extends MemReqCmd
|
||||
class LLCDataReq(ways: Int) extends MemReqCmd
|
||||
{
|
||||
val way = UInt(width = log2Up(ways))
|
||||
val isWriteback = Bool()
|
||||
override def clone = new LLCDataReq(ways)(conf).asInstanceOf[this.type]
|
||||
override def clone = new LLCDataReq(ways).asInstanceOf[this.type]
|
||||
}
|
||||
|
||||
class LLCTagReq(ways: Int)(implicit val conf: MemoryIFConfiguration) extends HasMemAddr
|
||||
class LLCTagReq(ways: Int) extends HasMemAddr
|
||||
{
|
||||
val way = UInt(width = log2Up(ways))
|
||||
override def clone = new LLCTagReq(ways)(conf).asInstanceOf[this.type]
|
||||
override def clone = new LLCTagReq(ways).asInstanceOf[this.type]
|
||||
}
|
||||
|
||||
class LLCMSHRFile(sets: Int, ways: Int, outstanding: Int, refill_cycles: Int)(implicit conf: MemoryIFConfiguration) extends Module
|
||||
class LLCMSHRFile(sets: Int, ways: Int, outstanding: Int, refill_cycles: Int) extends Module
|
||||
{
|
||||
val io = new Bundle {
|
||||
val cpu = Decoupled(new MemReqCmd).flip
|
||||
val repl_way = UInt(INPUT, log2Up(ways))
|
||||
val repl_dirty = Bool(INPUT)
|
||||
val repl_tag = UInt(INPUT, conf.addrBits - log2Up(sets))
|
||||
val repl_tag = UInt(INPUT, params(MIFAddrBits) - log2Up(sets))
|
||||
val data = Decoupled(new LLCDataReq(ways))
|
||||
val tag = Decoupled(new LLCTagReq(ways))
|
||||
val mem = new MemPipeIO
|
||||
@ -105,14 +105,14 @@ class LLCMSHRFile(sets: Int, ways: Int, outstanding: Int, refill_cycles: Int)(im
|
||||
}
|
||||
|
||||
class MSHR extends Bundle {
|
||||
val addr = UInt(width = conf.addrBits)
|
||||
val addr = UInt(width = params(MIFAddrBits))
|
||||
val way = UInt(width = log2Up(ways))
|
||||
val tag = io.cpu.bits.tag.clone
|
||||
val refilled = Bool()
|
||||
val refillCount = UInt(width = log2Up(refill_cycles))
|
||||
val requested = Bool()
|
||||
val old_dirty = Bool()
|
||||
val old_tag = UInt(width = conf.addrBits - log2Up(sets))
|
||||
val old_tag = UInt(width = params(MIFAddrBits) - log2Up(sets))
|
||||
val wb_busy = Bool()
|
||||
|
||||
override def clone = new MSHR().asInstanceOf[this.type]
|
||||
@ -188,10 +188,10 @@ class LLCMSHRFile(sets: Int, ways: Int, outstanding: Int, refill_cycles: Int)(im
|
||||
io.mem_resp_way := mshr(refillId).way
|
||||
}
|
||||
|
||||
class LLCWriteback(requestors: Int, refill_cycles: Int)(implicit conf: MemoryIFConfiguration) extends Module
|
||||
class LLCWriteback(requestors: Int, refill_cycles: Int) extends Module
|
||||
{
|
||||
val io = new Bundle {
|
||||
val req = Vec.fill(requestors){Decoupled(UInt(width = conf.addrBits)).flip }
|
||||
val req = Vec.fill(requestors){Decoupled(UInt(width = params(MIFAddrBits))).flip }
|
||||
val data = Vec.fill(requestors){Decoupled(new MemData).flip }
|
||||
val mem = new MemPipeIO
|
||||
}
|
||||
@ -237,12 +237,12 @@ class LLCWriteback(requestors: Int, refill_cycles: Int)(implicit conf: MemoryIFC
|
||||
io.mem.req_data.bits := io.data(who).bits
|
||||
}
|
||||
|
||||
class LLCData(latency: Int, sets: Int, ways: Int, refill_cycles: Int, leaf: Mem[UInt])(implicit conf: MemoryIFConfiguration) extends Module
|
||||
class LLCData(latency: Int, sets: Int, ways: Int, refill_cycles: Int, leaf: Mem[UInt]) extends Module
|
||||
{
|
||||
val io = new Bundle {
|
||||
val req = Decoupled(new LLCDataReq(ways)).flip
|
||||
val req_data = Decoupled(new MemData).flip
|
||||
val writeback = Decoupled(UInt(width = conf.addrBits))
|
||||
val writeback = Decoupled(UInt(width = params(MIFAddrBits)))
|
||||
val writeback_data = Decoupled(new MemData)
|
||||
val resp = Decoupled(new MemResp)
|
||||
val mem_resp = Valid(new MemResp).flip
|
||||
@ -250,7 +250,7 @@ class LLCData(latency: Int, sets: Int, ways: Int, refill_cycles: Int, leaf: Mem[
|
||||
val mem_resp_way = UInt(INPUT, log2Up(ways))
|
||||
}
|
||||
|
||||
val data = Module(new BigMem(sets*ways*refill_cycles, 1, latency-1, leaf, true)(Bits(width = conf.dataBits)))
|
||||
val data = Module(new BigMem(sets*ways*refill_cycles, 1, latency-1, leaf, true)(Bits(width = params(MIFDataBits))))
|
||||
class QEntry extends MemResp {
|
||||
val isWriteback = Bool()
|
||||
override def clone = new QEntry().asInstanceOf[this.type]
|
||||
@ -304,7 +304,7 @@ class LLCData(latency: Int, sets: Int, ways: Int, refill_cycles: Int, leaf: Mem[
|
||||
io.writeback_data.bits := q.io.deq.bits
|
||||
}
|
||||
|
||||
class MemReqArb(n: Int, refill_cycles: Int)(implicit conf: MemoryIFConfiguration) extends Module
|
||||
class MemReqArb(n: Int, refill_cycles: Int) extends Module
|
||||
{
|
||||
val io = new Bundle {
|
||||
val cpu = Vec.fill(n){new MemIO().flip}
|
||||
@ -347,16 +347,16 @@ class MemReqArb(n: Int, refill_cycles: Int)(implicit conf: MemoryIFConfiguration
|
||||
when (unlock) { lock := Bool(false) }
|
||||
}
|
||||
|
||||
abstract class DRAMSideLLCLike(implicit conf: MemoryIFConfiguration) extends Module {
|
||||
abstract class DRAMSideLLCLike extends Module {
|
||||
val io = new Bundle {
|
||||
val cpu = new MemIO().flip
|
||||
val mem = new MemPipeIO
|
||||
}
|
||||
}
|
||||
|
||||
class DRAMSideLLC(sets: Int, ways: Int, outstanding: Int, refill_cycles: Int, tagLeaf: Mem[UInt], dataLeaf: Mem[UInt])(implicit conf: MemoryIFConfiguration) extends DRAMSideLLCLike
|
||||
class DRAMSideLLC(sets: Int, ways: Int, outstanding: Int, refill_cycles: Int, tagLeaf: Mem[UInt], dataLeaf: Mem[UInt]) extends DRAMSideLLCLike
|
||||
{
|
||||
val tagWidth = conf.addrBits - log2Up(sets)
|
||||
val tagWidth = params(MIFAddrBits) - log2Up(sets)
|
||||
val metaWidth = tagWidth + 2 // valid + dirty
|
||||
|
||||
val memCmdArb = Module(new Arbiter(new MemReqCmd, 2))
|
||||
@ -504,8 +504,7 @@ object HellaQueue
|
||||
}
|
||||
}
|
||||
|
||||
class DRAMSideLLCNull(numRequests: Int, refillCycles: Int)(implicit conf: MemoryIFConfiguration)
|
||||
extends DRAMSideLLCLike {
|
||||
class DRAMSideLLCNull(numRequests: Int, refillCycles: Int) extends DRAMSideLLCLike {
|
||||
|
||||
val numEntries = numRequests * refillCycles
|
||||
val size = log2Down(numEntries) + 1
|
||||
|
@ -2,57 +2,58 @@ package uncore
|
||||
import Chisel._
|
||||
import scala.math._
|
||||
|
||||
case class AddressSpaceConfiguration(paddrBits: Int, vaddrBits: Int, pgIdxBits: Int, asidBits: Int, permBits:Int) {
|
||||
val ppnBits = paddrBits - pgIdxBits
|
||||
val vpnBits = vaddrBits - pgIdxBits
|
||||
case object PAddrBits extends Field[Int]
|
||||
case object VAddrBits extends Field[Int]
|
||||
case object PgIdxBits extends Field[Int]
|
||||
case object ASIdBits extends Field[Int]
|
||||
case object PermBits extends Field[Int]
|
||||
case object PPNBits extends Field[Int]
|
||||
case object VPNBits extends Field[Int]
|
||||
|
||||
case object MIFAddrBits extends Field[Int]
|
||||
case object MIFDataBits extends Field[Int]
|
||||
case object MIFTagBits extends Field[Int]
|
||||
case object MIFDataBeats extends Field[Int]
|
||||
|
||||
trait HasMemData extends Bundle {
|
||||
val data = Bits(width = params(MIFDataBits))
|
||||
}
|
||||
|
||||
case class MemoryIFConfiguration(addrBits: Int, dataBits: Int, tagBits: Int, dataBeats: Int)
|
||||
|
||||
abstract trait MemoryIFSubBundle extends Bundle {
|
||||
implicit val conf: MemoryIFConfiguration
|
||||
override def clone = this.getClass.getConstructors.head.newInstance(conf).asInstanceOf[this.type]
|
||||
trait HasMemAddr extends Bundle {
|
||||
val addr = UInt(width = params(MIFAddrBits))
|
||||
}
|
||||
|
||||
trait HasMemData extends MemoryIFSubBundle {
|
||||
val data = Bits(width = conf.dataBits)
|
||||
trait HasMemTag extends Bundle {
|
||||
val tag = UInt(width = params(MIFTagBits))
|
||||
}
|
||||
|
||||
trait HasMemAddr extends MemoryIFSubBundle {
|
||||
val addr = UInt(width = conf.addrBits)
|
||||
}
|
||||
|
||||
trait HasMemTag extends MemoryIFSubBundle {
|
||||
val tag = UInt(width = conf.tagBits)
|
||||
}
|
||||
|
||||
class MemReqCmd(implicit val conf: MemoryIFConfiguration) extends HasMemAddr with HasMemTag {
|
||||
class MemReqCmd extends HasMemAddr with HasMemTag {
|
||||
val rw = Bool()
|
||||
}
|
||||
|
||||
class MemResp(implicit val conf: MemoryIFConfiguration) extends HasMemData with HasMemTag
|
||||
class MemResp extends HasMemData with HasMemTag
|
||||
|
||||
class MemData(implicit val conf: MemoryIFConfiguration) extends HasMemData
|
||||
class MemData extends HasMemData
|
||||
|
||||
class MemIO(implicit val conf: MemoryIFConfiguration) extends Bundle {
|
||||
class MemIO extends Bundle {
|
||||
val req_cmd = Decoupled(new MemReqCmd)
|
||||
val req_data = Decoupled(new MemData)
|
||||
val resp = Decoupled(new MemResp).flip
|
||||
}
|
||||
|
||||
class MemPipeIO(implicit val conf: MemoryIFConfiguration) extends Bundle {
|
||||
class MemPipeIO extends Bundle {
|
||||
val req_cmd = Decoupled(new MemReqCmd)
|
||||
val req_data = Decoupled(new MemData)
|
||||
val resp = Valid(new MemResp).flip
|
||||
}
|
||||
|
||||
class MemSerializedIO(w: Int)(implicit val conf: MemoryIFConfiguration) extends Bundle
|
||||
class MemSerializedIO(w: Int) extends Bundle
|
||||
{
|
||||
val req = Decoupled(Bits(width = w))
|
||||
val resp = Valid(Bits(width = w)).flip
|
||||
}
|
||||
|
||||
class MemSerdes(w: Int)(implicit val conf: MemoryIFConfiguration) extends Module
|
||||
class MemSerdes(w: Int) extends Module
|
||||
{
|
||||
val io = new Bundle {
|
||||
val wide = new MemIO().flip
|
||||
@ -61,6 +62,7 @@ class MemSerdes(w: Int)(implicit val conf: MemoryIFConfiguration) extends Module
|
||||
val abits = io.wide.req_cmd.bits.toBits.getWidth
|
||||
val dbits = io.wide.req_data.bits.toBits.getWidth
|
||||
val rbits = io.wide.resp.bits.getWidth
|
||||
val dbeats = params(MIFDataBeats)
|
||||
|
||||
val out_buf = Reg(Bits())
|
||||
val in_buf = Reg(Bits())
|
||||
@ -68,7 +70,7 @@ class MemSerdes(w: Int)(implicit val conf: MemoryIFConfiguration) extends Module
|
||||
val s_idle :: s_read_addr :: s_write_addr :: s_write_idle :: s_write_data :: Nil = Enum(UInt(), 5)
|
||||
val state = Reg(init=s_idle)
|
||||
val send_cnt = Reg(init=UInt(0, log2Up((max(abits, dbits)+w-1)/w)))
|
||||
val data_send_cnt = Reg(init=UInt(0, log2Up(conf.dataBeats)))
|
||||
val data_send_cnt = Reg(init=UInt(0, log2Up(dbeats)))
|
||||
val adone = io.narrow.req.ready && send_cnt === UInt((abits-1)/w)
|
||||
val ddone = io.narrow.req.ready && send_cnt === UInt((dbits-1)/w)
|
||||
|
||||
@ -104,12 +106,12 @@ class MemSerdes(w: Int)(implicit val conf: MemoryIFConfiguration) extends Module
|
||||
}
|
||||
when (state === s_write_data && ddone) {
|
||||
data_send_cnt := data_send_cnt + UInt(1)
|
||||
state := Mux(data_send_cnt === UInt(conf.dataBeats-1), s_idle, s_write_idle)
|
||||
state := Mux(data_send_cnt === UInt(dbeats-1), s_idle, s_write_idle)
|
||||
send_cnt := UInt(0)
|
||||
}
|
||||
|
||||
val recv_cnt = Reg(init=UInt(0, log2Up((rbits+w-1)/w)))
|
||||
val data_recv_cnt = Reg(init=UInt(0, log2Up(conf.dataBeats)))
|
||||
val data_recv_cnt = Reg(init=UInt(0, log2Up(dbeats)))
|
||||
val resp_val = Reg(init=Bool(false))
|
||||
|
||||
resp_val := Bool(false)
|
||||
@ -127,21 +129,22 @@ class MemSerdes(w: Int)(implicit val conf: MemoryIFConfiguration) extends Module
|
||||
io.wide.resp.bits := io.wide.resp.bits.fromBits(in_buf)
|
||||
}
|
||||
|
||||
class MemDesserIO(w: Int)(implicit val conf: MemoryIFConfiguration) extends Bundle {
|
||||
class MemDesserIO(w: Int) extends Bundle {
|
||||
val narrow = new MemSerializedIO(w).flip
|
||||
val wide = new MemIO
|
||||
}
|
||||
|
||||
class MemDesser(w: Int)(implicit val conf: MemoryIFConfiguration) extends Module // test rig side
|
||||
class MemDesser(w: Int) extends Module // test rig side
|
||||
{
|
||||
val io = new MemDesserIO(w)
|
||||
val abits = io.wide.req_cmd.bits.toBits.getWidth
|
||||
val dbits = io.wide.req_data.bits.toBits.getWidth
|
||||
val rbits = io.wide.resp.bits.getWidth
|
||||
val dbeats = params(MIFDataBeats)
|
||||
|
||||
require(dbits >= abits && rbits >= dbits)
|
||||
val recv_cnt = Reg(init=UInt(0, log2Up((rbits+w-1)/w)))
|
||||
val data_recv_cnt = Reg(init=UInt(0, log2Up(conf.dataBeats)))
|
||||
val data_recv_cnt = Reg(init=UInt(0, log2Up(dbeats)))
|
||||
val adone = io.narrow.req.valid && recv_cnt === UInt((abits-1)/w)
|
||||
val ddone = io.narrow.req.valid && recv_cnt === UInt((dbits-1)/w)
|
||||
val rdone = io.narrow.resp.valid && recv_cnt === UInt((rbits-1)/w)
|
||||
@ -169,13 +172,13 @@ class MemDesser(w: Int)(implicit val conf: MemoryIFConfiguration) extends Module
|
||||
}
|
||||
when (state === s_data && io.wide.req_data.ready) {
|
||||
state := s_data_recv
|
||||
when (data_recv_cnt === UInt(conf.dataBeats-1)) {
|
||||
when (data_recv_cnt === UInt(dbeats-1)) {
|
||||
state := s_cmd_recv
|
||||
}
|
||||
data_recv_cnt := data_recv_cnt + UInt(1)
|
||||
}
|
||||
when (rdone) { // state === s_reply
|
||||
when (data_recv_cnt === UInt(conf.dataBeats-1)) {
|
||||
when (data_recv_cnt === UInt(dbeats-1)) {
|
||||
state := s_cmd_recv
|
||||
}
|
||||
recv_cnt := UInt(0)
|
||||
@ -189,7 +192,7 @@ class MemDesser(w: Int)(implicit val conf: MemoryIFConfiguration) extends Module
|
||||
io.wide.req_data.valid := state === s_data
|
||||
io.wide.req_data.bits.data := in_buf >> UInt(((rbits+w-1)/w - (dbits+w-1)/w)*w)
|
||||
|
||||
val dataq = Module(new Queue(new MemResp, conf.dataBeats))
|
||||
val dataq = Module(new Queue(new MemResp, dbeats))
|
||||
dataq.io.enq <> io.wide.resp
|
||||
dataq.io.deq.ready := recv_cnt === UInt((rbits-1)/w)
|
||||
|
||||
@ -198,18 +201,21 @@ class MemDesser(w: Int)(implicit val conf: MemoryIFConfiguration) extends Module
|
||||
}
|
||||
|
||||
//Adapter betweewn an UncachedTileLinkIO and a mem controller MemIO
|
||||
class MemIOUncachedTileLinkIOConverter(qDepth: Int)(implicit tlconf: TileLinkConfiguration, mifconf: MemoryIFConfiguration) extends Module {
|
||||
class MemIOUncachedTileLinkIOConverter(qDepth: Int) extends Module {
|
||||
val io = new Bundle {
|
||||
val uncached = new UncachedTileLinkIO().flip
|
||||
val mem = new MemIO
|
||||
}
|
||||
|
||||
require(tlconf.dataBits == mifconf.dataBits*mifconf.dataBeats)
|
||||
//require(tlconf.clientXactIdBits <= mifconf.tagBits)
|
||||
val co = params(TLCoherence)
|
||||
val tbits = params(MIFTagBits)
|
||||
val dbits = params(MIFDataBits)
|
||||
val dbeats = params(MIFDataBeats)
|
||||
require(params(TLDataBits) == dbits*dbeats)
|
||||
//require(params(TLClientXactIdBits) <= params(MIFTagBits))
|
||||
|
||||
val mem_cmd_q = Module(new Queue(new MemReqCmd, qDepth))
|
||||
val mem_data_q = Module(new Queue(new MemData, qDepth))
|
||||
val cnt_max = mifconf.dataBeats
|
||||
val cnt_max = dbeats
|
||||
|
||||
val cnt_out = Reg(UInt(width = log2Up(cnt_max+1)))
|
||||
val active_out = Reg(init=Bool(false))
|
||||
@ -222,7 +228,7 @@ class MemIOUncachedTileLinkIOConverter(qDepth: Int)(implicit tlconf: TileLinkCon
|
||||
val cnt_in = Reg(UInt(width = log2Up(cnt_max+1)))
|
||||
val active_in = Reg(init=Bool(false))
|
||||
val buf_in = Reg(Bits())
|
||||
val tag_in = Reg(UInt(width = mifconf.tagBits))
|
||||
val tag_in = Reg(UInt(width = tbits))
|
||||
|
||||
// Decompose outgoing TL Acquires into MemIO cmd and data
|
||||
when(!active_out && io.uncached.acquire.valid) {
|
||||
@ -232,7 +238,7 @@ class MemIOUncachedTileLinkIOConverter(qDepth: Int)(implicit tlconf: TileLinkCon
|
||||
buf_out := io.uncached.acquire.bits.payload.data
|
||||
tag_out := io.uncached.acquire.bits.payload.client_xact_id
|
||||
addr_out := io.uncached.acquire.bits.payload.addr
|
||||
has_data := tlconf.co.messageHasData(io.uncached.acquire.bits.payload)
|
||||
has_data := co.messageHasData(io.uncached.acquire.bits.payload)
|
||||
}
|
||||
when(active_out) {
|
||||
when(mem_cmd_q.io.enq.fire()) {
|
||||
@ -240,7 +246,7 @@ class MemIOUncachedTileLinkIOConverter(qDepth: Int)(implicit tlconf: TileLinkCon
|
||||
}
|
||||
when(mem_data_q.io.enq.fire()) {
|
||||
cnt_out := cnt_out + UInt(1)
|
||||
buf_out := buf_out >> UInt(mifconf.dataBits)
|
||||
buf_out := buf_out >> UInt(dbits)
|
||||
}
|
||||
when(cmd_sent_out && (!has_data || cnt_out === UInt(cnt_max))) {
|
||||
active_out := Bool(false)
|
||||
@ -264,7 +270,7 @@ class MemIOUncachedTileLinkIOConverter(qDepth: Int)(implicit tlconf: TileLinkCon
|
||||
when(!active_in && io.mem.resp.valid) {
|
||||
active_in := Bool(true)
|
||||
cnt_in := UInt(1)
|
||||
buf_in := io.mem.resp.bits.data << UInt(mifconf.dataBits*(cnt_max-1))
|
||||
buf_in := io.mem.resp.bits.data << UInt(dbits*(cnt_max-1))
|
||||
tag_in := io.mem.resp.bits.tag
|
||||
}
|
||||
when(active_in) {
|
||||
@ -272,7 +278,7 @@ class MemIOUncachedTileLinkIOConverter(qDepth: Int)(implicit tlconf: TileLinkCon
|
||||
active_in := Bool(false)
|
||||
}
|
||||
when(io.mem.resp.fire()) {
|
||||
buf_in := Cat(io.mem.resp.bits.data, buf_in(cnt_max*mifconf.dataBits-1,mifconf.dataBits))
|
||||
buf_in := Cat(io.mem.resp.bits.data, buf_in(cnt_max*dbits-1,dbits))
|
||||
cnt_in := cnt_in + UInt(1)
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +1,35 @@
|
||||
package uncore
|
||||
import Chisel._
|
||||
|
||||
case class PhysicalNetworkConfiguration(nEndpoints: Int, idBits: Int)
|
||||
case object LNMasters extends Field[Int]
|
||||
case object LNClients extends Field[Int]
|
||||
case object LNEndpoints extends Field[Int]
|
||||
|
||||
class PhysicalHeader(implicit conf: PhysicalNetworkConfiguration) extends Bundle {
|
||||
val src = UInt(width = conf.idBits)
|
||||
val dst = UInt(width = conf.idBits)
|
||||
class PhysicalHeader(n: Int) extends Bundle {
|
||||
val src = UInt(width = log2Up(n))
|
||||
val dst = UInt(width = log2Up(n))
|
||||
}
|
||||
|
||||
class PhysicalNetworkIO[T <: Data](dType: T)(implicit conf: PhysicalNetworkConfiguration) extends Bundle {
|
||||
val header = new PhysicalHeader
|
||||
class PhysicalNetworkIO[T <: Data](n: Int, dType: T) extends Bundle {
|
||||
val header = new PhysicalHeader(n)
|
||||
val payload = dType.clone
|
||||
override def clone = { new PhysicalNetworkIO(dType).asInstanceOf[this.type] }
|
||||
override def clone = new PhysicalNetworkIO(n,dType).asInstanceOf[this.type]
|
||||
}
|
||||
|
||||
abstract class PhysicalNetwork(conf: PhysicalNetworkConfiguration) extends Module
|
||||
|
||||
class BasicCrossbarIO[T <: Data](dType: T)(implicit conf: PhysicalNetworkConfiguration) extends Bundle {
|
||||
val in = Vec.fill(conf.nEndpoints){Decoupled(new PhysicalNetworkIO(dType))}.flip
|
||||
val out = Vec.fill(conf.nEndpoints){Decoupled(new PhysicalNetworkIO(dType))}
|
||||
class BasicCrossbarIO[T <: Data](n: Int, dType: T) extends Bundle {
|
||||
val in = Vec.fill(n){Decoupled(new PhysicalNetworkIO(n,dType))}.flip
|
||||
val out = Vec.fill(n){Decoupled(new PhysicalNetworkIO(n,dType))}
|
||||
}
|
||||
class BasicCrossbar[T <: Data](dType: T, count: Int = 1)(implicit conf: PhysicalNetworkConfiguration) extends PhysicalNetwork(conf) {
|
||||
val io = new BasicCrossbarIO(dType)
|
||||
|
||||
val rdyVecs = List.fill(conf.nEndpoints)(Vec.fill(conf.nEndpoints)(Bool()))
|
||||
abstract class PhysicalNetwork extends Module
|
||||
|
||||
class BasicCrossbar[T <: Data](n: Int, dType: T, count: Int = 1) extends PhysicalNetwork {
|
||||
val io = new BasicCrossbarIO(n, dType)
|
||||
|
||||
val rdyVecs = List.fill(n){Vec.fill(n)(Bool())}
|
||||
|
||||
io.out.zip(rdyVecs).zipWithIndex.map{ case ((out, rdys), i) => {
|
||||
val rrarb = Module(new LockingRRArbiter(io.in(0).bits, conf.nEndpoints, count))
|
||||
val rrarb = Module(new LockingRRArbiter(io.in(0).bits, n, count))
|
||||
(rrarb.io.in, io.in, rdys).zipped.map{ case (arb, in, rdy) => {
|
||||
arb.valid := in.valid && (in.bits.header.dst === UInt(i))
|
||||
arb.bits := in.bits
|
||||
@ -34,30 +37,26 @@ class BasicCrossbar[T <: Data](dType: T, count: Int = 1)(implicit conf: Physical
|
||||
}}
|
||||
out <> rrarb.io.out
|
||||
}}
|
||||
for(i <- 0 until conf.nEndpoints) {
|
||||
for(i <- 0 until n) {
|
||||
io.in(i).ready := rdyVecs.map(r => r(i)).reduceLeft(_||_)
|
||||
}
|
||||
}
|
||||
|
||||
case class LogicalNetworkConfiguration(idBits: Int, nMasters: Int, nClients: Int) {
|
||||
val nEndpoints = nMasters + nClients
|
||||
abstract class LogicalNetwork extends Module
|
||||
|
||||
class LogicalHeader extends Bundle {
|
||||
val src = UInt(width = log2Up(params(LNEndpoints)))
|
||||
val dst = UInt(width = log2Up(params(LNEndpoints)))
|
||||
}
|
||||
|
||||
abstract class LogicalNetwork[TileLinkType <: Bundle](implicit conf: LogicalNetworkConfiguration) extends Module
|
||||
|
||||
class LogicalHeader(implicit conf: LogicalNetworkConfiguration) extends Bundle {
|
||||
val src = UInt(width = conf.idBits)
|
||||
val dst = UInt(width = conf.idBits)
|
||||
}
|
||||
|
||||
class LogicalNetworkIO[T <: Data](dType: T)(implicit conf: LogicalNetworkConfiguration) extends Bundle {
|
||||
class LogicalNetworkIO[T <: Data](dType: T) extends Bundle {
|
||||
val header = new LogicalHeader
|
||||
val payload = dType.clone
|
||||
override def clone = { new LogicalNetworkIO(dType).asInstanceOf[this.type] }
|
||||
}
|
||||
|
||||
object DecoupledLogicalNetworkIOWrapper {
|
||||
def apply[T <: Data](in: DecoupledIO[T], src: UInt = UInt(0), dst: UInt = UInt(0))(implicit conf: LogicalNetworkConfiguration) = {
|
||||
def apply[T <: Data](in: DecoupledIO[T], src: UInt = UInt(0), dst: UInt = UInt(0)) = {
|
||||
val out = Decoupled(new LogicalNetworkIO(in.bits.clone)).asDirectionless
|
||||
out.valid := in.valid
|
||||
out.bits.payload := in.bits
|
||||
@ -69,7 +68,7 @@ object DecoupledLogicalNetworkIOWrapper {
|
||||
}
|
||||
|
||||
object DecoupledLogicalNetworkIOUnwrapper {
|
||||
def apply[T <: Data](in: DecoupledIO[LogicalNetworkIO[T]])(implicit conf: LogicalNetworkConfiguration) = {
|
||||
def apply[T <: Data](in: DecoupledIO[LogicalNetworkIO[T]]) = {
|
||||
val out = Decoupled(in.bits.payload.clone).asDirectionless
|
||||
out.valid := in.valid
|
||||
out.bits := in.bits.payload
|
||||
|
@ -1,27 +1,29 @@
|
||||
package uncore
|
||||
import Chisel._
|
||||
|
||||
case class TileLinkConfiguration(co: CoherencePolicyWithUncached, ln: LogicalNetworkConfiguration, addrBits: Int, masterXactIdBits: Int, clientXactIdBits: Int, dataBits: Int, writeMaskBits: Int, wordAddrBits: Int, atomicOpBits: Int)
|
||||
case object TLCoherence extends Field[CoherencePolicyWithUncached]
|
||||
case object TLAddrBits extends Field[Int]
|
||||
case object TLMasterXactIdBits extends Field[Int]
|
||||
case object TLClientXactIdBits extends Field[Int]
|
||||
case object TLDataBits extends Field[Int]
|
||||
case object TLWriteMaskBits extends Field[Int]
|
||||
case object TLWordAddrBits extends Field[Int]
|
||||
case object TLAtomicOpBits extends Field[Int]
|
||||
|
||||
abstract trait TileLinkSubBundle extends Bundle {
|
||||
implicit val tlconf: TileLinkConfiguration
|
||||
override def clone = this.getClass.getConstructors.head.newInstance(tlconf).asInstanceOf[this.type]
|
||||
trait HasPhysicalAddress extends Bundle {
|
||||
val addr = UInt(width = params(TLAddrBits))
|
||||
}
|
||||
|
||||
trait HasPhysicalAddress extends TileLinkSubBundle {
|
||||
val addr = UInt(width = tlconf.addrBits)
|
||||
trait HasClientTransactionId extends Bundle {
|
||||
val client_xact_id = Bits(width = params(TLClientXactIdBits))
|
||||
}
|
||||
|
||||
trait HasClientTransactionId extends TileLinkSubBundle {
|
||||
val client_xact_id = Bits(width = tlconf.clientXactIdBits)
|
||||
trait HasMasterTransactionId extends Bundle {
|
||||
val master_xact_id = Bits(width = params(TLMasterXactIdBits))
|
||||
}
|
||||
|
||||
trait HasMasterTransactionId extends TileLinkSubBundle {
|
||||
val master_xact_id = Bits(width = tlconf.masterXactIdBits)
|
||||
}
|
||||
|
||||
trait HasTileLinkData extends TileLinkSubBundle {
|
||||
val data = Bits(width = tlconf.dataBits)
|
||||
trait HasTileLinkData extends Bundle {
|
||||
val data = Bits(width = params(TLDataBits))
|
||||
}
|
||||
|
||||
trait SourcedMessage extends Bundle
|
||||
@ -30,7 +32,7 @@ trait MasterSourcedMessage extends SourcedMessage
|
||||
|
||||
object Acquire
|
||||
{
|
||||
def apply(a_type: Bits, addr: UInt, client_xact_id: UInt)(implicit conf: TileLinkConfiguration): Acquire = {
|
||||
def apply(a_type: Bits, addr: UInt, client_xact_id: UInt): Acquire = {
|
||||
val acq = new Acquire
|
||||
acq.a_type := a_type
|
||||
acq.addr := addr
|
||||
@ -41,42 +43,42 @@ object Acquire
|
||||
acq.atomic_opcode := Bits(0)
|
||||
acq
|
||||
}
|
||||
def apply(a_type: Bits, addr: UInt, client_xact_id: UInt, data: UInt)(implicit conf: TileLinkConfiguration): Acquire = {
|
||||
def apply(a_type: Bits, addr: UInt, client_xact_id: UInt, data: UInt): Acquire = {
|
||||
val acq = apply(a_type, addr, client_xact_id)
|
||||
acq.data := data
|
||||
acq
|
||||
}
|
||||
def apply(a_type: UInt, addr: UInt, client_xact_id: UInt, write_mask: Bits, data: UInt)(implicit conf: TileLinkConfiguration): Acquire = {
|
||||
def apply(a_type: UInt, addr: UInt, client_xact_id: UInt, write_mask: Bits, data: UInt): Acquire = {
|
||||
val acq = apply(a_type, addr, client_xact_id, data)
|
||||
acq.write_mask := write_mask
|
||||
acq
|
||||
}
|
||||
def apply(a_type: UInt, addr: UInt, client_xact_id: UInt, subword_addr: UInt, atomic_opcode: UInt, data: UInt)(implicit conf: TileLinkConfiguration): Acquire = {
|
||||
def apply(a_type: UInt, addr: UInt, client_xact_id: UInt, subword_addr: UInt, atomic_opcode: UInt, data: UInt): Acquire = {
|
||||
val acq = apply(a_type, addr, client_xact_id, data)
|
||||
acq.subword_addr := subword_addr
|
||||
acq.atomic_opcode := atomic_opcode
|
||||
acq
|
||||
}
|
||||
def apply(a: Acquire)(implicit conf: TileLinkConfiguration): Acquire = {
|
||||
def apply(a: Acquire): Acquire = {
|
||||
val acq = new Acquire
|
||||
acq := a
|
||||
acq
|
||||
}
|
||||
}
|
||||
|
||||
class Acquire(implicit val tlconf: TileLinkConfiguration) extends ClientSourcedMessage
|
||||
class Acquire extends ClientSourcedMessage
|
||||
with HasPhysicalAddress
|
||||
with HasClientTransactionId
|
||||
with HasTileLinkData {
|
||||
val a_type = UInt(width = tlconf.co.acquireTypeWidth)
|
||||
val write_mask = Bits(width = tlconf.writeMaskBits)
|
||||
val subword_addr = Bits(width = tlconf.wordAddrBits)
|
||||
val atomic_opcode = Bits(width = tlconf.atomicOpBits)
|
||||
val a_type = UInt(width = params(TLCoherence).acquireTypeWidth)
|
||||
val write_mask = Bits(width = params(TLWriteMaskBits))
|
||||
val subword_addr = Bits(width = params(TLWordAddrBits))
|
||||
val atomic_opcode = Bits(width = params(TLAtomicOpBits))
|
||||
}
|
||||
|
||||
object Probe
|
||||
{
|
||||
def apply(p_type: UInt, addr: UInt, master_xact_id: UInt)(implicit conf: TileLinkConfiguration) = {
|
||||
def apply(p_type: UInt, addr: UInt, master_xact_id: UInt) = {
|
||||
val prb = new Probe
|
||||
prb.p_type := p_type
|
||||
prb.addr := addr
|
||||
@ -85,22 +87,22 @@ object Probe
|
||||
}
|
||||
}
|
||||
|
||||
class Probe(implicit val tlconf: TileLinkConfiguration) extends MasterSourcedMessage
|
||||
class Probe extends MasterSourcedMessage
|
||||
with HasPhysicalAddress
|
||||
with HasMasterTransactionId {
|
||||
val p_type = UInt(width = tlconf.co.probeTypeWidth)
|
||||
val p_type = UInt(width = params(TLCoherence).probeTypeWidth)
|
||||
}
|
||||
|
||||
object Release
|
||||
{
|
||||
def apply(r_type: UInt, addr: UInt, data: UInt)(implicit conf: TileLinkConfiguration) = {
|
||||
def apply(r_type: UInt, addr: UInt, data: UInt): Release = {
|
||||
val rel = new Release
|
||||
rel.r_type := r_type
|
||||
rel.addr := addr
|
||||
rel.data := data
|
||||
rel
|
||||
}
|
||||
def apply(r_type: UInt, addr: UInt, client_xact_id: UInt, master_xact_id: UInt)(implicit conf: TileLinkConfiguration) = {
|
||||
def apply(r_type: UInt, addr: UInt, client_xact_id: UInt, master_xact_id: UInt): Release = {
|
||||
val rel = new Release
|
||||
rel.r_type := r_type
|
||||
rel.addr := addr
|
||||
@ -109,24 +111,24 @@ object Release
|
||||
rel.data := UInt(0)
|
||||
rel
|
||||
}
|
||||
def apply(r_type: UInt, addr: UInt, client_xact_id: UInt, master_xact_id: UInt, data: UInt)(implicit conf: TileLinkConfiguration): Release = {
|
||||
def apply(r_type: UInt, addr: UInt, client_xact_id: UInt, master_xact_id: UInt, data: UInt): Release = {
|
||||
val rel = apply(r_type, addr, client_xact_id, master_xact_id)
|
||||
rel.data := data
|
||||
rel
|
||||
}
|
||||
}
|
||||
|
||||
class Release(implicit val tlconf: TileLinkConfiguration) extends ClientSourcedMessage
|
||||
class Release extends ClientSourcedMessage
|
||||
with HasPhysicalAddress
|
||||
with HasClientTransactionId
|
||||
with HasMasterTransactionId
|
||||
with HasTileLinkData {
|
||||
val r_type = UInt(width = tlconf.co.releaseTypeWidth)
|
||||
val r_type = UInt(width = params(TLCoherence).releaseTypeWidth)
|
||||
}
|
||||
|
||||
object Grant
|
||||
{
|
||||
def apply(g_type: UInt, client_xact_id: UInt, master_xact_id: UInt)(implicit conf: TileLinkConfiguration) = {
|
||||
def apply(g_type: UInt, client_xact_id: UInt, master_xact_id: UInt): Grant = {
|
||||
val gnt = new Grant
|
||||
gnt.g_type := g_type
|
||||
gnt.client_xact_id := client_xact_id
|
||||
@ -134,40 +136,35 @@ object Grant
|
||||
gnt.data := UInt(0)
|
||||
gnt
|
||||
}
|
||||
def apply(g_type: UInt, client_xact_id: UInt, master_xact_id: UInt, data: UInt)(implicit conf: TileLinkConfiguration): Grant = {
|
||||
def apply(g_type: UInt, client_xact_id: UInt, master_xact_id: UInt, data: UInt): Grant = {
|
||||
val gnt = apply(g_type, client_xact_id, master_xact_id)
|
||||
gnt.data := data
|
||||
gnt
|
||||
}
|
||||
}
|
||||
|
||||
class Grant(implicit val tlconf: TileLinkConfiguration) extends MasterSourcedMessage
|
||||
class Grant extends MasterSourcedMessage
|
||||
with HasTileLinkData
|
||||
with HasClientTransactionId
|
||||
with HasMasterTransactionId {
|
||||
val g_type = UInt(width = tlconf.co.grantTypeWidth)
|
||||
val g_type = UInt(width = params(TLCoherence).grantTypeWidth)
|
||||
}
|
||||
|
||||
class Finish(implicit val tlconf: TileLinkConfiguration) extends ClientSourcedMessage with HasMasterTransactionId
|
||||
class Finish extends ClientSourcedMessage with HasMasterTransactionId
|
||||
|
||||
|
||||
class UncachedTileLinkIO(implicit conf: TileLinkConfiguration) extends Bundle {
|
||||
implicit val ln = conf.ln
|
||||
class UncachedTileLinkIO extends Bundle {
|
||||
val acquire = new DecoupledIO(new LogicalNetworkIO(new Acquire))
|
||||
val grant = new DecoupledIO(new LogicalNetworkIO(new Grant)).flip
|
||||
val finish = new DecoupledIO(new LogicalNetworkIO(new Finish))
|
||||
override def clone = { new UncachedTileLinkIO().asInstanceOf[this.type] }
|
||||
}
|
||||
|
||||
class TileLinkIO(implicit conf: TileLinkConfiguration) extends UncachedTileLinkIO()(conf) {
|
||||
class TileLinkIO extends UncachedTileLinkIO {
|
||||
val probe = new DecoupledIO(new LogicalNetworkIO(new Probe)).flip
|
||||
val release = new DecoupledIO(new LogicalNetworkIO(new Release))
|
||||
override def clone = { new TileLinkIO().asInstanceOf[this.type] }
|
||||
}
|
||||
|
||||
abstract class TileLinkArbiterLike(val arbN: Int)(implicit conf: TileLinkConfiguration) extends Module {
|
||||
implicit val (ln, co) = (conf.ln, conf.co)
|
||||
|
||||
abstract class TileLinkArbiterLike(val arbN: Int) extends Module {
|
||||
type MasterSourcedWithId = MasterSourcedMessage with HasClientTransactionId
|
||||
type ClientSourcedWithId = ClientSourcedMessage with HasClientTransactionId
|
||||
|
||||
@ -178,7 +175,7 @@ abstract class TileLinkArbiterLike(val arbN: Int)(implicit conf: TileLinkConfigu
|
||||
def hookupClientSource[M <: ClientSourcedWithId]
|
||||
(ins: Seq[DecoupledIO[LogicalNetworkIO[M]]],
|
||||
out: DecoupledIO[LogicalNetworkIO[M]]) {
|
||||
def hasData(m: LogicalNetworkIO[M]) = co.messageHasData(m.payload)
|
||||
def hasData(m: LogicalNetworkIO[M]) = params(TLCoherence).messageHasData(m.payload)
|
||||
val arb = Module(new RRArbiter(out.bits.clone, arbN))
|
||||
out <> arb.io.out
|
||||
ins.zipWithIndex.zip(arb.io.in).map{ case ((req,id), arb) => {
|
||||
@ -205,7 +202,8 @@ abstract class TileLinkArbiterLike(val arbN: Int)(implicit conf: TileLinkConfigu
|
||||
}
|
||||
}
|
||||
|
||||
abstract class UncachedTileLinkIOArbiter(n: Int)(implicit conf: TileLinkConfiguration) extends TileLinkArbiterLike(n)(conf) {
|
||||
abstract class UncachedTileLinkIOArbiter(n: Int)
|
||||
extends TileLinkArbiterLike(n) {
|
||||
val io = new Bundle {
|
||||
val in = Vec.fill(n){new UncachedTileLinkIO}.flip
|
||||
val out = new UncachedTileLinkIO
|
||||
@ -219,7 +217,7 @@ abstract class UncachedTileLinkIOArbiter(n: Int)(implicit conf: TileLinkConfigur
|
||||
finish_arb.io.in zip io.in map { case (arb, req) => arb <> req.finish }
|
||||
}
|
||||
|
||||
abstract class TileLinkIOArbiter(n: Int)(implicit conf: TileLinkConfiguration) extends TileLinkArbiterLike(n)(conf) {
|
||||
abstract class TileLinkIOArbiter(n: Int) extends TileLinkArbiterLike(n) {
|
||||
val io = new Bundle {
|
||||
val in = Vec.fill(n){new TileLinkIO}.flip
|
||||
val out = new TileLinkIO
|
||||
@ -267,9 +265,9 @@ abstract trait UsesNewId {
|
||||
in.client_xact_id
|
||||
}
|
||||
|
||||
class UncachedTileLinkIOArbiterThatAppendsArbiterId(val n: Int)(implicit conf: TileLinkConfiguration) extends UncachedTileLinkIOArbiter(n)(conf) with AppendsArbiterId
|
||||
class UncachedTileLinkIOArbiterThatPassesId(val n: Int)(implicit conf: TileLinkConfiguration) extends UncachedTileLinkIOArbiter(n)(conf) with PassesId
|
||||
class UncachedTileLinkIOArbiterThatUsesNewId(val n: Int)(implicit conf: TileLinkConfiguration) extends UncachedTileLinkIOArbiter(n)(conf) with UsesNewId
|
||||
class TileLinkIOArbiterThatAppendsArbiterId(val n: Int)(implicit conf: TileLinkConfiguration) extends TileLinkIOArbiter(n)(conf) with AppendsArbiterId
|
||||
class TileLinkIOArbiterThatPassesId(val n: Int)(implicit conf: TileLinkConfiguration) extends TileLinkIOArbiter(n)(conf) with PassesId
|
||||
class TileLinkIOArbiterThatUsesNewId(val n: Int)(implicit conf: TileLinkConfiguration) extends TileLinkIOArbiter(n)(conf) with UsesNewId
|
||||
class UncachedTileLinkIOArbiterThatAppendsArbiterId(val n: Int) extends UncachedTileLinkIOArbiter(n) with AppendsArbiterId
|
||||
class UncachedTileLinkIOArbiterThatPassesId(val n: Int) extends UncachedTileLinkIOArbiter(n) with PassesId
|
||||
class UncachedTileLinkIOArbiterThatUsesNewId(val n: Int) extends UncachedTileLinkIOArbiter(n) with UsesNewId
|
||||
class TileLinkIOArbiterThatAppendsArbiterId(val n: Int) extends TileLinkIOArbiter(n) with AppendsArbiterId
|
||||
class TileLinkIOArbiterThatPassesId(val n: Int) extends TileLinkIOArbiter(n) with PassesId
|
||||
class TileLinkIOArbiterThatUsesNewId(val n: Int) extends TileLinkIOArbiter(n) with UsesNewId
|
||||
|
@ -1,33 +1,34 @@
|
||||
package uncore
|
||||
import Chisel._
|
||||
|
||||
trait CoherenceAgentConfiguration {
|
||||
def tl: TileLinkConfiguration
|
||||
def nReleaseTransactions: Int
|
||||
def nAcquireTransactions: Int
|
||||
case object NReleaseTransactors extends Field[Int]
|
||||
case object NAcquireTransactors extends Field[Int]
|
||||
case object NClients extends Field[Int]
|
||||
|
||||
abstract trait CoherenceAgentParameters extends UsesParameters {
|
||||
val co = params(TLCoherence)
|
||||
val nReleaseTransactors = params(NReleaseTransactors)
|
||||
val nAcquireTransactors = params(NAcquireTransactors)
|
||||
val nTransactors = nReleaseTransactors + nAcquireTransactors
|
||||
val nClients = params(NClients)
|
||||
}
|
||||
|
||||
abstract class CoherenceAgent(implicit conf: CoherenceAgentConfiguration) extends Module {
|
||||
abstract class CoherenceAgent extends Module
|
||||
with CoherenceAgentParameters {
|
||||
val io = new Bundle {
|
||||
val inner = (new TileLinkIO()(conf.tl)).flip
|
||||
val outer = new UncachedTileLinkIO()(conf.tl)
|
||||
val incoherent = Vec.fill(conf.tl.ln.nClients){Bool()}.asInput
|
||||
val inner = (new TileLinkIO).flip
|
||||
val outer = new UncachedTileLinkIO
|
||||
val incoherent = Vec.fill(nClients){Bool()}.asInput
|
||||
}
|
||||
}
|
||||
|
||||
case class L2CoherenceAgentConfiguration(
|
||||
val tl: TileLinkConfiguration,
|
||||
val nReleaseTransactions: Int,
|
||||
val nAcquireTransactions: Int) extends CoherenceAgentConfiguration
|
||||
|
||||
class L2CoherenceAgent(bankId: Int)(implicit conf: CoherenceAgentConfiguration)
|
||||
extends CoherenceAgent {
|
||||
implicit val (tl, ln, co) = (conf.tl, conf.tl.ln, conf.tl.co)
|
||||
class L2CoherenceAgent(bankId: Int) extends CoherenceAgent {
|
||||
|
||||
// Create SHRs for outstanding transactions
|
||||
val nTrackers = conf.nReleaseTransactions + conf.nAcquireTransactions
|
||||
val trackerList = (0 until conf.nReleaseTransactions).map(id => Module(new VoluntaryReleaseTracker(id, bankId))) ++
|
||||
(conf.nReleaseTransactions until nTrackers).map(id => Module(new AcquireTracker(id, bankId)))
|
||||
val trackerList = (0 until nReleaseTransactors).map(id =>
|
||||
Module(new VoluntaryReleaseTracker(id, bankId))) ++
|
||||
(nReleaseTransactors until nTransactors).map(id =>
|
||||
Module(new AcquireTracker(id, bankId)))
|
||||
|
||||
// Propagate incoherence flags
|
||||
trackerList.map(_.io.tile_incoherent := io.incoherent.toBits)
|
||||
@ -85,12 +86,12 @@ class L2CoherenceAgent(bankId: Int)(implicit conf: CoherenceAgentConfiguration)
|
||||
}
|
||||
|
||||
|
||||
abstract class XactTracker()(implicit conf: CoherenceAgentConfiguration) extends Module {
|
||||
implicit val (tl, ln, co) = (conf.tl, conf.tl.ln, conf.tl.co)
|
||||
abstract class XactTracker extends Module {
|
||||
val (co, nClients) = (params(TLCoherence),params(NClients))
|
||||
val io = new Bundle {
|
||||
val inner = (new TileLinkIO).flip
|
||||
val outer = new UncachedTileLinkIO
|
||||
val tile_incoherent = Bits(INPUT, ln.nClients)
|
||||
val tile_incoherent = Bits(INPUT, params(NClients))
|
||||
val has_acquire_conflict = Bool(OUTPUT)
|
||||
val has_release_conflict = Bool(OUTPUT)
|
||||
}
|
||||
@ -100,15 +101,13 @@ abstract class XactTracker()(implicit conf: CoherenceAgentConfiguration) extends
|
||||
val c_gnt = io.inner.grant.bits
|
||||
val c_ack = io.inner.finish.bits
|
||||
val m_gnt = io.outer.grant.bits
|
||||
|
||||
}
|
||||
|
||||
class VoluntaryReleaseTracker(trackerId: Int, bankId: Int)(implicit conf: CoherenceAgentConfiguration)
|
||||
extends XactTracker()(conf) {
|
||||
class VoluntaryReleaseTracker(trackerId: Int, bankId: Int) extends XactTracker {
|
||||
val s_idle :: s_mem :: s_ack :: s_busy :: Nil = Enum(UInt(), 4)
|
||||
val state = Reg(init=s_idle)
|
||||
val xact = Reg{ new Release }
|
||||
val init_client_id = Reg(init=UInt(0, width = log2Up(ln.nClients)))
|
||||
val init_client_id = Reg(init=UInt(0, width = log2Up(nClients)))
|
||||
val incoming_rel = io.inner.release.bits
|
||||
|
||||
io.has_acquire_conflict := Bool(false)
|
||||
@ -153,17 +152,16 @@ class VoluntaryReleaseTracker(trackerId: Int, bankId: Int)(implicit conf: Cohere
|
||||
}
|
||||
}
|
||||
|
||||
class AcquireTracker(trackerId: Int, bankId: Int)(implicit conf: CoherenceAgentConfiguration)
|
||||
extends XactTracker()(conf) {
|
||||
class AcquireTracker(trackerId: Int, bankId: Int) extends XactTracker {
|
||||
val s_idle :: s_probe :: s_mem_read :: s_mem_write :: s_make_grant :: s_busy :: Nil = Enum(UInt(), 6)
|
||||
val state = Reg(init=s_idle)
|
||||
val xact = Reg{ new Acquire }
|
||||
val init_client_id = Reg(init=UInt(0, width = log2Up(ln.nClients)))
|
||||
val init_client_id = Reg(init=UInt(0, width = log2Up(nClients)))
|
||||
//TODO: Will need id reg for merged release xacts
|
||||
|
||||
val init_sharer_cnt = Reg(init=UInt(0, width = log2Up(ln.nClients)))
|
||||
val release_count = if (ln.nClients == 1) UInt(0) else Reg(init=UInt(0, width = log2Up(ln.nClients)))
|
||||
val probe_flags = Reg(init=Bits(0, width = ln.nClients))
|
||||
val init_sharer_cnt = Reg(init=UInt(0, width = log2Up(nClients)))
|
||||
val release_count = if (nClients == 1) UInt(0) else Reg(init=UInt(0, width = log2Up(nClients)))
|
||||
val probe_flags = Reg(init=Bits(0, width = nClients))
|
||||
val curr_p_id = PriorityEncoder(probe_flags)
|
||||
|
||||
val pending_outer_write = co.messageHasData(xact)
|
||||
@ -174,12 +172,12 @@ class AcquireTracker(trackerId: Int, bankId: Int)(implicit conf: CoherenceAgentC
|
||||
xact.addr, UInt(trackerId), c_rel.payload.data)
|
||||
val outer_read = Acquire(co.getUncachedReadAcquireType, xact.addr, UInt(trackerId))
|
||||
|
||||
val probe_initial_flags = Bits(width = ln.nClients)
|
||||
val probe_initial_flags = Bits(width = nClients)
|
||||
probe_initial_flags := Bits(0)
|
||||
if (ln.nClients > 1) {
|
||||
if (nClients > 1) {
|
||||
// issue self-probes for uncached read xacts to facilitate I$ coherence
|
||||
val probe_self = Bool(true) //co.needsSelfProbe(io.inner.acquire.bits.payload)
|
||||
val myflag = Mux(probe_self, Bits(0), UIntToOH(c_acq.header.src(log2Up(ln.nClients)-1,0)))
|
||||
val myflag = Mux(probe_self, Bits(0), UIntToOH(c_acq.header.src(log2Up(nClients)-1,0)))
|
||||
probe_initial_flags := ~(io.tile_incoherent | myflag)
|
||||
}
|
||||
|
||||
@ -219,9 +217,9 @@ class AcquireTracker(trackerId: Int, bankId: Int)(implicit conf: CoherenceAgentC
|
||||
when( io.inner.acquire.valid ) {
|
||||
xact := c_acq.payload
|
||||
init_client_id := c_acq.header.src
|
||||
init_sharer_cnt := UInt(ln.nClients) // TODO: Broadcast only
|
||||
init_sharer_cnt := UInt(nClients) // TODO: Broadcast only
|
||||
probe_flags := probe_initial_flags
|
||||
if(ln.nClients > 1) {
|
||||
if(nClients > 1) {
|
||||
release_count := PopCount(probe_initial_flags)
|
||||
state := Mux(probe_initial_flags.orR, s_probe,
|
||||
Mux(needs_outer_write, s_mem_write,
|
||||
@ -244,7 +242,7 @@ class AcquireTracker(trackerId: Int, bankId: Int)(implicit conf: CoherenceAgentC
|
||||
io.outer.acquire.bits.payload := outer_write_rel
|
||||
when(io.outer.acquire.ready) {
|
||||
io.inner.release.ready := Bool(true)
|
||||
if(ln.nClients > 1) release_count := release_count - UInt(1)
|
||||
if(nClients > 1) release_count := release_count - UInt(1)
|
||||
when(release_count === UInt(1)) {
|
||||
state := Mux(pending_outer_write, s_mem_write,
|
||||
Mux(pending_outer_read, s_mem_read, s_make_grant))
|
||||
@ -252,7 +250,7 @@ class AcquireTracker(trackerId: Int, bankId: Int)(implicit conf: CoherenceAgentC
|
||||
}
|
||||
} .otherwise {
|
||||
io.inner.release.ready := Bool(true)
|
||||
if(ln.nClients > 1) release_count := release_count - UInt(1)
|
||||
if(nClients > 1) release_count := release_count - UInt(1)
|
||||
when(release_count === UInt(1)) {
|
||||
state := Mux(pending_outer_write, s_mem_write,
|
||||
Mux(pending_outer_read, s_mem_read, s_make_grant))
|
||||
|
Loading…
Reference in New Issue
Block a user