fix(xilinx): DSP48E1 packing crash on xc7 + cluster registration - #100
Open
agent-maestro wants to merge 1 commit into
Open
fix(xilinx): DSP48E1 packing crash on xc7 + cluster registration#100agent-maestro wants to merge 1 commit into
agent-maestro wants to merge 1 commit into
Conversation
Two bugs in xilinx/pack_dsp_xc7.cc surface when synth_xilinx leaves
DSP48E1 cells in the netlist (no -nodsp):
1) walk_dsp() dereferenced ni->users.end() instead of begin(). The
indexed_store end() iterator points one past the last slot, and
operator* calls slots.at(index), which throws std::out_of_range
("__n (which is 1) >= size() (which is 1)") as soon as any DSP
has a COUT or other cascade net wired up. Use users.begin() — the
prior check_illegal_fanout() already guarantees entries() == 1.
2) After walk_dsp registers cascaded children under a root via
root->constr_children and child->cluster = root->name, the root's
own cluster was left as ClusterId(). HeAPPlacer::HeAPPlacer fills
cluster2cells only from cells whose cluster != ClusterId(), and
seed_placement / update_all_chains only walk cluster children
when starting from a root that has its cluster set. The result
was that cascaded DSPs got no cell_locs entry, and total_hpwl()
aborted with 'dict::at()' as soon as it touched a net user that
was a cascaded child. xcup already does the analogous
subcell->cluster = subcell->name (pack_dsp_xcup.cc:69); mirror
that for xc7 by setting root->cluster = root->name whenever
walk_dsp actually attached children.
Test: 16x DSP48E1 expm1 kernel on xc7a100t, freq 100.
- Before: terminate on _M_range_check at packing, then dict::at()
at placement after the first fix.
- After: "Routing complete." Post-route fmax 168.12 MHz (PASS).
Cell count drops vs -nodsp baseline: 414 vs 7279 SLICE_LUTX
(17x), 258 vs 356 SLICE_FFX; 16/240 DSP48E1 used.
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.
Summary
Fixes two bugs in
xilinx/pack_dsp_xc7.ccthat crash nextpnr-xilinx during DSP packing onxc7parts wheneversynth_xilinxleaves DSP48E1 cells in the netlist (i.e. anything other than-nodsp).Tested with a 16-DSP48E1 design (Q16.16 fixed-point
expm1kernel) onxc7a100tcsg324-1. Before this patch: terminates withstd::out_of_rangeduring DSP packing. After: routing completes; post-route fmax 168.12 MHz (PASS at 100 MHz), 414 SLICE_LUTX (vs 7279 with-nodsp).The two bugs
1.
walk_dspdereferencedusers.end()instead ofusers.begin()indexed_store<PortRef>::end()returns an iterator whose index equalsslots.size(), andoperator*callsslots.at(index). That throwsstd::out_of_range: __n (which is 1) >= size() (which is 1)the instant any DSP has a cascade net wired up (COUT / PCOUT / ACOUT / BCOUT) — which is every multi-DSP design.The existing
check_illegal_fanout(ni)call right above already guaranteesni->users.entries() == 1, sousers.begin()is the correct dereference.2.
pack_dspssetclusteron cascaded children but not on the rootwalk_dspcorrectly setschild->cluster = root->nameand pushes the child ontoroot->constr_children. But it never setsroot->cluster = root->name.HeAPPlacer::HeAPPlacerpopulatescluster2cellsonly from cells withcluster != ClusterId(). Result: cascaded DSPs get nocell_locsentry, andtotal_hpwl()aborts viadict::at()the first time it touches a net user that is a cascaded child.The xcup variant already does the equivalent (
pack_dsp_xcup.cc:69:subcell->cluster = subcell->name;). This patch mirrors that for xc7 by settingroot->cluster = root->namewheneverwalk_dspactually attached children.Patch
8 lines total, no behavioral change for designs without DSP cascades.
Test results
Test design: 16-DSP48E1
expm1_pipeline(Q16.16 fixed-point exp(x)-1),xc7a100tcsg324-1, target 100 MHz.-nodspbaseline2.10x fmax, 17.6x LUT reduction.
Test plan
8f178fc); confirm crash reproduces with the test design.Program finished normally.🤖 Generated with Claude Code