Skip to content

[pull] main from B-Lang-org:main#183

Merged
pull[bot] merged 18 commits into
chenm001:mainfrom
B-Lang-org:main
Jul 11, 2026
Merged

[pull] main from B-Lang-org:main#183
pull[bot] merged 18 commits into
chenm001:mainfrom
B-Lang-org:main

Conversation

@pull

@pull pull Bot commented Jul 11, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

krame505 and others added 18 commits July 11, 2026 13:33
This is a squash merge of GitHub PR 959, with a fix from PR 928.

Refactor handling of input port splitting to avoid flattening all
input ports into curried method arguments, and instead preserve tuples
of port values for inputs all the way through ASyntax as ATuples.

In the printing of ASyntax, method input types are now a List of types
rather than a single type.

Handle the case when a method argument has no ports.

Add missing ATuple plumbing all the way through Verilog backend.

APaths cleanup and fixes.

Drop PrimUnit args in AConv instead of trying to handle zero-width
wires in ASyntax.

Unified _PORT_ port naming: drop ARG/RES, suffix split ports

    Method ports are now named consistently: an argument is
    <meth>_<argnum> and a result is just <meth>.  When an input or
    output is split across several hardware ports, each port gets an
    extra _PORT_<portnum> suffix (e.g. enq_1_PORT_2, first_PORT_1).
    This replaces the _ARG_<a>_<p> and _RES_<n> scheme.

    MethodArg now carries a Maybe port index and MethodResult a Maybe
    result index (Nothing = un-split, no suffix); a shared
    splitPortNums helper and a new fs_port string drive the naming,
    and the dead fs_arg/fs_res are removed.

Support SplitPorts for noinline function arguments and results.

    Mechanism: a new `primNoInline` evaluator primitive records the
    (possibly split) input/output port names -- computed by the
    SplitPorts class during the wrapped module's elaboration, the same
    way `primMethod` records method ports -- onto the foreign-function
    value by rewriting ICForeign.foports during IExpand.  Unlike
    primMethod it leaves the value transparent, so a noinline result
    can be deconstructed in expressions.  No driver (bsc.hs) changes.
    Tests: testsuite/bsc.verilog/splitports/Noinline*.bs

Fix port mapping for imported methods with multiplicity > 1

    This is taken from PR 928.

    createMapForOneMeth pairs each method-internal port name with the
    actual Verilog port name.  The method side numbers ports with the
    multiplicity copy as the outer index and the arguments inner
    (matching the order AVerilogUtil's "inps" emits), but the Verilog
    side expanded the whole concatenated list with the ports outer and
    the copy inner.  For a method with more than one argument and
    multiplicity > 1 that transposed the two lists, producing
    mismatched connections (e.g. .A_2 wired to the A_3 net).

    Expand each section (inputs, enable, outputs) with the
    multiplicity copy as the outer loop and the ports inner, matching
    both the method side and AVerilogUtil.  The mult <= 1 path is
    unchanged.

    Adds bsc.verilog/portprops/IncorrectPortMapping.bsv, checking that
    each submodule port connects to its matching internal wire.
This is a squash merge of GitHub PR 983.

Add SplitVector utility.  The package only depends on the SplitPorts
*class* (defined in the Prelude), not on anything in the SplitPorts
package.

Add "unShallowSplit", "unDeepSplit", and "unNoSplit" utility
functions.
This is a squash merge of GitHub PR 923.

Store root-cause and class info in SolvedBinds for incoherence
diagnostics.

Diagnose transitive incoherence (T0158 warn vs error) based on class
annotation and -incoherent-instance-matches flag.

Test cases (with flag on and off) added.
This is a squash merge of GitHub PR 926.

Add the following simplification rule to ITransform:
  if c then undefined else e  -->  e

This fires during the improveIf fallthrough in IExpand for patterns
like invalid enum tag arms, eliminating redundant case blocks that
BSC was generating for pack/unpack of sum types.

The symmetric rule (if c then e else undefined --> e) is intentionally
absent: pack/unpack identity chains produce "if (x==k) k undefined"
with ICUndet in the else branch, and firing there would collapse the
chain before the k->x rule can convert it into an identity.

New test case and test fixes.
GitHub PR 929.

Use a size/type map instead of crawling the list of VMItems.
GitHub PR 936.

* Use strict ByteString with offset indexing for binary deserialization

Replace the [Word8] linked list in BinData's In monad state with a
strict ByteString and integer offset. This eliminates millions of
cons-cell allocations and pointer chases during .bo/.ba file reading.

* Use toStrict to convert lazy ByteString in readBinFilePath

B.toStrict is the canonical lazy-to-strict conversion and has been
available since bytestring 0.10, which predates the oldest supported
GHC (7.10.3). It replaces the equivalent BS.concat . B.toChunks.

* Remove now-unused hash functions from Util

* Use indexMaybe in BinData.getB

indexMaybe needs bytestring >= 0.11, which ships with every GHC in the
CI matrix (floor 9.6.7, plus 9.8/9.10/9.12/9.14), so it is safe within
the project's tested support range. It replaces the explicit bounds
check and the partial BS.index with a single total lookup — exactly one
bounds check per byte and no partial-function call.

* Split Bin Flags serialization into NOINLINE chunks

With the strict state-passing In monad, GHC's simplifier blows up on
the single 135-step writeBytes/readBytes chains in the Bin Flags
instance: GenABin.hs alone needed ~15.9 GB of heap at -O2 with GHC
9.6.7 (~14.2 GB with GHC 9.4.7) and panics with heap overflow at the
CI build's -M5G cap, as well as at the Makefile's default -M4G.

Splitting the chains into NOINLINE chunks of 15 fields bounds what the
simplifier sees at once: GenABin.hs now compiles in ~0.9 GB peak RSS
and 1:36 wall (GHC 9.6.7, -O2, x86-64 Linux). The .ba byte format is
unchanged - the same fields are serialized in the same order.
GitHub PR 954.

* Add test for PrimStringSplit type correctness with -trace-eval-types

* Compute PrimStringSplit result type directly instead of using resType

resType uses dropArrows on the prim's type, which requires type
normalization to see through ATFs. Construct the concrete type instead.

* Test the Invalid arm of PrimStringSplit with an empty string

The existing test only evaluated stringSplit on a non-empty string,
covering the Valid result path of the evaluator fix. Add a register
initialized from stringSplit "" so the Invalid (iMkInvalid) path is
also forced at elaboration time under -trace-eval-types.
simCOpt moves block-local defs into their using function; the order came
from the Id sort, which is hierarchy-dependent. Sort by base name.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The port list came from an AId-keyed map, whose Ord is run-dependent.
Sort by base name.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
tsort breaks ties by the run-dependent AId Ord. Rank def nodes by
id-name around the tsort so the statement order is stable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The member defs were ordered by an AId-keyed map, whose Ord is
run-dependent. Sort by base name.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GitHub PR 10001.

When an Inout port does not need to be rendered in Verilog with the
".io(io)" module port syntax -- that is, when the port is not
connected to other ports of the module -- use a simple port
declaration.  While the dot notation is part of the standard, some
tools do not support it (like Verilator).

If a module has multiple Inout ports that are connected, continue to
use the dot syntax.  The alternatives are no more portable: Verilator
rejects port aliases, SystemVerilog alias and the V1995 tran primitive
alike, and iverilog rejects alias too.  However, when generating the
dot syntax, BSC now uses a port name (".io(io)") rather than a
submodule signal (".io(mod$INOUT)").

This eliminates the need for the "basicinout.pl" script, therefore the
"-verilator-filter" tests are updated with a new script, as well as
improved to also test for the order in which multiple scripts are
applied.
Evaluating a dynamic PrimBNot pushes the negation through PrimIf
structure so that constant leaves can fold.  The push recursed into
both branches of every PrimIf with no memoization -- its definition
site carries the comment "XXX When the same heap ref appears twice,
this does twice the work!" -- and its leaf handler re-heaped a fresh
application per visit, so a negation over a SHARED conditional DAG
performed work (and allocated heap) proportional to the number of
root-to-leaf PATHS, exponential in the DAG's depth.

Conditional-update pipelines build exactly such DAGs: K stages of
conditional swaps over an N-element vector deepen the DAG by two
if-levels per stage.  The original bug-1490 design (VsortOriginal.bsv)
has been documented as exhausting a 256M heap since the initial
open-source release (see also github #659); the new BNotShared.bsv
test is starker: 4,792 defs whose conditional DAG contains ~2^129
then/else paths -- a per-path push cannot terminate, while the
memoized push compiles it in seconds with default flags.

The push (new function pushBNot) memoizes its result per heap cell
(heapBNots in the evaluator state, following the existing extractWires
wire-set cache), heaps intermediate results so pushed output remains a
DAG, guards against self-referential structure with a visited set, and
starts from the WHNF argument so that re-dispatch through the
evaluator can still collapse all-equal dynamic selects (their residual
forms are returned inline, never frozen into cells).

VsortOriginal.bsv now compiles within the standard heap limit, so its
expected-failure entry is flipped to a positive test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The GHC 9.12.2 and 9.14.1 CI jobs fail VsortOriginal at the 256M cap
("Heap exhausted") while GHC 9.6.7 passes.  The live set is ~20 MB; what
the cap was actually measuring is bsc's baked-in allocation-area hint
(-with-rtsopts=-H256m, src/comp/Makefile), which sizes the RTS heap
toward 256M regardless of need, with a steady state a few MB above it
(262-267 MiB observed on GHC 9.6.7 and 9.12.4).  Caps at or just above
the hint ride the RTS's boundary accounting, which shifts with GHC
version and OS -- the same edge that has needed repeated per-test nudges
(272, then 275 in 1eba705).

Set one uniform 288M cap -- the hint plus real margin -- and drop the
per-test overrides.  This still proves what the directory cares about:
bug 1490 made these compiles exhaust memory exponentially in the sort
depth, so any fixed few-hundred-MB cap separates fixed from broken by
orders of magnitude.  All six tests pass under a GHC 9.12.4 build at
288M.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
GitHub PR 1032.

* Fix instance-trie ordering and probing holes in coherence detection

Three defects let the PredTrie-based instance index (05865c6) select
or admit instances that the legacy all-pairs index would not, each
undermining the coherence certificate that instance resolution and the
planned coherent-dictionary work depend on:

1. Leaf ordering.  cmpQInsts yields only a partial order (non-
   overlapping instances are incomparable), and sortBy with the
   EQ-collapsed comparator is not a sound way to linearize a partial
   order: an incomparable instance between two comparable ones can
   keep the sort from ever comparing them.  A leaf then keeps a
   catch-all ahead of a strictly-more-specific instance, and a fully
   concrete pred selects the catch-all with no incoherence flagged
   (and no T0128, since the pair is orderable).  Order each leaf with
   a topological sort of the strict specificity edges instead, as
   getQInstsLegacy does for the whole list.  To keep this from adding
   pairwise comparisons, the overlap check and the leaf sort now share
   a lazily memoized cmpQInsts table keyed on the canonical index
   pair; same-leaf pairs were already being compared by the overlap
   probes, so the sort costs no additional cmpQInsts calls (library
   build time is unchanged).

2. Primitive type functions in instance heads.  An instance head like
   NP2 (TAdd a b) was keyed under Con TAdd, where probes for the
   numeric-literal instances it can evaluate to never look, so the
   overlap check silently admitted pairs the legacy index rejects with
   T0128.  Key unstable heads as Nothing (catch-all branch) so such
   instances are visible to every query and every overlap probe.

3. Stuck associated type functions in queries.  normT leaves a fully
   applied ATF in place when its class predicate is not yet
   satisfiable, and mkQueryElem keyed such a pred argument as
   Con (ATF), probing only the ATF's own (empty) branch plus the
   catch-all branch.  Concrete instances the pred could match after
   the ATF resolves were neither tried nor visible to the incoherence
   check, so a catch-all match was committed as if coherent.  Treat
   ATF heads as Free (probe all branches), like prim type functions.

Also treat prim-type-function heads as inconclusive in the legacy
index's canMatch pre-filter (TAdd a b vs TyNum heads are unifiable,
not a constructor clash).

New tests in bsc.typechecker/instances/order
GitHub PR 916.

Type expansion is only used if an ATF is uncovered, otherwise the
original type is used, to preserve behavior (structurally matching
type synonyms?) that existing code may be relying on.

Includes tests from PR 909, which was an earlier attempt that is
replaced by this change.
@pull pull Bot locked and limited conversation to collaborators Jul 11, 2026
@pull pull Bot added the ⤵️ pull label Jul 11, 2026
@pull
pull Bot merged commit 6be62d6 into chenm001:main Jul 11, 2026
13 of 31 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants