Documentation

Sparkle.Compiler.Elab

Compiler state tracking variable mappings and context

Instances For
    @[reducible, inline]

    Compiler monad: combines CircuitM builder with MetaM

    Equations
    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 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

            Execute an action with a new local declaration in MetaM scope

            Equations
            • One or more equations did not get rendered due to their size.
            Instances For

              Execute an action with a new let declaration in MetaM scope (for logic values)

              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
                    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
                                def Sparkle.Compiler.Elab.CompilerM.emitMemory (hint : String) (addrWidth dataWidth : Nat) (clk : String) (writeAddr writeData writeEnable readAddr : IR.AST.Expr) (named : Bool := false) :
                                Equations
                                • One or more equations did not get rendered due to their size.
                                Instances For
                                  def Sparkle.Compiler.Elab.CompilerM.emitMemoryComboRead (hint : String) (addrWidth dataWidth : Nat) (clk : String) (writeAddr writeData writeEnable readAddr : IR.AST.Expr) (named : Bool := false) :
                                  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

                                      Add a retained parameter, rejecting duplicate module declarations.

                                      Equations
                                      • One or more equations did not get rendered due to their size.
                                      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

                                          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
                                                  def Sparkle.Compiler.Elab.lowerZeroExtendWire (hint sourceWire : String) (targetWidth : IR.Type.DimExpr) (isNamed : Bool := false) :

                                                  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
                                                    Equations
                                                    • One or more equations did not get rendered due to their size.
                                                    Instances For

                                                      Extract a Nat literal from an expression

                                                      Equations
                                                      Instances For

                                                        Extract values from a List (BitVec n) expression into an array of (value, width) pairs

                                                        Extract values from an Array (BitVec n) expression

                                                        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
                                                                  partial def Sparkle.Compiler.Elab.translateExprToWire (e : Lean.Expr) (hint : String := "wire") (isTopLevel isNamed : Bool := false) :

                                                                  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.

                                                                  partial def Sparkle.Compiler.Elab.translateExprToWireImpl (e : Lean.Expr) (hint : String := "wire") (isTopLevel isNamed : Bool := false) :

                                                                  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.fst, Signal.snd, Signal.map Prod.fst/Prod.snd

                                                                    partial def Sparkle.Compiler.Elab.handleApplicative (e : Lean.Expr) (name : Lean.Name) (args : Array Lean.Expr) (hint : String) (isNamed : Bool) :

                                                                    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.

                                                                    partial def Sparkle.Compiler.Elab.handleBitVecOps (e : Lean.Expr) (name : Lean.Name) (args : Array Lean.Expr) (hint : String) (isNamed : Bool) :

                                                                    Handle BitVec.extractLsb', shifts, concat, isPrimitive dispatch

                                                                    partial def Sparkle.Compiler.Elab.handleRegister (e : Lean.Expr) (name : Lean.Name) (args : Array Lean.Expr) (hint : String) (isNamed : Bool) :

                                                                    Handle Signal.register, Signal.registerWithEnable

                                                                    partial def Sparkle.Compiler.Elab.handleMux (e : Lean.Expr) (name : Lean.Name) (args : Array Lean.Expr) (hint : String) (isNamed : Bool) :

                                                                    Handle Signal.mux, lutMuxTree

                                                                    partial def Sparkle.Compiler.Elab.handleMemory (e : Lean.Expr) (name : Lean.Name) (args : Array Lean.Expr) (hint : String) (isNamed : Bool) :

                                                                    Handle Signal.memory, Signal.memoryComboRead

                                                                    partial def Sparkle.Compiler.Elab.handleLoop (e : Lean.Expr) (name : Lean.Name) (args : Array Lean.Expr) (hint : String) (isNamed : Bool) :

                                                                    Handle Signal.loop, HWVector.get

                                                                    partial def Sparkle.Compiler.Elab.handleCircuitMonad (e : Lean.Expr) (name : Lean.Name) (args : Array Lean.Expr) (hint : String) (isNamed : Bool) :

                                                                    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.

                                                                    Translate a Nat shift amount argument to a hardware wire. Unwraps BitVec.toNat / Fin.val if the Nat came from a BitVec signal, otherwise treats it as a constant shift amount.

                                                                    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 split Prod.fst e / Prod.snd e (positional names out_0, out_1, …).
                                                                    • single-constructor inductive (i.e. user record) → for each field, recurse on e.field and 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
                                                                      partial def Sparkle.Compiler.Elab.openRecordInputs.walk (body : Lean.Expr) (params : Array Lean.Expr) (inner : Lean.Expr) (idx : Nat) (binders : Array Lean.Expr) (subst : Array (Lean.FVarId × Lean.Expr)) (opened : Bool) :

                                                                      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
                                                                              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

                                                                                    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.
                                                                                                        Instances For