1
0

diplomacy: place Monitors inside LazyModules sinks

We used to place Monitors at the point of the ':='.
This was problematic because the clock domain might be wrong.
Thus, we needed to shove Monitors a lot.

Furthermore, now that we have cross-module ':=', you might not even
have access to the wires at the point where ':=' is invoked.
This commit is contained in:
Wesley W. Terpstra
2017-09-22 16:55:12 -07:00
parent cfb7f13408
commit bc225a4e82
7 changed files with 41 additions and 105 deletions

View File

@ -94,9 +94,9 @@ class TLAsyncCrossing(depth: Int = 8, sync: Int = 3)(implicit p: Parameters) ext
val source = LazyModule(new TLAsyncCrossingSource(sync))
val sink = LazyModule(new TLAsyncCrossingSink(depth, sync))
val _ = (sink.node := source.node) // no monitor
val in = (source.node := nodeIn)
val out = (nodeOut := sink.node)
sink.node := source.node
source.node := nodeIn
nodeOut := sink.node
lazy val module = new LazyModuleImp(this) {
val io = IO(new Bundle {
@ -108,17 +108,8 @@ class TLAsyncCrossing(depth: Int = 8, sync: Int = 3)(implicit p: Parameters) ext
source.module.clock := io.in_clock
source.module.reset := io.in_reset
in.foreach { lm =>
lm.module.clock := io.in_clock
lm.module.reset := io.in_reset
}
sink.module.clock := io.out_clock
sink.module.reset := io.out_reset
out.foreach { lm =>
lm.module.clock := io.out_clock
lm.module.reset := io.out_reset
}
}
}
@ -133,7 +124,7 @@ class TLRAMAsyncCrossing(txns: Int)(implicit p: Parameters) extends LazyModule {
model.node := fuzz.node
cross.node := TLFragmenter(4, 256)(TLDelayer(0.1)(model.node))
val monitor = (ram.node := cross.node)
ram.node := cross.node
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
@ -147,12 +138,6 @@ class TLRAMAsyncCrossing(txns: Int)(implicit p: Parameters) extends LazyModule {
cross.module.io.in_reset := reset
cross.module.io.out_clock := clocks.io.clock_out
cross.module.io.out_reset := reset
// Push the Monitor into the right clock domain
monitor.foreach { m =>
m.module.clock := clocks.io.clock_out
m.module.reset := reset
}
}
}

View File

@ -240,7 +240,7 @@ class TLFuzzRAM(txns: Int)(implicit p: Parameters) extends LazyModule
ram2.node := TLFragmenter(16, 256)(xbar2.node)
xbar.node := TLWidthWidget(16)(TLHintHandler()(xbar2.node))
cross.node := TLFragmenter(4, 256)(TLBuffer()(xbar.node))
val monitor = (ram.node := cross.node)
ram.node := cross.node
gpio.node := TLFragmenter(4, 32)(TLBuffer()(xbar.node))
lazy val module = new LazyModuleImp(this) with UnitTestModule {
@ -255,12 +255,6 @@ class TLFuzzRAM(txns: Int)(implicit p: Parameters) extends LazyModule
cross.module.io.in_reset := reset
cross.module.io.out_clock := clocks.io.clock_out
cross.module.io.out_reset := reset
// Push the Monitor into the right clock domain
monitor.foreach { m =>
m.module.clock := clocks.io.clock_out
m.module.reset := reset
}
}
}

View File

@ -8,26 +8,22 @@ import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.util.{HeterogeneousBag, PlusArg}
case class TLMonitorArgs(edge: () => Seq[TLEdge], sourceInfo: SourceInfo, p: Parameters)
case class TLMonitorArgs(edge: TLEdge)
abstract class TLMonitorBase(args: TLMonitorArgs) extends MonitorBase()(args.sourceInfo, args.p)
abstract class TLMonitorBase(args: TLMonitorArgs) extends Module
{
def legalize(bundle: TLBundleSnoop, edge: TLEdge, reset: Bool): Unit
lazy val module = new LazyModuleImp(this) {
val edges = args.edge()
val io = IO(new Bundle {
val in = HeterogeneousBag(edges.map(p => new TLBundleSnoop(p.bundle))).flip
})
(edges zip io.in).foreach { case (e, in) => legalize(in, e, reset) }
val io = new Bundle {
val in = new TLBundleSnoop(args.edge.bundle).flip
}
def legalize(bundle: TLBundleSnoop, edge: TLEdge, reset: Bool): Unit
legalize(io.in, args.edge, reset)
}
class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args)
{
def extra = {
sourceInfo match {
args.edge.sourceInfo match {
case SourceLine(filename, line, col) => s" (connected at $filename:$line:$col)"
case _ => ""
}

View File

@ -10,7 +10,6 @@ import freechips.rocketchip.util.RationalDirection
import scala.collection.mutable.ListBuffer
case object TLMonitorBuilder extends Field[TLMonitorArgs => TLMonitorBase](args => new TLMonitor(args))
case object TLCombinationalCheck extends Field[Boolean](false)
object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLEdgeIn, TLBundle]
{
@ -24,25 +23,9 @@ object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TL
override def labelI(ei: TLEdgeIn) = (ei.manager.beatBytes * 8).toString
override def labelO(eo: TLEdgeOut) = (eo.manager.beatBytes * 8).toString
override def connect(edges: () => Seq[TLEdgeIn], bundles: () => Seq[(TLBundle, TLBundle)], enableMonitoring: Boolean)
(implicit p: Parameters, sourceInfo: SourceInfo): (Option[TLMonitorBase], () => Unit) = {
val monitor = if (enableMonitoring) Some(LazyModule(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) } }
eval.foreach { case (bi, bo) =>
bi <> bo
if (p(TLCombinationalCheck)) {
// It is forbidden for valid to depend on ready in TL2
// If someone did that, then this will create a detectable combinational loop
bo.a.ready := bi.a.ready && bo.a.valid
bi.b.ready := bo.b.ready && bi.b.valid
bo.c.ready := bi.c.ready && bo.c.valid
bi.d.ready := bo.d.ready && bi.d.valid
bo.e.ready := bi.e.ready && bo.e.valid
}
}
})
override def monitor(bundle: TLBundle, edge: TLEdgeIn) {
val monitor = Module(edge.params(TLMonitorBuilder)(TLMonitorArgs(edge)))
monitor.io.in := TLBundleSnoop(bundle, bundle)
}
override def mixO(pd: TLClientPortParameters, node: OutwardNode[TLClientPortParameters, TLManagerPortParameters, TLBundle]): TLClientPortParameters =

View File

@ -106,9 +106,9 @@ class TLRationalCrossing(direction: RationalDirection = Symmetric)(implicit p: P
val source = LazyModule(new TLRationalCrossingSource)
val sink = LazyModule(new TLRationalCrossingSink(direction))
val _ = (sink.node := source.node) // no monitor
val in = (source.node := nodeIn)
val out = (nodeOut := sink.node)
sink.node := source.node
source.node := nodeIn
nodeOut := sink.node
lazy val module = new LazyModuleImp(this) {
val io = IO(new Bundle {
@ -120,17 +120,8 @@ class TLRationalCrossing(direction: RationalDirection = Symmetric)(implicit p: P
source.module.clock := io.in_clock
source.module.reset := io.in_reset
in.foreach { lm =>
lm.module.clock := io.in_clock
lm.module.reset := io.in_reset
}
sink.module.clock := io.out_clock
sink.module.reset := io.out_reset
out.foreach { lm =>
lm.module.clock := io.out_clock
lm.module.reset := io.out_reset
}
}
}