Conversation
Its deliberately-corrupted DBs made SanityCheck print its violation diagnostic into every test log (CI and local) while the intercepting tests passed, reading as a failure that never happened. The check itself still runs after every stage in every stage test via StageRunner. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…perations reference Resolves knowledge-gap tickets from the hog-fpga, castle-drawing and starfield learner runs. Operations reference (closes #113, #114 in part): - add `Bit`/`Boolean` to the Comparison `Applies to:` line, plus a subsection covering them as operands and stating that ordering comparisons are rejected - normalize the Selection section to the `Applies to:` convention and introduce that convention once at the top of the Operations part - cross-link the `Bit`/`Boolean` and Enumeration type sections to the operations that apply to them, and link comparison-ops from from-verilog Elaboration-time vs hardware (closes #109, #107, #103): - qualify the "both branches" rule: Scala checks both, but only literal widths are tracked at the Scala type level, so a parameterized `generate if` needs no guard. Note the ED implicit `.toScalaBoolean` and the RT/DF hardware-`if` default - drop "these loops are unrolled by the compiler", contradicted by the adjacent example: a process loop stays a loop - document the process-scope iterator as a hardware value that cannot be read into Scala, with the design-scope-loop alternative - qualify the part-select base as allowing a process loop iterator, and add the variable-base row to the from-verilog table Verilog mappings (closes #106, #91, #112): - document `localparam`: a `val` is emitted only when it is a DFHDL constant, which the `: Int <> CONST` ascription forces - list an inline expression as a valid child-port connection - document enum declaration scope, and that the generated typedef's placement follows usage rather than the Scala declaration site - document the generated global definitions/package files, which were previously only visible inside generated snippets Naming (closes #110): - a port sharing a design class's name is not a collision; types and terms are separate namespaces. Remove the `@targetName` workaround that contradicted the page's own `new` recommendation Bit concatenation (closes #95): - document the per-bit connection loop and the ascribed-`var` lane accumulation as the two ways to build a value from a collection All added snippets and generated HDL were compiled against 0.22.0+38-ba527c30-SNAPSHOT.
…` for HDL naming (#454) Scala rejects `@targetName` on a top-level class, so a design could not emit a module name different from its Scala class name. DFHDL naming now reads a dedicated `@dfhdl.hw.annotation.setName` annotation in the plugin's `getFinalName`, covering ports, variables, methods, design parameters, and design classes (including top-level ones) through the one mechanism. The annotation is a plain StaticAnnotation, kept out of IR annotation lists; `@targetName` remains a purely Scala/JVM concern (the AES defs keep it for erasure disambiguation alongside the new annotation). Platforms submodule migrated accordingly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e first block (#456) A default value on a DFHDL parameter in a non-first (curried) parameter block crashed scalac at Erasure: the companion default getter takes the earlier blocks' parameters as arguments, which the plugin's parameter threading cannot consume. MetaContextPlacerPhase now reports clear errors instead: a design/interface class must declare all its DFHDL parameters in a single parameter block, and a defaulted DFHDL parameter must be in the first block. Plain Scala blocks stay free, so a dependent-typed DFHDL block after a plain block (RTGenericRom's `depth.type`-sized ROM) remains legal. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fixes #459 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…named `top` (#458) PreTyperPhase's auto-@top injection spelled the annotation as an unqualified `top` identifier, which a design class itself named `top` (the common Verilog top-module convention) captured, failing compilation with an inscrutable "Cyclic reference involving class top". The injection is now anchored at the root (`@_root_.dfhdl.top(true)`), immune to both the class-name capture and a user package/object named `dfhdl`. TopAnnotPhase matches the annotation by resolved symbol and the plugin's rightmostName-based detection matches the qualified spelling, so no consumer changes. Regression test: issues/i458.scala keeps the design class unannotated so the auto-injection path is the one exercised; without the fix the whole lib test scope fails compilation on it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n vectors Fixes DFiantHDL#117 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ew relative `.eby` (#119) An anonymous +/-/* cone assigned or connected to a wider value now re-evaluates at the target's width and sign, matching Verilog's assignment-context width propagation: every operand widens (recursively through the anonymous cone) and the operations stay modular at the target width. The carry spelling is kept where provably identical: a binary op over leaf operands, same sign as the target, whose carry width fits the target exactly (bare `a +^ b`) or exceeds it decidably (carry + truncating resize). A promoted carry op is never extended, only truncated; extension of a carry result is sign/op-dependent and was the root of the formally confirmed miscompiles: result-level zero-extension of unsigned chains meeting signed targets, shallow (top-only) promotion of nested chains, zero-extension of a widened subtraction carry, and the illegal EXTEND_S(<expr>) emission (out-of-range bit-select). `.eby(k)` is a new relative widen-by operation on UInt/SInt/Bits, sugar for `.resize(width + k)`. All printers render a widening relatively (DFHDL `.eby(k)`, Verilog `EBY_U`/`EBY_S`, VHDL `eby`) exactly when the target width is an anonymous `base + k` increment of the source width, so parametric widening stays symbol-free while named/literal widths keep their absolute spelling. The Verilog EXTEND_S/EBY_S operands are guaranteed indexable by a new NamedVerilogSelection widening criterion plus a fused sign-conversion emission; VHDL carry mul prints infix (numeric_std mul is already full-width; `cmul` was emitted but never defined in dfhdl_pkg). Verified by per-output yosys SAT miter proofs against a hand-written Verilog golden (19/19, from 10 failures before the fix) and by the full test suite, with zero reference-output churn. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e canonical widening form The IR gains one invariant: an arithmetic Func's type always equals its (aligned) operands' type. The carry operators elaborate as modular funcs over operands widened by explicit aliases (`x +^ y` is `x.eby(1) + y.eby(1)` after common-width alignment), with no special-cased Func return type, and the target-context widening in toDFXIntOf loses its carry-fit branch: the widening always evaluates at the target, and the SPELLING of the result is reconstructed at print time by two new DFValAnalysis extractors: `Eby` (literal-delta widening alias) and `CarryFunc`, whose carry-width equations (max+1 for +/-, operand-width sum for *) are decided symbolically via the linear-form calculus, so a parametric `a *^ b` reconstructs even though its operand delta is not a literal. Printers: DFHDL prints CarryFunc as `x op^ y`; VHDL reconstructs cadd/csub and prints a carry mul infix (numeric_std multiplication is already full-width; the previously emitted `cmul` was never defined in dfhdl_pkg); Verilog prints a carry func bare exactly when every consumer provides its width context (a net RHS or a same-width func operand) and the explicit EBY/EXTEND operand forms otherwise, so the self-determined-context truncation genus is structurally impossible and the NamedVerilogSelection carry-naming criteria are deleted. The Verilog-semantics warning machinery derives carry-ness from the CarryFunc shape and walks through the operand widening aliases. Widening printouts prefer the RELATIVE `.eby(k)` spelling as the canonical form whenever the delta is a known bit count, including between literal widths (a widening between literals carries no spelling in the IR, so `x.resize(9)` over an 8-bit x prints back as `x.eby(1)`); a width given by a named parameter or constant keeps its absolute spelling by name. A deliberate semantic edge of the unification: an anonymous explicit-carry result consumed by a wider context now re-evaluates at that context (naming the value pins its width), matching how every other anonymous arithmetic expression composes. Verified by the 19-case yosys SAT miter matrix against the Verilog golden and the full test suite. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ns (#116) The TC width-fit check decided only when the width difference folded to a constant, so `SInt(2 * W) <> a * b` (RHS width W) errored as undefined. The decision now falls back to a linear-form non-negativity proof over the validity domain (every width >= 1): `2 * W >= W` is accepted for a free parameter W, and a provably violated relation (`W >= 2 * W`) upgrades the vague undefined error to the definitive larger-than one. A literal target against a free parameter (`16 >= W`) stays undecidable and is still conservatively rejected. The proof core moves into the shared Calc so it runs in the same linearization mode as the diff; equality/similarity queries remain proof-free. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…HDL-aware diagnostics (#455) Fixes #455 A `reduce(_ ++ _)` over raw port part-selects can never typecheck: `reduce` fixes its type parameter to the element type, which carries the port's own modifier and, until now, the width argument's singleton type (`Bits[LANE.type]`), and no operation result can land back on either. Three independent defects hid behind the one report: - A non-literal width survived as a singleton type. It now collapses where the value ENTERS the width algebra: `IntParam.fromValue`'s precise conversion is restricted to `Int & Singleton` (a `DFConstInt32` parameter falls to the wide conversion, now monomorphic at `IntParam[Int]`), so `Bits(LANE)` is `Bits[Int]` while `Bits(8)` stays `Bits[8]`, and the element ascription `Seq[Bits[Int] <> VAL]` makes the reduce work by plain subsumption, with no conversions and no adapters in the elaborated IR. An abstract `Int & Singleton` type parameter (generic code over literal widths, e.g. `Matrix`) still gets the precise conversion, deferring precision rather than dropping it. The explicitly written singleton type (`Bits[LANE.type]`) remains available through its `ValueOf` given. - The plugin's `CustomReporter` re-rendered the same inline-expansion error up to three times, once at a corrupt position: a macro-synthesized tree's innermost frame pairs the user's source file with the span of the macro's own splice, and dropping the outer position chain exposed it while also bypassing the compiler's position-keyed dedup. The position is now normalized to the first inline frame that belongs to the compiled unit, and the normalized (position, message) pair is deduplicated in `isHidden` so the error count matches what is rendered. - The type printers hid the modifier: a port-typed requirement printed as `<> VAL`, rendering the remaining mismatch identically on both sides. Both twins (the plugin's `modifierText` and core's `ShowType`) now name a port by its direction, and a type mismatch whose required side is a DFHDL value is re-issued without the compiler's postscript (the transparent-inline note and the import suggestions never apply to a DFHDL mismatch). The repro now reports once, at the user's expression: `Found: Bits[Int] <> VAL / Required: Bits[Int] <> IN`. The workaround reported in the issue (ascribing the singleton element type) compiled but failed elaboration with a width error; the collapsed ascription and `.bits` are the correct spellings. Regression tests pin the collapse and the working reduce in `SameWidthArithSpec` and the printed types in `TypePrinterSpec`; the reporter behavior is manually verified, since `assertPluginError` renders without going through `CustomReporter`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…al diagnostic rewriting Follow-up to the issue #455 diagnostics: the one error the un-ascribed reduce-over-port-slices shape still (correctly) produces now carries a dedicated remedy instead of a bare mismatch. The rewriter recognizes the shape (a plain computed value against a declaration-modified requirement of the SAME DFHDL type), identifies the enclosing call by name (the typed tree does not exist yet at reporting time, but the unit's parse tree does, and the innermost `Apply` with an argument containing the error span is the call whose type parameter was committed), and spells the one-token fix with the actual type: `.reduce[Bits[Int] <> VAL](...)`. An unidentified caller keeps a conditional wording of the same note. The rewriting itself (position normalization, dedup identity, postscript drop, guide rails) moves out of `CustomReporter` into a shared `DiagnosticRewriter` that `PluginTestPhase` now applies to its nested snippet compilations, so `assertPluginError` specs assert on exactly what a user reads; previously the reporter's behavior was manually verifiable only. The normalization's unit-source anchor becomes an explicit parameter: a nested diagnostic's position chain extends past the snippet's virtual source into the enclosing real unit (the marker call site), so the outermost frame does not identify the compiled unit there. The new `assertSinglePluginError` asserts a snippet produces EXACTLY one error, which pins the dedup on top of the message text: the typer re-raises this mismatch through the inline expansion of `++`, once at a corrupt macro-splice position, and all re-raises must collapse into one rendered diagnostic. `TypePrinterSpec` pins the full guide-railed message that way. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
In a DFHDL compilation the compiler's selection-error addenda mislead rather than help: the import-suggestion machinery proposes DFHDL's internal conversions (`InitValue.fromValue`, `Exact.fromValue` and friends) for EVERY receiver, including plain Scala ones, and the extension-attempt transcript restates the receiver in raw types over dozens of lines. The diagnostic rewriter now reduces a `NotAMember` error to its core sentence, `value mem is not a member of UInt[Int] <> OUT`, cutting at the exact addendum openers `ErrorReporting.selectErrorAddendum` can append (the leading period there belongs to the addendum). A tried-but-failed extension keeps that one fact as a bare ` (extension method tried)`; the did-you-mean hint, which only appears when no other addendum does, is kept, and so is the `-explain` explanation. `TypePrinterSpec` pins all three shapes through the real rewriting path: no extension involved, extension tried, and a plain `Int` receiver. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rrors Upstream computes the hint only when no other addendum exists, and in a DFHDL compilation the import-suggestion addendum is never empty: the Exact/DFVal conversions make every selection on every receiver look "available as an extension method", which is the same mechanism behind the stripped import spam. So `x.toStrig` never said "did you mean x.toString?" to a DFHDL user at all; stripping alone cannot restore what was never computed. The rewriter recomputes the hint after the strip, exactly the way `NotAMember.msg` would have (`DidYouMean.memberCandidates`, `closestTo`, `didYouMean`, all public API). The message's `site` and `proto` are private constructor parameters, reached by reflection; any failure there just means no hint. The extension-tried variant keeps its bare parenthetical without a hint, matching upstream, where an attempted extension also suppresses it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fixes #457 Applying `.width` on a DFType constructor is now the DFHDL counterpart of Verilog's `$clog2` width derivation: construct the type with `.until`/`.to` and recover the width the constructor computed, as a constant DFHDL `Int` rather than a plain Scala `Int`, so a parametric width stays symbolic: val ADDR_WIDTH = UInt.until(DEPTH).width // elaborates as clog2(DEPTH) `.length` joins it for the types where "how many" is a natural question: for `Bits`/`UInt`/`SInt` DFTypes and values it is the number of bits, identical to `.width`; for vector DFTypes it is the number of elements, matching the value-level vector `length` that already existed. The user guide gains a "Width and Length Queries" section in the type-system Operations reference; the `clog2` anti-pattern warning now completes its own story with the recovery idiom; and the Vector Element Access table drops a stale `vec.size` row (no such member exists) in favor of the verified `length`/`width` rows. `WidthLengthQueriesSpec` pins the elaborated constants, including the symbolic parametric width and the vector length/width distinction. `TypePrinterSpec`'s extension-tried diagnostic case moves from `o.length`, which this change makes legal, to `Bit`'s `length`, which no extension serves. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… generated code Follow-up to #457. `val ADDR_WIDTH = UInt.until(N).width` elaborated without the binding's name: `toDFConst` mints a fresh NAMED const for a literal width, but a parametric width already exists as an anonymous member (`clog2(N)`, created inside the type constructor), and the handle was returned untouched, so the printers inlined the expression at every use site instead of declaring the constant. The new `toDFConstQuery` sibling rebinds a pre-existing constant reached under a named context through a named Ident, never a meta restamp (issue #449), and the three user-facing query sites use it: `DFType.Ops.width` (which the `length` delegates share), the vector type `length`, and the value-level `DFVal.width`. The generated code then reads val ADDR_WIDTH: Int <> CONST = clog2(N) val a = UInt(ADDR_WIDTH) <> OUT with the constant referenced by name everywhere, including width checks (`.resize(ADDR_WIDTH)`). `toDFConst` itself stays wrap-free on purpose: operations pass constants as function ARGUMENTS under the operation's own context (`repeat`'s count, for example), and a wrap there would steal the result's name for an argument. The plugin's naming scope completes the picture: only the spine apply of a `val` carries its name, so an inner query such as `value.width.toScalaInt` stays anonymous and creates no member, and the full suite shows no other printed-output change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Resolves DFiantHDL#115 and DFiantHDL#88 A derived parameter is not declared as a parameter in DFHDL: a parameter default cannot reference a sibling parameter (now stated at the Parameter Block Syntax `_default_` bullet), and no separate parameter is needed, since the derived value is computed in the design body as a named constant that serves everywhere a parameter would, port widths included. The new subsection demonstrates the pattern with a generic register parameterized solely by its initialization value (`Bits[Int] <> CONST`), deriving the register length with the `.length` query and sizing the ports with it. The generated Verilog and VHDL are included inline, both captured from real runs and lint-verified (verilator, ghdl): the derived constant appears by name (a Verilog localparam, a VHDL generic), the parameter width is fixed by the applied argument while its value stays overridable, and keeping two parameters consistent by hand, the mismatch trap of dfhdl_by_agents#88, is ruled out by construction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…NCs printed natively per backend A value-receiver width/length query now elaborates to a `DFVal.Func` with the new `Op.width`/`Op.length` instead of materializing a constant, so the generated code keeps the value-to-width relation: SystemVerilog spells `$bits(x)`/`$size(x)`, VHDL spells `x'length`/`bitWidth(x)` (constant arguments only: a design-level constant becomes a generic whose default cannot name a port), and the pre-SV Verilog dialects inline the width parameter expression (shared `AbstractValPrinter.csInlinedWidth`). Type-receiver queries still materialize width constants. - `Func` constData reads the argument's TYPE, so the query is constant over a non-constant argument; `calcFuncData` gets the matching type-driven case. - `IntExprCalc` linearizes the queries through the argument type's width parameters, with product-base equivalence so `vec.width` matches `W * N`; `linearOfTypeWidth` moved into `Calc` (mode-consistent; its `widthIntOpt` shortcut folded top-design parameters through their defaults). - `DropStructsVecs` folds length-over-vector into the element-count parameter value before flattening destroys it; width needs no fold. - DFacsimile folds the queries to per-instance resolved constants (`paramDependent` walks the argument's type refs for them). - Docs: the InitReg inter-dependent-parameters outputs now show `$bits(INIT)`/`INIT'length` (verilator/ghdl lint-verified); the type-system query section documents the native spellings. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ock body `process(all): y := x` parses as a type ascription and used to fail with obscure typer errors. Two interception points now report a dedicated error spelling out the fix from the statement's own source: the PreTyper parse-tree rewrite (well-formed trees; the statement is neutralized so no follow-on errors surface) and a CustomReporter override for bodies that fail the type parse (a parser error skips every plugin phase while the typer still runs, so the recovered tree's ascription errors are rewritten at reporting and collapsed onto one). The override is gated on a parser error having been reported, so ordinary compilations never pay for it. The nested snippet pipeline now types parser-recovered trees like the real pipeline, making the override testable (`assertPluginErrors`); RTProcessSpec is renamed ProcessSpec and hosts the new tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…#464) A narrow anonymous arithmetic chain inside a `.sel` assigned to a wider target evaluated modularly at the operand width, with only the selection result extended afterward, silently diverging from the Verilog `?:` it translates (whose branch operands are context-determined). An anonymous DFXInt-typed sel converted to a wider type now re-types to the target, with each branch re-entering the widening and the condition untouched, so `dx := c.sel(xb - xa, xa - xb)` emits `c ? (xb - xa) : (xa - xb)` in the wider assignment context, faithful to the source intent. The promotion machinery moves to its own CarryPromote file: widenedOpt (the widening decision and fresh-func construction) and the Verilog-semantics warning helpers; the general toDFXIntOf conversion stays in DFDecimal and falls back to the leaf conversion when no widening applies. All six probe shapes (carry-fit, beyond-carry, unsigned, mixed-sign, nested sel, sel-inside-arith) are SAT-proven equivalent to a hand-written `?:` golden via a yosys miter. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…464) A conditional expression in a type-free position (a connection RHS or an operand of a wider operation) was typed by its branches and converted as a leaf, evaluating the branches modularly at the narrow width and only extending the selected result, silently diverging from the per-branch assignments it lowers to. An anonymous DFXInt-typed conditional header converted to a wider type now re-evaluates each branch at the target: a fresh terminal ident over the widened re-evaluation is built inside each branch block (branch-local named values stay in scope), the superseded terminal is dropped explicitly (idents are consumed positionally, so the sweep alone would keep the narrow cone alive), and the header is revised in place to the target type, the same revision its construction applies. The type-driven positions were already faithful (each branch converts under the expected type at construction) and are regression-pinned. Mid-construction the designDB flat snapshot is unavailable (open-owner state), so the conditional structure is recovered from the raw creation-ordered member list via ref walks; and to keep that list properly nested, MutableDB gains a re-entrant `insertingAfter` insertion mode that places additions right after an anchor inside a built block. All four probe shapes (connection, arith-operand, match, nested if) are SAT-proven equivalent to a hand-written `?:` golden via a yosys miter. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ings see through conditionals (#464) Two remaining divergences of the target-context widening model and one diagnostic gap: - A shift's LEFT operand is context-determined in Verilog (the amount is self-determined), so an anonymous shift converted to a wider SAME-SIGN type now re-types to the target and its left operand re-enters the widening: the carry bit survives a `>>` and a `<<` pushes into the extension range. A sign-CROSSING shift context stays a leaf: a shift evaluates at its operand's own signedness (an arithmetic-vs-logical `>>` difference), so the conversion cannot move to the operands and the explicit spelling states the intent there. - Unary minus is truncation-commutative and joins the widened arithmetic ops, so a negation cone re-evaluates at the target instead of wrapping narrow and extending. - The Verilog-semantics narrow-chain detectors descend anonymous conditional-expression branches (via the recovery shared with the widening), so a chain hidden one `if`/`match` away from a `/`, `%`, comparison, or shift is no longer silently missed. All six probe shapes are SAT-proven equivalent to a hand-written golden via a yosys miter. Also drops two redundant `asInstanceOf[ir.DFDecimal]` casts (`asIR` is precisely typed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
NVC gained Verilog support (matured in 1.22), so NVC.scala is split QuestaSim-style into NVCCommon + NVCVHDL + NVCVerilog. The Verilog front-end analyzes with `-a --keywords=1364-1995|2001` (an analysis option, unlike the VHDL front-end's global `--std`), predicts the Verilog work-library units (one WORK.<NAME> per module plus WORK.<TOP>.elab, no secondary architecture unit), and requires NVC >= 1.22. The SystemVerilog dialects throw: NVC cannot parse the generated sv output (size casts, unpacked-array typedefs). Since NVC is one binary serving both languages, `nvc` is now a both-languages selection like `questa`/`vivado`: bare `-t nvc` sets both tools, and in the `a/b` slash syntax it resolves by slot (first=Verilog, second=VHDL). AvailableTools holds the per-language front-ends in the verilog*/vhdl* scopes plus a questa-style marker object with the matching SimulatorOptions conversions. Linting generated output additionally waits on an upstream fix: released NVC rejects a block comment inside a `define macro body (nickg/nvc#1636), which dfhdl_defs.vh uses for its Verilator lint pragmas. Once a release carries the fix, raise NVCVerilog's version floor and enable nvc in FullCompileSpec's Verilog linters and testApps' verilogTools. Verified locally on NVC 1.22.1 that analyze/elaborate/run of the full AES CipherSim works end-to-end once past that preprocessor limitation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…im image Xezim (https://github.com/aionhw/xezim) is a SystemVerilog simulator with no local install channel, so it runs from the DFTools v1.2.0 `sim-xezim` image (linux-x64 only): the `auto` tools-location falls back to the image whenever no local `xezim` exists. A single invocation parses, elaborates, and runs, so linting maps to `--compile -s <top>` and simulating to `--simulate -s <top>`; all sv dialects map to `--sv2017` (1800-2023 grammar by default, no IEEE 1364 mode, so v95/v2001 throw). The simulate command pins `--max-time 1000s` because xezim's default silently caps simulated time at 100us, unlike the other simulators' unbounded default. xezim exits 0 even when it reports errors, so the tool's ProcessLogger owns error detection (compile `: error:` diagnostics, `Simulation error:` elaboration failures, and runtime `** Error`/`** Fatal`). Foreign IP DPI libraries are wired via `--dpi-lib`. Verified end-to-end through the image (WSL apptainer): EmptyDesign lint and simulate run green, and an AES lint fails correctly through the logger. Broader enablement waits on upstream fixes, all reported with minimal reproductions: - aionhw/xezim#106: false "Implicit net under `default_nettype none" on explicit wire ports with unpacked-array typedef types (blocks the vector/opaque-port designs, e.g. the AES suite); - aionhw/xezim#107: exit code 0 on parse/elaboration/runtime errors; - aionhw/xezim#108: DPI-C imports inside a parameterized child module are silently no-op'd (blocks every DPI foreign IP, so the ips sim specs do not list xezim yet; found via a vga_monitor validation run that confirmed the rest of the chain works under xezim). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Aug 9, 2026
soronpo
pushed a commit
that referenced
this pull request
Aug 13, 2026
…ard's reach Fixes #482 `dfhdl.top` was a top-level member of the `dfhdl` package, so every `import dfhdl.*` bound the name `top`. A user's own design class named `top` (the standard Verilog top-module name) then lost name resolution to it from any OTHER compilation unit: a package member referenced across files is the lowest-precedence binding, below a wildcard import. `new top(WIDTH = 8)` was checked against the annotation's constructor and reported "dfhdl.top does not have a parameter WIDTH", naming neither the collision nor what the identifier had resolved to. #465 had fixed only the declaration-site half (#458), by qualifying the plugin's injected annotation. The annotation now lives at `dfhdl.hw.annotation.top`, beside the other user-facing hardware annotations, and reaches user code only through an explicit import or the `@hw.annotation.top` spelling. Nothing named `top` enters scope through `import dfhdl.*`. `dfhdl.hw.annotation` becomes a PACKAGE rather than an object to host it: `top` needs five option sets that live downstream in `lib` and cannot be compiled into core's object, while a package is open across subprojects. `constraints` stays in the same file, since `HWAnnotation` is sealed. The plugin's auto-injection is spelled `_root_.dfhdl.hw.annotation.top`, so an auto-topped design still needs no import; only a hand-written `@top` does. `rightmostName`-based detection keeps matching every spelling. `ElaborationChecksSpec` takes its import on line 1 rather than a new line, because 46 of its assertions pin absolute line numbers. A test-scope `type top = dfhdl.hw.annotation.top` alias would have spared the test files their import, and was rejected: it reproduces this very bug inside lib's test scope, where the regression fixture lives. Co-Authored-By: Claude Opus 5 (1M context) <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.