TLRational: test all corners
In order to ensure that verilator is happy, we launch both clocks from a clock divider. Sadly, it does not follow the spec wrt. derived clocks. See the verilator manual section on "Generated Clocks".
This commit is contained in:
parent
91d1880dbf
commit
5045696f92
@ -149,35 +149,73 @@ class TLRationalCrossing(direction: RationalDirection = Symmetric)(implicit p: P
|
|||||||
/** Synthesizeable unit tests */
|
/** Synthesizeable unit tests */
|
||||||
import unittest._
|
import unittest._
|
||||||
|
|
||||||
class TLRAMRationalCrossing(implicit p: Parameters) extends LazyModule {
|
class TLRAMRationalCrossingSource(implicit p: Parameters) extends LazyModule {
|
||||||
|
val node = TLRationalOutputNode()
|
||||||
val fuzz = LazyModule(new TLFuzzer(5000))
|
val fuzz = LazyModule(new TLFuzzer(5000))
|
||||||
val model = LazyModule(new TLRAMModel)
|
val model = LazyModule(new TLRAMModel)
|
||||||
val cross = LazyModule(new TLRationalCrossing(FastToSlow))
|
|
||||||
val delay = LazyModule(new TLDelayer(0.25))
|
|
||||||
val ram = LazyModule(new TLRAM(AddressSet(0x0, 0x3ff)))
|
|
||||||
|
|
||||||
model.node := fuzz.node
|
model.node := fuzz.node
|
||||||
cross.node := TLDelayer(0.25)(TLFragmenter(4, 256)(model.node))
|
node := TLRationalCrossingSource()(TLDelayer(0.25)(model.node))
|
||||||
val monitor1 = (delay.node := cross.node)
|
|
||||||
val monitor2 = (ram.node := delay.node)
|
lazy val module = new LazyModuleImp(this) {
|
||||||
val monitors = monitor1.toList ++ monitor2.toList
|
val io = new Bundle {
|
||||||
|
val finished = Bool(OUTPUT)
|
||||||
|
val out = node.bundleOut
|
||||||
|
}
|
||||||
|
io.finished := fuzz.module.io.finished
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TLRAMRationalCrossingSink(direction: RationalDirection)(implicit p: Parameters) extends LazyModule {
|
||||||
|
val node = TLRationalInputNode()
|
||||||
|
val ram = LazyModule(new TLRAM(AddressSet(0x0, 0x3ff)))
|
||||||
|
|
||||||
|
ram.node := TLFragmenter(4, 256)(TLDelayer(0.25)(TLRationalCrossingSink(direction)(node)))
|
||||||
|
|
||||||
|
lazy val module = new LazyModuleImp(this) {
|
||||||
|
val io = new Bundle {
|
||||||
|
val in = node.bundleIn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TLRAMRationalCrossing(implicit p: Parameters) extends LazyModule {
|
||||||
|
val sym_fast_source = LazyModule(new TLRAMRationalCrossingSource)
|
||||||
|
val sym_slow_sink = LazyModule(new TLRAMRationalCrossingSink(Symmetric))
|
||||||
|
sym_slow_sink.node := sym_fast_source.node
|
||||||
|
|
||||||
|
val sym_slow_source = LazyModule(new TLRAMRationalCrossingSource)
|
||||||
|
val sym_fast_sink = LazyModule(new TLRAMRationalCrossingSink(Symmetric))
|
||||||
|
sym_fast_sink.node := sym_slow_source.node
|
||||||
|
|
||||||
|
val fix_fast_source = LazyModule(new TLRAMRationalCrossingSource)
|
||||||
|
val fix_slow_sink = LazyModule(new TLRAMRationalCrossingSink(FastToSlow))
|
||||||
|
fix_slow_sink.node := fix_fast_source.node
|
||||||
|
|
||||||
|
val fix_slow_source = LazyModule(new TLRAMRationalCrossingSource)
|
||||||
|
val fix_fast_sink = LazyModule(new TLRAMRationalCrossingSink(SlowToFast))
|
||||||
|
fix_fast_sink.node := fix_slow_source.node
|
||||||
|
|
||||||
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
|
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
|
||||||
io.finished := fuzz.module.io.finished
|
io.finished :=
|
||||||
|
sym_fast_source.module.io.finished &&
|
||||||
|
sym_slow_source.module.io.finished &&
|
||||||
|
fix_fast_source.module.io.finished &&
|
||||||
|
fix_slow_source.module.io.finished
|
||||||
|
|
||||||
// Shove the RAM into another clock domain
|
// Generate faster clock (still divided so verilator approves)
|
||||||
val clocks = Module(new util.Pow2ClockDivider(2))
|
val fast = Module(new util.Pow2ClockDivider(1))
|
||||||
ram.module.clock := clocks.io.clock_out
|
sym_fast_source.module.clock := fast.io.clock_out
|
||||||
delay.module.clock := clocks.io.clock_out
|
sym_fast_sink .module.clock := fast.io.clock_out
|
||||||
|
fix_fast_source.module.clock := fast.io.clock_out
|
||||||
|
fix_fast_sink .module.clock := fast.io.clock_out
|
||||||
|
|
||||||
// ... and safely cross TL2 into it
|
// Generate slower clock
|
||||||
cross.module.io.in_clock := clock
|
val slow = Module(new util.Pow2ClockDivider(2))
|
||||||
cross.module.io.in_reset := reset
|
sym_slow_source.module.clock := slow.io.clock_out
|
||||||
cross.module.io.out_clock := clocks.io.clock_out
|
sym_slow_sink .module.clock := slow.io.clock_out
|
||||||
cross.module.io.out_reset := reset
|
fix_slow_source.module.clock := slow.io.clock_out
|
||||||
|
fix_slow_sink .module.clock := slow.io.clock_out
|
||||||
// Push the Monitors into the right clock domain
|
|
||||||
monitors.foreach { m => m.module.clock := clocks.io.clock_out }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user