-
Notifications
You must be signed in to change notification settings - Fork 27
refactor: add CHI-related code from coupledl2 #144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,342 @@ | ||||||||||||||||||||||||||||||||
| /*************************************************************************************** | ||||||||||||||||||||||||||||||||
| * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences | ||||||||||||||||||||||||||||||||
| * Copyright (c) 2020-2021 Peng Cheng Laboratory | ||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||
| * XiangShan is licensed under Mulan PSL v2. | ||||||||||||||||||||||||||||||||
| * You can use this software according to the terms and conditions of the Mulan PSL v2. | ||||||||||||||||||||||||||||||||
| * You may obtain a copy of Mulan PSL v2 at: | ||||||||||||||||||||||||||||||||
| * http://license.coscl.org.cn/MulanPSL2 | ||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||
| * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, | ||||||||||||||||||||||||||||||||
| * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, | ||||||||||||||||||||||||||||||||
| * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. | ||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||
| * See the Mulan PSL v2 for more details. | ||||||||||||||||||||||||||||||||
| ***************************************************************************************/ | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| package utility.chi | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| import chisel3._ | ||||||||||||||||||||||||||||||||
| import chisel3.util._ | ||||||||||||||||||||||||||||||||
| import freechips.rocketchip.util.{AsyncQueueParams, AsyncBundle, AsyncQueueSource, AsyncQueueSink} | ||||||||||||||||||||||||||||||||
| import freechips.rocketchip.util.AsyncResetSynchronizerShiftReg | ||||||||||||||||||||||||||||||||
| import org.chipsalliance.cde.config.Parameters | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| class AsyncChannelIO[+T <: Data](gen: T, params: AsyncQueueParams = AsyncQueueParams()) extends Bundle { | ||||||||||||||||||||||||||||||||
| val flitpend = Output(Bool()) | ||||||||||||||||||||||||||||||||
| val flit = new AsyncBundle(UInt(gen.getWidth.W), params) | ||||||||||||||||||||||||||||||||
| val lcrdv = Flipped(new AsyncBundle(UInt(0.W), params)) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| class AsyncDownwardsLinkIO( | ||||||||||||||||||||||||||||||||
| params: AsyncQueueParams = AsyncQueueParams() | ||||||||||||||||||||||||||||||||
| )(implicit p: Parameters) extends Bundle with HasLinkSwitch { | ||||||||||||||||||||||||||||||||
| val req = new AsyncChannelIO(new CHIREQ, params) | ||||||||||||||||||||||||||||||||
| val rsp = new AsyncChannelIO(new CHIRSP, params) | ||||||||||||||||||||||||||||||||
| val dat = new AsyncChannelIO(new CHIDAT, params) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| class AsyncUpwardsLinkIO( | ||||||||||||||||||||||||||||||||
| params: AsyncQueueParams = AsyncQueueParams() | ||||||||||||||||||||||||||||||||
| )(implicit p: Parameters) extends Bundle with HasLinkSwitch { | ||||||||||||||||||||||||||||||||
| val rsp = new AsyncChannelIO(new CHIRSP, params) | ||||||||||||||||||||||||||||||||
| val dat = new AsyncChannelIO(new CHIDAT, params) | ||||||||||||||||||||||||||||||||
| val snp = new AsyncChannelIO(new CHISNP, params) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| class AsyncPortIO( | ||||||||||||||||||||||||||||||||
| params: AsyncQueueParams = AsyncQueueParams() | ||||||||||||||||||||||||||||||||
| )(implicit p: Parameters) extends Bundle with HasPortSwitch with HasSystemCoherencyInterface { | ||||||||||||||||||||||||||||||||
| val tx = new AsyncDownwardsLinkIO(params) | ||||||||||||||||||||||||||||||||
| val rx = Flipped(new AsyncUpwardsLinkIO(params)) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| /* | ||||||||||||||||||||||||||||||||
| * This module enhances the standard async bridge by adding a front-end shadow buffer | ||||||||||||||||||||||||||||||||
| * to decouple local processing from asynchronous latency and provide instant credit | ||||||||||||||||||||||||||||||||
| * return to upstream modules | ||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||
| * rx: DownStream(CMN) → [Shadow Buffer (16)] → [AsyncQueueSink (4)] → [AsyncQueueSource (4)] → Upstream (L2) | ||||||||||||||||||||||||||||||||
| * ↑ | ||||||||||||||||||||||||||||||||
| * Instant Credit return | ||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||
| * tx: UpStream(L2) → [Shadow Buffer (16)] → [AsyncQueueSource (4)] → [AsyncQueueSink (4)] → Downstream (CMN) | ||||||||||||||||||||||||||||||||
| * ↑ ↑ | ||||||||||||||||||||||||||||||||
| * CHI Credit + over Credit(4) Credit manage to gen back-pressure | ||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||
| object ToAsyncBundleWithBuf { | ||||||||||||||||||||||||||||||||
| def channel[T <: Data]( | ||||||||||||||||||||||||||||||||
| chn: ChannelIO[T], | ||||||||||||||||||||||||||||||||
| params: AsyncQueueParams = AsyncQueueParams(depth = 4), | ||||||||||||||||||||||||||||||||
| name: Option[String] = None | ||||||||||||||||||||||||||||||||
| ): (Data, Bool) = { | ||||||||||||||||||||||||||||||||
| /* | ||||||||||||||||||||||||||||||||
| 1. Shadow Buffer (depth=16, flow mode for low latency) | ||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||
| val shadow_buffer = Module(new Queue(chiselTypeOf(chn.flit), 16, flow = true, pipe = false)) | ||||||||||||||||||||||||||||||||
| if (name.isDefined) { shadow_buffer.suggestName("shadowBuffer_" + name.get) } | ||||||||||||||||||||||||||||||||
| shadow_buffer.io.enq.valid := chn.flitv | ||||||||||||||||||||||||||||||||
| shadow_buffer.io.enq.bits := chn.flit | ||||||||||||||||||||||||||||||||
| /* | ||||||||||||||||||||||||||||||||
| 2. For rx channel (CMN->L2), send out lcrdv right after a flit entering Shadow buffer if has space | ||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||
| val deqReady = shadow_buffer.io.deq.ready | ||||||||||||||||||||||||||||||||
| dontTouch(deqReady) | ||||||||||||||||||||||||||||||||
| assert(!chn.flitv || shadow_buffer.io.enq.ready, s"${name.getOrElse("ToAsyncBundle")}: Shadow buffer overflow!") | ||||||||||||||||||||||||||||||||
| /* | ||||||||||||||||||||||||||||||||
| 3. AsyncQueueSource (depth=4) | ||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||
| val source = Module(new AsyncQueueSource(chiselTypeOf(chn.flit), params)) | ||||||||||||||||||||||||||||||||
| if (name.isDefined) { source.suggestName("asyncQSource_" + name.get) } | ||||||||||||||||||||||||||||||||
| source.io.enq <> shadow_buffer.io.deq | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| (source.io.async, deqReady) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| object ToAsyncBundle { | ||||||||||||||||||||||||||||||||
| def channel[T <: Data]( | ||||||||||||||||||||||||||||||||
| chn: ChannelIO[T], | ||||||||||||||||||||||||||||||||
| params: AsyncQueueParams = AsyncQueueParams(), | ||||||||||||||||||||||||||||||||
| name: Option[String] = None | ||||||||||||||||||||||||||||||||
| ) = { | ||||||||||||||||||||||||||||||||
| val source = Module(new AsyncQueueSource(chiselTypeOf(chn.flit), params)) | ||||||||||||||||||||||||||||||||
| if (name.isDefined) { source.suggestName("asyncQSource_" + name.get) } | ||||||||||||||||||||||||||||||||
| source.io.enq.valid := chn.flitv | ||||||||||||||||||||||||||||||||
| source.io.enq.bits := chn.flit | ||||||||||||||||||||||||||||||||
| source.io.async | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| def bitPulse( | ||||||||||||||||||||||||||||||||
| bit: Bool, | ||||||||||||||||||||||||||||||||
| params: AsyncQueueParams = AsyncQueueParams(), | ||||||||||||||||||||||||||||||||
| name: Option[String] = None | ||||||||||||||||||||||||||||||||
| ) = { | ||||||||||||||||||||||||||||||||
| val source = Module(new AsyncQueueSource(UInt(0.W), params)) | ||||||||||||||||||||||||||||||||
| if (name.isDefined) { source.suggestName("asyncQBitSource_" + name.get) } | ||||||||||||||||||||||||||||||||
| source.io.enq.valid := bit | ||||||||||||||||||||||||||||||||
| source.io.enq.bits := DontCare | ||||||||||||||||||||||||||||||||
| source.io.async | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| object FromAsyncBundle { | ||||||||||||||||||||||||||||||||
| def channel( | ||||||||||||||||||||||||||||||||
| async: AsyncBundle[UInt], | ||||||||||||||||||||||||||||||||
| params: AsyncQueueParams = AsyncQueueParams(), | ||||||||||||||||||||||||||||||||
| name: Option[String] = None, | ||||||||||||||||||||||||||||||||
| lcrdvReady: Option[Bool]= None | ||||||||||||||||||||||||||||||||
| ) = { | ||||||||||||||||||||||||||||||||
| val gen = chiselTypeOf(async.mem.head) | ||||||||||||||||||||||||||||||||
| val out = Wire(new ChannelIO(gen)) | ||||||||||||||||||||||||||||||||
| val sink = Module(new AsyncQueueSink(gen, params)) | ||||||||||||||||||||||||||||||||
| if (name.isDefined) { sink.suggestName("asyncQSink_" + name.get) } | ||||||||||||||||||||||||||||||||
| sink.io.async <> async | ||||||||||||||||||||||||||||||||
| sink.io.deq.ready := lcrdvReady.getOrElse(true.B) | ||||||||||||||||||||||||||||||||
| out.flitv := sink.io.deq.valid & sink.io.deq.ready | ||||||||||||||||||||||||||||||||
| out.flit := sink.io.deq.bits | ||||||||||||||||||||||||||||||||
| // flitpend and lcrdv are assigned independently | ||||||||||||||||||||||||||||||||
| out.flitpend := DontCare | ||||||||||||||||||||||||||||||||
| out.lcrdv := DontCare | ||||||||||||||||||||||||||||||||
| out | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| def bitPulse[T <: Data]( | ||||||||||||||||||||||||||||||||
| async: AsyncBundle[T], | ||||||||||||||||||||||||||||||||
| params: AsyncQueueParams = AsyncQueueParams(), | ||||||||||||||||||||||||||||||||
| name: Option[String] = None | ||||||||||||||||||||||||||||||||
| ): Bool = { | ||||||||||||||||||||||||||||||||
| val gen = chiselTypeOf(async.mem.head) | ||||||||||||||||||||||||||||||||
| val sink = Module(new AsyncQueueSink(gen, params)) | ||||||||||||||||||||||||||||||||
| if (name.isDefined) { sink.suggestName("asyncQBitSink_" + name.get) } | ||||||||||||||||||||||||||||||||
| sink.io.async <> async | ||||||||||||||||||||||||||||||||
| sink.io.deq.ready := true.B | ||||||||||||||||||||||||||||||||
| sink.io.deq.valid | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| class CHIAsyncBridgeSource(params: AsyncQueueParams = AsyncQueueParams())(implicit p: Parameters) extends Module { | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| val numSyncReg = params.sync | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| val io = IO(new Bundle() { | ||||||||||||||||||||||||||||||||
| val enq = Flipped(new PortIO) | ||||||||||||||||||||||||||||||||
| val async = new AsyncPortIO(params) | ||||||||||||||||||||||||||||||||
| val resetFinish = Output(Bool()) | ||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| val async_tx_req = ToAsyncBundleWithBuf.channel(io.enq.tx.req, params, Some("txreq_flit")) | ||||||||||||||||||||||||||||||||
| val async_tx_rsp = ToAsyncBundleWithBuf.channel(io.enq.tx.rsp, params, Some("txrsp_flit")) | ||||||||||||||||||||||||||||||||
| val async_tx_dat = ToAsyncBundleWithBuf.channel(io.enq.tx.dat, params, Some("txdat_flit")) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| io.async.tx.req.flit <> async_tx_req._1 | ||||||||||||||||||||||||||||||||
| io.async.tx.rsp.flit <> async_tx_rsp._1 | ||||||||||||||||||||||||||||||||
| io.async.tx.dat.flit <> async_tx_dat._1 | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| io.enq.tx.req.lcrdv <> FromAsyncBundle.bitPulse(io.async.tx.req.lcrdv, params, Some("txreq_lcrdv")) | ||||||||||||||||||||||||||||||||
| io.enq.tx.rsp.lcrdv <> FromAsyncBundle.bitPulse(io.async.tx.rsp.lcrdv, params, Some("txrsp_lcrdv")) | ||||||||||||||||||||||||||||||||
| io.enq.tx.dat.lcrdv <> FromAsyncBundle.bitPulse(io.async.tx.dat.lcrdv, params, Some("txdat_lcrdv")) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| io.enq.rx.rsp <> FromAsyncBundle.channel(io.async.rx.rsp.flit, params, Some("rxrsp_flit")) | ||||||||||||||||||||||||||||||||
| io.enq.rx.dat <> FromAsyncBundle.channel(io.async.rx.dat.flit, params, Some("rxdat_flit")) | ||||||||||||||||||||||||||||||||
| io.enq.rx.snp <> FromAsyncBundle.channel(io.async.rx.snp.flit, params, Some("rxsnp_flit")) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| io.async.rx.rsp.lcrdv <> ToAsyncBundle.bitPulse(io.enq.rx.rsp.lcrdv, params, Some("rxrsp_lcrdv")) | ||||||||||||||||||||||||||||||||
| io.async.rx.dat.lcrdv <> ToAsyncBundle.bitPulse(io.enq.rx.dat.lcrdv, params, Some("rxdat_lcrdv")) | ||||||||||||||||||||||||||||||||
| io.async.rx.snp.lcrdv <> ToAsyncBundle.bitPulse(io.enq.rx.snp.lcrdv, params, Some("rxsnp_lcrdv")) | ||||||||||||||||||||||||||||||||
|
Comment on lines
+179
to
+185
|
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| io.async.txsactive := io.enq.txsactive | ||||||||||||||||||||||||||||||||
| io.async.rx.linkactiveack := io.enq.rx.linkactiveack | ||||||||||||||||||||||||||||||||
| io.async.tx.linkactivereq := io.enq.tx.linkactivereq | ||||||||||||||||||||||||||||||||
| io.async.syscoreq := io.enq.syscoreq | ||||||||||||||||||||||||||||||||
| io.async.tx.req.flitpend := io.enq.tx.req.flitpend | ||||||||||||||||||||||||||||||||
| io.async.tx.dat.flitpend := io.enq.tx.dat.flitpend | ||||||||||||||||||||||||||||||||
| io.async.tx.rsp.flitpend := io.enq.tx.rsp.flitpend | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| withClockAndReset(clock, reset) { | ||||||||||||||||||||||||||||||||
| val resetFinish = Wire(Bool()) | ||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||
| // Below is a typical synchronizer with two registers | ||||||||||||||||||||||||||||||||
| // │ | ||||||||||||||||||||||||||||||||
| // ┌────┐ ┌────┐ │ | ||||||||||||||||||||||||||||||||
| // output signal ◄───┤ \/ │◄─┤ \/ │◄────│────── input signal | ||||||||||||||||||||||||||||||||
| // │ │ │ │ │ | ||||||||||||||||||||||||||||||||
| // └────┘ └────┘ │ | ||||||||||||||||||||||||||||||||
| // output clock │ | ||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||
| io.enq.rxsactive := AsyncResetSynchronizerShiftReg(io.async.rxsactive, numSyncReg, 0, Some("sync_rxsactive")) | ||||||||||||||||||||||||||||||||
| io.enq.tx.linkactiveack := AsyncResetSynchronizerShiftReg(io.async.tx.linkactiveack, numSyncReg, 0, Some("sync_tx_linkactiveack")) | ||||||||||||||||||||||||||||||||
| io.enq.rx.linkactivereq := AsyncResetSynchronizerShiftReg(io.async.rx.linkactivereq, numSyncReg, 0, Some("sync_rx_linkactivereq")) && resetFinish | ||||||||||||||||||||||||||||||||
| io.enq.syscoack := AsyncResetSynchronizerShiftReg(io.async.syscoack, numSyncReg, 0, Some("sync_syscoack")) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| io.enq.rx.rsp.flitpend := AsyncResetSynchronizerShiftReg(io.async.rx.rsp.flitpend, numSyncReg, 0, Some("sync_rx_rsp_flitpend")) | ||||||||||||||||||||||||||||||||
| io.enq.rx.dat.flitpend := AsyncResetSynchronizerShiftReg(io.async.rx.dat.flitpend, numSyncReg, 0, Some("sync_rx_dat_flitpend")) | ||||||||||||||||||||||||||||||||
| io.enq.rx.snp.flitpend := AsyncResetSynchronizerShiftReg(io.async.rx.snp.flitpend, numSyncReg, 0, Some("sync_rx_snp_flitpend")) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| val RESET_FINISH_MAX = 100 | ||||||||||||||||||||||||||||||||
| val resetFinishCounter = withReset(reset.asAsyncReset)(RegInit(0.U((log2Ceil(RESET_FINISH_MAX) + 1).W))) | ||||||||||||||||||||||||||||||||
| when (resetFinishCounter < RESET_FINISH_MAX.U) { | ||||||||||||||||||||||||||||||||
| resetFinishCounter := resetFinishCounter + 1.U | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| resetFinish := resetFinishCounter >= RESET_FINISH_MAX.U | ||||||||||||||||||||||||||||||||
| io.resetFinish := resetFinish | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| dontTouch(io) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| class CHIAsyncBridgeSink(params: AsyncQueueParams = AsyncQueueParams())(implicit p: Parameters) extends Module { | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| val numSyncReg = params.sync | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| val io = IO(new Bundle() { | ||||||||||||||||||||||||||||||||
| val async = Flipped(new AsyncPortIO(params)) | ||||||||||||||||||||||||||||||||
| val deq = new PortIO | ||||||||||||||||||||||||||||||||
| val resetFinish = Output(Bool()) | ||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| val txreq_lcrdvReady = Wire(Bool()) | ||||||||||||||||||||||||||||||||
| val txrsp_lcrdvReady = Wire(Bool()) | ||||||||||||||||||||||||||||||||
| val txdat_lcrdvReady = Wire(Bool()) | ||||||||||||||||||||||||||||||||
| io.deq.tx.req <> FromAsyncBundle.channel(io.async.tx.req.flit, params, Some("txreq_flit"), Some(txreq_lcrdvReady)) | ||||||||||||||||||||||||||||||||
| io.deq.tx.rsp <> FromAsyncBundle.channel(io.async.tx.rsp.flit, params, Some("txrsp_flit"), Some(txrsp_lcrdvReady)) | ||||||||||||||||||||||||||||||||
| io.deq.tx.dat <> FromAsyncBundle.channel(io.async.tx.dat.flit, params, Some("txdat_flit"), Some(txdat_lcrdvReady)) | ||||||||||||||||||||||||||||||||
|
Comment on lines
+240
to
+242
|
||||||||||||||||||||||||||||||||
| io.deq.tx.req <> FromAsyncBundle.channel(io.async.tx.req.flit, params, Some("txreq_flit"), Some(txreq_lcrdvReady)) | |
| io.deq.tx.rsp <> FromAsyncBundle.channel(io.async.tx.rsp.flit, params, Some("txrsp_flit"), Some(txrsp_lcrdvReady)) | |
| io.deq.tx.dat <> FromAsyncBundle.channel(io.async.tx.dat.flit, params, Some("txdat_flit"), Some(txdat_lcrdvReady)) | |
| val async_tx_req = FromAsyncBundle.channel(io.async.tx.req.flit, params, Some("txreq_flit"), Some(txreq_lcrdvReady)) | |
| val async_tx_rsp = FromAsyncBundle.channel(io.async.tx.rsp.flit, params, Some("txrsp_flit"), Some(txrsp_lcrdvReady)) | |
| val async_tx_dat = FromAsyncBundle.channel(io.async.tx.dat.flit, params, Some("txdat_flit"), Some(txdat_lcrdvReady)) | |
| io.deq.tx.req.flitv := async_tx_req.flitv | |
| io.deq.tx.req.flit := async_tx_req.flit | |
| io.deq.tx.req.flitpend := false.B | |
| io.deq.tx.rsp.flitv := async_tx_rsp.flitv | |
| io.deq.tx.rsp.flit := async_tx_rsp.flit | |
| io.deq.tx.rsp.flitpend := false.B | |
| io.deq.tx.dat.flitv := async_tx_dat.flitv | |
| io.deq.tx.dat.flit := async_tx_dat.flit | |
| io.deq.tx.dat.flitpend := false.B |
Copilot
AI
Apr 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
io.deq.rx.{rsp,dat}.lcrdv is already driven from the async side (FromAsyncBundle.bitPulse(...)), but later the module also instantiates LCredit2Decoupled(io.deq.rx.{rsp,dat}, ...) which will try to manage/drive L-Credits for the same channels. This creates conflicting ownership of lcrdv and risks double-driving / inconsistent credit behavior; please choose a single L-Credit source and remove the other path.
| io.deq.rx.rsp.lcrdv <> FromAsyncBundle.bitPulse(io.async.rx.rsp.lcrdv, params, Some("rxrsp_lcrdv")) | |
| io.deq.rx.dat.lcrdv <> FromAsyncBundle.bitPulse(io.async.rx.dat.lcrdv, params, Some("rxdat_lcrdv")) | |
| // `io.deq.rx.rsp.lcrdv` and `io.deq.rx.dat.lcrdv` are owned by the | |
| // downstream LCredit2Decoupled(...) path. Do not also drive them from the | |
| // async bridge, or the channels will have conflicting L-Credit sources. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ToAsyncBundleWithBuf.channelreturnsshadow_buffer.io.deq.readyas the "ready" signal. If this is intended to indicate shadow-buffer space for instant L-Credit return, it should be based onshadow_buffer.io.enq.ready(space to accept a new flit), not dequeue readiness. Usingdeq.readyhere can cause credits to be returned even when the buffer is full.