Equations
- Sparkle.Compiler.Elab.instInhabitedPort = { default := { name := "default", ty := Sparkle.IR.Type.HWType.bit } }
Compiler state tracking variable mappings and context
- varMap : List (Lean.FVarId × String)
- dimVarMap : List (Lean.FVarId × IR.Type.DimExpr)
- symbolicMode : Bool
- exprCache : Option (IO.Ref (Lean.ExprStructMap String))
Instances For
Compiler monad: combines CircuitM builder with MetaM
Equations
Instances For
Get the current compiler state (from ReaderT)
Instances For
Lookup a variable mapping. Consults the reader-scoped
varMap first, then falls back to the persistent
sparkleFvarWireMap IORef.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Lookup a retained symbolic dimension variable.
Equations
- Sparkle.Compiler.Elab.CompilerM.lookupDimVar fvarId = do let s ← Sparkle.Compiler.Elab.CompilerM.getCompilerState pure (List.lookup fvarId s.dimVarMap)
Instances For
Execute an action with a retained Nat binder in scope.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Execute an action with an additional variable mapping in scope
Equations
- One or more equations did not get rendered due to their size.
Instances For
Lift MetaM into CompilerM
Equations
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Sparkle.Compiler.Elab.CompilerM.freshName hint named = do let cs ← get match Sparkle.IR.Builder.CircuitM.freshName hint named cs with | (name, cs') => do set cs' pure name
Instances For
Equations
- Sparkle.Compiler.Elab.CompilerM.emitAssign lhs rhs = do let cs ← get match Sparkle.IR.Builder.CircuitM.emitAssign lhs rhs cs with | (PUnit.unit, cs') => set cs'
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Look up the HW width of a wire by name (from wires, inputs, or outputs)
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Look up a wire width without forcing retained dimensions to concrete Nats.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Sparkle.Compiler.Elab.CompilerM.addModuleToDesign m = do let cs ← get match Sparkle.IR.Builder.CircuitM.addModuleToDesign m cs with | (PUnit.unit, cs') => set cs'
Instances For
Primitive Registry: Maps Lean function names to IR operators
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Sparkle.Compiler.Elab.isPrimitive name = Sparkle.Compiler.Elab.primitiveRegistry.any fun (x : Lean.Name × Sparkle.IR.AST.Operator) => match x with | (n, snd) => n == name
Instances For
Equations
Instances For
Preserve a retained top-level Nat binder as a closed symbolic dimension.
Infer hardware types with retained dimensions when parameter synthesis is active. The established concrete inference path remains untouched for ordinary APIs.
Extract ResetKind from a Signal dom α expression.
We whnf-reduce the dom argument and then use Lean's
evalExpr to evaluate it as a DomainConfig, reading the
resetKind field directly. Falls back to .asynchronous
(the historical default) if the expression doesn't reduce
to a literal DomainConfig.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Syntactically identify Signal binders so symbolic-width diagnostics are not swallowed by the fallback path for erased configuration arguments.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Helper to extract a Nat literal or OfNat.ofNat wrap.
Build a concrete or symbolic IR slice without freezing either bound.
Equations
Instances For
Equations
- Sparkle.Compiler.Elab.makeSliceFromStartLength source start length = Sparkle.Compiler.Elab.makeSliceExpr source ((start.mkAdd length).mkSub (Sparkle.IR.Type.DimExpr.literal 1)) start
Instances For
Lower unsigned extension/truncation while retaining parameter expressions. SystemVerilog assignment performs both operations correctly for symbolic vector widths; the established concat/slice lowering remains for concrete IR.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Wrap a MetaM whnf with counters.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Wrap Lean.Meta.unfoldDefinition? with counters.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Canonical, pass-stable key for a hardware-denoting expression: abstract every free variable to a constant named after the WIRE it denotes (wire names are stable within a module synth — they are what the emitted Verilog/C refers to), then hash the abstracted expression.
Hashing the expression directly does not work: fvars are fresh per
traversal, so two occurrences denoting the same hardware hash differently
(measured 2079038327 vs 1490760256 for two let num occurrences whose
fvars both mapped to _gen_pS, _gen_y). After abstraction the key is
equal exactly when the denoted hardware is the same — which also makes it
the correct INSTANCE identity for multi-output sub-modules: calls with
different argument wires get different keys (issue #120), while repeated
projections of one let engine := … binder share one key (issue #71).
Equations
- One or more equations did not get rendered due to their size.
Instances For
Caching shim around translateExprToWireImpl. All early-
intercept handlers (Signal HAdd/HSub/etc., OfNat literals,
...) currently return straight from the inner impl, which
means they never write back to the cache. Wrapping here
means every successful translate caches its result —
so subsequent identical sub-trees become a HashMap lookup
instead of a full re-walk through ~10 handlers + Meta.
Detect unsynthesizable patterns (if-then-else, Decidable) and throw errors
Equations
- One or more equations did not get rendered due to their size.
Instances For
Handle Signal.ap — binary op lifting, concat/sshiftRight special cases.
Also handles N-ary applicative chains
f <$> a₁ <*> a₂ <*> ... <*> aₙ (n ≥ 2).
These desugar to nested Signal.ap calls — the
outermost is Signal.ap (Signal.ap (... (Signal.map f a₁) ...) aₙ₋₁) aₙ.
We strip the chain into the inner Signal.map f a₁ plus
the trailing argument signals [a₂, ..., aₙ], then apply
f to the wires sequentially. For chains whose f is
a pure op (or / and / xor / add / etc.) operating
pairwise on a left-fold, this resolves into a chain of
binary IR ops.
Handle Bind.bind / Pure.pure specialised to the
Sparkle Circuit monad.
Lean's do-notation desugars to Bind.bind m k /
Pure.pure v where Bind/Pure are typeclass projections.
unfoldDefinition? (the default tryInline path) cannot
reduce typeclass projections — it stops at the symbol with
the instance still opaque, and the elaborator gives up.
For Sparkle's Circuit monad the bind/pure unfold to pure
value-level Prod manipulation that the existing Prod /
Signal-map rules already lower. We force a .all
transparency reduce on the whole expression and recurse,
mirroring how Prod.rec / Prod.casesOn are handled.
Handle a Lean function call by either inlining the body
(the default) or emitting a sub-module instance (only
when the declaration is tagged @[hardware_module]).
Default = inline keeps the generated Verilog flat, which is
what most users want for alias-style helpers and small
combinational functions: writing
def passthrough x := x shouldn't multiply the module
count of every caller.
Opt INTO sub-module emission with @[hardware_module] for
designs you want to see as their own Verilog module foo
block — a CPU, an ALU you intend to re-use, an arbiter,
etc. Downstream tools (P&R, OOC synth, hierarchical
timing) can then treat the boundary as a real compile
unit.
@[inline_hardware] is accepted as a self-documenting
synonym for "always inline". Today it has no effect over
the default, but it stays binding if a future heuristic
ever auto-promotes a definition to a module.
Split a return value of type ρ into a list of
(suggested-port-name, leaf-Lean-expr) pairs at the
Lean-expression level — one entry per Signal dom τ leaf
under ρ.
Handled shapes:
Signal dom τ→ one anonymous leaf carrying the original expression.Prod α β→ recursively splitProd.fst e/Prod.snd e(positional namesout_0,out_1, …).- single-constructor inductive (i.e. user record) →
for each field, recurse on
e.fieldand prefix the field name so each leaf gets a human-readable port (dmac,payloadValid, …).
Falls back to [(none, e)] if the type doesn't match any
of the above — that keeps non-Signal payloads round-
tripping through the legacy single-wire path.
"Open" record-typed parameters at the synth boundary.
For a function body = fun (p₁ : T₁) (rec : MyRec) (p₂) => …
where MyRec is a single-constructor inductive whose
fields are all Signal …, rewrite to
fun (p₁) (f₁ : F₁) (f₂ : F₂) … (p₂) => body p₁ { f₁, f₂, … } p₂
so the IR elaborator sees per-field Signal inputs instead
of an unsplittable record argument.
Records with no Signal fields (or with non-Signal mixed
in) are left untouched. Recursion is one-level — a record
whose fields are themselves records is partially opened
(the outer record is unwrapped; inner records pass
through). Good enough for the common HFT-NIC case where
each layer's RxIn is a flat record of Signals.
Implementation: walk params with a worker that recurses
inside successive forallTelescopeReducing callbacks so
every fvar stays in scope when mkLambdaFVars runs at
the deepest layer. No IO.Ref shenanigans — the worker
threads state purely.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Deep-strip every Signal.memoize x sub-expression to x
in a Lean expression tree. Signal.memoize is a sim-only
identity wrapper used by Compiler C2 to cache per-cycle
register reads; for synthesis it serves no purpose and
causes infinite-loop hangs in FSM-shaped circuits where
register-read → register-write → memoize chain re-enters
via Signal.loop body inlining. Stripping them once at
the synth entry point breaks the cycle definitively.
Implementation: post-order traversal — strip children
first, then check if THIS node is Signal.memoize and
unwrap if so. Does not recurse under binders (lambdas)
because BVars under a binder have no fvar-binding yet and
the memoize wrap there will be handled by Signal.loop's
handler when it instantiates the binder.
Equations
- Sparkle.Compiler.Elab.synthesizeCombinationalWithParameters declName parameters = Sparkle.Compiler.Elab.synthesizeCombinationalCore declName parameters true
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Plain-text Verilog elaborator.
#synthesizeVerilog id synthesises id and prints the resulting
SystemVerilog to stdout. Output is plain text — no MIME wrapper,
no highlighting — so it works identically under lake build,
lake env lean, CI, and any Jupyter kernel.
For a syntax-highlighted view inside JupyterLab use #showVerilog
instead; for writing to a file use #writeVerilogDesign id "path".
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Highlighted Verilog viewer for JupyterLab.
#showVerilog id synthesises id and renders the SystemVerilog
output inside an HTML <pre><code class="language-verilog"> block,
routed through xeus-lean's text/html MIME channel so JupyterLab's
bundled highlight.js paints the source.
Outside Jupyter (plain lake env lean, CI) the MIME marker bytes
are still emitted but ESC / RS aren't visible, so the listing reads
as the raw HTML. In that case prefer #synthesizeVerilog for a
clean text dump or #writeVerilogDesign to land the SV on disk.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Emit the CUDA batch backend (.cu): N independent instances of the
design, one GPU thread each — Monte-Carlo / fuzzing / test-vector sweeps.
Compile: nvcc -O2 -std=c++17 -shared -Xcompiler -fPIC -o lib<top>.so <top>.cu.
See docs/CudaSim.md.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Emit the CUDA intra backend (.cu): ONE design instance with one GPU
thread per top-level sub-module instance (PE-per-thread) — makes a single
large design (systolic array, core bank) simulate faster. Analysis
failures (Mealy boundaries, unsupported connections, …) surface here as
build errors with the offender named. Compile with -rdc=true.
See docs/CudaIntraSim-design.md.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Combined command: synthesize once, emit both Verilog and optimized C++ simulation
Equations
- One or more equations did not get rendered due to their size.
Instances For
Combined command with observable wires: emit both Verilog and optimized C++ simulation, with JIT code restricted to only the specified observable wires
Equations
- One or more equations did not get rendered due to their size.
Instances For
#sim — Generate typed JIT simulator from a Signal DSL definition.
Usage: def counter : Signal Domain (BitVec 8) := ... #sim counter
Generates: counter.Sim.SimInput, SimOutput, Simulator, load, jitCppPath
Equations
- One or more equations did not get rendered due to their size.