Conversation
DBG_FLAGS carried -DVCD_OUTPUT inline, so the textual trace, the waveform, and -g -O0 all rode on one ifdef DEBUG. A waveform therefore cost -O0 plus eight log streams, a textual trace cost a full VCD dump, and DEBUG+SAIF tripped the VCD/SAIF mutual-exclusion #error even though those two are not in conflict. 127c00d worked around the last part in rtlsim alone, by making -DVCD_OUTPUT conditional on SAIF -- a dependency from a debug variable onto a power-analysis one, which left the other four backends unable to trace and capture activity in the same run. Give VCD its own ifdef VCD block mirroring SAIF's, across all five Verilator backends and the unittest harness. --trace/--trace-structs move with it; -g -O0 stays with DEBUG. The #error is preserved as the single enforcement point and now fires only on a genuine --vcd --saif request. blackbox.sh gains --vcd, propagated in both build_driver and run_app since the test target relinks the model, and rejects --vcd on simx as it already rejects --saif. Verified on rtlsim: --vcd alone writes trace.vcd with no --debug, --saif alone writes trace.saif, --debug=1 --saif writes both run.log and the SAIF and passes, and --vcd --saif is the only combination reaching the #error. BREAKING: --debug alone no longer writes trace.vcd; pass --vcd. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Four graphics memory modules declared a local VX_lsu_mem_if named mem_bus_if and bound it to a .lsu_mem_if port on a module that also has a mem_bus_if port. Verilator and Vivado accept it; sv2v's scoper resolves the binding to the port instead of the local and aborts. Yosys cannot read SystemVerilog interfaces, so sv2v is unavoidable on that flow -- this blocked ASIC synthesis of the graphics units outright. Renaming the local to lsu_mem_if resolves it with no functional change: gfx_tex on rtlsim is bit-identical before and after (instrs=49168, cycles=137275). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The seed table was computed with SystemVerilog `real` in an initial
block. Verilator and Vivado constant-fold it, but yosys has no
floating-point support and cannot elaborate the module at all.
The replacement is exact integer arithmetic, chosen to be bit-identical
to the rounded floating-point result rather than merely close:
seed_rom[i] = (2^33 * SEED_N + d) / (2 * d), d = 2*SEED_N + 2*i + 1
which is the round-to-nearest of 2^32 * SEED_N / d. Verified equal to the
previous table for every entry.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…n.mk A partially-copied directory got Makefile, common.mk and *.in. Any other included fragment was left behind, so an include that resolves in the source tree fails from build/ -- invisible until someone runs the target there. The flattened DUT trees' catalog.mk and build.mk were missing from every build tree, which broke `make -C build/hw/syn/xilinx/dut <dut>` and the fpga_gate along with it. Also stop .gitignore's `/.*` from swallowing .github. Ignore rules do not apply to tracked files, so the existing workflows were unaffected and the rule looked harmless -- but a NEW workflow or action was silently dropped from every commit, with nothing to notice. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
31 per-DUT Makefiles were 31 copies of the same eight assignments, differing only in their values. They are now one catalog.mk per flow (_PRJ/_IP/_CFG/_INC/_PKG/_EXT per DUT, with the include and package fragments shared) plus one build.mk that the dispatcher copies in as the work tree's Makefile -- the role the per-DUT files played. Adding a DUT touches catalog.mk only. The dispatcher's 21 (resp. 10) identical target blocks collapse to one pattern rule over $(DUTS), which also gains `%-power` and `list`. Semantics-preserving, checked rather than assumed: every DUT's resolved variables were dumped before and after and diffed. 20 of 21 matched exactly; the differing one was rtu_top, which lost its unittest include and two packages in the first pass. rtu_top is removed here instead -- its wrapper duplicated hw/unittest/rtu_core and nothing referenced it. `override CONFIGS +=` on the flows' mandatory defines, so a CONFIGS on a make command line adds to -DSYNTHESIS -DVIVADO and the DUT's own config rather than replacing them. Command-line variables win over `+=` with no warning; fpga_gate only escaped this because it passes CONFIGS through the environment, which appends. Drops the tcu-sparse-amo-rvc synthesis case, which no DUT provided. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Four asap7_* files sat in ci/ because that is where the installer was written, not because they belong to CI: they are standard-cell collateral, and hw/syn/libs/ is where the rest of it lives. configure copies only Makefile, *.mk and *.in out of a hw* directory, so the manifest and preparation script are not in the build tree. They are inputs rather than build artifacts, so install.sh.in reads them from the source tree through @VORTEX_HOME@ instead of being copied; only the installer itself is instantiated. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…fixes
The flow could only synthesize whatever TOP_LEVEL_ENTITY it was handed.
dut/catalog.mk now declares the twelve DUTs -- the same
hw/unittest/*/VX_*_top.sv wrappers the Xilinx flow synthesizes -- as a
top, an include path and a define set each, and dut/Makefile forwards
them to the flow. No per-DUT Makefiles are needed: the flow already
includes hw/syn/extensions.mk, which derives each extension's RTL_PKGS
and include paths from the resolved XCONFIGS.
PREFIX defaults to the DUT name so each gets its own tree. That is
load-bearing, not hygienic: $(BUILD_DIR)/src is cached and is NOT
regenerated when EXTRA_INCLUDE changes, so two DUTs sharing a tree
silently synthesize the first one's sources.
synth_summary.py collapses reports/{stat_lib,sram_area,worst_slack,tns,
power}.rpt into one synth_summary.csv, mirroring what the Xilinx flow's
project.tcl already writes. Format knowledge stays next to the tool that
produces it, so a consumer needs no parser per report.
Two measurement bugs, both of which made a number look right while being
wrong:
- report_wns is worst NEGATIVE slack and clamps at zero, so every design
that closed reported 0.00 and an Fmax derived from it was the target
clock read back. run_sta.tcl now also emits report_worst_slack, which
is signed: om at 800 MHz closes with +0.0318 ns, i.e. 820.9 MHz. ABC
maps to the target period and stops, so closing with picoseconds of
margin is the normal outcome and the sign is the whole signal -- 2
digits of precision is not enough to see it.
- A CONFIGS on a make command line silently defeats every `CONFIGS +=`
in a makefile. dut/Makefile passed each DUT's defines that way, which
killed the flow's own `CONFIGS += -DSYNTHESIS -DASIC -DYOSYS`, so the
ASIC RAM path was never taken and arrays inferred to flip-flops: the
cache DUT came out at 1.08M cells, 122,724 um^2 and zero SRAM area
against an actual 423k / 47,068 / 16,307. The dispatcher now uses the
flow's documented EXTRA_CONFIGS channel and the mandatory defines are
`override`, so the trap cannot be re-armed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
fpga_gate.py was 856 lines of which the great majority -- catalog loading, config_hash, threshold resolution, known_issue, the resumable session, the scheduler, the gate and the report -- says nothing about Vivado. Only the metric names, the build invocation, the log markers and "what makes two runs comparable" do. Those move behind a Tool adapter in ci/synth_gate.py; fpga_gate.py becomes an entry point that pins --tool=xilinx. The Yosys adapter lands in the next commit. No behaviour change, verified against the previous script rather than argued: identical --list output, identical config_hash for all twelve builds (11 of 12 still matching their recorded baselines -- tensor was already stale from the impl_strategy addition, under both versions), and identical verdicts and report tables across unchanged/worse/better metrics, record mode, and the build-failure path. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The open-source counterpart of fpga_gate: the same golden/threshold/
ratchet discipline over sv2v -> Yosys -> ABC -> OpenSTA on ASAP7 (RVT,
TT), gating post-synthesis Fmax and standard-cell area. Same DUTs as the
Xilinx gate -- the hw/unittest wrappers, declared once in
hw/syn/yosys/dut/catalog.mk -- so `make -C hw/syn/yosys/dut om` and the
gate build the same thing, and a divergence between the two tools is a
finding rather than an artefact of two DUT lists.
Fmax does not mean on this flow what it means on Vivado. ABC maps to the
target period and stops, so a DUT that closes does so with picoseconds of
margin and its Fmax sits just above the clock it was built for by
construction. Cell area is the metric that actually moves; the
target-frequency check is the real Fmax assertion.
Tool versions are part of config_hash, which they are not on the Vivado
side: Yosys/ABC move area between releases by more than the 5%
tolerance, so a toolchain bump must read as STALE ("re-record") rather
than as a regression blaming the RTL. The strings are normalised to drop
the git sha and the compiler that built the binary, so rebuilding the
same yosys does not invalidate every number.
CI: its own nightly workflow, not a ci.yml cell. A DUT is 1-2 hours, so
eleven in one cell would be a day -- the builds fan out to one standalone
hosted job each, fail-fast disabled so one regression cannot cancel the
ten other measurements. Like fpga_gate.yml it pins master and skips
itself when master has not moved, but a hosted runner keeps no state
between runs, so the "already gated" marker is an actions-cache entry
keyed by SHA and spec hash rather than a file in ~/.cache. synth_report.py
joins the per-job reports into one summary table.
Baselines recorded for the five characterised DUTs; the other six carry a
known_issue naming what is missing, so the nightly builds and reports
them without asserting numbers nobody has reviewed. The cross-check
against the FPGA goldens is what says the memory inference is right:
cache 89 BRAM / 16,307 um^2 SRAM, raster 10 / 3,728, tex 0 / 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
continuous_integration.md 3.5 covers both gates and what a Tool adapter supplies; 4.5 is the new fan-out workflow. synthesis_analysis.md gains the dut/ dispatcher and the gate, plus the two things a reader needs before trusting an Fmax from this flow: ABC closes to the target, and report_wns clamps at zero. AGENTS.md gets the synthesis baselines under the same never-hand-edit rule as the perf ones, and the note that the two gates measure the same modules -- so the DUT catalogs must stay in step. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
No description provided.