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)
- 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
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
Lift CircuitM operations by modifying the circuit state
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
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
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
Helper to extract a Nat literal or OfNat.ofNat wrap.
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
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
- 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
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
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.