Repository navigation
axi_to_obi: Tie off the demux channels each converter never uses - #7
Open
DanielKellerM wants to merge 3 commits into
Open
DanielKellerM wants to merge 3 commits into
DanielKellerM wants to merge 3 commits into
Conversation
The read/write demux only routes AR to the read converter and AW/W to the write converter, but the unused channels were still wired, so ready and valid paths of one converter fed the other. Combined with a manager whose R ready depends on its W ready (e.g. iDMA), this forms a structural combinational loop. Tie off the dead channels, and the write converter R when ATOPs are disabled. Legal traffic is unaffected. An ATOP sent to a converter without UseAtop was never executed as an atomic; it now also trips an assertion.
This was referenced Oct 6, 2026
DanielKellerM
added a commit
to pulp-platform/gwaihir
that referenced
this pull request
Oct 6, 2026
iDMA devel deploy 378fa46 (#267 on #271), pinned by commit until 0.7.4 is tagged. axi_obi points at pulp-platform/axi_obi#7 until it merges.
Author
hopang-0221
pushed a commit
to pulp-platform/gwaihir
that referenced
this pull request
Oct 9, 2026
iDMA devel deploy 378fa46 (#267 on #271), pinned by commit until 0.7.4 is tagged. axi_obi points at pulp-platform/axi_obi#7 until it merges.
Lore0599
force-pushed
the
fix/rw-split-comb-loop
branch
from
October 10, 2026 08:26
d912bcf to
030136e
Compare
Lore0599
added a commit
to pulp-platform/gwaihir
that referenced
this pull request
Oct 11, 2026
* [Bender][hw][sw][CI] MXCore Feature and Kernel Updates MXCore now supports accumulator preload for C += AxB MXCore now supports BF16 output quantization MXCore now supports multi-context configuration [hw] MXCore interrupt on job(s) done only [sw] Extended mxcore.c with PRELOAD/MULTI_JOB modes, disabled by default [sw] Added mxcore_multi.c (with PRELOAD/MULTI_JOB) for work-splitting a large GEMM across 16 clusters [CI] Extend CI with new MXCore kernels * [Bender] Bump MXCore with Quantizer Fixes Result scales are now unsigned/biased like the input scales, in line with OCP spec * deps: Bump iDMA to devel for the planar MX layout iDMA devel drops the inline 33 B MX block for separate data and E8M0 scale planes. Move l2_dma_mx_roundtrip to the planes, with a 2D quant and dequant that step the scale plane by the scale stride. Pinned by commit until iDMA 0.7.4 is tagged. * hw: Wire the mx4 iDMA timing cuts (103) and frontend parameters TimingCuts 103 (mx_beat_push, dfe_ready_ahead, dfe_reg_flags, wdp_head_spill, outst_cnt_reg) and BufferDepth 3 to the backend; DataWidth and ComputeOps to the reg64 frontends. * deps: Bump iDMA to devel 6d64058 and axi_obi to the comb-loop fix iDMA devel deploy 378fa46 (#267 on #271), pinned by commit until 0.7.4 is tagged. axi_obi points at pulp-platform/axi_obi#7 until it merges. * deps: Bump iDMA to v0.7.4 * sw: Add an iDMA to MXCore MX end-to-end test The cluster DMA gathers FP32 A and B ([N][K]) from L2 and quantizes them into MXCore's operand planes, MXCore runs the GEMM in FP32 and MXFP8, and the DMA dequantizes the MXFP8 result. verify.py checks the operand planes and the FP32 result bit-exactly; the result scale and dequant checks are reported but not gating until #119, since MXCore writes signed result scales. * sw: Gate the mx_e2e result scale, MXFP8 result and dequant checks MXCore now writes E8M0 result scales (pulp-platform/MXCore#1), so the c_scale, c_mx and c_deq checks are bit-exact and gating. * sw: Port mx_e2e to the MXCore preload register map MXCore d45847f (#126) inserts the preload pointer and tile size registers; without the port the job never completes. * sw: Add an FP16 variant of the MX end-to-end test mx_e2e_fp16 runs the same flow from FP16 sources with the FP16 MX quant and dequant ops. verify.py now takes its goldens from iDMA's test/idma_mx_golden.h (quant/dequant) and MXCore's PyGolden (layout, GEMM, result quantization) instead of local math, also checks the iDMA dequant of the planes MXCore wrote, and checks canaries around every L2 output. * sw: Preload the mx_e2e canaries and fix the golden pointer types Core byte stores to the L2 canaries before the run made MXCore's result port hang (HCI RQ-3 on the result mux) in both variants, so the canaries are now part of the preloaded image. The ctypes goldens passed 64-bit pointers as int, which truncated them and crashed verify.py. * [hw] Minor mem tile rtl changes for timing improvement * Fix lint issue * Bump AXI obi --------- Co-authored-by: Jayanth Jonnalagadda <jjonnalagadd@iis.ee.ethz.ch> Co-authored-by: Hong Pang <hopang@iis.ee.ethz.ch> Co-authored-by: Lorenzo Leone <lleone@iis.ee.ethz.ch>
Lore0599
reviewed
Oct 11, 2026
There was a problem hiding this comment.
I'm not the official maintainer of this repo but let me add few comments below.
In general I think the fixes you've done solve the comb loop.
My concerns are the following:
- To my understanding, it makes sense to tie off the R channels (and W) in your specific situation (DMA comb loop). However, when we have ATOP, the R path on the write adapter is actually used. Therefore, don't we have the comb loop risk again?
- For the reason above, I think it might make sense to add a spill register to cut the comb loop. Since this has a HW cost, and I think it's not a necessary cost in case of no ATOP support, I added it only in the atomic path.
In general, I have the feeling that R->W dependency is not really AXI compliant, therefore the coupling done by the DMA is not the best, even though I don't have a solution to it at the moment (except adding huge buffers in the DMA).
Perhaps in the ATOP support is less likely that the manager couples R-W, however I still think it's better to avoid the comb loop here instead of relying on the endpoint behaviour.
@micprog @colluca @DanielKellerM I would like to have your opinion regarding the comment above.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #6 (
fix-strb), since that is the revision gwaihir uses.The read/write demux in
axi_to_obionly sends AR to the read converter and AW/W to the write converter, but the unused channels were still connected. Their ready/valid paths coupled the two converters, so a manager whose R ready depends on its W ready (iDMA does this) closes a combinational loop through the converter. SpyGlass reports it as CombLoop on the gwaihir mem tiles (iDMA ->axi_to_obi). The loop can never be sensitized, but it is a real gate cycle.This ties off the dead channels (read converter AW/W/B, write converter AR) and, when
UseAtopis off, the write converter R. No change in area or latency.Checked with a lockstep Questa 2026.1 testbench, old vs new module driven by
axi_rand_master, with every output compared each cycle: 0 mismatches for UseAtop=0/1 at AXI 32/64 bit, 3000 ATOPs in the UseAtop=1 runs. The Verilator lint warnings are the same as before. Together with the matching iDMA fix, gwaihir'smem_tile_small/mem_tile_largehave 0 CombLoop.The new assertion fires if an ATOP reaches a converter without
UseAtop. Before, such an ATOP was done as a plain write and returned a junk R. Now its R is dropped.