1
0

tilelink2 Crossing: cut the crossing between clock domains

This commit is contained in:
Wesley W. Terpstra 2016-09-29 17:32:18 -07:00
parent 20f42a8762
commit 6d8c965f04
2 changed files with 87 additions and 19 deletions

View File

@ -6,33 +6,63 @@ import Chisel._
import chisel3.internal.sourceinfo.SourceInfo import chisel3.internal.sourceinfo.SourceInfo
import util._ import util._
class TLAsyncCrossing(depth: Int = 8, sync: Int = 3) extends LazyModule class TLAsyncCrossingSource(sync: Int = 3) extends LazyModule
{ {
val node = TLIdentityNode() val node = TLAsyncSourceNode()
lazy val module = new LazyModuleImp(this) { lazy val module = new LazyModuleImp(this) {
val io = new Bundle { val io = new Bundle {
val in = node.bundleIn val in = node.bundleIn
val in_clock = Clock(INPUT)
val in_reset = Bool(INPUT)
val out = node.bundleOut val out = node.bundleOut
val out_clock = Clock(INPUT)
val out_reset = Bool(INPUT)
} }
// Transfer all TL2 bundles from/to the same domains
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
out.a <> AsyncIrrevocableCrossing(io.in_clock, io.in_reset, in.a, io.out_clock, io.out_reset, depth, sync) val bce = edgeIn.manager.anySupportAcquire && edgeIn.client.anySupportProbe
in.d <> AsyncIrrevocableCrossing(io.out_clock, io.out_reset, out.d, io.in_clock, io.in_reset, depth, sync) val depth = edgeOut.manager.depth
if (edgeOut.manager.anySupportAcquire && edgeOut.client.anySupportProbe) { out.a := ToAsyncBundle(in.a, depth, sync)
in.b <> AsyncIrrevocableCrossing(io.out_clock, io.out_reset, out.b, io.in_clock, io.in_reset, depth, sync) in.d := FromAsyncBundle(out.d, sync)
out.c <> AsyncIrrevocableCrossing(io.in_clock, io.in_reset, in.c, io.out_clock, io.out_reset, depth, sync)
out.e <> AsyncIrrevocableCrossing(io.in_clock, io.in_reset, in.e, io.out_clock, io.out_reset, depth, sync) if (bce) {
in.b := FromAsyncBundle(out.b, sync)
out.c := ToAsyncBundle(in.c, depth, sync)
out.e := ToAsyncBundle(in.e, depth, sync)
} else { } else {
in.b.valid := Bool(false) in.b.valid := Bool(false)
in.c.ready := Bool(true) in.c.ready := Bool(true)
in.e.ready := Bool(true) in.e.ready := Bool(true)
out.b.ridx := UInt(0)
out.c.widx := UInt(0)
out.e.widx := UInt(0)
}
}
}
}
class TLAsyncCrossingSink(depth: Int = 8, sync: Int = 3) extends LazyModule
{
val node = TLAsyncSinkNode(depth)
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
val bce = edgeOut.manager.anySupportAcquire && edgeOut.client.anySupportProbe
out.a := FromAsyncBundle(in.a, sync)
in.d := ToAsyncBundle(out.d, depth, sync)
if (bce) {
in.b := ToAsyncBundle(out.b, depth, sync)
out.c := FromAsyncBundle(in.c, sync)
out.e := FromAsyncBundle(in.e, sync)
} else {
in.b.widx := UInt(0)
in.c.ridx := UInt(0)
in.e.ridx := UInt(0)
out.b.ready := Bool(true) out.b.ready := Bool(true)
out.c.valid := Bool(false) out.c.valid := Bool(false)
out.e.valid := Bool(false) out.e.valid := Bool(false)
@ -41,6 +71,44 @@ class TLAsyncCrossing(depth: Int = 8, sync: Int = 3) extends LazyModule
} }
} }
class TLAsyncCrossing(depth: Int = 8, sync: Int = 3) extends LazyModule
{
val nodeIn = TLInputNode()
val nodeOut = TLOutputNode()
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)
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = nodeIn.bundleIn
val in_clock = Clock(INPUT)
val in_reset = Bool(INPUT)
val out = nodeOut.bundleOut
val out_clock = Clock(INPUT)
val out_reset = Bool(INPUT)
}
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
}
}
}
/** Synthesizeable unit tests */ /** Synthesizeable unit tests */
import unittest._ import unittest._
@ -51,8 +119,8 @@ class TLRAMCrossing extends LazyModule {
val cross = LazyModule(new TLAsyncCrossing) val cross = LazyModule(new TLAsyncCrossing)
model.node := fuzz.node model.node := fuzz.node
cross.node := TLFragmenter(4, 256)(model.node) cross.nodeIn := TLFragmenter(4, 256)(model.node)
val monitor = (ram.node := cross.node) val monitor = (ram.node := cross.nodeOut)
lazy val module = new LazyModuleImp(this) with HasUnitTestIO { lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
io.finished := fuzz.module.io.finished io.finished := fuzz.module.io.finished

View File

@ -224,8 +224,8 @@ class TLFuzzRAM extends LazyModule
xbar2.node := TLAtomicAutomata()(model.node) xbar2.node := TLAtomicAutomata()(model.node)
ram2.node := TLFragmenter(16, 256)(xbar2.node) ram2.node := TLFragmenter(16, 256)(xbar2.node)
xbar.node := TLWidthWidget(16)(TLHintHandler()(xbar2.node)) xbar.node := TLWidthWidget(16)(TLHintHandler()(xbar2.node))
cross.node := TLFragmenter(4, 256)(TLBuffer()(xbar.node)) cross.nodeIn := TLFragmenter(4, 256)(TLBuffer()(xbar.node))
val monitor = (ram.node := cross.node) val monitor = (ram.node := cross.nodeOut)
gpio.node := TLFragmenter(4, 32)(TLBuffer()(xbar.node)) gpio.node := TLFragmenter(4, 32)(TLBuffer()(xbar.node))
lazy val module = new LazyModuleImp(this) with HasUnitTestIO { lazy val module = new LazyModuleImp(this) with HasUnitTestIO {