From ecdfb528c5d8491ff5a645b33d1204d880ddcdef Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 7 Sep 2016 13:55:22 -0700 Subject: [PATCH] crossing: refactor AsyncDecoupled to provide AsyncDecoupledCrossing with no clock domain --- src/main/scala/junctions/crossing.scala | 86 ++++++++----------- src/main/scala/junctions/nasti.scala | 45 +++++----- .../scala/rocketchip/DebugTransport.scala | 27 +++--- src/main/scala/uncore/devices/Debug.scala | 30 ++++--- 4 files changed, 91 insertions(+), 97 deletions(-) diff --git a/src/main/scala/junctions/crossing.scala b/src/main/scala/junctions/crossing.scala index 0f71362e..802504c0 100644 --- a/src/main/scala/junctions/crossing.scala +++ b/src/main/scala/junctions/crossing.scala @@ -1,13 +1,13 @@ package junctions import Chisel._ -class Crossing[T <: Data](gen: T, enq_sync: Boolean, deq_sync: Boolean) extends Bundle { +class Crossing[T <: Data](gen: T) extends Bundle { val enq = Decoupled(gen).flip() val deq = Decoupled(gen) - val enq_clock = if (enq_sync) Some(Clock(INPUT)) else None - val deq_clock = if (deq_sync) Some(Clock(INPUT)) else None - val enq_reset = if (enq_sync) Some(Bool(INPUT)) else None - val deq_reset = if (deq_sync) Some(Bool(INPUT)) else None + val enq_clock = Clock(INPUT) + val deq_clock = Clock(INPUT) + val enq_reset = Bool(INPUT) + val deq_reset = Bool(INPUT) } // Output is 1 for one cycle after any edge of 'in' @@ -87,11 +87,11 @@ class AsyncHandshakeSink[T <: Data](gen: T, sync: Int, clock: Clock, reset: Bool } class AsyncHandshake[T <: Data](gen: T, sync: Int = 2) extends Module { - val io = new Crossing(gen, true, true) + val io = new Crossing(gen) require (sync >= 2) - val source = Module(new AsyncHandshakeSource(gen, sync, io.enq_clock.get, io.enq_reset.get)) - val sink = Module(new AsyncHandshakeSink (gen, sync, io.deq_clock.get, io.deq_reset.get)) + val source = Module(new AsyncHandshakeSource(gen, sync, io.enq_clock, io.enq_reset)) + val sink = Module(new AsyncHandshakeSink (gen, sync, io.deq_clock, io.deq_reset)) source.io.enq <> io.enq io.deq <> sink.io.deq @@ -101,50 +101,38 @@ class AsyncHandshake[T <: Data](gen: T, sync: Int = 2) extends Module { source.io.pop := sink.io.pop } -class AsyncDecoupledTo[T <: Data](gen: T, depth: Int = 0, sync: Int = 2) extends Module { - val io = new Crossing(gen, false, true) +class AsyncScope extends Module { val io = new Bundle } +object AsyncScope { def apply() = Module(new AsyncScope) } - // !!! if depth == 0 { use Handshake } else { use AsyncFIFO } - val crossing = Module(new AsyncHandshake(gen, sync)).io - crossing.enq_clock.get := clock - crossing.enq_reset.get := reset - crossing.enq <> io.enq - crossing.deq_clock.get := io.deq_clock.get - crossing.deq_reset.get := io.deq_reset.get - io.deq <> crossing.deq -} - -object AsyncDecoupledTo { - // source is in our clock domain, output is in the 'to' clock domain - def apply[T <: Data](to_clock: Clock, to_reset: Bool, source: DecoupledIO[T], depth: Int = 0, sync: Int = 2): DecoupledIO[T] = { - val to = Module(new AsyncDecoupledTo(source.bits, depth, sync)) - to.io.deq_clock.get := to_clock - to.io.deq_reset.get := to_reset - to.io.enq <> source - to.io.deq +object AsyncDecoupledCrossing +{ + // takes from_source from the 'from' clock domain and puts it into the 'to' clock domain + def apply[T <: Data](from_clock: Clock, from_reset: Bool, from_source: DecoupledIO[T], to_clock: Clock, to_reset: Bool, depth: Int = 3, sync: Int = 2): DecoupledIO[T] = { + // !!! if depth == 0 { use Handshake } else { use AsyncFIFO } + val crossing = Module(new AsyncHandshake(from_source.bits, sync)).io + crossing.enq_clock := from_clock + crossing.enq_reset := from_reset + crossing.enq <> from_source + crossing.deq_clock := to_clock + crossing.deq_reset := to_reset + crossing.deq } } -class AsyncDecoupledFrom[T <: Data](gen: T, depth: Int = 0, sync: Int = 2) extends Module { - val io = new Crossing(gen, true, false) - - // !!! if depth == 0 { use Handshake } else { use AsyncFIFO } - val crossing = Module(new AsyncHandshake(gen, sync)).io - crossing.enq_clock.get := io.enq_clock.get - crossing.enq_reset.get := io.enq_reset.get - crossing.enq <> io.enq - crossing.deq_clock.get := clock - crossing.deq_reset.get := reset - io.deq <> crossing.deq -} - -object AsyncDecoupledFrom { - // source is in the 'from' clock domain, output is in our clock domain - def apply[T <: Data](from_clock: Clock, from_reset: Bool, source: DecoupledIO[T], depth: Int = 0, sync: Int = 2): DecoupledIO[T] = { - val from = Module(new AsyncDecoupledFrom(source.bits, depth, sync)) - from.io.enq_clock.get := from_clock - from.io.enq_reset.get := from_reset - from.io.enq <> source - from.io.deq +object AsyncDecoupledTo +{ + // takes source from your clock domain and puts it into the 'to' clock domain + def apply[T <: Data](to_clock: Clock, to_reset: Bool, source: DecoupledIO[T], depth: Int = 3, sync: Int = 2): DecoupledIO[T] = { + val scope = AsyncScope() + AsyncDecoupledCrossing(scope.clock, scope.reset, source, to_clock, to_reset, depth, sync) + } +} + +object AsyncDecoupledFrom +{ + // takes from_source from the 'from' clock domain and puts it into your clock domain + def apply[T <: Data](from_clock: Clock, from_reset: Bool, from_source: DecoupledIO[T], depth: Int = 3, sync: Int = 2): DecoupledIO[T] = { + val scope = AsyncScope() + AsyncDecoupledCrossing(from_clock, from_reset, from_source, scope.clock, scope.reset, depth, sync) } } diff --git a/src/main/scala/junctions/nasti.scala b/src/main/scala/junctions/nasti.scala index 41251ac3..3ae1fbc2 100644 --- a/src/main/scala/junctions/nasti.scala +++ b/src/main/scala/junctions/nasti.scala @@ -706,32 +706,33 @@ class NastiMemoryDemux(nRoutes: Int)(implicit p: Parameters) extends NastiModule } } +object AsyncNastiCrossing { + // takes from_source from the 'from' clock domain to the 'to' clock domain + def apply(from_clock: Clock, from_reset: Bool, from_source: NastiIO, to_clock: Clock, to_reset: Bool, depth: Int = 3, sync: Int = 2) = { + val to_sink = Wire(new NastiIO()(from_source.p)) + + to_sink.aw <> AsyncDecoupledCrossing(from_clock, from_reset, from_source.aw, to_clock, to_reset, depth, sync) + to_sink.ar <> AsyncDecoupledCrossing(from_clock, from_reset, from_source.ar, to_clock, to_reset, depth, sync) + to_sink.w <> AsyncDecoupledCrossing(from_clock, from_reset, from_source.w, to_clock, to_reset, depth, sync) + from_source.b <> AsyncDecoupledCrossing(to_clock, to_reset, to_sink.b, from_clock, from_reset, depth, sync) + from_source.r <> AsyncDecoupledCrossing(to_clock, to_reset, to_sink.r, from_clock, from_reset, depth, sync) + + to_sink // is now to_source + } +} + object AsyncNastiTo { - // source(master) is in our clock domain, output is in the 'to' clock domain - def apply[T <: Data](to_clock: Clock, to_reset: Bool, source: NastiIO, depth: Int = 3, sync: Int = 2)(implicit p: Parameters): NastiIO = { - val sink = Wire(new NastiIO) - - sink.aw <> AsyncDecoupledTo(to_clock, to_reset, source.aw, depth, sync) - sink.ar <> AsyncDecoupledTo(to_clock, to_reset, source.ar, depth, sync) - sink.w <> AsyncDecoupledTo(to_clock, to_reset, source.w, depth, sync) - source.b <> AsyncDecoupledFrom(to_clock, to_reset, sink.b, depth, sync) - source.r <> AsyncDecoupledFrom(to_clock, to_reset, sink.r, depth, sync) - - sink + // takes source from your clock domain and puts it into the 'to' clock domain + def apply(to_clock: Clock, to_reset: Bool, source: NastiIO, depth: Int = 3, sync: Int = 2): NastiIO = { + val scope = AsyncScope() + AsyncNastiCrossing(scope.clock, scope.reset, source, to_clock, to_reset, depth, sync) } } object AsyncNastiFrom { - // source(master) is in the 'from' clock domain, output is in our clock domain - def apply[T <: Data](from_clock: Clock, from_reset: Bool, source: NastiIO, depth: Int = 3, sync: Int = 2)(implicit p: Parameters): NastiIO = { - val sink = Wire(new NastiIO) - - sink.aw <> AsyncDecoupledFrom(from_clock, from_reset, source.aw, depth, sync) - sink.ar <> AsyncDecoupledFrom(from_clock, from_reset, source.ar, depth, sync) - sink.w <> AsyncDecoupledFrom(from_clock, from_reset, source.w, depth, sync) - source.b <> AsyncDecoupledTo(from_clock, from_reset, sink.b, depth, sync) - source.r <> AsyncDecoupledTo(from_clock, from_reset, sink.r, depth, sync) - - sink + // takes from_source from the 'from' clock domain and puts it into your clock domain + def apply(from_clock: Clock, from_reset: Bool, from_source: NastiIO, depth: Int = 3, sync: Int = 2): NastiIO = { + val scope = AsyncScope() + AsyncNastiCrossing(from_clock, from_reset, from_source, scope.clock, scope.reset, depth, sync) } } diff --git a/src/main/scala/rocketchip/DebugTransport.scala b/src/main/scala/rocketchip/DebugTransport.scala index 92fd0f29..846a6500 100644 --- a/src/main/scala/rocketchip/DebugTransport.scala +++ b/src/main/scala/rocketchip/DebugTransport.scala @@ -86,19 +86,19 @@ class JtagDTMWithSync(implicit val p: Parameters) extends Module { } else { val req_sync = Module (new AsyncMailbox()) val resp_sync = Module (new AsyncMailbox()) - req_sync.io.enq := jtag_dtm.io.dtm_req - req_sync.io.enq_clock.get := io.jtag.TCK - req_sync.io.enq_reset.get := io.jtag.TRST - req_sync.io.deq_clock.get := clock - req_sync.io.deq_reset.get := reset - dtm_req := req_sync.io.deq + req_sync.io.enq := jtag_dtm.io.dtm_req + req_sync.io.enq_clock := io.jtag.TCK + req_sync.io.enq_reset := io.jtag.TRST + req_sync.io.deq_clock := clock + req_sync.io.deq_reset := reset + dtm_req := req_sync.io.deq - jtag_dtm.io.dtm_resp := resp_sync.io.deq - resp_sync.io.deq_clock.get := io.jtag.TCK - resp_sync.io.deq_reset.get := io.jtag.TRST - resp_sync.io.enq_clock.get := clock - resp_sync.io.enq_reset.get := reset - resp_sync.io.enq := dtm_resp + jtag_dtm.io.dtm_resp := resp_sync.io.deq + resp_sync.io.deq_clock := io.jtag.TCK + resp_sync.io.deq_reset := io.jtag.TRST + resp_sync.io.enq_clock := clock + resp_sync.io.enq_reset := reset + resp_sync.io.enq := dtm_resp } } @@ -121,6 +121,5 @@ class AsyncMailbox extends BlackBox { // this mailbox just has a fixed width of 64 bits, which is enough // for our specific purpose here. - val io = new Crossing(UInt(width=64), true, true) - + val io = new Crossing(UInt(width=64)) } diff --git a/src/main/scala/uncore/devices/Debug.scala b/src/main/scala/uncore/devices/Debug.scala index 7443c9ac..310bdc68 100644 --- a/src/main/scala/uncore/devices/Debug.scala +++ b/src/main/scala/uncore/devices/Debug.scala @@ -982,22 +982,28 @@ class DebugModule ()(implicit val p:cde.Parameters) } +object AsyncDebugBusCrossing { + // takes from_source from the 'from' clock domain to the 'to' clock domain + def apply(from_clock: Clock, from_reset: Bool, from_source: DebugBusIO, to_clock: Clock, to_reset: Bool, depth: Int = 3, sync: Int = 2) = { + val to_sink = Wire(new DebugBusIO()(from_source.p)) + to_sink.req <> AsyncDecoupledCrossing(from_clock, from_reset, from_source.req, to_clock, to_reset, depth, sync) + from_source.resp <> AsyncDecoupledCrossing(to_clock, to_reset, to_sink.resp, from_clock, from_reset, depth, sync) + to_sink // is now to_source + } +} + object AsyncDebugBusFrom { // OutsideClockDomain - def apply(from_clock: Clock, from_reset: Bool, source: DebugBusIO, depth: Int = 0, sync: Int = 2)(implicit p: Parameters): DebugBusIO = { - val sink = Wire(new DebugBusIO) - sink.req <> AsyncDecoupledFrom(from_clock, from_reset, source.req) - source.resp <> AsyncDecoupledTo(from_clock, from_reset, sink.resp) - sink + // takes from_source from the 'from' clock domain and puts it into your clock domain + def apply(from_clock: Clock, from_reset: Bool, from_source: DebugBusIO, depth: Int = 0, sync: Int = 2): DebugBusIO = { + val scope = AsyncScope() + AsyncDebugBusCrossing(from_clock, from_reset, from_source, scope.clock, scope.reset, depth, sync) } } object AsyncDebugBusTo { // OutsideClockDomain - def apply(to_clock: Clock, to_reset: Bool, source: DebugBusIO, depth: Int = 0, sync: Int = 2)(implicit p: Parameters): DebugBusIO = { - val sink = Wire(new DebugBusIO) - sink.req <> AsyncDecoupledTo(to_clock, to_reset, source.req) - source.resp <> AsyncDecoupledFrom(to_clock, to_reset, sink.resp) - sink + // takes source from your clock domain and puts it into the 'to' clock domain + def apply(to_clock: Clock, to_reset: Bool, source: DebugBusIO, depth: Int = 0, sync: Int = 2): DebugBusIO = { + val scope = AsyncScope() + AsyncDebugBusCrossing(scope.clock, scope.reset, source, to_clock, to_reset, depth, sync) } } - -