dual read port srams

This commit is contained in:
Richard Yan
2024-10-23 15:09:43 -07:00
parent 8307d8d154
commit 0a54018650
4 changed files with 40 additions and 19 deletions

View File

@@ -2,7 +2,7 @@ package radiance.memory
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import freechips.rocketchip.diplomacy.{AddressSet, TransferSizes, IdRange} import freechips.rocketchip.diplomacy.{AddressSet, TransferSizes, IdRange, BufferParams}
import freechips.rocketchip.tilelink._ import freechips.rocketchip.tilelink._
import freechips.rocketchip.util.BundleField import freechips.rocketchip.util.BundleField
import org.chipsalliance.cde.config.Parameters import org.chipsalliance.cde.config.Parameters
@@ -77,23 +77,29 @@ class DuplicatorNode(override val name: String = "dup")
sourceEnq.bits := nodeIn.a.bits.source sourceEnq.bits := nodeIn.a.bits.source
val idQueue = Queue(sourceEnq, entries = 4, pipe = false, flow = false) val idQueue = Queue(sourceEnq, entries = 4, pipe = false, flow = false)
val srcMatch = nodeOuts.map(_.d.bits.source(inSourceWidth - 1, 0) === idQueue.bits) val srcMatch = nodeOuts.map(_.d.bits.source(inSourceWidth - 1, 0) === idQueue.bits)
idQueue.ready := nodeIn.d.ready && srcMatch.reduce(_ || _) idQueue.ready := nodeIn.d.fire
assert(sourceEnq.fire === nodeIn.a.fire) assert(sourceEnq.fire === nodeIn.a.fire)
assert(idQueue.fire === nodeIn.d.fire) assert(idQueue.fire === nodeIn.d.fire)
(nodeOuts zip srcMatch).foreach { case (o, m) => (nodeOuts lazyZip srcMatch lazyZip Seq(0, inSourceEnd)).foreach { case (o, m, p) =>
o.a.bits := nodeIn.a.bits o.a.bits := nodeIn.a.bits
o.a.bits.source := nodeIn.a.bits.source | inSourceEnd.U o.a.bits.source := nodeIn.a.bits.source | p.U
o.a.valid := nodeIn.a.valid o.a.valid := nodeIn.a.valid
nodeIn.d.bits := o.d.bits
nodeIn.d.bits.source := o.d.bits.source(inSourceWidth - 1, 0)
nodeIn.d.valid := o.d.valid
o.d.ready := nodeIn.d.ready && m o.d.ready := nodeIn.d.ready && m
} }
assert(!(nodeOuts.head.a.ready && nodeOuts.last.a.ready) || !nodeIn.a.valid, "double output fire") nodeIn.d.bits := MuxCase(DontCare, (nodeOuts zip srcMatch).map { case (o, m) =>
m -> o.d.bits
})
nodeIn.d.bits.source := MuxCase(DontCare, (nodeOuts zip srcMatch).map { case (o, m) =>
m -> o.d.bits.source(inSourceWidth - 1, 0)
})
nodeIn.d.valid := (nodeOuts zip srcMatch).map { case (o, m) => o.d.valid && m }.reduce(_ || _)
nodeIn.a.ready := nodeOuts.map(_.a.ready).reduce(_ || _) && sourceEnq.ready nodeIn.a.ready := nodeOuts.map(_.a.ready).reduce(_ || _) && sourceEnq.ready
assert(!(nodeOuts.head.a.ready && nodeOuts.last.a.ready) || !nodeIn.a.valid, "double output fire")
} }
} }
@@ -105,24 +111,30 @@ object DuplicatorNode {
class DoubleOutXbar(clients: Seq[TLNode], override val name: String = "2o_xbar") class DoubleOutXbar(clients: Seq[TLNode], override val name: String = "2o_xbar")
(implicit p: Parameters) extends LazyModule { (implicit p: Parameters) extends LazyModule {
val xbar0 = TLXbar(TLArbiter.lowestIndexFirst) val xbar0 = TLXbar(TLArbiter.lowestIndexFirst, Some("double_out_xbar0"))
val xbar1 = TLXbar(TLArbiter.lowestIndexFirst) val xbar1 = TLXbar(TLArbiter.lowestIndexFirst, Some("double_out_xbar1"))
implicit val disableMonitors: Boolean = false implicit val disableMonitors: Boolean = false
val bufGen = () => TLBuffer(ace = BufferParams(0), bd = BufferParams(2, flow = false, pipe = false))
val dupedIds = clients.map(connectOne(_, DuplicatorNode.apply)).map { c => val dupedIds = clients.map(connectOne(_, DuplicatorNode.apply)).map { c =>
val id0 = connectOne(c, TLIdentityNode.apply) val id0 = connectOne(c, TLIdentityNode.apply)
val id1 = connectOne(c, TLIdentityNode.apply) val id1 = connectOne(c, TLIdentityNode.apply)
xbar0 := id0 xbar0 := connectOne(id0, bufGen)
xbar1 := id1 xbar1 := connectOne(id1, bufGen)
Seq(id0, id1) Seq(id0, id1)
}.transpose }.transpose
lazy val module = new LazyModuleImp(this) { lazy val module = new LazyModuleImp(this) {
val id0InReadys = VecInit(dupedIds.head.map(_.in.head._1.a.ready)).asUInt val id0InReadys = VecInit(dupedIds.head.map(_.in.head._1.a.ready)).asUInt
val id1InValids = VecInit(dupedIds.last.map(_.in.head._1.a.valid)).asUInt val id1InValids = VecInit(dupedIds.last.map(_.in.head._1.a.valid)).asUInt
(dupedIds.last.map(_.out.head._1.a.valid) zip (id1InValids & (~id0InReadys).asUInt).asBools) val id1OutValids = dupedIds.last.map(_.out.head._1.a.valid)
val id1InReadys = dupedIds.last.map(_.in.head._1.a.ready)
val id1OutReadys = VecInit(dupedIds.last.map(_.out.head._1.a.ready)).asUInt
(id1OutValids zip (id1InValids & (~id0InReadys).asUInt).asBools)
.foreach { case (o, i) => o := i } .foreach { case (o, i) => o := i }
(id1InReadys zip (id1OutReadys & (~id0InReadys).asUInt).asBools)
.foreach { case (i, o) => i := o }
} }
} }

View File

@@ -16,6 +16,7 @@ class RWSplitterNode(visibility: Option[AddressSet], override val name: String =
// splits & arbitrates them into one client node per type of operation; // splits & arbitrates them into one client node per type of operation;
// there will be N incoming edges, two outgoing edges, with two N:1 muxes; // there will be N incoming edges, two outgoing edges, with two N:1 muxes;
// it keeps the read and write channels fully separate to allow parallel processing. // it keeps the read and write channels fully separate to allow parallel processing.
suggestName(name)
val node = TLNexusNode( val node = TLNexusNode(
clientFn = { seq => clientFn = { seq =>
val in_mapping = TLXbar.mapInputIds(seq) val in_mapping = TLXbar.mapInputIds(seq)
@@ -155,6 +156,11 @@ object RWSplitterNode {
LazyModule(new RWSplitterNode(None, name = valName.value)).node LazyModule(new RWSplitterNode(None, name = valName.value)).node
} }
def apply(name: String)
(implicit p: Parameters, valName: ValName, sourceInfo: SourceInfo): TLNexusNode = {
LazyModule(new RWSplitterNode(None, name = name)).node
}
def apply(visibility: AddressSet) def apply(visibility: AddressSet)
(implicit p: Parameters, valName: ValName, sourceInfo: SourceInfo): TLNexusNode = { (implicit p: Parameters, valName: ValName, sourceInfo: SourceInfo): TLNexusNode = {
apply(visibility, valName.value) apply(visibility, valName.value)

View File

@@ -53,10 +53,12 @@ object XbarWithExtPolicy {
object XbarWithExtPolicyNoFallback { object XbarWithExtPolicyNoFallback {
def apply(nameSuffix: Option[String] = None) def apply(nameSuffix: Option[String] = None)
(implicit p: Parameters): (XbarWithExtPolicy, TLIdentityNode) = { (implicit p: Parameters): (XbarWithExtPolicy, TLIdentityNode, TLIdentityNode) = {
val inIdNode = TLIdentityNode() val inIdNode = TLIdentityNode()
val outIdNode = TLIdentityNode()
val xbar = LazyModule(new XbarWithExtPolicy(nameSuffix, false)) val xbar = LazyModule(new XbarWithExtPolicy(nameSuffix, false))
xbar.node :=* inIdNode xbar.node :=* inIdNode
(xbar, inIdNode) outIdNode :=* xbar.node
(xbar, inIdNode, outIdNode)
} }
} }

View File

@@ -108,7 +108,8 @@ class VirgoSharedMemComponents(
// tensor core read nodes // tensor core read nodes
val tcDistNodes = Seq.fill(smemBanks)(tcNodeFanouts.map(connectOne(_, () => DistributorNode(smemWidth, wordSize)))) val tcDistNodes = Seq.fill(smemBanks)(tcNodeFanouts.map(connectOne(_, () => DistributorNode(smemWidth, wordSize))))
val tcNodes = tcDistNodes.map { tcBank => val tcNodes = tcDistNodes.map { tcBank =>
Seq.fill(smemSubbanks)(tcBank.map(connectOne(_, () => TLBuffer(BufferParams(2, false, false)))).map(connectXbarName(_, Some("tc_dist_fanout")))) Seq.fill(smemSubbanks)(tcBank.map(connectOne(_,
() => TLBuffer(BufferParams(2, false, false)))).map(connectXbarName(_, Some("tc_dist_fanout"))))
} // (banks, subbanks, tc client) } // (banks, subbanks, tc client)
val unalignedRWNodes: ArrayBuffer[ArrayBuffer[TLNexusNode]] = // mutable for readability val unalignedRWNodes: ArrayBuffer[ArrayBuffer[TLNexusNode]] = // mutable for readability
@@ -195,7 +196,7 @@ class VirgoSharedMemComponents(
val laneSerialXbar = laneSerialXbars.get(rw)(lid) val laneSerialXbar = laneSerialXbars.get(rw)(lid)
laneSerialXbar._1.policySlaveNode := coreSerialPolicy.get(rw)(lid) laneSerialXbar._1.policySlaveNode := coreSerialPolicy.get(rw)(lid)
coresRW.foreach(laneSerialXbar._2 := _) coresRW.foreach(laneSerialXbar._2 := _)
connectXbarName(connectOne(laneSerialXbar._1.node, TLEphemeralNode.apply), Some(s"lane_${lid}_serial_out")) connectXbarName(connectOne(laneSerialXbar._3, TLEphemeralNode.apply), Some(s"lane_${lid}_serial_out"))
} }
} }
case NotSerialized => Seq.fill(2)(unalignedRWNodes.toSeq.flatten.map(connectXbar.apply)) case NotSerialized => Seq.fill(2)(unalignedRWNodes.toSeq.flatten.map(connectXbar.apply))
@@ -216,7 +217,7 @@ class VirgoSharedMemComponents(
(uniformRNodes, uniformWNodes, nonuniformRNodes, nonuniformWNodes) (uniformRNodes, uniformWNodes, nonuniformRNodes, nonuniformWNodes)
} else { } else {
val splitterNodes = radianceSmemFanout.map { connectOne(_, RWSplitterNode.apply) } val splitterNodes = radianceSmemFanout.map { connectOne(_, () => RWSplitterNode("rad_fanout_splitter")) }
// these nodes access an entire line simultaneously // these nodes access an entire line simultaneously
val uniformRNodes: Seq[Seq[Seq[TLNexusNode]]] = spadReadNodes val uniformRNodes: Seq[Seq[Seq[TLNexusNode]]] = spadReadNodes
val uniformWNodes: Seq[Seq[Seq[TLNexusNode]]] = (spadWriteNodes zip spadSpWriteNodes).map { case (wb, wsb) => val uniformWNodes: Seq[Seq[Seq[TLNexusNode]]] = (spadWriteNodes zip spadSpWriteNodes).map { case (wb, wsb) =>
@@ -259,7 +260,7 @@ class VirgoSharedMemComponentsImp[T <: VirgoSharedMemComponents]
(xbarsRW zip policiesRW).foreach { case (xbars, policies) => (xbarsRW zip policiesRW).foreach { case (xbars, policies) =>
// for each lane, if any core is valid // for each lane, if any core is valid
val coreValids = xbars.map(_._2.in.map(_._1)).transpose.map { core => VecInit(core.map(_.a.valid)).asUInt.orR } val coreValids = xbars.map(_._2.in.map(_._1)).transpose.map { core => VecInit(core.map(_.a.valid)).asUInt.orR }
val select = xbars.map(_._2.out.map(_._1)).transpose.map { core => VecInit(core.map(_.a.ready)).asUInt.orR } val select = xbars.map(_._3.in.map(_._1)).transpose.map { core => VecInit(core.map(_.a.fire)).asUInt.orR }
val coreSelect = TLArbiter.roundRobin(outer.numCores, VecInit(coreValids).asUInt, VecInit(select).asUInt.orR) val coreSelect = TLArbiter.roundRobin(outer.numCores, VecInit(coreValids).asUInt, VecInit(select).asUInt.orR)
// TODO: roll this into XbarWithExtPolicy // TODO: roll this into XbarWithExtPolicy
xbars.foreach { lane => xbars.foreach { lane =>