From b1a37d0dda1d0e5e2dba7c888b4fe622af786fc2 Mon Sep 17 00:00:00 2001 From: Hansung Kim Date: Thu, 18 Jan 2024 18:15:18 -0800 Subject: [PATCH] Streamline upstream flow with regards to CoalSourceGen CoalescerSourceGen was prematurely reclaiming sourceIds in the presence of coalResp backpressure, since it was not referring to coalResp.fire and instead setting ready to always-true. With this change CoalSourceGen properly propagates both downstream and upstream backpressure. --- .../scala/radiance/memory/Coalescing.scala | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/src/main/scala/radiance/memory/Coalescing.scala b/src/main/scala/radiance/memory/Coalescing.scala index a932914..d2d0fbb 100644 --- a/src/main/scala/radiance/memory/Coalescing.scala +++ b/src/main/scala/radiance/memory/Coalescing.scala @@ -797,6 +797,7 @@ class CoalescerSourceGen( val outReq = Decoupled(coalReqT.cloneType) // outResp is only needed for telling the downstream TL node that this // sourcegen module is always ready to take in responses. + val inResp = Decoupled(respT.cloneType) // No need for inResp, since coalescerNode is directly replied by the // outResp TileLink bundle. val outResp = Flipped(Decoupled(respT.cloneType)) @@ -812,12 +813,13 @@ class CoalescerSourceGen( // passthrough logic io.outReq <> io.inReq + io.inResp <> io.outResp + // "man-in-the-middle" - io.inReq.ready := io.outReq.ready && sourceGen.io.id.valid // overwrite bits affected by sourcegen backpressure + io.inReq.ready := io.outReq.ready && sourceGen.io.id.valid io.outReq.valid := io.inReq.valid && sourceGen.io.id.valid io.outReq.bits.source := sourceGen.io.id.bits - io.outResp.ready := true.B // should be always ready to reclaim old ID } class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) @@ -927,21 +929,20 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) // The request coming out of MultiCoalescer still needs to go through source // ID generation. - // We pull the sourcegen part out of MultiCoalescer to a separate Module to - // reduce IO bloat in the coalescer and top-level clutter. + // The source generator needs to be on both upstream and downstream flow, as + // it needs to snoop on both reqs and resps to allocate/free the sourceIds. // // The overall flow looks like: - // ┌────────────────┐ ┌─────────────────────┐ ┌────────────────────┐ - // │ CoalShiftQueue ├─┤ Mono/MultiCoalescer ├─┤ CoalescerSourceGen ├── TileLink req - // └────────────────┘ └─────────────────────┘ └────────────────────┘ - // ^ - // ┌────────────┐ ┌─────────────┐ │ - // │ RespQueues ├─┤ Uncoalescer ├──┴────── TileLink resp - // └────────────┘ └─────────────┘ + // + // ┌────────────────┐ ┌─────────────────────┐ ┌────────────────────┐ ┌───────────────┐ + // │ CoalShiftQueue ├─┤ Mono/MultiCoalescer ├─┤ CoalSourceGen(gen) ├─┤ InFlightTable ├── TileLink req + // └────────────────┘ └─────────────────────┘ └────────────────────┘ └───────────────┘ + // ┌────────────┐ ┌─────────────┐ ┌────────────────────────┐ ┌───────────────┐ + // │ RespQueues ├─┤ Uncoalescer ├─┤ CoalSourceGen(reclaim) ├─┤ InFlightTable ├── TileLink resp + // └────────────┘ └─────────────┘ └────────────────────────┘ └───────────────┘ // val coalSourceGen = Module(new CoalescerSourceGen(config, coalReqT, tlCoal.d.bits)) coalSourceGen.io.inReq <> coalescer.io.coalReq - coalSourceGen.io.outResp <> tlCoal.d // InflightTable IO // @@ -1071,8 +1072,10 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) // Uncoalescer IO // // Connect coalesced response - uncoalescer.io.coalResp.valid := tlCoal.d.valid - uncoalescer.io.coalResp.bits.fromTLD(tlCoal.d.bits, tlCoal.d.fire) + uncoalescer.io.coalResp.valid := coalSourceGen.io.inResp.valid + uncoalescer.io.coalResp.bits.fromTLD(coalSourceGen.io.inResp.bits, coalSourceGen.io.inResp.fire) + coalSourceGen.io.inResp.ready := uncoalescer.io.coalResp.ready + // Connect lookup result from InflightTable uncoalescer.io.inflightLookup <> inflightTable.io.lookup // InflightTable IO: Look up the table with incoming coalesced responses @@ -1099,9 +1102,11 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) } } } - // Uncoalescer backpressure: stall downstream when uncoalescer is not ready - // to accept new coalesced response - tlCoal.d.ready := uncoalescer.io.coalResp.ready + + // coalSourceGen is the last module before going to downstream + // This handles backpressure to the downstream when uncoalescer is not ready, + // because uncoalescer is connected before coalSourceGen. + coalSourceGen.io.outResp <> tlCoal.d // Debug dontTouch(coalescer.io.coalReq)