diplomacy: remove node arity and allow empty Nexus nodes (Xbars)
This removes the mostly obsolete 'numIn/Out' range restrictions on nodes. It also makes it possible to connect optional crossbars that disappear. val x = TLXbar() x := master slave := x val y = TLXbar() x :=* y // only connect y if it gets used This will create crossbar x, but crossbar y will disappear.
This commit is contained in:
@ -24,10 +24,8 @@ case class AHBMasterNode(portParams: Seq[AHBMasterPortParameters])(implicit valN
|
||||
case class AHBSlaveNode(portParams: Seq[AHBSlavePortParameters])(implicit valName: ValName) extends SinkNode(AHBImp)(portParams)
|
||||
case class AHBNexusNode(
|
||||
masterFn: Seq[AHBMasterPortParameters] => AHBMasterPortParameters,
|
||||
slaveFn: Seq[AHBSlavePortParameters] => AHBSlavePortParameters,
|
||||
numMasterPorts: Range.Inclusive = 1 to 999,
|
||||
numSlavePorts: Range.Inclusive = 1 to 999)(
|
||||
slaveFn: Seq[AHBSlavePortParameters] => AHBSlavePortParameters)(
|
||||
implicit valName: ValName)
|
||||
extends NexusNode(AHBImp)(masterFn, slaveFn, numMasterPorts, numSlavePorts)
|
||||
extends NexusNode(AHBImp)(masterFn, slaveFn)
|
||||
|
||||
case class AHBIdentityNode()(implicit valName: ValName) extends IdentityNode(AHBImp)()
|
||||
|
@ -10,37 +10,40 @@ import scala.math.{min,max}
|
||||
|
||||
class AHBFanout()(implicit p: Parameters) extends LazyModule {
|
||||
val node = AHBNexusNode(
|
||||
numSlavePorts = 1 to 1,
|
||||
numMasterPorts = 1 to 32,
|
||||
masterFn = { case Seq(m) => m },
|
||||
slaveFn = { seq => seq(0).copy(slaves = seq.flatMap(_.slaves)) })
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
// Require consistent bus widths
|
||||
val (io_out, edgesOut) = node.out.unzip
|
||||
val port0 = edgesOut(0).slave
|
||||
edgesOut.foreach { edge =>
|
||||
val port = edge.slave
|
||||
require (port.beatBytes == port0.beatBytes,
|
||||
s"${port.slaves.map(_.name)} ${port.beatBytes} vs ${port0.slaves.map(_.name)} ${port0.beatBytes}")
|
||||
if (node.edges.in.size >= 1) {
|
||||
require (node.edges.in.size == 1, "AHBFanout does not support multiple masters")
|
||||
require (node.edges.out.size > 0, "AHBFanout requires at least one slave")
|
||||
|
||||
// Require consistent bus widths
|
||||
val (io_out, edgesOut) = node.out.unzip
|
||||
val port0 = edgesOut(0).slave
|
||||
edgesOut.foreach { edge =>
|
||||
val port = edge.slave
|
||||
require (port.beatBytes == port0.beatBytes,
|
||||
s"${port.slaves.map(_.name)} ${port.beatBytes} vs ${port0.slaves.map(_.name)} ${port0.beatBytes}")
|
||||
}
|
||||
|
||||
val port_addrs = edgesOut.map(_.slave.slaves.map(_.address).flatten)
|
||||
val routingMask = AddressDecoder(port_addrs)
|
||||
val route_addrs = port_addrs.map(_.map(_.widen(~routingMask)).distinct)
|
||||
|
||||
val (in, _) = node.in(0)
|
||||
val a_sel = Vec(route_addrs.map(seq => seq.map(_.contains(in.haddr)).reduce(_ || _)))
|
||||
val d_sel = Reg(a_sel)
|
||||
|
||||
when (in.hready) { d_sel := a_sel }
|
||||
(a_sel zip io_out) foreach { case (sel, out) =>
|
||||
out := in
|
||||
out.hsel := in.hsel && sel
|
||||
}
|
||||
|
||||
in.hreadyout := !Mux1H(d_sel, io_out.map(!_.hreadyout))
|
||||
in.hresp := Mux1H(d_sel, io_out.map(_.hresp))
|
||||
in.hrdata := Mux1H(d_sel, io_out.map(_.hrdata))
|
||||
}
|
||||
|
||||
val port_addrs = edgesOut.map(_.slave.slaves.map(_.address).flatten)
|
||||
val routingMask = AddressDecoder(port_addrs)
|
||||
val route_addrs = port_addrs.map(_.map(_.widen(~routingMask)).distinct)
|
||||
|
||||
val (in, _) = node.in(0)
|
||||
val a_sel = Vec(route_addrs.map(seq => seq.map(_.contains(in.haddr)).reduce(_ || _)))
|
||||
val d_sel = Reg(a_sel)
|
||||
|
||||
when (in.hready) { d_sel := a_sel }
|
||||
(a_sel zip io_out) foreach { case (sel, out) =>
|
||||
out := in
|
||||
out.hsel := in.hsel && sel
|
||||
}
|
||||
|
||||
in.hreadyout := !Mux1H(d_sel, io_out.map(!_.hreadyout))
|
||||
in.hresp := Mux1H(d_sel, io_out.map(_.hresp))
|
||||
in.hrdata := Mux1H(d_sel, io_out.map(_.hrdata))
|
||||
}
|
||||
}
|
||||
|
@ -23,10 +23,8 @@ case class APBMasterNode(portParams: Seq[APBMasterPortParameters])(implicit valN
|
||||
case class APBSlaveNode(portParams: Seq[APBSlavePortParameters])(implicit valName: ValName) extends SinkNode(APBImp)(portParams)
|
||||
case class APBNexusNode(
|
||||
masterFn: Seq[APBMasterPortParameters] => APBMasterPortParameters,
|
||||
slaveFn: Seq[APBSlavePortParameters] => APBSlavePortParameters,
|
||||
numMasterPorts: Range.Inclusive = 1 to 1,
|
||||
numSlavePorts: Range.Inclusive = 1 to 1)(
|
||||
slaveFn: Seq[APBSlavePortParameters] => APBSlavePortParameters)(
|
||||
implicit valName: ValName)
|
||||
extends NexusNode(APBImp)(masterFn, slaveFn, numMasterPorts, numSlavePorts)
|
||||
extends NexusNode(APBImp)(masterFn, slaveFn)
|
||||
|
||||
case class APBIdentityNode()(implicit valName: ValName) extends IdentityNode(APBImp)()
|
||||
|
@ -10,36 +10,39 @@ import scala.math.{min,max}
|
||||
|
||||
class APBFanout()(implicit p: Parameters) extends LazyModule {
|
||||
val node = APBNexusNode(
|
||||
numSlavePorts = 1 to 1,
|
||||
numMasterPorts = 1 to 32,
|
||||
masterFn = { case Seq(m) => m },
|
||||
slaveFn = { seq => seq(0).copy(slaves = seq.flatMap(_.slaves)) })
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
val (in, _) = node.in(0)
|
||||
if (node.edges.in.size >= 1) {
|
||||
require (node.edges.in.size == 1, "APBFanout does not support multiple masters")
|
||||
require (node.edges.out.size > 0, "APBFanout requires at least one slave")
|
||||
|
||||
// Require consistent bus widths
|
||||
val (io_out, edgesOut) = node.out.unzip
|
||||
val port0 = edgesOut(0).slave
|
||||
edgesOut.foreach { edge =>
|
||||
val port = edge.slave
|
||||
require (port.beatBytes == port0.beatBytes,
|
||||
s"${port.slaves.map(_.name)} ${port.beatBytes} vs ${port0.slaves.map(_.name)} ${port0.beatBytes}")
|
||||
val (in, _) = node.in(0)
|
||||
|
||||
// Require consistent bus widths
|
||||
val (io_out, edgesOut) = node.out.unzip
|
||||
val port0 = edgesOut(0).slave
|
||||
edgesOut.foreach { edge =>
|
||||
val port = edge.slave
|
||||
require (port.beatBytes == port0.beatBytes,
|
||||
s"${port.slaves.map(_.name)} ${port.beatBytes} vs ${port0.slaves.map(_.name)} ${port0.beatBytes}")
|
||||
}
|
||||
|
||||
val port_addrs = edgesOut.map(_.slave.slaves.map(_.address).flatten)
|
||||
val routingMask = AddressDecoder(port_addrs)
|
||||
val route_addrs = port_addrs.map(_.map(_.widen(~routingMask)).distinct)
|
||||
|
||||
val sel = Vec(route_addrs.map(seq => seq.map(_.contains(in.paddr)).reduce(_ || _)))
|
||||
(sel zip io_out) foreach { case (sel, out) =>
|
||||
out := in
|
||||
out.psel := sel && in.psel
|
||||
out.penable := sel && in.penable
|
||||
}
|
||||
|
||||
in.pready := !Mux1H(sel, io_out.map(!_.pready))
|
||||
in.pslverr := Mux1H(sel, io_out.map(_.pslverr))
|
||||
in.prdata := Mux1H(sel, io_out.map(_.prdata))
|
||||
}
|
||||
|
||||
val port_addrs = edgesOut.map(_.slave.slaves.map(_.address).flatten)
|
||||
val routingMask = AddressDecoder(port_addrs)
|
||||
val route_addrs = port_addrs.map(_.map(_.widen(~routingMask)).distinct)
|
||||
|
||||
val sel = Vec(route_addrs.map(seq => seq.map(_.contains(in.paddr)).reduce(_ || _)))
|
||||
(sel zip io_out) foreach { case (sel, out) =>
|
||||
out := in
|
||||
out.psel := sel && in.psel
|
||||
out.penable := sel && in.penable
|
||||
}
|
||||
|
||||
in.pready := !Mux1H(sel, io_out.map(!_.pready))
|
||||
in.pslverr := Mux1H(sel, io_out.map(_.pslverr))
|
||||
in.prdata := Mux1H(sel, io_out.map(_.prdata))
|
||||
}
|
||||
}
|
||||
|
@ -23,17 +23,14 @@ case class AXI4MasterNode(portParams: Seq[AXI4MasterPortParameters])(implicit va
|
||||
case class AXI4SlaveNode(portParams: Seq[AXI4SlavePortParameters])(implicit valName: ValName) extends SinkNode(AXI4Imp)(portParams)
|
||||
case class AXI4NexusNode(
|
||||
masterFn: Seq[AXI4MasterPortParameters] => AXI4MasterPortParameters,
|
||||
slaveFn: Seq[AXI4SlavePortParameters] => AXI4SlavePortParameters,
|
||||
numMasterPorts: Range.Inclusive = 1 to 999,
|
||||
numSlavePorts: Range.Inclusive = 1 to 999)(
|
||||
slaveFn: Seq[AXI4SlavePortParameters] => AXI4SlavePortParameters)(
|
||||
implicit valName: ValName)
|
||||
extends NexusNode(AXI4Imp)(masterFn, slaveFn, numMasterPorts, numSlavePorts)
|
||||
extends NexusNode(AXI4Imp)(masterFn, slaveFn)
|
||||
case class AXI4AdapterNode(
|
||||
masterFn: AXI4MasterPortParameters => AXI4MasterPortParameters = { m => m },
|
||||
slaveFn: AXI4SlavePortParameters => AXI4SlavePortParameters = { s => s },
|
||||
numPorts: Range.Inclusive = 0 to 999)(
|
||||
slaveFn: AXI4SlavePortParameters => AXI4SlavePortParameters = { s => s })(
|
||||
implicit valName: ValName)
|
||||
extends AdapterNode(AXI4Imp)(masterFn, slaveFn, numPorts)
|
||||
extends AdapterNode(AXI4Imp)(masterFn, slaveFn)
|
||||
case class AXI4IdentityNode()(implicit valName: ValName) extends IdentityNode(AXI4Imp)()
|
||||
|
||||
object AXI4AsyncImp extends SimpleNodeImp[AXI4AsyncMasterPortParameters, AXI4AsyncSlavePortParameters, AXI4AsyncEdgeParameters, AXI4AsyncBundle]
|
||||
|
@ -18,8 +18,6 @@ class AXI4Xbar(
|
||||
require (awQueueDepth >= 1)
|
||||
|
||||
val node = AXI4NexusNode(
|
||||
numMasterPorts = 1 to 999,
|
||||
numSlavePorts = 1 to 999,
|
||||
masterFn = { seq =>
|
||||
seq(0).copy(
|
||||
userBits = seq.map(_.userBits).max,
|
||||
@ -56,14 +54,14 @@ class AXI4Xbar(
|
||||
val awIn = Seq.fill(io_in .size) { Module(new Queue(UInt(width = io_out.size), awQueueDepth, flow = true)) }
|
||||
val awOut = Seq.fill(io_out.size) { Module(new Queue(UInt(width = io_in .size), awQueueDepth, flow = true)) }
|
||||
|
||||
val requestARIO = Vec(io_in.map { i => Vec(outputPorts.map { o => o(i.ar.bits.addr) }) })
|
||||
val requestAWIO = Vec(io_in.map { i => Vec(outputPorts.map { o => o(i.aw.bits.addr) }) })
|
||||
val requestROI = Vec(io_out.map { o => Vec(inputIdRanges.map { i => i.contains(o.r.bits.id) }) })
|
||||
val requestBOI = Vec(io_out.map { o => Vec(inputIdRanges.map { i => i.contains(o.b.bits.id) }) })
|
||||
val requestARIO = io_in.map { i => Vec(outputPorts.map { o => o(i.ar.bits.addr) }) }
|
||||
val requestAWIO = io_in.map { i => Vec(outputPorts.map { o => o(i.aw.bits.addr) }) }
|
||||
val requestROI = io_out.map { o => inputIdRanges.map { i => i.contains(o.r.bits.id) } }
|
||||
val requestBOI = io_out.map { o => inputIdRanges.map { i => i.contains(o.b.bits.id) } }
|
||||
|
||||
// W follows the path dictated by the AW Q
|
||||
for (i <- 0 until io_in.size) { awIn(i).io.enq.bits := requestAWIO(i).asUInt }
|
||||
val requestWIO = Vec(awIn.map { q => if (io_out.size > 1) Vec(q.io.deq.bits.toBools) else Vec.fill(1){Bool(true)} })
|
||||
val requestWIO = awIn.map { q => if (io_out.size > 1) q.io.deq.bits.toBools else Seq(Bool(true)) }
|
||||
|
||||
// We need an intermediate size of bundle with the widest possible identifiers
|
||||
val wide_bundle = AXI4BundleParameters.union(io_in.map(_.params) ++ io_out.map(_.params))
|
||||
|
Reference in New Issue
Block a user