From 9b55063de67c921e37424454c44fd21aed1589b4 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 6 Sep 2017 14:20:46 -0700 Subject: [PATCH 01/26] clint: support a configurable number of interrupt register stages --- src/main/scala/devices/tilelink/Clint.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/devices/tilelink/Clint.scala b/src/main/scala/devices/tilelink/Clint.scala index c1235176..2848ed4c 100644 --- a/src/main/scala/devices/tilelink/Clint.scala +++ b/src/main/scala/devices/tilelink/Clint.scala @@ -25,7 +25,7 @@ object ClintConsts def ints = 2 } -case class ClintParams(baseAddress: BigInt = 0x02000000) +case class ClintParams(baseAddress: BigInt = 0x02000000, intStages: Int = 0) { def address = AddressSet(baseAddress, ClintConsts.size-1) } @@ -71,8 +71,8 @@ class CoreplexLocalInterrupter(params: ClintParams)(implicit p: Parameters) exte val ipi = Seq.fill(nTiles) { RegInit(UInt(0, width = 1)) } io.int.zipWithIndex.foreach { case (int, i) => - int(0) := ipi(i)(0) // msip - int(1) := time.asUInt >= timecmp(i).asUInt // mtip + int(0) := ShiftRegister(ipi(i)(0), params.intStages) // msip + int(1) := ShiftRegister(time.asUInt >= timecmp(i).asUInt, params.intStages) // mtip } /* 0000 msip hart 0 From ed70b243bde723e205220762955774fa28bf02ff Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 6 Sep 2017 14:21:09 -0700 Subject: [PATCH 02/26] plic: support a configurable number of interrupt register stages --- src/main/scala/devices/tilelink/Plic.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/devices/tilelink/Plic.scala b/src/main/scala/devices/tilelink/Plic.scala index 5581352e..94b0e186 100644 --- a/src/main/scala/devices/tilelink/Plic.scala +++ b/src/main/scala/devices/tilelink/Plic.scala @@ -52,7 +52,7 @@ object PLICConsts require(hartBase >= enableBase(maxHarts)) } -case class PLICParams(baseAddress: BigInt = 0xC000000, maxPriorities: Int = 7) +case class PLICParams(baseAddress: BigInt = 0xC000000, maxPriorities: Int = 7, intStages: Int = 0) { require (maxPriorities >= 0) def address = AddressSet(baseAddress, PLICConsts.size-1) @@ -166,7 +166,7 @@ class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule val (maxPri, maxDev) = findMax(effectivePriority) maxDevs(hart) := maxDev - harts(hart) := Reg(next = maxPri) > Cat(UInt(1), threshold(hart)) + harts(hart) := ShiftRegister(Reg(next = maxPri) > Cat(UInt(1), threshold(hart)), params.intStages) } def priorityRegField(x: UInt) = if (nPriorities > 0) RegField(32, x) else RegField.r(32, x) From 3e3024c2566e520be93dfb080aa9f5e8dce8e473 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 6 Sep 2017 18:15:59 -0700 Subject: [PATCH 03/26] ShiftQueue: fix bug in !flow case --- src/main/scala/util/ShiftQueue.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/util/ShiftQueue.scala b/src/main/scala/util/ShiftQueue.scala index 5914da89..d2baa988 100644 --- a/src/main/scala/util/ShiftQueue.scala +++ b/src/main/scala/util/ShiftQueue.scala @@ -26,7 +26,7 @@ class ShiftQueue[T <: Data](gen: T, val wdata = if (i == entries-1) io.enq.bits else Mux(valid(i+1), elts(i+1), io.enq.bits) val wen = Mux(io.deq.ready, - paddedValid(i+1) || io.enq.fire() && valid(i), + paddedValid(i+1) || io.enq.fire() && (Bool(i == 0 && !flow) || valid(i)), io.enq.fire() && paddedValid(i-1) && !valid(i)) when (wen) { elts(i) := wdata } From 50d5d8c1fd8c39a919f8339a0413a2b87cacf100 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 6 Sep 2017 14:26:26 -0700 Subject: [PATCH 04/26] ShiftQueue: added a helper object --- src/main/scala/util/ShiftQueue.scala | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/scala/util/ShiftQueue.scala b/src/main/scala/util/ShiftQueue.scala index d2baa988..ecedefbb 100644 --- a/src/main/scala/util/ShiftQueue.scala +++ b/src/main/scala/util/ShiftQueue.scala @@ -52,3 +52,12 @@ class ShiftQueue[T <: Data](gen: T, io.mask := valid.asUInt io.count := PopCount(io.mask) } + +object ShiftQueue +{ + def apply[T <: Data](enq: DecoupledIO[T], entries: Int = 2, pipe: Boolean = false, flow: Boolean = false): DecoupledIO[T] = { + val q = Module(new ShiftQueue(enq.bits.cloneType, entries, pipe, flow)) + q.io.enq <> enq + q.io.deq + } +} From 2d93262f712bb71868732302ac5e3da38c80411e Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 6 Sep 2017 14:27:45 -0700 Subject: [PATCH 05/26] RationalCrossing: use ShiftQueues These are faster and small don't cost much more. --- src/main/scala/util/RationalCrossing.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/scala/util/RationalCrossing.scala b/src/main/scala/util/RationalCrossing.scala index 214a7273..8db10717 100644 --- a/src/main/scala/util/RationalCrossing.scala +++ b/src/main/scala/util/RationalCrossing.scala @@ -73,10 +73,10 @@ class RationalCrossingSource[T <: Data](gen: T, direction: RationalDirection = S val deq = io.deq val enq = direction match { - case Symmetric => Queue(io.enq, 1, flow=true) - case Flexible => Queue(io.enq, 2) + case Symmetric => ShiftQueue(io.enq, 1, flow=true) + case Flexible => ShiftQueue(io.enq, 2) case FastToSlow => io.enq - case SlowToFast => Queue(io.enq, 2) + case SlowToFast => ShiftQueue(io.enq, 2) } val count = RegInit(UInt(0, width = 2)) @@ -109,9 +109,9 @@ class RationalCrossingSink[T <: Data](gen: T, direction: RationalDirection = Sym val enq = io.enq val deq = Wire(io.deq) direction match { - case Symmetric => io.deq <> Queue(deq, 1, pipe=true) - case Flexible => io.deq <> Queue(deq, 2) - case FastToSlow => io.deq <> Queue(deq, 2) + case Symmetric => io.deq <> ShiftQueue(deq, 1, pipe=true) + case Flexible => io.deq <> ShiftQueue(deq, 2) + case FastToSlow => io.deq <> ShiftQueue(deq, 2) case SlowToFast => io.deq <> deq } From 6bfea86dbfe478c8b628be481e488de33906aa24 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 6 Sep 2017 15:04:46 -0700 Subject: [PATCH 06/26] config: support p.lift(key) to optionally return a value --- src/main/scala/config/Config.scala | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/scala/config/Config.scala b/src/main/scala/config/Config.scala index c7930ee6..8b88829d 100644 --- a/src/main/scala/config/Config.scala +++ b/src/main/scala/config/Config.scala @@ -6,9 +6,14 @@ class Field[T] abstract class View { final def apply[T](pname: Field[T]): T = apply(pname, this) - final def apply[T](pname: Field[T], site: View): T = find(pname, site).asInstanceOf[T] + final def apply[T](pname: Field[T], site: View): T = find(pname, site) match { + case Some(x) => x.asInstanceOf[T] + } - protected[config] def find(pname: Any, site: View): Any + final def lift[T](pname: Field[T]): Option[T] = lift(pname, this) + final def lift[T](pname: Field[T], site: View): Option[T] = find(pname, site).map(_.asInstanceOf[T]) + + protected[config] def find(pname: Any, site: View): Option[Any] } abstract class Parameters extends View { @@ -16,7 +21,7 @@ abstract class Parameters extends View { final def alter(f: (View, View, View) => PartialFunction[Any,Any]): Parameters = Parameters(f) ++ this final def alterPartial(f: PartialFunction[Any,Any]): Parameters = Parameters((_,_,_) => f) ++ this - protected[config] def chain(site: View, tail: View, pname: Any): Any + protected[config] def chain(site: View, tail: View, pname: Any): Option[Any] protected[config] def find(pname: Any, site: View) = chain(site, new TerminalView, pname) } @@ -37,8 +42,7 @@ class Config(p: Parameters) extends Parameters { // Internal implementation: private class TerminalView extends View { - private class Unusable - def find(pname: Any, site: View): Any = pname match { case x: Unusable => () } + def find(pname: Any, site: View): Option[Any] = None } private class ChainView(head: Parameters, tail: View) extends View { @@ -56,6 +60,6 @@ private class EmptyParameters extends Parameters { private class PartialParameters(f: (View, View, View) => PartialFunction[Any,Any]) extends Parameters { protected[config] def chain(site: View, tail: View, pname: Any) = { val g = f(site, this, tail) - if (g.isDefinedAt(pname)) g.apply(pname) else tail.find(pname, site) + if (g.isDefinedAt(pname)) Some(g.apply(pname)) else tail.find(pname, site) } } From 1b705f62f6a5d5dd315f1226254d0997bd7f63f2 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 6 Sep 2017 15:30:25 -0700 Subject: [PATCH 07/26] =?UTF-8?q?diplomacy:=20support=20:=3D=3F=20for=20un?= =?UTF-8?q?known=20star=20inference?= --- src/main/scala/diplomacy/Nodes.scala | 29 +++++++++++++++++++++++++- src/main/scala/diplomacy/package.scala | 17 +++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/main/scala/diplomacy/Nodes.scala b/src/main/scala/diplomacy/Nodes.scala index 8906f64b..06103b3c 100644 --- a/src/main/scala/diplomacy/Nodes.scala +++ b/src/main/scala/diplomacy/Nodes.scala @@ -4,10 +4,27 @@ package freechips.rocketchip.diplomacy import Chisel._ import chisel3.internal.sourceinfo.SourceInfo -import freechips.rocketchip.config.Parameters +import freechips.rocketchip.config.{Parameters,Field} import freechips.rocketchip.util.HeterogeneousBag import scala.collection.mutable.ListBuffer +object CardinalityInferenceDirection { + val cases = Seq(SOURCE_TO_SINK, SINK_TO_SOURCE, NO_INFERENCE) + sealed trait T { + def flip = this match { + case SOURCE_TO_SINK => SINK_TO_SOURCE + case SINK_TO_SOURCE => SOURCE_TO_SINK + case NO_INFERENCE => NO_INFERENCE + } + } + + case object SOURCE_TO_SINK extends T + case object SINK_TO_SOURCE extends T + case object NO_INFERENCE extends T +} + +case object CardinalityInferenceDirectionKey extends Field[CardinalityInferenceDirection.T] + // DI = Downwards flowing Parameters received on the inner side of the node // UI = Upwards flowing Parameters generated by the inner side of the node // EI = Edge Parameters describing a connection on the inner side of the node @@ -84,6 +101,8 @@ trait InwardNodeHandle[DI, UI, BI <: Data] inward.:*=(h)(p, sourceInfo) def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = inward.:=*(h)(p, sourceInfo) + def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = + inward.:=?(h)(p, sourceInfo) } sealed trait NodeBinding @@ -264,6 +283,14 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( override def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_ONCE, true) override def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_STAR, true) override def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_QUERY, true) + override def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = { + p.lift(CardinalityInferenceDirectionKey) match { + case Some(CardinalityInferenceDirection.SOURCE_TO_SINK) => this :=* h + case Some(CardinalityInferenceDirection.SINK_TO_SOURCE) => this :*= h + case Some(CardinalityInferenceDirection.NO_INFERENCE) => this := h + case None => this := h + } + } def connectButDontMonitor(h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_ONCE, false) def connectButDontMonitorSlaves(h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_STAR, false) diff --git a/src/main/scala/diplomacy/package.scala b/src/main/scala/diplomacy/package.scala index 64219a1c..0567f2fa 100644 --- a/src/main/scala/diplomacy/package.scala +++ b/src/main/scala/diplomacy/package.scala @@ -3,6 +3,7 @@ package freechips.rocketchip import chisel3.internal.sourceinfo.{SourceInfo, SourceLine, UnlocatableSourceInfo} +import freechips.rocketchip.config.Parameters package object diplomacy { @@ -20,4 +21,20 @@ package object diplomacy bitIndexes(x.clearBit(lowest), lowest +: tail) } } + + def LeftStar[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { + case CardinalityInferenceDirectionKey => CardinalityInferenceDirection.SINK_TO_SOURCE + }) + def RightStar[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { + case CardinalityInferenceDirectionKey => CardinalityInferenceDirection.SOURCE_TO_SINK + }) + def NoStar[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { + case CardinalityInferenceDirectionKey => CardinalityInferenceDirection.NO_INFERENCE + }) + def FlipStar[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { + case CardinalityInferenceDirectionKey => p + .lift(CardinalityInferenceDirectionKey) + .map(_.flip) + .getOrElse(CardinalityInferenceDirection.NO_INFERENCE) + }) } From 80965e82307607ba2f9f06caf131ccd4a1f9e5a6 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 6 Sep 2017 15:44:54 -0700 Subject: [PATCH 08/26] =?UTF-8?q?tilelink=20Buffer:=20use=20new=20:=3D=3F?= =?UTF-8?q?=20adapter=20API?= --- src/main/scala/tilelink/Buffer.scala | 18 ++++++++++++++---- src/main/scala/tilelink/Bus.scala | 8 +++++--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main/scala/tilelink/Buffer.scala b/src/main/scala/tilelink/Buffer.scala index 3a8869de..4ce803cc 100644 --- a/src/main/scala/tilelink/Buffer.scala +++ b/src/main/scala/tilelink/Buffer.scala @@ -73,7 +73,7 @@ object TLBuffer d: BufferParams, e: BufferParams)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { val buffer = LazyModule(new TLBuffer(a, b, c, d, e)) - buffer.node := x + buffer.node :=? x buffer.node } } @@ -82,18 +82,19 @@ class TLBufferChain(depth: Int)(implicit p: Parameters) extends LazyModule { val nodeIn = TLInputNode() val nodeOut = TLOutputNode() + val node = NodeHandle(nodeIn, nodeOut) val buf_chain = if (depth > 0) { val chain = List.fill(depth)(LazyModule(new TLBuffer(BufferParams.default))) - (chain.init zip chain.tail) foreach { case(prev, next) => next.node :=* prev.node } + (chain.init zip chain.tail) foreach { case(prev, next) => next.node :=? prev.node } chain } else { List(LazyModule(new TLBuffer(BufferParams.none))) } - buf_chain.head.node :=* nodeIn - nodeOut :=* buf_chain.last.node + buf_chain.head.node :=? nodeIn + nodeOut :=? buf_chain.last.node lazy val module = new LazyModuleImp(this) { val io = new Bundle { @@ -102,3 +103,12 @@ class TLBufferChain(depth: Int)(implicit p: Parameters) extends LazyModule { } } } + +object TLBufferChain +{ + def apply(depth: Int)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { + val buffer = LazyModule(new TLBufferChain(depth)) + buffer.node :=? x + buffer.node + } +} diff --git a/src/main/scala/tilelink/Bus.scala b/src/main/scala/tilelink/Bus.scala index d9a7f364..d6774c56 100644 --- a/src/main/scala/tilelink/Bus.scala +++ b/src/main/scala/tilelink/Bus.scala @@ -68,9 +68,11 @@ abstract class TLBusWrapper(params: TLBusParams, val busName: String)(implicit p protected def inwardBufNode: TLInwardNode = master_buffer.node protected def bufferChain(depth: Int, name: Option[String] = None): (TLInwardNode, TLOutwardNode) = { - val chain = LazyModule(new TLBufferChain(depth)) - name.foreach { n => chain.suggestName(s"${busName}_${n}_TLBufferChain")} - (chain.nodeIn, chain.nodeOut) + RightStar { implicit p => + val chain = LazyModule(new TLBufferChain(depth)) + name.foreach { n => chain.suggestName(s"${busName}_${n}_TLBufferChain")} + (chain.nodeIn, chain.nodeOut) + } } def bufferFromMasters: TLInwardNode = inwardBufNode From d5c6494f593cf855999757c3476ba39941d44e38 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 6 Sep 2017 14:37:22 -0700 Subject: [PATCH 09/26] tilelink: Bus.toRationalSlaves can have a BufferChain --- src/main/scala/tilelink/Bus.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/tilelink/Bus.scala b/src/main/scala/tilelink/Bus.scala index d6774c56..5efdfd86 100644 --- a/src/main/scala/tilelink/Bus.scala +++ b/src/main/scala/tilelink/Bus.scala @@ -86,10 +86,10 @@ abstract class TLBusWrapper(params: TLBusParams, val busName: String)(implicit p source.node } - def toRationalSlaves(name: Option[String] = None): TLRationalOutwardNode = { + def toRationalSlaves(name: Option[String] = None, addBuffers: Int = 0): TLRationalOutwardNode = LeftStar { implicit p => val source = LazyModule(new TLRationalCrossingSource()) name.foreach{ n => source.suggestName(s"${busName}_${n}_TLRationalCrossingSource")} - source.node :*= outwardNode + source.node :=? TLBufferChain(addBuffers)(outwardNode) source.node } From 040f7e1d49b1f10da5fd6245944bc7e98e9acdee Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 6 Sep 2017 14:58:04 -0700 Subject: [PATCH 10/26] tilelink: add Bus.toSyncSlaves for easy BufferChain attachment --- src/main/scala/tilelink/Bus.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/tilelink/Bus.scala b/src/main/scala/tilelink/Bus.scala index 5efdfd86..fbf2fc7d 100644 --- a/src/main/scala/tilelink/Bus.scala +++ b/src/main/scala/tilelink/Bus.scala @@ -79,7 +79,7 @@ abstract class TLBusWrapper(params: TLBusParams, val busName: String)(implicit p def bufferToSlaves: TLOutwardNode = outwardBufNode - def toAsyncSlaves(sync: Int = 3, name: Option[String] = None): TLAsyncOutwardNode = { + def toAsyncSlaves(sync: Int = 3, name: Option[String] = None, addBuffers: Int = 0): TLAsyncOutwardNode = { val source = LazyModule(new TLAsyncCrossingSource(sync)) name.foreach{ n => source.suggestName(s"${busName}_${n}_TLAsyncCrossingSource")} source.node :*= outwardNode From 4911a7d44f7e0fa47aee7593eeec35f25021dc15 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 6 Sep 2017 14:42:47 -0700 Subject: [PATCH 11/26] tilelink Bus: toAsyncSlaves now supports BufferChains --- src/main/scala/tilelink/Bus.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/scala/tilelink/Bus.scala b/src/main/scala/tilelink/Bus.scala index fbf2fc7d..f46e8c18 100644 --- a/src/main/scala/tilelink/Bus.scala +++ b/src/main/scala/tilelink/Bus.scala @@ -79,10 +79,14 @@ abstract class TLBusWrapper(params: TLBusParams, val busName: String)(implicit p def bufferToSlaves: TLOutwardNode = outwardBufNode - def toAsyncSlaves(sync: Int = 3, name: Option[String] = None, addBuffers: Int = 0): TLAsyncOutwardNode = { + def toSyncSlaves(name: Option[String] = None, addBuffers: Int = 0): TLOutwardNode = LeftStar { implicit p => + TLBufferChain(addBuffers)(outwardBufNode) + } + + def toAsyncSlaves(sync: Int = 3, name: Option[String] = None, addBuffers: Int = 0): TLAsyncOutwardNode = LeftStar { implicit p => val source = LazyModule(new TLAsyncCrossingSource(sync)) name.foreach{ n => source.suggestName(s"${busName}_${n}_TLAsyncCrossingSource")} - source.node :*= outwardNode + source.node :=? TLBufferChain(addBuffers)(outwardNode) source.node } From fd8a51a9105837853ebf4e787342cb5faceeb690 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 6 Sep 2017 14:40:13 -0700 Subject: [PATCH 12/26] coreplex: rename externalBuffers to externalMasterBuffers --- src/main/scala/coreplex/RocketCoreplex.scala | 6 +++--- src/main/scala/tile/RocketTile.scala | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/scala/coreplex/RocketCoreplex.scala b/src/main/scala/coreplex/RocketCoreplex.scala index d1e7fd0c..feee369e 100644 --- a/src/main/scala/coreplex/RocketCoreplex.scala +++ b/src/main/scala/coreplex/RocketCoreplex.scala @@ -45,19 +45,19 @@ trait HasRocketTiles extends HasSystemBus val wrapper = crossing match { case SynchronousCrossing(params) => { val wrapper = LazyModule(new SyncRocketTile(tp, i)(pWithExtra)) - sbus.fromSyncTiles(params, tp.externalBuffers, tp.name) :=* wrapper.masterNode + sbus.fromSyncTiles(params, tp.externalMasterBuffers, tp.name) :=* wrapper.masterNode wrapper.slaveNode :*= pbus.bufferToSlaves wrapper } case AsynchronousCrossing(depth, sync) => { val wrapper = LazyModule(new AsyncRocketTile(tp, i)(pWithExtra)) - sbus.fromAsyncTiles(depth, sync, tp.externalBuffers, tp.name) :=* wrapper.masterNode + sbus.fromAsyncTiles(depth, sync, tp.externalMasterBuffers, tp.name) :=* wrapper.masterNode wrapper.slaveNode :*= pbus.toAsyncSlaves(sync, tp.name) wrapper } case RationalCrossing(direction) => { val wrapper = LazyModule(new RationalRocketTile(tp, i)(pWithExtra)) - sbus.fromRationalTiles(direction, tp.externalBuffers, tp.name) :=* wrapper.masterNode + sbus.fromRationalTiles(direction, tp.externalMasterBuffers, tp.name) :=* wrapper.masterNode wrapper.slaveNode :*= pbus.toRationalSlaves(tp.name) wrapper } diff --git a/src/main/scala/tile/RocketTile.scala b/src/main/scala/tile/RocketTile.scala index 4b2ff7ca..ea27e584 100644 --- a/src/main/scala/tile/RocketTile.scala +++ b/src/main/scala/tile/RocketTile.scala @@ -20,7 +20,7 @@ case class RocketTileParams( dataScratchpadBytes: Int = 0, boundaryBuffers: Boolean = false, name: Option[String] = Some("tile"), - externalBuffers: Int = 0) extends TileParams { + externalMasterBuffers: Int = 0) extends TileParams { require(icache.isDefined) require(dcache.isDefined) } From 1a87ed1193a04695482a2a1eac47e02b05d2922b Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 6 Sep 2017 14:58:34 -0700 Subject: [PATCH 13/26] coreplex: add externalSlaveBuffers configuration option --- src/main/scala/coreplex/RocketCoreplex.scala | 6 +++--- src/main/scala/tile/RocketTile.scala | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/scala/coreplex/RocketCoreplex.scala b/src/main/scala/coreplex/RocketCoreplex.scala index feee369e..b57f0f2c 100644 --- a/src/main/scala/coreplex/RocketCoreplex.scala +++ b/src/main/scala/coreplex/RocketCoreplex.scala @@ -46,19 +46,19 @@ trait HasRocketTiles extends HasSystemBus case SynchronousCrossing(params) => { val wrapper = LazyModule(new SyncRocketTile(tp, i)(pWithExtra)) sbus.fromSyncTiles(params, tp.externalMasterBuffers, tp.name) :=* wrapper.masterNode - wrapper.slaveNode :*= pbus.bufferToSlaves + wrapper.slaveNode :*= pbus.toSyncSlaves(tp.name, tp.externalSlaveBuffers) wrapper } case AsynchronousCrossing(depth, sync) => { val wrapper = LazyModule(new AsyncRocketTile(tp, i)(pWithExtra)) sbus.fromAsyncTiles(depth, sync, tp.externalMasterBuffers, tp.name) :=* wrapper.masterNode - wrapper.slaveNode :*= pbus.toAsyncSlaves(sync, tp.name) + wrapper.slaveNode :*= pbus.toAsyncSlaves(sync, tp.name, tp.externalSlaveBuffers) wrapper } case RationalCrossing(direction) => { val wrapper = LazyModule(new RationalRocketTile(tp, i)(pWithExtra)) sbus.fromRationalTiles(direction, tp.externalMasterBuffers, tp.name) :=* wrapper.masterNode - wrapper.slaveNode :*= pbus.toRationalSlaves(tp.name) + wrapper.slaveNode :*= pbus.toRationalSlaves(tp.name, tp.externalSlaveBuffers) wrapper } } diff --git a/src/main/scala/tile/RocketTile.scala b/src/main/scala/tile/RocketTile.scala index ea27e584..a98917b9 100644 --- a/src/main/scala/tile/RocketTile.scala +++ b/src/main/scala/tile/RocketTile.scala @@ -20,7 +20,8 @@ case class RocketTileParams( dataScratchpadBytes: Int = 0, boundaryBuffers: Boolean = false, name: Option[String] = Some("tile"), - externalMasterBuffers: Int = 0) extends TileParams { + externalMasterBuffers: Int = 0, + externalSlaveBuffers: Int = 0) extends TileParams { require(icache.isDefined) require(dcache.isDefined) } From 5626cdd18f574ed8ae55a06f2b14f76f40347db0 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 6 Sep 2017 16:07:31 -0700 Subject: [PATCH 14/26] util: add the IdentityModule, useful to dedup wires --- src/main/scala/util/IdentityModule.scala | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/main/scala/util/IdentityModule.scala diff --git a/src/main/scala/util/IdentityModule.scala b/src/main/scala/util/IdentityModule.scala new file mode 100644 index 00000000..62c6994c --- /dev/null +++ b/src/main/scala/util/IdentityModule.scala @@ -0,0 +1,24 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.tilelink + +import Chisel._ + +class IdentityModule[T <: Data](gen: T) extends Module +{ + val io = new Bundle { + val in = gen.cloneType.flip + val out = gen.cloneType + } + + io.out := io.in +} + +object IdentityModule +{ + def apply[T <: Data](x: T): T = { + val identity = Module(new IdentityModule(x)) + identity.io.in := x + identity.io.out + } +} From 42f1ae27fc35378456db5b8f18e1b22f938b6bfd Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 6 Sep 2017 16:07:58 -0700 Subject: [PATCH 15/26] Xbar: use the IdentityModule to encourage wider fanout --- src/main/scala/tilelink/Xbar.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/tilelink/Xbar.scala b/src/main/scala/tilelink/Xbar.scala index 8e0f184b..eb6d00dd 100644 --- a/src/main/scala/tilelink/Xbar.scala +++ b/src/main/scala/tilelink/Xbar.scala @@ -219,7 +219,7 @@ object TLXbar def fanout[T <: TLChannel](input: DecoupledIO[T], select: Seq[Bool]) = { val filtered = Wire(Vec(select.size, input)) for (i <- 0 until select.size) { - filtered(i).bits := input.bits + filtered(i).bits := IdentityModule(input.bits) // force fanout of wires filtered(i).valid := input.valid && select(i) } input.ready := Mux1H(select, filtered.map(_.ready)) From 09d8d476c572ac1a29f45073a8309ace7051badd Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 7 Sep 2017 13:29:14 -0700 Subject: [PATCH 16/26] config: require Parameters keys to be Field[T] This has been good practice for ages. Enforce it. --- src/main/scala/config/Config.scala | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/scala/config/Config.scala b/src/main/scala/config/Config.scala index 8b88829d..457dd184 100644 --- a/src/main/scala/config/Config.scala +++ b/src/main/scala/config/Config.scala @@ -2,7 +2,7 @@ package freechips.rocketchip.config -class Field[T] +abstract class Field[T] abstract class View { final def apply[T](pname: Field[T]): T = apply(pname, this) @@ -13,7 +13,7 @@ abstract class View { final def lift[T](pname: Field[T]): Option[T] = lift(pname, this) final def lift[T](pname: Field[T], site: View): Option[T] = find(pname, site).map(_.asInstanceOf[T]) - protected[config] def find(pname: Any, site: View): Option[Any] + protected[config] def find[T](pname: Field[T], site: View): Option[T] } abstract class Parameters extends View { @@ -21,8 +21,8 @@ abstract class Parameters extends View { final def alter(f: (View, View, View) => PartialFunction[Any,Any]): Parameters = Parameters(f) ++ this final def alterPartial(f: PartialFunction[Any,Any]): Parameters = Parameters((_,_,_) => f) ++ this - protected[config] def chain(site: View, tail: View, pname: Any): Option[Any] - protected[config] def find(pname: Any, site: View) = chain(site, new TerminalView, pname) + protected[config] def chain[T](site: View, tail: View, pname: Field[T]): Option[T] + protected[config] def find[T](pname: Field[T], site: View) = chain(site, new TerminalView, pname) } object Parameters { @@ -34,7 +34,7 @@ object Parameters { class Config(p: Parameters) extends Parameters { def this(f: (View, View, View) => PartialFunction[Any,Any]) = this(Parameters(f)) - protected[config] def chain(site: View, tail: View, pname: Any) = p.chain(site, tail, pname) + protected[config] def chain[T](site: View, tail: View, pname: Field[T]) = p.chain(site, tail, pname) override def toString = this.getClass.getSimpleName def toInstance = this } @@ -42,24 +42,24 @@ class Config(p: Parameters) extends Parameters { // Internal implementation: private class TerminalView extends View { - def find(pname: Any, site: View): Option[Any] = None + def find[T](pname: Field[T], site: View): Option[T] = None } private class ChainView(head: Parameters, tail: View) extends View { - def find(pname: Any, site: View) = head.chain(site, tail, pname) + def find[T](pname: Field[T], site: View) = head.chain(site, tail, pname) } private class ChainParameters(x: Parameters, y: Parameters) extends Parameters { - def chain(site: View, tail: View, pname: Any) = x.chain(site, new ChainView(y, tail), pname) + def chain[T](site: View, tail: View, pname: Field[T]) = x.chain(site, new ChainView(y, tail), pname) } private class EmptyParameters extends Parameters { - def chain(site: View, tail: View, pname: Any) = tail.find(pname, site) + def chain[T](site: View, tail: View, pname: Field[T]) = tail.find(pname, site) } private class PartialParameters(f: (View, View, View) => PartialFunction[Any,Any]) extends Parameters { - protected[config] def chain(site: View, tail: View, pname: Any) = { + protected[config] def chain[T](site: View, tail: View, pname: Field[T]) = { val g = f(site, this, tail) - if (g.isDefinedAt(pname)) Some(g.apply(pname)) else tail.find(pname, site) + if (g.isDefinedAt(pname)) Some(g.apply(pname).asInstanceOf[T]) else tail.find(pname, site) } } From 655a08f12e2104cc459eb22902fab3630c71d0f2 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 7 Sep 2017 13:29:59 -0700 Subject: [PATCH 17/26] config: support default values for Field[T] keys --- src/main/scala/config/Config.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/scala/config/Config.scala b/src/main/scala/config/Config.scala index 457dd184..0f4db18e 100644 --- a/src/main/scala/config/Config.scala +++ b/src/main/scala/config/Config.scala @@ -2,7 +2,11 @@ package freechips.rocketchip.config -abstract class Field[T] +abstract class Field[T] private (val default: Option[T]) +{ + def this() = this(None) + def this(x: T) = this(Some(x)) +} abstract class View { final def apply[T](pname: Field[T]): T = apply(pname, this) @@ -42,7 +46,7 @@ class Config(p: Parameters) extends Parameters { // Internal implementation: private class TerminalView extends View { - def find[T](pname: Field[T], site: View): Option[T] = None + def find[T](pname: Field[T], site: View): Option[T] = pname.default } private class ChainView(head: Parameters, tail: View) extends View { From 7a8364ef08218e9b801a94ba5777835010e7b0a2 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 7 Sep 2017 13:33:07 -0700 Subject: [PATCH 18/26] diplomacy: leverage new Parameters defaults --- src/main/scala/diplomacy/Nodes.scala | 12 ++++++------ src/main/scala/diplomacy/package.scala | 5 +---- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/main/scala/diplomacy/Nodes.scala b/src/main/scala/diplomacy/Nodes.scala index 06103b3c..838cb489 100644 --- a/src/main/scala/diplomacy/Nodes.scala +++ b/src/main/scala/diplomacy/Nodes.scala @@ -23,7 +23,8 @@ object CardinalityInferenceDirection { case object NO_INFERENCE extends T } -case object CardinalityInferenceDirectionKey extends Field[CardinalityInferenceDirection.T] +case object CardinalityInferenceDirectionKey extends + Field[CardinalityInferenceDirection.T](CardinalityInferenceDirection.NO_INFERENCE) // DI = Downwards flowing Parameters received on the inner side of the node // UI = Upwards flowing Parameters generated by the inner side of the node @@ -284,11 +285,10 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( override def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_STAR, true) override def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_QUERY, true) override def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = { - p.lift(CardinalityInferenceDirectionKey) match { - case Some(CardinalityInferenceDirection.SOURCE_TO_SINK) => this :=* h - case Some(CardinalityInferenceDirection.SINK_TO_SOURCE) => this :*= h - case Some(CardinalityInferenceDirection.NO_INFERENCE) => this := h - case None => this := h + p(CardinalityInferenceDirectionKey) match { + case CardinalityInferenceDirection.SOURCE_TO_SINK => this :=* h + case CardinalityInferenceDirection.SINK_TO_SOURCE => this :*= h + case CardinalityInferenceDirection.NO_INFERENCE => this := h } } diff --git a/src/main/scala/diplomacy/package.scala b/src/main/scala/diplomacy/package.scala index 0567f2fa..93714d62 100644 --- a/src/main/scala/diplomacy/package.scala +++ b/src/main/scala/diplomacy/package.scala @@ -32,9 +32,6 @@ package object diplomacy case CardinalityInferenceDirectionKey => CardinalityInferenceDirection.NO_INFERENCE }) def FlipStar[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { - case CardinalityInferenceDirectionKey => p - .lift(CardinalityInferenceDirectionKey) - .map(_.flip) - .getOrElse(CardinalityInferenceDirection.NO_INFERENCE) + case CardinalityInferenceDirectionKey => p(CardinalityInferenceDirectionKey).flip }) } From a45035774408c5ca5115b9d2f03ae7c458298cd7 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 7 Sep 2017 13:41:26 -0700 Subject: [PATCH 19/26] tilelink: Monitor construction method is unconditional Whether or not a Monitor should be placed is decided by diplomacy. --- src/main/scala/coreplex/Configs.scala | 3 --- src/main/scala/tilelink/Nodes.scala | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/scala/coreplex/Configs.scala b/src/main/scala/coreplex/Configs.scala index 710d1f57..3394e054 100644 --- a/src/main/scala/coreplex/Configs.scala +++ b/src/main/scala/coreplex/Configs.scala @@ -36,9 +36,6 @@ class BaseCoreplexConfig extends Config ((site, here, up) => { case PLICParams => PLICParams() case ClintParams => ClintParams() case DTSTimebase => BigInt(1000000) // 1 MHz - // TileLink connection global parameters - case TLMonitorBuilder => (args: TLMonitorArgs) => Some(LazyModule(new TLMonitor(args))) - case TLCombinationalCheck => false case TLBusDelayProbability => 0.0 }) diff --git a/src/main/scala/tilelink/Nodes.scala b/src/main/scala/tilelink/Nodes.scala index 513399ba..4d4912f4 100644 --- a/src/main/scala/tilelink/Nodes.scala +++ b/src/main/scala/tilelink/Nodes.scala @@ -9,8 +9,8 @@ import freechips.rocketchip.diplomacy._ import freechips.rocketchip.util.RationalDirection import scala.collection.mutable.ListBuffer -case object TLMonitorBuilder extends Field[TLMonitorArgs => Option[TLMonitorBase]] -case object TLCombinationalCheck extends Field[Boolean] +case object TLMonitorBuilder extends Field[TLMonitorArgs => TLMonitorBase](args => LazyModule(new TLMonitor(args))) +case object TLCombinationalCheck extends Field[Boolean](false) object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLEdgeIn, TLBundle] { @@ -26,7 +26,7 @@ object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TL override def connect(edges: () => Seq[TLEdgeIn], bundles: () => Seq[(TLBundle, TLBundle)], enableMonitoring: Boolean) (implicit p: Parameters, sourceInfo: SourceInfo): (Option[TLMonitorBase], () => Unit) = { - val monitor = if (enableMonitoring) p(TLMonitorBuilder)(TLMonitorArgs(edges, sourceInfo, p)) else None + val monitor = if (enableMonitoring) Some(p(TLMonitorBuilder)(TLMonitorArgs(edges, sourceInfo, p))) else None (monitor, () => { val eval = bundles () monitor.foreach { m => (eval zip m.module.io.in) foreach { case ((i,o), m) => m := TLBundleSnoop(o,i) } } From 1365c5f90c11a51889a9b03b3bb40c6f619fdb1e Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 7 Sep 2017 14:25:33 -0700 Subject: [PATCH 20/26] diplomacy: implement DisableMonitors scope --- src/main/scala/diplomacy/Nodes.scala | 18 ++++++++---------- src/main/scala/diplomacy/package.scala | 6 ++++++ src/main/scala/rocket/Frontend.scala | 4 ++-- .../scala/rocket/ScratchpadSlavePort.scala | 14 ++++++++------ src/main/scala/tile/RocketTile.scala | 18 ++++++++++++------ 5 files changed, 36 insertions(+), 24 deletions(-) diff --git a/src/main/scala/diplomacy/Nodes.scala b/src/main/scala/diplomacy/Nodes.scala index 838cb489..16b655df 100644 --- a/src/main/scala/diplomacy/Nodes.scala +++ b/src/main/scala/diplomacy/Nodes.scala @@ -23,9 +23,11 @@ object CardinalityInferenceDirection { case object NO_INFERENCE extends T } -case object CardinalityInferenceDirectionKey extends +private case object CardinalityInferenceDirectionKey extends Field[CardinalityInferenceDirection.T](CardinalityInferenceDirection.NO_INFERENCE) +private case object MonitorsEnabled extends Field[Boolean](true) + // DI = Downwards flowing Parameters received on the inner side of the node // UI = Upwards flowing Parameters generated by the inner side of the node // EI = Edge Parameters describing a connection on the inner side of the node @@ -249,7 +251,7 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( lazy val bundleIn = wireI(flipI(HeterogeneousBag(edgesIn .map(inner.bundleI(_))))) // connects the outward part of a node with the inward part of this node - private def bind(h: OutwardNodeHandle[DI, UI, BI], binding: NodeBinding, enableMonitoring: Boolean) + private def bind(h: OutwardNodeHandle[DI, UI, BI], binding: NodeBinding) (implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = { val x = this // x := y val y = h.outward @@ -276,14 +278,14 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( (x.bundleIn(iStart+j), y.bundleOut(oStart+j)) } } - val (out, newbinding) = inner.connect(edges _, bundles _, enableMonitoring) + val (out, newbinding) = inner.connect(edges _, bundles _, p(MonitorsEnabled)) LazyModule.stack.head.bindings = newbinding :: LazyModule.stack.head.bindings out } - override def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_ONCE, true) - override def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_STAR, true) - override def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_QUERY, true) + override def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_ONCE) + override def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_STAR) + override def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_QUERY) override def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = { p(CardinalityInferenceDirectionKey) match { case CardinalityInferenceDirection.SOURCE_TO_SINK => this :=* h @@ -292,10 +294,6 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( } } - def connectButDontMonitor(h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_ONCE, false) - def connectButDontMonitorSlaves(h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_STAR, false) - def connectButDontMonitorMasters(h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_QUERY, false) - // meta-data for printing the node graph protected[diplomacy] def colour = inner.colour protected[diplomacy] def reverse = inner.reverse diff --git a/src/main/scala/diplomacy/package.scala b/src/main/scala/diplomacy/package.scala index 93714d62..2fd34f4c 100644 --- a/src/main/scala/diplomacy/package.scala +++ b/src/main/scala/diplomacy/package.scala @@ -34,4 +34,10 @@ package object diplomacy def FlipStar[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { case CardinalityInferenceDirectionKey => p(CardinalityInferenceDirectionKey).flip }) + def EnableMonitors[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { + case MonitorsEnabled => true + }) + def DisableMonitors[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { + case MonitorsEnabled => false + }) } diff --git a/src/main/scala/rocket/Frontend.scala b/src/main/scala/rocket/Frontend.scala index 465e521d..ee824da0 100644 --- a/src/main/scala/rocket/Frontend.scala +++ b/src/main/scala/rocket/Frontend.scala @@ -8,7 +8,7 @@ import Chisel.ImplicitConversions._ import chisel3.core.withReset import freechips.rocketchip.config._ import freechips.rocketchip.coreplex._ -import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} +import freechips.rocketchip.diplomacy._ import freechips.rocketchip.tilelink._ import freechips.rocketchip.tile._ import freechips.rocketchip.util._ @@ -61,7 +61,7 @@ class Frontend(val icacheParams: ICacheParams, hartid: Int)(implicit p: Paramete masterNode := icache.masterNode // Avoid breaking tile dedup due to address constants in the monitor - icache.slaveNode.map { _ connectButDontMonitor slaveNode } + DisableMonitors { implicit p => icache.slaveNode.map { _ := slaveNode } } } class FrontendBundle(outer: Frontend) extends CoreBundle()(outer.p) { diff --git a/src/main/scala/rocket/ScratchpadSlavePort.scala b/src/main/scala/rocket/ScratchpadSlavePort.scala index 5c942d2f..9a1b9088 100644 --- a/src/main/scala/rocket/ScratchpadSlavePort.scala +++ b/src/main/scala/rocket/ScratchpadSlavePort.scala @@ -103,16 +103,18 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend with HasCor val slaveNode = TLInputNode() // Up to two uses for this input node: // 1) Frontend always exists, but may or may not have a scratchpad node + // 2) ScratchpadSlavePort always has a node, but only exists when the HellaCache has a scratchpad val fg = LazyModule(new TLFragmenter(fetchWidth*coreInstBytes, p(CacheBlockBytes), earlyAck=true)) val ww = LazyModule(new TLWidthWidget(xLen/8)) - frontend.slaveNode connectButDontMonitorSlaves fg.node - fg.node connectButDontMonitorSlaves ww.node - ww.node connectButDontMonitorSlaves slaveNode - - // 2) ScratchpadSlavePort always has a node, but only exists when the HellaCache has a scratchpad val scratch = tileParams.dcache.flatMap(d => d.scratch.map(s => LazyModule(new ScratchpadSlavePort(AddressSet(s, d.dataScratchpadBytes-1))))) - scratch foreach { lm => lm.node connectButDontMonitor TLFragmenter(xLen/8, p(CacheBlockBytes), earlyAck=true)(slaveNode) } + + DisableMonitors { implicit p => + frontend.slaveNode :*= fg.node + fg.node :*= ww.node + ww.node :*= slaveNode + scratch foreach { lm => lm.node := TLFragmenter(xLen/8, p(CacheBlockBytes), earlyAck=true)(slaveNode) } + } def findScratchpadFromICache: Option[AddressSet] = scratch.map { s => val finalNode = frontend.masterNode.edgesOut.head.manager.managers.find(_.nodePath.last == s.node) diff --git a/src/main/scala/tile/RocketTile.scala b/src/main/scala/tile/RocketTile.scala index a98917b9..74cbf56c 100644 --- a/src/main/scala/tile/RocketTile.scala +++ b/src/main/scala/tile/RocketTile.scala @@ -191,7 +191,7 @@ abstract class RocketTileWrapper(rtp: RocketTileParams, hartid: Int)(implicit p: def optionalSlaveBuffer(in: TLOutwardNode): TLOutwardNode = { if (rtp.boundaryBuffers) { val sbuf = LazyModule(new TLBuffer(BufferParams.flow, BufferParams.none, BufferParams.none, BufferParams.none, BufferParams.none)) - sbuf.node connectButDontMonitorSlaves in + DisableMonitors { implicit p => sbuf.node :*= in } sbuf.node } else { in @@ -217,7 +217,7 @@ class SyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) masterNode :=* optionalMasterBuffer(rocket.masterNode) val slaveNode = new TLInputNode() { override def reverse = true } - rocket.slaveNode connectButDontMonitorSlaves optionalSlaveBuffer(slaveNode) + DisableMonitors { implicit p => rocket.slaveNode :*= optionalSlaveBuffer(slaveNode) } // Fully async interrupts need synchronizers. // Others need no synchronization. @@ -237,8 +237,11 @@ class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters val slaveNode = new TLAsyncInputNode() { override def reverse = true } val sink = LazyModule(new TLAsyncCrossingSink) - rocket.slaveNode connectButDontMonitorSlaves sink.node - sink.node connectButDontMonitorSlaves slaveNode + + DisableMonitors { implicit p => + rocket.slaveNode :*= sink.node + sink.node :*= slaveNode + } // Fully async interrupts need synchronizers, // as do those coming from the periphery clock. @@ -261,8 +264,11 @@ class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Paramet val slaveNode = new TLRationalInputNode() { override def reverse = true } val sink = LazyModule(new TLRationalCrossingSink(SlowToFast)) - sink.node connectButDontMonitorSlaves slaveNode - rocket.slaveNode connectButDontMonitorSlaves optionalSlaveBuffer(sink.node) + + DisableMonitors { implicit p => + sink.node :*= slaveNode + rocket.slaveNode :*= optionalSlaveBuffer(sink.node) + } // Fully async interrupts need synchronizers. // Those coming from periphery clock need a From 80ed27683e08d9b2a16ec173dd239c0255378301 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 7 Sep 2017 14:33:09 -0700 Subject: [PATCH 21/26] diplomacy: protect against API leakage --- src/main/scala/diplomacy/Nodes.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/scala/diplomacy/Nodes.scala b/src/main/scala/diplomacy/Nodes.scala index 16b655df..c8cbae05 100644 --- a/src/main/scala/diplomacy/Nodes.scala +++ b/src/main/scala/diplomacy/Nodes.scala @@ -97,7 +97,7 @@ case class NodeHandle[DI, UI, BI <: Data, DO, UO, BO <: Data] trait InwardNodeHandle[DI, UI, BI <: Data] { - val inward: InwardNode[DI, UI, BI] + protected[diplomacy] val inward: InwardNode[DI, UI, BI] def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = inward.:=(h)(p, sourceInfo) def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = @@ -115,7 +115,7 @@ case object BIND_STAR extends NodeBinding trait InwardNode[DI, UI, BI <: Data] extends BaseNode with InwardNodeHandle[DI, UI, BI] { - val inward = this + protected[diplomacy] val inward = this protected[diplomacy] val numPI: Range.Inclusive require (!numPI.isEmpty, s"No number of inputs would be acceptable to ${name}${lazyModule.line}") @@ -138,17 +138,17 @@ trait InwardNode[DI, UI, BI <: Data] extends BaseNode with InwardNodeHandle[DI, protected[diplomacy] val iStar: Int protected[diplomacy] val iPortMapping: Seq[(Int, Int)] protected[diplomacy] val iParams: Seq[UI] - val bundleIn: HeterogeneousBag[BI] + protected[diplomacy] val bundleIn: HeterogeneousBag[BI] } trait OutwardNodeHandle[DO, UO, BO <: Data] { - val outward: OutwardNode[DO, UO, BO] + protected[diplomacy] val outward: OutwardNode[DO, UO, BO] } trait OutwardNode[DO, UO, BO <: Data] extends BaseNode with OutwardNodeHandle[DO, UO, BO] { - val outward = this + protected[diplomacy] val outward = this protected[diplomacy] val numPO: Range.Inclusive require (!numPO.isEmpty, s"No number of outputs would be acceptable to ${name}${lazyModule.line}") @@ -171,7 +171,7 @@ trait OutwardNode[DO, UO, BO <: Data] extends BaseNode with OutwardNodeHandle[DO protected[diplomacy] val oStar: Int protected[diplomacy] val oPortMapping: Seq[(Int, Int)] protected[diplomacy] val oParams: Seq[DO] - val bundleOut: HeterogeneousBag[BO] + protected[diplomacy] val bundleOut: HeterogeneousBag[BO] } abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( From bef593c21a9eac6b52370cedd1a3fd6385addcff Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 7 Sep 2017 14:56:09 -0700 Subject: [PATCH 22/26] diplomacy: edges now capture their Parameters --- src/main/scala/diplomacy/Nodes.scala | 31 +++++++++++++++------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/main/scala/diplomacy/Nodes.scala b/src/main/scala/diplomacy/Nodes.scala index c8cbae05..7fc892e8 100644 --- a/src/main/scala/diplomacy/Nodes.scala +++ b/src/main/scala/diplomacy/Nodes.scala @@ -121,16 +121,16 @@ trait InwardNode[DI, UI, BI <: Data] extends BaseNode with InwardNodeHandle[DI, require (!numPI.isEmpty, s"No number of inputs would be acceptable to ${name}${lazyModule.line}") require (numPI.start >= 0, s"${name} accepts a negative number of inputs${lazyModule.line}") - private val accPI = ListBuffer[(Int, OutwardNode[DI, UI, BI], NodeBinding)]() + private val accPI = ListBuffer[(Int, OutwardNode[DI, UI, BI], NodeBinding, Parameters)]() private var iRealized = false protected[diplomacy] def iPushed = accPI.size - protected[diplomacy] def iPush(index: Int, node: OutwardNode[DI, UI, BI], binding: NodeBinding)(implicit sourceInfo: SourceInfo) { + protected[diplomacy] def iPush(index: Int, node: OutwardNode[DI, UI, BI], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo) { val info = sourceLine(sourceInfo, " at ", "") val noIs = numPI.size == 1 && numPI.contains(0) require (!noIs, s"${name}${lazyModule.line} was incorrectly connected as a sink" + info) require (!iRealized, s"${name}${lazyModule.line} was incorrectly connected as a sink after it's .module was used" + info) - accPI += ((index, node, binding)) + accPI += ((index, node, binding, p)) } protected[diplomacy] lazy val iBindings = { iRealized = true; accPI.result() } @@ -154,16 +154,16 @@ trait OutwardNode[DO, UO, BO <: Data] extends BaseNode with OutwardNodeHandle[DO require (!numPO.isEmpty, s"No number of outputs would be acceptable to ${name}${lazyModule.line}") require (numPO.start >= 0, s"${name} accepts a negative number of outputs${lazyModule.line}") - private val accPO = ListBuffer[(Int, InwardNode [DO, UO, BO], NodeBinding)]() + private val accPO = ListBuffer[(Int, InwardNode [DO, UO, BO], NodeBinding, Parameters)]() private var oRealized = false protected[diplomacy] def oPushed = accPO.size - protected[diplomacy] def oPush(index: Int, node: InwardNode [DO, UO, BO], binding: NodeBinding)(implicit sourceInfo: SourceInfo) { + protected[diplomacy] def oPush(index: Int, node: InwardNode [DO, UO, BO], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo) { val info = sourceLine(sourceInfo, " at ", "") val noOs = numPO.size == 1 && numPO.contains(0) require (!noOs, s"${name}${lazyModule.line} was incorrectly connected as a source" + info) require (!oRealized, s"${name}${lazyModule.line} was incorrectly connected as a source after it's .module was used" + info) - accPO += ((index, node, binding)) + accPO += ((index, node, binding, p)) } protected[diplomacy] lazy val oBindings = { oRealized = true; accPO.result() } @@ -186,22 +186,22 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] protected[diplomacy] lazy val (oPortMapping, iPortMapping, oStar, iStar) = { - val oStars = oBindings.filter { case (_,_,b) => b == BIND_STAR }.size - val iStars = iBindings.filter { case (_,_,b) => b == BIND_STAR }.size - val oKnown = oBindings.map { case (_, n, b) => b match { + val oStars = oBindings.filter { case (_,_,b,_) => b == BIND_STAR }.size + val iStars = iBindings.filter { case (_,_,b,_) => b == BIND_STAR }.size + val oKnown = oBindings.map { case (_, n, b, _) => b match { case BIND_ONCE => 1 case BIND_QUERY => n.iStar case BIND_STAR => 0 }}.foldLeft(0)(_+_) - val iKnown = iBindings.map { case (_, n, b) => b match { + val iKnown = iBindings.map { case (_, n, b, _) => b match { case BIND_ONCE => 1 case BIND_QUERY => n.oStar case BIND_STAR => 0 }}.foldLeft(0)(_+_) val (iStar, oStar) = resolveStar(iKnown, oKnown, iStars, oStars) - val oSum = oBindings.map { case (_, n, b) => b match { + val oSum = oBindings.map { case (_, n, b, _) => b match { case BIND_ONCE => 1 case BIND_QUERY => n.iStar case BIND_STAR => oStar }}.scanLeft(0)(_+_) - val iSum = iBindings.map { case (_, n, b) => b match { + val iSum = iBindings.map { case (_, n, b, _) => b match { case BIND_ONCE => 1 case BIND_QUERY => n.oStar case BIND_STAR => iStar }}.scanLeft(0)(_+_) @@ -212,11 +212,11 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( (oSum.init zip oSum.tail, iSum.init zip iSum.tail, oStar, iStar) } - lazy val oPorts = oBindings.flatMap { case (i, n, _) => + lazy val oPorts = oBindings.flatMap { case (i, n, _, _) => val (start, end) = n.iPortMapping(i) (start until end) map { j => (j, n) } } - lazy val iPorts = iBindings.flatMap { case (i, n, _) => + lazy val iPorts = iBindings.flatMap { case (i, n, _, _) => val (start, end) = n.oPortMapping(i) (start until end) map { j => (j, n) } } @@ -240,6 +240,9 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( lazy val externalEdgesOut = if (externalOut) {edgesOut} else { Seq() } lazy val externalEdgesIn = if (externalIn) {edgesIn} else { Seq() } + lazy val paramsOut: Seq[Parameters] = (oPortMapping zip oBindings).flatMap { case ((s, e), b) => Seq.fill(e-s) { b._4 } } + lazy val paramsIn: Seq[Parameters] = (iPortMapping zip iBindings).flatMap { case ((s, e), b) => Seq.fill(e-s) { b._4 } } + val flip = false // needed for blind nodes private def flipO(b: HeterogeneousBag[BO]) = if (flip) b.flip else b private def flipI(b: HeterogeneousBag[BI]) = if (flip) b else b.flip From 06a244f9f94873786a2916e0dfc56644a7f5562f Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 7 Sep 2017 15:03:09 -0700 Subject: [PATCH 23/26] diplomacy: rename {Left,Right}Star to refer to {Source,Sink}Cardinality --- src/main/scala/diplomacy/package.scala | 8 ++++---- src/main/scala/tilelink/Bus.scala | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/scala/diplomacy/package.scala b/src/main/scala/diplomacy/package.scala index 2fd34f4c..90e9ee71 100644 --- a/src/main/scala/diplomacy/package.scala +++ b/src/main/scala/diplomacy/package.scala @@ -22,16 +22,16 @@ package object diplomacy } } - def LeftStar[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { + def SinkCardinality[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { case CardinalityInferenceDirectionKey => CardinalityInferenceDirection.SINK_TO_SOURCE }) - def RightStar[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { + def SourceCardinality[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { case CardinalityInferenceDirectionKey => CardinalityInferenceDirection.SOURCE_TO_SINK }) - def NoStar[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { + def UnaryCardinality[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { case CardinalityInferenceDirectionKey => CardinalityInferenceDirection.NO_INFERENCE }) - def FlipStar[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { + def FlipCardinality[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { case CardinalityInferenceDirectionKey => p(CardinalityInferenceDirectionKey).flip }) def EnableMonitors[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { diff --git a/src/main/scala/tilelink/Bus.scala b/src/main/scala/tilelink/Bus.scala index f46e8c18..0dcb5b7a 100644 --- a/src/main/scala/tilelink/Bus.scala +++ b/src/main/scala/tilelink/Bus.scala @@ -68,7 +68,7 @@ abstract class TLBusWrapper(params: TLBusParams, val busName: String)(implicit p protected def inwardBufNode: TLInwardNode = master_buffer.node protected def bufferChain(depth: Int, name: Option[String] = None): (TLInwardNode, TLOutwardNode) = { - RightStar { implicit p => + SourceCardinality { implicit p => val chain = LazyModule(new TLBufferChain(depth)) name.foreach { n => chain.suggestName(s"${busName}_${n}_TLBufferChain")} (chain.nodeIn, chain.nodeOut) @@ -79,18 +79,18 @@ abstract class TLBusWrapper(params: TLBusParams, val busName: String)(implicit p def bufferToSlaves: TLOutwardNode = outwardBufNode - def toSyncSlaves(name: Option[String] = None, addBuffers: Int = 0): TLOutwardNode = LeftStar { implicit p => + def toSyncSlaves(name: Option[String] = None, addBuffers: Int = 0): TLOutwardNode = SinkCardinality { implicit p => TLBufferChain(addBuffers)(outwardBufNode) } - def toAsyncSlaves(sync: Int = 3, name: Option[String] = None, addBuffers: Int = 0): TLAsyncOutwardNode = LeftStar { implicit p => + def toAsyncSlaves(sync: Int = 3, name: Option[String] = None, addBuffers: Int = 0): TLAsyncOutwardNode = SinkCardinality { implicit p => val source = LazyModule(new TLAsyncCrossingSource(sync)) name.foreach{ n => source.suggestName(s"${busName}_${n}_TLAsyncCrossingSource")} source.node :=? TLBufferChain(addBuffers)(outwardNode) source.node } - def toRationalSlaves(name: Option[String] = None, addBuffers: Int = 0): TLRationalOutwardNode = LeftStar { implicit p => + def toRationalSlaves(name: Option[String] = None, addBuffers: Int = 0): TLRationalOutwardNode = SinkCardinality { implicit p => val source = LazyModule(new TLRationalCrossingSource()) name.foreach{ n => source.suggestName(s"${busName}_${n}_TLRationalCrossingSource")} source.node :=? TLBufferChain(addBuffers)(outwardNode) From e831acba9c5b54294e792783f0964fe8b40f2bdd Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 7 Sep 2017 15:07:08 -0700 Subject: [PATCH 24/26] adapters: support bulk connections --- src/main/scala/amba/ahb/ToTL.scala | 2 +- src/main/scala/amba/axi4/Buffer.scala | 2 +- src/main/scala/amba/axi4/Deinterleaver.scala | 2 +- src/main/scala/amba/axi4/Fragmenter.scala | 2 +- src/main/scala/amba/axi4/IdIndexer.scala | 2 +- src/main/scala/amba/axi4/ToTL.scala | 2 +- src/main/scala/amba/axi4/UserYanker.scala | 2 +- src/main/scala/tilelink/AsyncCrossing.scala | 4 ++-- src/main/scala/tilelink/AtomicAutomata.scala | 2 +- src/main/scala/tilelink/CacheCork.scala | 2 +- src/main/scala/tilelink/Delayer.scala | 2 +- src/main/scala/tilelink/FIFOFixer.scala | 2 +- src/main/scala/tilelink/Fragmenter.scala | 2 +- src/main/scala/tilelink/HintHandler.scala | 2 +- src/main/scala/tilelink/Isolation.scala | 2 +- src/main/scala/tilelink/Map.scala | 2 +- src/main/scala/tilelink/NodeNumberer.scala | 2 +- src/main/scala/tilelink/RationalCrossing.scala | 4 ++-- src/main/scala/tilelink/SourceShrinker.scala | 2 +- src/main/scala/tilelink/ToAHB.scala | 2 +- src/main/scala/tilelink/ToAPB.scala | 2 +- src/main/scala/tilelink/ToAXI4.scala | 2 +- src/main/scala/tilelink/WidthWidget.scala | 2 +- 23 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/main/scala/amba/ahb/ToTL.scala b/src/main/scala/amba/ahb/ToTL.scala index d2aa84e7..d63f8f38 100644 --- a/src/main/scala/amba/ahb/ToTL.scala +++ b/src/main/scala/amba/ahb/ToTL.scala @@ -139,7 +139,7 @@ object AHBToTL { def apply()(x: AHBOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { val tl = LazyModule(new AHBToTL) - tl.node := x + tl.node :=? x tl.node } } diff --git a/src/main/scala/amba/axi4/Buffer.scala b/src/main/scala/amba/axi4/Buffer.scala index c7c5bfa8..3f81fa67 100644 --- a/src/main/scala/amba/axi4/Buffer.scala +++ b/src/main/scala/amba/axi4/Buffer.scala @@ -62,7 +62,7 @@ object AXI4Buffer ar: BufferParams, r: BufferParams)(x: AXI4OutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): AXI4OutwardNode = { val buffer = LazyModule(new AXI4Buffer(aw, w, b, ar, r)) - buffer.node := x + buffer.node :=? x buffer.node } } diff --git a/src/main/scala/amba/axi4/Deinterleaver.scala b/src/main/scala/amba/axi4/Deinterleaver.scala index fc04866f..74948a77 100644 --- a/src/main/scala/amba/axi4/Deinterleaver.scala +++ b/src/main/scala/amba/axi4/Deinterleaver.scala @@ -108,7 +108,7 @@ object AXI4Deinterleaver // applied to the AXI4 source node; y.node := AXI4Deinterleaver()(x.node) def apply(maxReadBytes: Int)(x: AXI4OutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): AXI4OutwardNode = { val deinterleaver = LazyModule(new AXI4Deinterleaver(maxReadBytes)) - deinterleaver.node := x + deinterleaver.node :=? x deinterleaver.node } } diff --git a/src/main/scala/amba/axi4/Fragmenter.scala b/src/main/scala/amba/axi4/Fragmenter.scala index 9282a6a2..f1be60ee 100644 --- a/src/main/scala/amba/axi4/Fragmenter.scala +++ b/src/main/scala/amba/axi4/Fragmenter.scala @@ -208,7 +208,7 @@ object AXI4Fragmenter // applied to the AXI4 source node; y.node := AXI4Fragmenter()(x.node) def apply()(x: AXI4OutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): AXI4OutwardNode = { val fragmenter = LazyModule(new AXI4Fragmenter) - fragmenter.node := x + fragmenter.node :=? x fragmenter.node } } diff --git a/src/main/scala/amba/axi4/IdIndexer.scala b/src/main/scala/amba/axi4/IdIndexer.scala index 5a4ddb34..afb0c028 100644 --- a/src/main/scala/amba/axi4/IdIndexer.scala +++ b/src/main/scala/amba/axi4/IdIndexer.scala @@ -84,7 +84,7 @@ object AXI4IdIndexer // applied to the AXI4 source node; y.node := AXI4IdIndexer(idBits)(x.node) def apply(idBits: Int)(x: AXI4OutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): AXI4OutwardNode = { val indexer = LazyModule(new AXI4IdIndexer(idBits)) - indexer.node := x + indexer.node :=? x indexer.node } } diff --git a/src/main/scala/amba/axi4/ToTL.scala b/src/main/scala/amba/axi4/ToTL.scala index b9801855..54610873 100644 --- a/src/main/scala/amba/axi4/ToTL.scala +++ b/src/main/scala/amba/axi4/ToTL.scala @@ -168,7 +168,7 @@ object AXI4ToTL { def apply()(x: AXI4OutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { val tl = LazyModule(new AXI4ToTL) - tl.node := x + tl.node :=? x tl.node } } diff --git a/src/main/scala/amba/axi4/UserYanker.scala b/src/main/scala/amba/axi4/UserYanker.scala index f0c6efbc..58afdedb 100644 --- a/src/main/scala/amba/axi4/UserYanker.scala +++ b/src/main/scala/amba/axi4/UserYanker.scala @@ -100,7 +100,7 @@ object AXI4UserYanker // applied to the AXI4 source node; y.node := AXI4UserYanker(idBits, maxFlight)(x.node) def apply(capMaxFlight: Option[Int] = None)(x: AXI4OutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): AXI4OutwardNode = { val yanker = LazyModule(new AXI4UserYanker(capMaxFlight)) - yanker.node := x + yanker.node :=? x yanker.node } } diff --git a/src/main/scala/tilelink/AsyncCrossing.scala b/src/main/scala/tilelink/AsyncCrossing.scala index df6214e0..5d8ba48e 100644 --- a/src/main/scala/tilelink/AsyncCrossing.scala +++ b/src/main/scala/tilelink/AsyncCrossing.scala @@ -80,7 +80,7 @@ object TLAsyncCrossingSource // applied to the TL source node; y.node := TLAsyncCrossingSource()(x.node) def apply(sync: Int = 3)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLAsyncOutwardNode = { val source = LazyModule(new TLAsyncCrossingSource(sync)) - source.node := x + source.node :=? x source.node } } @@ -90,7 +90,7 @@ object TLAsyncCrossingSink // applied to the TL source node; y.node := TLAsyncCrossingSink()(x.node) def apply(depth: Int = 8, sync: Int = 3)(x: TLAsyncOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { val sink = LazyModule(new TLAsyncCrossingSink(depth, sync)) - sink.node := x + sink.node :=? x sink.node } } diff --git a/src/main/scala/tilelink/AtomicAutomata.scala b/src/main/scala/tilelink/AtomicAutomata.scala index 201f0569..293c5127 100644 --- a/src/main/scala/tilelink/AtomicAutomata.scala +++ b/src/main/scala/tilelink/AtomicAutomata.scala @@ -265,7 +265,7 @@ object TLAtomicAutomata // applied to the TL source node; y.node := TLAtomicAutomata(x.node) def apply(logical: Boolean = true, arithmetic: Boolean = true, concurrency: Int = 1, passthrough: Boolean = true)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { val atomics = LazyModule(new TLAtomicAutomata(logical, arithmetic, concurrency, passthrough)) - atomics.node := x + atomics.node :=? x atomics.node } diff --git a/src/main/scala/tilelink/CacheCork.scala b/src/main/scala/tilelink/CacheCork.scala index 50156018..29f18dbc 100644 --- a/src/main/scala/tilelink/CacheCork.scala +++ b/src/main/scala/tilelink/CacheCork.scala @@ -131,7 +131,7 @@ object TLCacheCork // applied to the TL source node; y.node := TLCacheCork()(x.node) def apply(unsafe: Boolean = false)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { val cork = LazyModule(new TLCacheCork(unsafe)) - cork.node := x + cork.node :=? x cork.node } } diff --git a/src/main/scala/tilelink/Delayer.scala b/src/main/scala/tilelink/Delayer.scala index 4f0e4aad..6bb69413 100644 --- a/src/main/scala/tilelink/Delayer.scala +++ b/src/main/scala/tilelink/Delayer.scala @@ -81,7 +81,7 @@ object TLDelayer // applied to the TL source node; y.node := TLDelayer(0.01)(x.node) def apply(q: Double)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { val delayer = LazyModule(new TLDelayer(q)) - delayer.node := x + delayer.node :=? x delayer.node } } diff --git a/src/main/scala/tilelink/FIFOFixer.scala b/src/main/scala/tilelink/FIFOFixer.scala index f44746b6..e647b986 100644 --- a/src/main/scala/tilelink/FIFOFixer.scala +++ b/src/main/scala/tilelink/FIFOFixer.scala @@ -122,7 +122,7 @@ object TLFIFOFixer // applied to the TL source node; y.node := TLFIFOFixer()(x.node) def apply(policy: Policy = all)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { val fixer = LazyModule(new TLFIFOFixer(policy)) - fixer.node := x + fixer.node :=? x fixer.node } } diff --git a/src/main/scala/tilelink/Fragmenter.scala b/src/main/scala/tilelink/Fragmenter.scala index 15030e69..1aafe1b0 100644 --- a/src/main/scala/tilelink/Fragmenter.scala +++ b/src/main/scala/tilelink/Fragmenter.scala @@ -292,7 +292,7 @@ object TLFragmenter // applied to the TL source node; y.node := TLFragmenter(x.node, 256, 4) def apply(minSize: Int, maxSize: Int, alwaysMin: Boolean = false, earlyAck: Boolean = false)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { val fragmenter = LazyModule(new TLFragmenter(minSize, maxSize, alwaysMin, earlyAck)) - fragmenter.node := x + fragmenter.node :=? x fragmenter.node } } diff --git a/src/main/scala/tilelink/HintHandler.scala b/src/main/scala/tilelink/HintHandler.scala index 24dc274c..40df8ed2 100644 --- a/src/main/scala/tilelink/HintHandler.scala +++ b/src/main/scala/tilelink/HintHandler.scala @@ -100,7 +100,7 @@ object TLHintHandler // applied to the TL source node; y.node := TLHintHandler(x.node) def apply(supportManagers: Boolean = true, supportClients: Boolean = false, passthrough: Boolean = true)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { val hints = LazyModule(new TLHintHandler(supportManagers, supportClients, passthrough)) - hints.node := x + hints.node :=? x hints.node } } diff --git a/src/main/scala/tilelink/Isolation.scala b/src/main/scala/tilelink/Isolation.scala index 78993586..f437e867 100644 --- a/src/main/scala/tilelink/Isolation.scala +++ b/src/main/scala/tilelink/Isolation.scala @@ -79,7 +79,7 @@ object TLIsolation // **** WARNING: the isolation functions must bring the values to 0 **** def apply(fOut: (Bool, UInt) => UInt, fIn: (Bool, UInt) => UInt)(x: TLAsyncOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): (TLAsyncOutwardNode, () => (Bool, Bool)) = { val iso = LazyModule(new TLIsolation(fOut, fIn)) - iso.node := x + iso.node :=? x (iso.node, () => (iso.module.io.iso_out, iso.module.io.iso_in)) } } diff --git a/src/main/scala/tilelink/Map.scala b/src/main/scala/tilelink/Map.scala index 95fb2246..05c17185 100644 --- a/src/main/scala/tilelink/Map.scala +++ b/src/main/scala/tilelink/Map.scala @@ -48,7 +48,7 @@ object TLMap // applied to the TL source node; y.node := TLMap(fn)(x.node) def apply(fn: AddressSet => BigInt)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { val map = LazyModule(new TLMap(fn)) - map.node := x + map.node :=? x map.node } } diff --git a/src/main/scala/tilelink/NodeNumberer.scala b/src/main/scala/tilelink/NodeNumberer.scala index 882350d8..1f7fa6f3 100644 --- a/src/main/scala/tilelink/NodeNumberer.scala +++ b/src/main/scala/tilelink/NodeNumberer.scala @@ -67,7 +67,7 @@ object TLNodeNumberer // applied to the TL source node; y.node := TLBuffer(x.node) def apply(nodeAddressOffset: Option[Int] = None)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { val numberer = LazyModule(new TLNodeNumberer(nodeAddressOffset)) - numberer.node := x + numberer.node :=? x numberer.node } } diff --git a/src/main/scala/tilelink/RationalCrossing.scala b/src/main/scala/tilelink/RationalCrossing.scala index 5603c0aa..5283b30d 100644 --- a/src/main/scala/tilelink/RationalCrossing.scala +++ b/src/main/scala/tilelink/RationalCrossing.scala @@ -92,7 +92,7 @@ object TLRationalCrossingSource // applied to the TL source node; y.node := TLRationalCrossingSource()(x.node) def apply()(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLRationalOutwardNode = { val source = LazyModule(new TLRationalCrossingSource) - source.node := x + source.node :=? x source.node } } @@ -102,7 +102,7 @@ object TLRationalCrossingSink // applied to the TL source node; y.node := TLRationalCrossingSink()(x.node) def apply(direction: RationalDirection = Symmetric)(x: TLRationalOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { val sink = LazyModule(new TLRationalCrossingSink(direction)) - sink.node := x + sink.node :=? x sink.node } } diff --git a/src/main/scala/tilelink/SourceShrinker.scala b/src/main/scala/tilelink/SourceShrinker.scala index 3a1e9a30..5f7aa3d8 100644 --- a/src/main/scala/tilelink/SourceShrinker.scala +++ b/src/main/scala/tilelink/SourceShrinker.scala @@ -83,7 +83,7 @@ object TLSourceShrinker // applied to the TL source node; y.node := TLSourceShrinker(n)(x.node) def apply(maxInFlight: Int)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { val shrinker = LazyModule(new TLSourceShrinker(maxInFlight)) - shrinker.node := x + shrinker.node :=? x shrinker.node } } diff --git a/src/main/scala/tilelink/ToAHB.scala b/src/main/scala/tilelink/ToAHB.scala index c1e504f8..cadae46e 100644 --- a/src/main/scala/tilelink/ToAHB.scala +++ b/src/main/scala/tilelink/ToAHB.scala @@ -195,7 +195,7 @@ object TLToAHB // applied to the TL source node; y.node := TLToAHB()(x.node) def apply(aFlow: Boolean = true)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): AHBOutwardNode = { val ahb = LazyModule(new TLToAHB(aFlow)) - ahb.node := x + ahb.node :=? x ahb.node } } diff --git a/src/main/scala/tilelink/ToAPB.scala b/src/main/scala/tilelink/ToAPB.scala index 7d9f7c3d..2d0bf2ae 100644 --- a/src/main/scala/tilelink/ToAPB.scala +++ b/src/main/scala/tilelink/ToAPB.scala @@ -94,7 +94,7 @@ object TLToAPB // applied to the TL source node; y.node := TLToAPB()(x.node) def apply(aFlow: Boolean = true)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): APBOutwardNode = { val apb = LazyModule(new TLToAPB(aFlow)) - apb.node := x + apb.node :=? x apb.node } } diff --git a/src/main/scala/tilelink/ToAXI4.scala b/src/main/scala/tilelink/ToAXI4.scala index e4f39419..3d9d4784 100644 --- a/src/main/scala/tilelink/ToAXI4.scala +++ b/src/main/scala/tilelink/ToAXI4.scala @@ -223,7 +223,7 @@ object TLToAXI4 // applied to the TL source node; y.node := TLToAXI4(beatBytes)(x.node) def apply(beatBytes: Int, combinational: Boolean = true, adapterName: Option[String] = None, stripBits: Int = 0)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): AXI4OutwardNode = { val axi4 = LazyModule(new TLToAXI4(beatBytes, combinational, adapterName, stripBits)) - axi4.node := x + axi4.node :=? x axi4.node } diff --git a/src/main/scala/tilelink/WidthWidget.scala b/src/main/scala/tilelink/WidthWidget.scala index b6c4fa9a..6bc5e37c 100644 --- a/src/main/scala/tilelink/WidthWidget.scala +++ b/src/main/scala/tilelink/WidthWidget.scala @@ -200,7 +200,7 @@ object TLWidthWidget // applied to the TL source node; y.node := WidthWidget(x.node, 16) def apply(innerBeatBytes: Int)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { val widget = LazyModule(new TLWidthWidget(innerBeatBytes)) - widget.node := x + widget.node :=? x widget.node } } From 6879f5bfb1952df9733b3da3706eee2cab51e27e Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 7 Sep 2017 15:42:40 -0700 Subject: [PATCH 25/26] tilelink: Xbar now allows for fanout control --- src/main/scala/diplomacy/Parameters.scala | 11 +++++++ src/main/scala/tilelink/Xbar.scala | 38 ++++++++++++++++++----- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/main/scala/diplomacy/Parameters.scala b/src/main/scala/diplomacy/Parameters.scala index f7273e6a..4133b52f 100644 --- a/src/main/scala/diplomacy/Parameters.scala +++ b/src/main/scala/diplomacy/Parameters.scala @@ -293,3 +293,14 @@ object BufferParams val flow = BufferParams(1, true, false) val pipe = BufferParams(1, false, true) } + +case class TriStateValue(value: Boolean, set: Boolean) +{ + def update(orig: Boolean) = if (set) value else orig +} + +object TriStateValue +{ + implicit def apply(value: Boolean): TriStateValue = TriStateValue(value, true) + def unset = TriStateValue(false, false) +} diff --git a/src/main/scala/tilelink/Xbar.scala b/src/main/scala/tilelink/Xbar.scala index eb6d00dd..26c91801 100644 --- a/src/main/scala/tilelink/Xbar.scala +++ b/src/main/scala/tilelink/Xbar.scala @@ -3,9 +3,31 @@ package freechips.rocketchip.tilelink import Chisel._ -import freechips.rocketchip.config.Parameters +import freechips.rocketchip.config._ import freechips.rocketchip.diplomacy._ +// Trades off slave port proximity against routing resource cost +object ForceFanout +{ + def apply[T]( + a: TriStateValue = TriStateValue.unset, + b: TriStateValue = TriStateValue.unset, + c: TriStateValue = TriStateValue.unset, + d: TriStateValue = TriStateValue.unset, + e: TriStateValue = TriStateValue.unset)(body: Parameters => T)(implicit p: Parameters) = + { + body(p.alterPartial { + case ForceFanoutKey => p(ForceFanoutKey) match { + case ForceFanoutParams(pa, pb, pc, pd, pe) => + ForceFanoutParams(a.update(pa), b.update(pb), c.update(pc), d.update(pd), e.update(pe)) + } + }) + } +} + +private case class ForceFanoutParams(a: Boolean, b: Boolean, c: Boolean, d: Boolean, e: Boolean) +private case object ForceFanoutKey extends Field(ForceFanoutParams(false, false, false, false, false)) + class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parameters) extends LazyModule { val node = TLNexusNode( @@ -157,11 +179,11 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parame def filter[T](data: Seq[T], mask: Seq[Boolean]) = (data zip mask).filter(_._2).map(_._1) // Fanout the input sources to the output sinks - val portsAOI = transpose((in zip requestAIO) map { case (i, r) => TLXbar.fanout(i.a, r) }) - val portsBIO = transpose((out zip requestBOI) map { case (o, r) => TLXbar.fanout(o.b, r) }) - val portsCOI = transpose((in zip requestCIO) map { case (i, r) => TLXbar.fanout(i.c, r) }) - val portsDIO = transpose((out zip requestDOI) map { case (o, r) => TLXbar.fanout(o.d, r) }) - val portsEOI = transpose((in zip requestEIO) map { case (i, r) => TLXbar.fanout(i.e, r) }) + val portsAOI = transpose((in zip requestAIO) map { case (i, r) => TLXbar.fanout(i.a, r, node.paramsOut.map(_(ForceFanoutKey).a)) }) + val portsBIO = transpose((out zip requestBOI) map { case (o, r) => TLXbar.fanout(o.b, r, node.paramsIn .map(_(ForceFanoutKey).b)) }) + val portsCOI = transpose((in zip requestCIO) map { case (i, r) => TLXbar.fanout(i.c, r, node.paramsOut.map(_(ForceFanoutKey).c)) }) + val portsDIO = transpose((out zip requestDOI) map { case (o, r) => TLXbar.fanout(o.d, r, node.paramsIn .map(_(ForceFanoutKey).d)) }) + val portsEOI = transpose((in zip requestEIO) map { case (i, r) => TLXbar.fanout(i.e, r, node.paramsOut.map(_(ForceFanoutKey).e)) }) // Arbitrate amongst the sources for (o <- 0 until out.size) { @@ -216,10 +238,10 @@ object TLXbar } // Replicate an input port to each output port - def fanout[T <: TLChannel](input: DecoupledIO[T], select: Seq[Bool]) = { + def fanout[T <: TLChannel](input: DecoupledIO[T], select: Seq[Bool], force: Seq[Boolean] = Nil) = { val filtered = Wire(Vec(select.size, input)) for (i <- 0 until select.size) { - filtered(i).bits := IdentityModule(input.bits) // force fanout of wires + filtered(i).bits := (if (force.lift(i).getOrElse(false)) IdentityModule(input.bits) else input.bits) filtered(i).valid := input.valid && select(i) } input.ready := Mux1H(select, filtered.map(_.ready)) From e723a3f42bc47e53c41f2ae1ad22c9d68d9c8427 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 7 Sep 2017 16:01:42 -0700 Subject: [PATCH 26/26] MemoryBus: fanout the A for performance --- src/main/scala/coreplex/MemoryBus.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/coreplex/MemoryBus.scala b/src/main/scala/coreplex/MemoryBus.scala index 277b54c3..336bc529 100644 --- a/src/main/scala/coreplex/MemoryBus.scala +++ b/src/main/scala/coreplex/MemoryBus.scala @@ -67,7 +67,7 @@ trait HasMemoryBus extends HasSystemBus with HasPeripheryBus with HasInterruptBu val mbus = new MemoryBus(mbusParams) for (bank <- 0 until nBanksPerChannel) { val offset = (bank * nMemoryChannels) + channel - in := sbus.toMemoryBus + ForceFanout(a = true) { implicit p => in := sbus.toMemoryBus } mbus.fromCoherenceManager := TLFilter(TLFilter.Mmask(AddressSet(offset * blockBytes, mask)))(out) } mbus