=============== Troubleshooting =============== Gotchas encountered running Flow A, kept here so they don't have to be re-discovered per design. Environment / install ======================== ``externally-managed-environment`` on ``pip install --user fusesoc`` Ubuntu 24.04 blocks system-wide/user pip installs (PEP 668). Use a venv instead — see :doc:`getting-started`. ``ImportError: cannot import name 'walk_tool_packages' from 'edalize.edatool'`` Version mismatch between FuseSoC and the auto-installed Edalize. Fix: ``pip install --upgrade edalize``. ``this core was not found`` running a design from a local checkout FuseSoC doesn't scan the working directory for ``.core`` files by default — add ``--cores-root .`` to the ``fusesoc run`` command. Synthesis =========== Edalize's Yosys backend crashes with a ``TypeError`` before reading ``yosys_template`` The Tool-API Yosys backend requires a non-empty ``arch`` value in the ``.core`` file's ``tools.yosys`` section, even when a full custom ``yosys_template`` overrides its entire built-in flow anyway. Set ``arch: generic`` as a placeholder. OpenSTA/OpenROAD fails to parse the mapped netlist, or complains about ``signed`` Yosys still emits the ``signed`` qualifier on port/wire declarations after synthesis; OpenSTA/OpenROAD's Verilog reader doesn't support it. Strip it after synthesis (it carries no structural meaning at this point): .. code-block:: sh sed -i 's/ signed / /g' .v Registers left as behavioral ``always`` blocks instead of real cells ``dfflibmap`` must run **before** ``abc`` in the synthesis script. Without it, OpenSTA/OpenROAD's Verilog reader — which only understands gate instantiations — fails to parse the netlist. Gate-level simulation ======================== 100% "Unable to match ModPath" errors during SDF-annotated simulation Missing ``-gspecify``. It's disabled by default in Icarus; without it, specify blocks are parsed but ignored, so ``$sdf_annotate`` has no ModPath objects to attach delays to. The simulation may still report a "pass" in this state — that's a **false positive** caused by zero real delay ever being applied. Verify real annotation actually happened by checking the SDF verbose log for nonzero "Putting delay:" lines, or by checking the "Unable to match ModPath" error count dropped to 0%. ``Could not find net. Did you run iverilog with '-ginterconnect'?`` Missing ``-ginterconnect``, required for SDF INTERCONNECT (net/wire delay) matching. Functional mismatches appear only in the post-route SDF-annotated simulation, not at RTL or post-synthesis Check static timing first (``report_worst_slack -max`` and ``-min``) — if both are comfortably MET, it is likely **not** a real setup/hold violation but a testbench-timing artifact: the stimulus is being driven on the same clock edge the DUT's own input-capture register uses, leaving zero margin once real nonzero SDF cell/interconnect delays are applied. Moving the stimulus-driving block to the opposite edge (e.g. from ``posedge`` to ``negedge`` if the DUT captures on ``posedge``) typically resolves it, giving roughly half a clock period of margin. Confirm with a controlled, single-variable experiment (only change the stimulus edge, re-run against the same routed netlist and SDF file) before concluding this is the cause — a checker sampling-edge race can look similar but does *not* go away when the checker (rather than the stimulus) is moved to the other edge. Vectorless ``report_power`` numbers look implausible (too high, or don't respond to the clock period) ``report_power`` with no VCD loaded uses OpenSTA's default/vectorless switching-activity assumption, which can overstate real power by an order of magnitude and isn't meaningfully tied to the clock period. Capture a VCD from an already-verified-passing gate-level simulation and use ``read_vcd`` before ``report_power`` — see the real-activity power section in :doc:`running-your-own-design`. A useful sanity check once you have both numbers: real-activity power should generally go *up*, not down, from pre-route to post-route (added interconnect parasitics add switching capacitance) — if the vectorless numbers show the opposite trend, that's further evidence they weren't physically meaningful to begin with. Place & route =============== ``GPL-0326 toplevel port is not placed`` during ``global_placement`` Run ``place_pins`` before ``global_placement`` — every top-level port needs a placed location first. IO pins end up clustered on one edge instead of spread across all four ``global_placement`` moves standard cells to satisfy its density target but does **not** move already-placed pins along with them. Call ``place_pins`` a second time, after ``global_placement``. Placer compacts the whole design into part of the die instead of spreading uniformly The default target density (0.70) lets the placer satisfy the density constraint with a wirelength-optimal blob rather than a uniform spread. Pass an explicit ``-density`` close to your actual target utilization to ``global_placement``. ``detailed_route``/TritonRoute crashes or segfaults Confirmed (via a null-pointer dereference in ``dmesg``, not memory exhaustion) to be unsafe inside the OpenROAD GUI process. Run ``pnr.tcl`` headless (``openroad -no_init -exit ...``), not with ``-gui``. Everything up to (not including) routing can still be typed into the GUI's Scripting console for visual inspection if needed. ``[ERROR EST-0005] Run global_route before estimating parasitics for global routing`` Reloading a written ``.def`` in a fresh ``openroad`` session does not restore the linked-network/global-route state that ``extract_parasitics``/``estimate_parasitics`` need. Keep floorplanning through PPA reporting in one uninterrupted script/session rather than splitting it across separate invocations. ``$sdf_annotate`` fails to match instances between the netlist and SDF ``_route.v`` and ``_route.sdf`` must be written from the **same live** ``pnr.tcl`` session — instance names must match exactly between the two files. Icarus's default min:typ:max delay selection has nothing to pick for "typ" ``write_sdf`` needs the ``-include_typ`` flag; without it, OpenROAD only emits min/max delays. Multi-file designs (Bender / ``read_slang``) =============================================== ``sorry: Overriding the default variable lifetime is not yet supported`` Icarus Verilog does not support a per-declaration ``automatic``/ ``static`` lifetime override (e.g. ``automatic integer x;`` inside a procedural block with a different default lifetime) — this is a real Icarus limitation, not a SystemVerilog error; ``read_slang`` handles the same construct correctly. Fix: remove the qualifier if the variable is always written before read in every iteration where it's used (usually safe — check this holds before removing it blindly). ``error: '--ignore-unknown-modules' no longer supported with sv-elab`` Recent ``read_slang``/sv-elab builds have removed this flag. Drop it rather than searching for a replacement — it's only needed when a referenced module genuinely isn't in the flist, which a correct ``Bender.yml`` should prevent in the first place. ``--compat-mode`` is deprecated/always-on (safe to drop too); ``--keep-hierarchy`` is explicitly flagged experimental/may-crash by the tool itself — avoid unless you specifically need preserved hierarchy for reporting. ``couldn't read file "scripts/yosys_common.tcl": no such file or directory`` Path is relative to the *caller's* working directory, which differs between ``synth.tcl`` (run by Edalize from ``build/_/synth-yosys/``, three levels below the project root) and ``ppa_report.tcl``/``pnr.tcl`` (run standalone from the project root). Use ``../../../scripts/yosys_common.tcl`` in ``synth.tcl`` and plain ``scripts/yosys_common.tcl`` in the other two — this is already correct in the versions under ``flow-a/scripts/``; this entry exists for when the ``source`` line gets copy-pasted between contexts by hand. ``parameter '' not found in '.dut'`` during gate-level simulation Synthesis flattens/resolves module parameters, so the mapped/routed netlist's top module no longer declares them. A testbench that worked fine for RTL sim with ``dut #(.PARAM(PARAM)) dut (...)`` will fail to elaborate against any post-synthesis or post-route netlist. Fix: in the **gate-level copy** of the testbench only, drop the parameter override entirely (``dut #(...) dut`` → ``dut dut``) — this changes nothing functionally as long as the mapped netlist was synthesized with the same parameter value as the default. ``Unable to bind wire/reg/memory '..'`` during gate-level simulation A hierarchical debug reference into an internal submodule signal (``dut.u_sub.internal_signal``) in the testbench. Synthesis renames/flattens internal nets, so these references can't resolve against a gate-level netlist even when the design itself is correct. Remove or comment out these references in the **gate-level copy** of the testbench only — never edit the original RTL testbench used for pre-synthesis simulation. Garbled/non-hex characters (e.g. ``@AA@``) in ``$display`` output during SDF-annotated simulation, alongside functional mismatches Distinct from the clock-edge race described above (that one produces clean-but-wrong hex values on a *clocked* design) — this pattern, on a combinational path, means the output is still partially ``X`` when sampled: Verilog's 4-state ternary (``cond ? "PASS" : "FAIL"``) bitwise-blends both string literals when ``cond`` itself evaluates to ``X``, producing corrupted text rather than picking one string. Root cause is almost always insufficient settling time between driving inputs and sampling outputs in the testbench — a delay like ``#1`` sized for a zero-delay functional model is nowhere near enough once real SDF gate/wire delays are annotated on a multi-ns combinational path. Fix: increase the testbench's settling delay to at least 2x the real critical-path delay found in ``timing_fmax.rpt``/ ``timing_postroute.rpt`` before re-running. FuseSoC doesn't notice RTL edits when the ``.core`` file's fileset only lists a Bender-generated flist Expected, not a bug: when RTL sources are read via ``iverilog_options: [-f, ]`` rather than individually declared under ``filesets:`` (see :doc:`running-your-own-design`), FuseSoC's own change-tracking only sees the flist file itself, not the sources it references. In practice ``fusesoc run`` always re-invokes ``iverilog`` fresh regardless, so this doesn't currently cause stale results — but it means any future incremental/cached build tooling added to this flow would need to hash the flist's *referenced* files, not just the flist, to stay correct. Documentation build ====================== ``sphinx-build -W`` fails on a warning The CI workflow (``.github/workflows/docs.yml``) treats every Sphinx warning as an error. Common causes: a ``.. toctree::`` entry pointing at a page that doesn't exist yet, or a duplicate section label across pages. Run ``sphinx-build -W docs docs/_build/html`` locally before pushing to catch these early.