Golf scores on ASAP7, a predictive 7 nm library: never fabricated, and like sky130's score it counts no wires. sky130, a real 130 nm process, is the default. How ASAP7 is scored, and its quirks.

Tasks / _example

Bitwise AND _example

A toy task that runs the whole pipeline: y = a & b on N bits.

open for submissions tutorial parametric scored at N = 16

Par
28.03µm²·nsband · 100.1 µm² × 0.28 ns
Record
28.03µm²·nsband · 100.1 µm² × 0.28 ns
Under par
0%
Par
0.0784µm²·nsband · 1.400 µm² × 0.056 ns
Record
0.0784µm²·nsband · 1.400 µm² × 0.056 ns
Under par
0%

Score

ASAP7 · area × time · µm²·ns · lower is better
_example: the score of each entry by date2 entries by date (x) and score in µm²·ns (y); the line is the best score so far, the dashed line par. The table under the chart lists the same numbers.262728293026 Oct2 Nov9 Novdate enteredscore (µm²·ns) · lower is betterpar: band, 28.03 µm²·nsPAR28.03 · provedthe best score so farband_lp · proved reference · 2026-10-29T10:46:16Z · Score: 28.03 µm²·ns · Area: 100.1 µm² · Delay: 280 psband · proved reference · par · 2026-10-29T10:46:16Z · Score: 28.03 µm²·ns · Area: 100.1 µm² · Delay: 280 ps
_example: the score of each entry by date2 entries by date (x) and score in µm²·ns (y); the line is the best score so far, the dashed line par. The table under the chart lists the same numbers.26283026 Oct2 Nov9 Novdate enteredscore (µm²·ns) · lower is betterpar: band, 28.03 µm²·nsPARthe best score so farband_lp · proved reference · 2026-10-29T10:46:16Z · Score: 28.03 µm²·ns · Area: 100.1 µm² · Delay: 280 psband · proved reference · par · 2026-10-29T10:46:16Z · Score: 28.03 µm²·ns · Area: 100.1 µm² · Delay: 280 ps
  • proved reference
  • the best score so far
  • par
Score = area × time: the sky130 cell area of the scored netlist in µm² times the critical-path delay in ns, from the pinned flow, so µm²·ns. Lower is better. It is the one ranked number: Par (the best proved reference's score, the bar to beat), Record (the best accepted score so far, par while no submission beats it), Under par (how far the record is below par, as a share of par's score) and the leaderboard use it. The Pareto front, area in GE (NAND2 gate equivalents), depth and the other numbers are for exploring, under compare the designs; reproduce a score says how to get the same numbers. Rated with Yosys 0.53 (git 53c22ab7, the Homebrew build for macOS arm64, clang++ 17, -O3) and its yosys-abc (ABC 1.01 of 6 May 2025): the flow is deterministic on that build (measured on 52 designs). Another build of the same version can break ABC's ties differently (measured: 3 fdivp designs, up to 2.9% in delay), so a number made on another platform may differ slightly: the build and its hashes. Dots are the entries by date; the proved references are the first entries, dated by when they joined the task.
every entry by date
datedesignkindscore (µm²·ns)area × time
2026-10-29bandproved reference · par28.03100.1 µm² × 0.28 ns
2026-10-29band_lpproved reference28.03100.1 µm² × 0.28 ns
_example: the score of each entry by date2 entries by date (x) and score in µm²·ns (y); the line is the best score so far, the dashed line par. The table under the chart lists the same numbers.0.0750.080.08526 Oct2 Nov9 Novdate enteredscore (µm²·ns) · lower is betterpar: band, 0.0784 µm²·nsPAR0.0784 · provedthe best score so farband_lp · proved reference · 2026-10-29T10:46:16Z · Score: 0.0784 µm²·ns · Area: 1.400 µm² · Delay: 56 psband · proved reference · par · 2026-10-29T10:46:16Z · Score: 0.0784 µm²·ns · Area: 1.400 µm² · Delay: 56 ps
_example: the score of each entry by date2 entries by date (x) and score in µm²·ns (y); the line is the best score so far, the dashed line par. The table under the chart lists the same numbers.0.0750.080.08526 Oct2 Nov9 Novdate enteredscore (µm²·ns) · lower is betterpar: band, 0.0784 µm²·nsPARthe best score so farband_lp · proved reference · 2026-10-29T10:46:16Z · Score: 0.0784 µm²·ns · Area: 1.400 µm² · Delay: 56 psband · proved reference · par · 2026-10-29T10:46:16Z · Score: 0.0784 µm²·ns · Area: 1.400 µm² · Delay: 56 ps
  • proved reference
  • the best score so far
  • par
Score = area × time: the ASAP7 cell area of the scored netlist in µm² times the critical-path delay in ns, from the pinned flow, so µm²·ns. Lower is better. In this view Par (the best proved reference's score, the bar to beat), Record (the best accepted score so far, par while no submission beats it), Under par (how far the record is below par, as a share of par's score) and the leaderboard use it; the records' ranked score is sky130's, the default view. The Pareto front, area in GE (NAND2 gate equivalents), depth and the other numbers are for exploring, under compare the designs; reproduce a score says how to get the same numbers. ASAP7 view. These numbers are on ASAP7 (asap7sc7p5t), a predictive 7 nm library made for research: it has never been fabricated, so no chip can confirm them. Like sky130's score they count no wires. sky130, a real 130 nm process, is the default view (how ASAP7 is scored, and its quirks). Rated with Yosys 0.53 (git 53c22ab7, the Homebrew build for macOS arm64, clang++ 17, -O3) and its yosys-abc (ABC 1.01 of 6 May 2025): the flow is deterministic on that build (measured on 52 designs). Another build of the same version can break ABC's ties differently (measured: 3 fdivp designs, up to 2.9% in delay), so a number made on another platform may differ slightly: the build and its hashes. Dots are the entries by date; the proved references are the first entries, dated by when they joined the task.
every entry by date
datedesignkindscore (µm²·ns)area × time
2026-10-29bandproved reference · par0.07841.400 µm² × 0.056 ns
2026-10-29band_lpproved reference0.07841.400 µm² × 0.056 ns

Your first submission, step by step

Step 0, once per machine. Install:

step 0
git clone https://github.com/thomasnormal/svgolf
cd svgolf
python3.12 -m pip install -r requirements.txt
# the trusted Lean and the checker's evaluator
lake build
# the pinned sky130 liberty, checked by its hash
python3.12 score/ppa.py --fetch-liberty

lake build takes about 6 minutes and 1 GB of disk the first time, on a laptop that already had the Lean toolchain (README.md's Step 0 says what was measured where; elan's first download of the toolchain comes on top): Lake clones proglib (formerly lean-surfaces) and its packages from github.com, so it needs network access there, and builds the LeanModels.Sv modules svGolf uses; Mathlib is cloned, never built.

  1. Copy the reference pair

    The task's own design and proof are a complete, accepted submission. Start from them.

    shell
    cp tasks/_example/reference/band_tactics.sv solution.sv
    cp tasks/_example/reference/band_tactics.lean Solution.lean
    
  2. Score it, no Lean

    The golfing inner loop, about a second: the ranked area and delay of the pinned flow.

    shell
    python3.12 score/ppa.py solution.sv --task tasks/_example --no-mapped
    
    what it prints
    {
      "ppa": {
        ...
        "area_um2_sky130": 100.096,
        ...
        "delay_ps_sky130": 280,
        ...
      },
      "score": {
        "area_ge": 21.328,
        ...
        "depth": 1,
        ...
    }
    
  3. Check it without a proof

    Every stage that needs no proof, the task's oracle included. It never accepts; it exits 0 when every stage passed, and leaves the staged design in stage/.

    shell
    python3.12 check.py tasks/_example solution.sv --unproved --stage-dir stage
    
    what it prints (JSON on stdout, the last line on stderr)
    stdout (excerpt):
    {"accepted": false, "stage": "unproved", "unproved_ok": true,
     "notes": ["--unproved: every check that needs no proof passed (source, extract, banlist, fourstate, design, score, postsynth); the proof stages were not run, so the design is not accepted"],
     "dev_hint": "cd ... && LEAN_PATH=stage/build lake env lean <YourFile>.lean ...", ...}
    stderr: one line as each long stage starts (check: <stage> ...), then last:
    ranked (sky130 A0'): 100.096 um^2 x 280 ps = 28.03 um2*ns; par 28.03 (band)
    
  4. Probe the design

    How the tactics read your design, before you write a proof: a probe file compiled against the staged design. It prints the design's declarations and its sites (here one, plain#0, the module-level assign) with the bits each drives and reads; the proving guide, section 0, has a longer probe and its whole output for the adder.

    shell
    cat > Probe.lean <<'EOF'
    import Submission.Design
    import SvGolf.Comb
    import LeanModels.Sv.CombEqTactic
    import LeanModels.Sv.CombLib
    
    namespace Submission
    open LeanModels.Sv LeanModels.Sv.CombView LeanModels.Sv.CombLib LeanModels.Sv.CombEq SvGolf
    
    example (N : Nat) (hN : 1 ≤ N) : CombDesign (design.sem N) := by
      sv_structure?
      sv_structure
      all_goals (intros; omega)
    
    end Submission
    EOF
    LEAN_PATH=stage/build lake env lean Probe.lean
    
  5. Check it with the proof

    Your proof, the comparator, the kernel replay, the score and the post-synthesis check: about a minute. The post-synthesis check runs LIGHT by default (a subset of the vectors, for local feedback), so stderr also says accepted, but the check was INCOMPLETE … rerun with --postsynth full: expected, since the next step runs it in full itself.

    shell
    python3.12 check.py tasks/_example solution.sv Solution.lean
    
    what it prints (excerpt)
    stdout (excerpt):
    {"accepted": true, "stage": "done", "errors": [],
     "ppa": {"area_um2_sky130": 100.096, "delay_ps_sky130": 280, ...}, ...}
    stderr, last:
    ranked (sky130 A0'): 100.096 um^2 x 280 ps = 28.03 um2*ns; par 28.03 (band)
    
  6. Record it

    The whole check again, in full mode and in the OS sandbox. The reference is par, so this is a private trial: --data-dir keeps the record out of the board.

    shell
    python3.12 leaderboard/leaderboard.py add --task _example --player YOUR_HANDLE \
        --sv solution.sv --lean Solution.lean --data-dir my-records
    
    what it prints
    added _example/<hash>: YOUR_HANDLE, 100.0960 um^2, 280 ps (21.328 GE, depth 1), 38 proof lines -> my-records/_example/<hash>.json
      post-synthesis check: full mode (4130 vectors)
      the ranked sky130 score (A0', sky130_a0_v3): 100.096 um^2, 280 ps (area x time 28.03 um2*ns); input drive sky130_fd_sc_hd__buf_8
      ...
    

Then golf. Change solution.sv, score each variant with score/ppa.py, run the check without a proof before you prove, and prove it: the proving guide is the reference, and the adder is the first real task.

This text quotes sky130 numbers and compares the designs on sky130, the default library; the score, the boards and the charts of this page are on ASAP7, where the order of the designs can differ.

Compute the bitwise AND of two N-bit inputs, y = a & b, combinationally, and prove it for every N ≥ 1.

The optimum is obvious: one AND gate per bit, 100.1 µm² with a 0.28 ns critical path on sky130 for N = 16 (21.328 GE, depth 1). The task exists to run the whole pipeline (statement, proof, checker, banlist, scoring) on a design small enough to read in one sitting, and to be the template for real tasks. Its reference proofs are complete for every width: band_tactics with the sv_comb tactics, the route of the real tasks and the proof the walk-through starts from, and band by hand, walking the design's structure symbolically. The run-time operators + - * / % ** and the ordering comparisons < <= > >= are banned only to exercise the banlist.

Interface #

Write a module with exactly this header: port names, directions, widths and order matter, and so do the module's name and its parameters.

band.sv
module band #(parameter int N = 4) (
  input  logic [N-1:0] a,
  input  logic [N-1:0] b,
  output logic [N-1:0] y
);
portdirectionwidth (bits)
ainputN
binputN
youtputN

The trusted statement #

A proof must establish the task's trusted statement, the constant SvGolf.Tasks.Example.Statement of Spec.lean (module tasks._example.Spec). Below it is split into the properties a circuit must have, one card each: what the property guarantees in plain words, and its exact Lean text. Every proved reference has all of them. The last tab, what does not count, lists the designs the checker rejects.

Properties

A design meets the trusted statement exactly when, for every width N with 1 ≤ N < 2^31, it has all of the properties below. Lean checks that, together, they say exactly what the statement says, nothing less and nothing more (the theorem statement_iff_properties).

PARAMS_IN_RANGE is the range the statement covers, not a property: every other card must hold at each value in it.

PARAMS_IN_RANGErangeThe widths the statement covers: every N with 1 ≤ N < 2^31 (the values an int parameter holds).

The statement covers every width N with 1 ≤ N < 2^31 at once (the module's parameter is an int, which holds no larger value): one proof works for all of them, not just for the width the design is scored at (N = 16). Every property below must hold at each width.

ParamsInRange
/-- The widths the statement covers: every `N` with `1 ≤ N < 2^31` (the values an `int` parameter
holds). -/
def ParamsInRange (N : Nat) : Prop :=
  1 ≤ N ∧ N < 2 ^ 31
svgolf/tasks/_example/Properties.lean:17Open in code
INTERFACEExactly these ports, in this order, with these widths.

The module has exactly the input ports a and b (N bits each) and exactly the output port y (N bits), with these widths, in this order. Nothing is missing and nothing is extra: an extra input could serve as a hidden mode pin, and the checker and the scoring tools drive and read the design by these names and widths.

Interface
/-- Exactly these ports, in this order, with these widths. -/
def Interface (N : Nat) (d : Design2) : Prop :=
  inputPorts d = [("a", N), ("b", N)] ∧ outputPorts d = [("y", N)]
svgolf/tasks/_example/Properties.lean:22Open in code
UNCLOCKEDNo process runs at a clock edge (no always_ff, no always @(posedge …)).

No process of the design runs at a clock edge: no always_ff, no always @(posedge …), no asynchronous-reset block; only continuous assignments and always_comb blocks. The task is combinational, so it never needs one. The rule closes a gap between Lean's model of SystemVerilog, which the proof is about, and real tools: the model runs every clocked block once per cycle whatever its clock does, so a design that registers correct outputs on a clock nothing drives would look right there, while a simulator sees a clock that never ticks and synthesis removes the registers.

Unclocked
/-- No process runs at a clock edge (no `always_ff`, no `always @(posedge …)`). -/
def Unclocked (d : Design2) : Prop :=
  ∀ p ∈ d.processes.toList, p.isEdgePhase = false
svgolf/tasks/_example/Properties.lean:26Open in code
LOOP_FREENo combinational loop: the design lowers to continuous assigns (Design2.lowerComb) that are ranked (Acyclic): each reads only what lower-ranked ones write.

The design has no combinational loop: written as continuous assignments (each always_comb block becomes one), its processes can be ranked so that each reads only what lower-ranked ones write. A latch (an always_comb block that keeps a value on some path) is refused with it. Lean's model starts every signal at x and settles, so it would read a loop at one state, while a circuit powers up in any 0/1 state the loop can hold and keeps it; the rule removes that question instead of answering it. The ranking is of processes, not bits, so a process that reads a part of a signal it writes itself is refused too, even when no bit depends on itself: write such bits as separate assignments.

LoopFree
/-- No combinational loop: the design lowers to continuous assigns (`Design2.lowerComb`) that are
ranked (`Acyclic`): each reads only what lower-ranked ones write. -/
def LoopFree (d : Design2) : Prop :=
  ∃ d', d.lowerComb = some d' ∧ Acyclic d'
svgolf/tasks/_example/Properties.lean:30Open in code
TERMINATESUnder every schedule and every stimulus, the run completes.

Whatever order the simulator picks for processes that are ready at the same moment (the schedule), and whatever values the inputs take, simulating the design completes: every cycle settles. A combinational loop that oscillates fails this, and so does a design the tools could not read. It is also what gives the next property its teeth: that one is about completed runs, and a design with no completed run would satisfy it without computing anything.

Terminates
/-- Under every schedule and every stimulus, the run completes. -/
def Terminates (d : Design2) : Prop :=
  ∀ (σ : ScheduleOracle) (stim : List SvState), ∃ tr, Runs2 d σ stim tr
svgolf/tasks/_example/Properties.lean:35Open in code
COMPUTES_ANDIn every completed run, every cycle whose stimulus drives a and b with known values ends with y holding their bitwise AND.

In every cycle in which the inputs a and b are driven with known 0/1 values, the output y settles to a & b, their bitwise AND. The outputs must be fully known 0/1 values in every cycle of every run, whatever the earlier cycles were, so they cannot depend on history.

ComputesAnd
/-- In every completed run, every cycle whose stimulus drives `a` and `b` with known values ends
with `y` holding their bitwise AND. -/
def ComputesAnd (N : Nat) (d : Design2) : Prop :=
  d ⊨₂ spec2 fun stim tr =>
    ∀ (c : Nat) (inputs st : SvState), stim[c]? = some inputs → tr[c]? = some st →
      ∀ (a b : BitVec N),
        HoldAll inputs [("a", N), ("b", N)] (a, b, ()) →
        HoldAll st [("y", N)] (a &&& b, ())
svgolf/tasks/_example/Properties.lean:39Open in code

Definitions

The names the properties use, each with its Lean text. Trusted text is what a proof is about; a helper of Properties.lean is not trusted: Lean checks it as part of statement_iff_properties.

This task's trusted text

StatementSpec.leanThe trusted challenge statement that these properties restate, part by part.
Statement
/-- **The challenge statement.** A submission proves
`SvGolf.Tasks.Example.Statement Submission.design.sem`. -/
abbrev Statement : (Nat → LeanModels.Sv.Design2) → Prop := task.Statement
svgolf/tasks/_example/Spec.lean:38Open in code
taskSpec.leanThe task as data: the parameter range, the ports at each parameter value, and the function the outputs must compute.
task
/-- The task: inputs `a b : BitVec N`, output `y = a &&& b`, for `1 ≤ N < 2^31`. -/
def task : CombTask where
  inRange N := 1 ≤ N ∧ N < 2 ^ 31
  inputs N := [("a", N), ("b", N)]
  outputs N := [("y", N)]
  fn _ := fun (a, b, ()) => (a &&& b, ())
svgolf/tasks/_example/Spec.lean:31Open in code

The shared trusted base

CombTask.SatisfiedAtTask.leanThe trusted form of a combinational statement at one parameter value: the interface, then no clock and termination, then the function.
SatisfiedAt
/-- The statement at one parameter value: interface; no clocked process, no
combinational loop and termination; function. Conjunct 2 is the triple
`Unclocked d ∧ LoopFree d ∧ Terminates2 d`. -/
def SatisfiedAt (N : Nat) (d : Design2) : Prop :=
  t.Interface N d ∧ (Unclocked d ∧ LoopFree d ∧ Terminates2 d) ∧ t.Computes N d
svgolf/SvGolf/Task.lean:262Open in code
inputPortsTask.leanThe design's input ports, each with its declared width, in declaration order.
inputPorts
/-- The input ports of `d` with their declared widths, in declaration order.
`instantiate2` lists the ports first, in port-list order. A declaration is
an input port iff its `isInput` flag is set. -/
def inputPorts (d : Design2) : List Sig :=
  d.decls.toList.filterMap fun dc => if dc.isInput then some (dc.name, dc.width) else none
svgolf/SvGolf/Task.lean:178Open in code
outputPortsTask.leanThe design's output ports, each with its declared width, in declaration order.
outputPorts
/-- The output ports of `d` with their declared widths, in declaration order.
A declaration is an output port iff its `isOutput` flag is set. -/
def outputPorts (d : Design2) : List Sig :=
  d.decls.toList.filterMap fun dc => if dc.isOutput then some (dc.name, dc.width) else none
svgolf/SvGolf/Task.lean:184Open in code
HoldAllTask.leanHoldAll st ports values: in the state st, every listed port holds its value as a known bit vector (no x, no z) of exactly the port's width.
HoldAll
/-- `HoldAll st sigs v`: in state `st`, every port `(n, w)` of `sigs` is bound
to the fully known `w`-bit vector that `v` assigns it. -/
def HoldAll (st : SvState) : (sigs : List Sig) → Vals (sigs.map Prod.snd) → Prop
  | [], _ => True
  | (n, _) :: sigs, v => SvState.lookup st n = some (LVec.ofBitVec v.1) ∧ HoldAll st sigs v.2
svgolf/SvGolf/Task.lean:197Open in code
⊨₂Spec2.leand ⊨₂ P: in every completed run of the design d, under every schedule and every stimulus, the stimulus and the trace satisfy P.
Models2
/-- `d ⊨₂ P` — for **every** legal schedule, every stimulus, and every
completed run (`Runs2`), the trace satisfies `P`. Introduce from a raw
∀-fuel fact with `Models2.of_run`; eliminate against a concrete run with
`Models2.run` / `Models2.runs`. Says nothing about whether runs complete —
pair it with `Terminates2`. -/
def Models2 (d : Design2) (P : TraceProp2) : Prop :=
  ∀ (σ : ScheduleOracle) (stim tr : List SvState), Runs2 d σ stim tr → P d stim tr

@[inherit_doc] scoped infix:50 " ⊨₂ " => Models2
LeanModels/Sv/Spec2.lean:141Open in code
spec2Spec2.leanTurns a property of a stimulus (one input entry per cycle) and a trace (one snapshot of every signal per cycle) into the form ⊨₂ takes.
spec2
/-- Lift a design-agnostic stimulus/trace predicate into `⊨₂`
(`d ⊨₂ spec2 fun stim tr => …`). -/
def spec2 (P : List SvState → List SvState → Prop) : TraceProp2 := fun _ stim tr => P stim tr
LeanModels/Sv/Spec2.lean:151Open in code
Runs2Spec2.leanRuns2 d σ stim tr: simulating d under the schedule σ on the stimulus stim completes, with the trace tr.
Runs2
/-- The fuel-abstracted Design2 run judgment: *some* fuel completes the run
of `d` under schedule `σ` and stimulus `stim` with trace `tr`. The only place
fuel appears in a Design2 spec. -/
def Runs2 (d : Design2) (σ : ScheduleOracle) (stim tr : List SvState) : Prop :=
  ∃ fuel, run2 d σ fuel stim = .ok tr
LeanModels/Sv/Spec2.lean:121Open in code
ScheduleOracleSemantics.leanA legal schedule: the order in which the simulator runs the processes that are ready at the same moment. The statement quantifies over all of them.
ScheduleOracle
/-- A legal schedule: at invocation `k`, orders the ready process list.
`choose_perm` is the legality proof — every invocation is a permutation of
the ready list — so `∀ σ : ScheduleOracle` ranges over exactly the legal
schedules. See the module docstring for the invocation-counter protocol. -/
structure ScheduleOracle where
  /-- Invocation counter and ready process indices in, execution order out. -/
  choose : Nat → List Nat → List Nat
  /-- Every invocation yields a permutation of the ready list. -/
  choose_perm : ∀ (k : Nat) (ready : List Nat), (choose k ready).Perm ready
LeanModels/Sv/Semantics.lean:151Open in code
Process2.isEdgePhaseSem2.leanTrue for the processes that run at the clock edge: always_ff, always @(posedge …) and asynchronous-reset blocks.
isEdgePhase
/-- Edge-phase processes: every posedge-clocked block, INCLUDING the
async-reset ones (the posedge fires with reset asserted too — the body's
reset branch is what holds the state, pin3 CYCLE 4). -/
def Process2.isEdgePhase : Process2 → Bool
  | .alwaysFF _ _ | .alwaysPlain _ _ | .alwaysFFR _ _ _ _ => true
  | _ => false
LeanModels/Sv/Sem2.lean:650Open in code

What does not count

Designs that try to score without meeting the statement (negatives), or that exploit a place where the proof's reading and the scored netlist could differ (attacks). The checker stops at the first stage that refuses; each design is listed with that stage.

Refused before any proof is tried

The checker's static stages read the text itself and refuse it: an operator the task bans, a construct that two tools read differently, an unknown (x or z) value that could arise, or a program the language forbids.

  • casex_item.sv (attack, stopped at source): A case item with an x digit: ls-sv computes a & b, while Yosys treats the item as a match and drives an unknown value at 0 GE.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      logic s;
      assign s = 1'b0;
      always_comb
        case (s)
          1'bx: y = '0;
          default: y = a & b;
        endcase
    endmodule
    
  • priority_nomatch.sv (attack, stopped at source): A priority case that never matches, which lets Yosys drive anything (0 GE).

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      always_comb begin
        y = a & b;
        priority case (1'b1)
          (a[0] & ~a[0]): y = '0;
        endcase
      end
    endmodule
    
  • unique0_nomatch.sv (attack, stopped at source): A harmless unique0 case that never matches, refused like every unique, unique0 and priority qualifier because they let synthesis read a case differently from simulation.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      always_comb begin
        y = a & b;
        unique0 case (1'b1)
          (a[0] & ~a[0]): y = '0;
        endcase
      end
    endmodule
    
  • unique_first_const.sv (attack, stopped at source): A harmless-looking unique case (1'b1) whose first item is the constant 1, so two items can match at once.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      always_comb begin
        y = '0;
        unique case (1'b1)
          1'b1: y = a & b;
          a[0]: y = a | b;
        endcase
      end
    endmodule
    
  • unique_nomatch.sv (attack, stopped at source): A unique case that never matches, which lets Yosys drive anything (0 GE).

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      always_comb begin
        y = a & b;
        unique case (1'b1)
          (a[0] & ~a[0]): y = '0;
        endcase
      end
    endmodule
    
  • unique_overlap.sv (attack, stopped at source): A unique case with overlapping items, where Yosys ORs the arms of the items that both match.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      always_comb begin
        y = a & b;
        unique case (1'b1)
          a[1]: y = a & b;
          a[0]: y = a | b;
        endcase
      end
    endmodule
    
  • unique_rare.sv (attack, stopped at source): The same overlap confined to one input pattern in 2^24.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      always_comb begin
        y = a & b;
        unique case (1'b1)
          (a[7:0] == 8'hEF): y = a & b;
          (b == 16'h1234):   y = a | b;
        endcase
      end
    endmodule
    
  • z_rare.sv (attack, stopped at source): A case item with z digits that Yosys ignores, so the netlist differs on one input in 2^28.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      always_comb
        case ({a, b})
          32'hDEAD_BEEz: y = '0;
          default: y = a & b;
        endcase
    endmodule
    
  • zconst_param.sv (attack, stopped at source): x and z bits hidden in local parameters built by concatenation, used as case items.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      localparam logic [1:0] K0 = {1'b0, 1'bz};
      localparam logic [1:0] K1 = {1'b1, 1'bx};
      always_comb
        case (a[1:0])
          K0: y = a | b;
          K1: y = a | b;
          default: y = a & b;
        endcase
    endmodule
    
  • zeq_pair_if.sv (attack, stopped at source): Comparisons against constants with z digits: unknown in ls-sv, always true in Yosys.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      always_comb
        if ((a[1:0] == 2'b0z) || (a[1:0] == 2'b1z)) y = a | b;
        else y = a & b;
    endmodule
    
  • zpair_or.sv (attack, stopped at source): Two complementary case items with z digits: neither matches in ls-sv, together they match every input in Yosys.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      always_comb
        case ({a[0], b[0]})
          2'b0z: y = a | b;
          2'b1z: y = a | b;
          default: y = a & b;
        endcase
    endmodule
    
  • extra_in.sv (negative, stopped at extract): A hidden extra input port: the statement allows exactly the task's ports.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      input  logic         en,
      output logic [N-1:0] y
    );
      assign y = en ? (a & b) : '0;
    endmodule
    
  • wide_out.sv (negative, stopped at extract): The output is N + 1 bits wide instead of N.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N:0]   y
    );
      assign y = a & b;
    endmodule
    
  • array_sum.sv (attack, stopped at banlist): Sums an unpacked array with the .sum() method: run-time addition in disguise.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      logic [N-1:0] arr [2];
      assign arr[0] = a & b;
      assign arr[1] = '0;
      assign y = arr.sum();
    endmodule
    
  • for_counter_skip.sv (attack, stopped at banlist): A for loop that skips an iteration by incrementing its own counter: simulation and synthesis disagree on the result.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      always_comb begin
        y = a & b;
        for (int k = 0; k < 2; k++) begin
          if (k == 1) y = '0;
          k = k + 1;
        end
      end
    endmodule
    
  • for_counter_write.sv (attack, stopped at banlist): A for loop whose body overwrites its own counter: Yosys ignores the write, while a simulator can loop forever.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      always_comb begin
        y = '0;
        for (int k = 0; k < 2; k++) begin
          k = int'(a[0]);
          y = y | (a & b);
        end
      end
    endmodule
    
  • arith_and.sv (negative, stopped at banlist): The right function, written with run-time + and -, which this task bans.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      assign y = (a + b) - (a | b);
    endmodule
    
  • latch_never.sv (attack, stopped at fourstate): An always_latch that is never enabled: unknown in simulation, while Yosys resolves the latch to a constant.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      logic r;
      logic t;
      assign t = a[0] & ~a[0];
      always_latch begin
        if (t) r = 1'b1;
      end
      always_comb begin
        if (!r) y = a | b;
        else y = a & b;
      end
    endmodule
    
  • latch_star.sv (attack, stopped at fourstate): The same never-enabled latch, written with always @*.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      logic r;
      always @* begin
        if (a[0] & ~a[0]) r = 1'b1;
      end
      always @* begin
        if (!r) y = a | b;
        else y = a & b;
      end
    endmodule
    
  • oob_rare.sv (attack, stopped at fourstate): An out-of-range read that changes the netlist's output on a single input pair, too rare for any sampling to find.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      logic [2*N-1:0] wa;
      logic [3*N-1:0] wb;
      logic [N-1:0]   pa, pb;
      logic           rare, t;
      logic [3:0]     k;
      assign wa   = {N{2'b10}};
      assign wb   = {N{3'b011}};
      assign pa   = wa[N-1:0];
      assign pb   = wb[N-1:0];
      assign rare = (&(~(a ^ pa))) & (&(~(b ^ pb)));
      assign k    = 4'b0001;
      assign t    = k[{rare, 2'b00}];
      always_comb
        if (t) y = (a & b) ^ {{(N-1){1'b0}}, rare};
        else y = a & b;
    endmodule
    
  • oob_select.sv (attack, stopped at fourstate): An index that always reads past the end of a 4-bit vector: an unknown value that ls-sv and Yosys resolve differently.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      logic [3:0] k;
      logic       t;
      assign k = 4'b0101;
      assign t = k[{1'b1, a[1:0]}] ? 1'b0 : 1'b1;
      always_comb
        if (t) y = a | b;
        else y = a & b;
    endmodule
    
  • param_divzero.sv (attack, stopped at fourstate): A constant 1 / 0 used as a case item: an unknown value without an x literal, matched by Yosys and never by ls-sv.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      localparam logic [1:0] K = 2'd1 / 2'd0;
      always_comb
        case (a[1:0])
          K: y = a | b;
          default: y = a & b;
        endcase
    endmodule
    
  • rare_mid.sv (attack, stopped at fourstate): An out-of-range read that changes the output on about one input in 512: sampling finds it only with the full vector set.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      logic [2*N-1:0] wa;
      logic [N-1:0]   pa, ma;
      logic           rare, t;
      logic [3:0]     k;
      assign wa   = {N{2'b10}};
      assign pa   = wa[N-1:0];
      assign ma   = ~({N{1'b1}} << 9);
      assign rare = &(~(a ^ pa) | ~ma);
      assign k    = 4'b0001;
      assign t    = k[{rare, 2'b00}];
      always_comb
        if (t) y = (a & b) ^ {{(N-1){1'b0}}, rare};
        else y = a & b;
    endmodule
    
  • undriven_mux.sv (attack, stopped at fourstate): A multiplexer steered by a signal that nothing drives: ls-sv and Yosys pick different branches.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      logic u, t;
      assign t = u ? 1'b0 : 1'b1;
      always_comb
        if (t) y = a | b;
        else y = a & b;
    endmodule
    
  • undriven_offpoint.sv (attack, stopped at fourstate): The same undriven multiplexer, driven at the scoring width N = 16 only: at every other width ls-sv and Yosys pick different branches.

    the design, with its comments left out
    module band #(parameter int N = 16) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      logic u, t;
      generate
        if (N == 16) begin : g_drv
          assign u = 1'b1;
        end
      endgenerate
      assign t = u ? 1'b0 : 1'b1;
      always_comb
        if (t) y = a | b;
        else   y = a & b;
    endmodule
    
  • reads_x.sv (negative, stopped at fourstate): Reads a net that nothing drives, so its value is unknown (x).

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      logic [N-1:0] z;
      assign y = a & b & ~z;
    endmodule
    
  • fn_uninit.sv (attack, stopped at design): A function reads a local variable before assigning it: unknown in SystemVerilog, a fixed value in Yosys, and a construct ls-sv cannot run.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      function automatic logic f(input logic s);
        logic r;
        if (s) r = 1'b1;
        f = r;
      endfunction
      always_comb
        if (f(a[0])) y = a | b;
        else y = a & b;
    endmodule
    
Rejected at the proof

These pass every static check. The proof that comes with each one does not compile, or does not prove the statement: a design that is wrong somewhere in the task's range (or has other ports) has no proof at all, and a proof that leaves a goal unproved is never accepted.

  • or_gate.sv (negative, stopped at solution): The wrong function: OR instead of AND.

    the design, with its comments left out
    module band #(parameter int N = 4) (
      input  logic [N-1:0] a,
      input  logic [N-1:0] b,
      output logic [N-1:0] y
    );
      assign y = a | b;
    endmodule
    
Spec.lean, verbatim (58 lines)
import SvGolf.Task

/-!
# Task `_example`: N-bit bitwise AND (TRUSTED)

The toy task that exercises the svGolf pipeline end to end. It is not a real
challenge: the optimum (N two-input AND gates, depth 1) is obvious.

Module (port order as written; `N` is the module's only parameter):

```systemverilog
module band #(parameter int N = 4) (
  input  logic [N-1:0] a,
  input  logic [N-1:0] b,
  output logic [N-1:0] y
);
```

Statement: for every `N` with `1 ≤ N < 2^31` (the values an `int` parameter
holds), the design has exactly the ports `a`, `b` (inputs, `N` bits) and `y`
(output, `N` bits), no process is clocked, there is no combinational loop,
every run terminates, and in
every cycle whose stimulus drives `a` and `b` with known values the
snapshot's `y` is `a &&& b`.
-/

namespace SvGolf.Tasks.Example

open SvGolf

/-- The task: inputs `a b : BitVec N`, output `y = a &&& b`, for `1 ≤ N < 2^31`. -/
def task : CombTask where
  inRange N := 1 ≤ N ∧ N < 2 ^ 31
  inputs N := [("a", N), ("b", N)]
  outputs N := [("y", N)]
  fn _ := fun (a, b, ()) => (a &&& b, ())

/-- **The challenge statement.** A submission proves
`SvGolf.Tasks.Example.Statement Submission.design.sem`. -/
abbrev Statement : (Nat → LeanModels.Sv.Design2) → Prop := task.Statement

/-! Sanity checks on the statement's data (closed, by `decide`). -/

/-- The scoring point `N = 16` is in range. -/
example : task.inRange 16 := by simp [task]

/-- The range ends below `2^31`, the values an `int` parameter holds. -/
example : task.inRange (2 ^ 31 - 1) ∧ ¬ task.inRange (2 ^ 31) := by simp [task]

/-- The input names are distinct (the non-vacuity theorem
`CombTask.SatisfiedAt.exists_run` needs it), at every `N`. -/
example (N : Nat) : ((task.inputs N).map Prod.fst).Nodup := by
  simp [task]

/-- The function on a concrete value: `0b1100 &&& 0b1010 = 0b1000`. -/
example : (task.fn 4 (0b1100#4, 0b1010#4, ())).1 = 0b1000#4 := by decide

end SvGolf.Tasks.Example

Its trusted text

The modules specific to this task. Like every task, it also rests on the shared trusted base (the ls-sv semantics of SystemVerilog and svGolf's statement helpers), and a proof may import any module of the ls-sv library. Nothing else is trusted: proof helpers are kernel-checked like any submission.

modulerolelinessha256
tasks._example.Specsvgolf/tasks/_example/Spec.leantask statement58433e431a44d7

How to participate #

  1. Write a circuit with the task's exact interface.
  2. Prove in Lean 4 that it meets the trusted statement; the proving guide shows how.
  3. Check and record it (how to submit): the checker accepts the pair or says which stage refused it, as it does for each design under what does not count.
  4. Beat par: an accepted design whose score (area × time) is below that of the best proved reference. The leaderboard ranks by it.

How to submit

You hand in two files: solution.sv, a module with the exact header under Interface, and Solution.lean, a Lean 4 proof that it meets the trusted statement. Your first submission, above, copies a reference pair and runs each command below with what it prints.

Step 0, once per machine. Install:

  • elan, which installs the Lean toolchain that lean-toolchain pins (leanprover/lean4:v4.33.0-rc1) on first use;
  • Yosys 0.53 with its yosys-abc (every pinned tool and file: Reproduce a score);
  • Verilator 5, a C++ compiler and make, for the post-synthesis check (it compiles Verilator's model of the netlist);
  • Python 3.12 with python3.12 -m pip install -r requirements.txt (pyslang==11.0.0, the extractor's SystemVerilog frontend).
step 0
git clone https://github.com/thomasnormal/svgolf
cd svgolf
python3.12 -m pip install -r requirements.txt
# the trusted Lean and the checker's evaluator
lake build
# the pinned sky130 liberty, checked by its hash
python3.12 score/ppa.py --fetch-liberty

lake build takes about 6 minutes and 1 GB of disk the first time, on a laptop that already had the Lean toolchain (README.md's Step 0 says what was measured where; elan's first download of the toolchain comes on top): Lake clones proglib (formerly lean-surfaces) and its packages from github.com, so it needs network access there, and builds the LeanModels.Sv modules svGolf uses; Mathlib is cloned, never built.

Then, for each design, from the same directory: find it without Lean and check it once without a proof (the golfing loop and step 1), write its proof (the proving guide shows how), then check the pair and record it (steps 2 and 3):

shell
# the golfing loop: ranked area and delay, ~2 s, no Lean
python3.12 score/ppa.py solution.sv --task tasks/_example \
    --no-mapped --path
# 1. no proof needed; never accepts; exits 0 when every
#    stage passed, ending with area x time and par
python3.12 check.py tasks/_example solution.sv --unproved
# 2. the real check: prints "accepted": true; its
#    post-synthesis check is LIGHT by default (a subset of
#    the vectors, for local feedback), so stderr also says
#    "accepted, but the check was INCOMPLETE ... rerun with
#    --postsynth full": expected, since step 3 runs the
#    full one itself
python3.12 check.py tasks/_example solution.sv Solution.lean
# 3. record it: the whole check again, full and sandboxed
python3.12 leaderboard/leaderboard.py add --task _example \
    --player YOUR_HANDLE --assisted-by "TOOL OR MODEL" \
    --sv solution.sv --lean Solution.lean \
    --notes "YOUR DESIGN IN ONE LINE"

Done: step 3 prints added _example/HASH: YOUR_HANDLE, … once the pair has passed the whole check, full and sandboxed, and its record is written (what it writes, and where: below); otherwise it prints REFUSED with the reasons and records nothing. Step 2's "accepted": true, with its INCOMPLETE line, is feedback for you, not a record.

score/ppa.py is the inner loop of golfing: it runs the source gate and the pinned flow and prints the ranked numbers, area_um2_sky130 and delay_ps_sky130. It does not check the banlist, the 4-state rules, whether ls-sv can read the design, the post-synthesis simulation or the task's function, and needs no proof: run step 1 before you prove.

The Lean file. The checker extracts your .sv itself and writes the trusted module Submission.Design; Goal unfolds to SvGolf.Tasks.Example.Statement Submission.design.sem, the task's statement of your design:

Submission.Design (generated: you never write it)
import LeanModels.Sv.Ingest2
import tasks._example.Spec

namespace Submission
load_design_sv2 design from "<the envelope of your .sv>"
abbrev Goal : Prop := SvGolf.Tasks.Example.Statement design.sem
end Submission

Your Solution.lean imports it and proves Goal:

Solution.lean (a skeleton)
import Submission.Design
import SvGolf.Comb
import LeanModels.Sv.CombEqTactic   -- the sv_comb tactics
import LeanModels.Sv.CombLib        -- the plain-Lean library

namespace Submission
open LeanModels.Sv LeanModels.Sv.CombView LeanModels.Sv.CombLib
open LeanModels.Sv.CombEq SvGolf

-- in `namespace Submission`, this is
-- `theorem Submission.solution : Submission.Goal`
theorem solution : Goal := by
  -- your proof; a complete one:
  -- tasks/_example/reference/band.lean

end Submission

File names and paths are free (here solution.sv and Solution.lean); the module name Submission, the import Submission.Design header and the theorem solution : Goal are fixed. The proving guide, section 0, shows the loop: stage the design, print its equations with a probe file, then prove.

Step 3 writes your record's three files (.json, .sv and .lean, named by the record's hash) to leaderboard/data/_example/, the directory a pull request adds. Then open a pull request against https://github.com/thomasnormal/svgolf that adds them; CI re-verifies it. There is no submission server: nothing is sent anywhere by these commands. For a private trial, add --data-dir DIR: the record then goes to DIR and the board stays as it is. Repeat --assisted-by for each tool or AI system that helped, or leave it out.

YOUR_HANDLE is your public name: the board and the record's page show it. It is 1 to 32 characters, letters, digits, ., _ or -, the first a letter or a digit ([A-Za-z0-9][A-Za-z0-9._-]{0,31}). --notes is optional: one line on the design (at most 2000 characters), shown on the record's page. In a private trial (--data-dir DIR), add --from-check RESULT.json records the JSON that a check.py … --postsynth full --ppa require run printed instead of checking again; the board's own leaderboard/data/ refuses a stored result.

the sandbox, and machines without one

leaderboard.py add runs the check with --sandbox require: the proof's Lean, the extractor, Yosys and Verilator must run inside the operating system's sandbox (Seatbelt on macOS, bubblewrap on Linux). Where that sandbox is missing or fails its self-test, the check stops with an infrastructure error and nothing is recorded. On such a machine, --sandbox auto runs the check without it (and says so on stderr), and --sandbox off skips it: your proof file then runs with your own privileges, and the record is for your own use, since an official record is made with the sandbox or not at all. add also weighs the ranked sky130 numbers, which need the pinned liberty (Step 0). On a shared machine whose Lean calls go through a wrapper, set SVGOLF_LEAN_WRAP; check.py and leaderboard.py both read it, and SVGOLF_LEAN_WRAP_ONCE=1 takes the wrapper once for a whole run.

Leaderboard

by score · ASAP7

No submissions yet. Par, the bar to beat, is the proved reference band: 28.03 µm²·ns (100.1 µm² × 0.28 ns).

  1. ⚑
    par proved reference
    28.03100.1 µm² × 0.28 ns

No submissions yet. Par, the bar to beat, is the proved reference band: 0.0784 µm²·ns (1.400 µm² × 0.056 ns).

  1. ⚑
    par proved reference
    0.07841.400 µm² × 0.056 ns
score: area × time, µm²·nspar

At a glance

top module
band
parameters
N in range 1 <= N < 2^31
scoring point
N = 16
depth budget
none
banned run-time operators
+ - * / % **, and the run-time ordering comparisons < <= > >= (Yosys builds each as its own adder, an $alu; equality stays allowed)

The toy bans run-time arithmetic only to exercise the banlist end to end (tests/_example/negative/arith_and.sv).

allowed axioms
propext, Classical.choice, Quot.sound
proof time limit
300 s of CPU time (a wall-clock backstop of 1500 s stops a proof that waits)

Compare the designs

ASAP7 · any two numbers · lower is better
_example: area against delay2 designs by Delay (ps) (x) and Area (µm²) (y); lower is better on both. The table under the chart lists the same numbers.95100105110260270280290300Delay (ps)Area (µm²) · lower is betterthe Pareto front of the proved designs2 designs at this point · band · proved reference · par · band_lp · proved reference · Delay: 280 ps · Area: 100.1 µm²2 designs at this point · band · proved reference · par · band_lp · proved reference · Delay: 280 ps · Area: 100.1 µm²
_example: area against delay2 designs by Delay (ps) (x) and Area (µm²) (y); lower is better on both. The table under the chart lists the same numbers.100110260280300Delay (ps)Area (µm²) · lower is betterthe Pareto front of the proved designs2 designs at this point · band · proved reference · par · band_lp · proved reference · Delay: 280 ps · Area: 100.1 µm²2 designs at this point · band · proved reference · par · band_lp · proved reference · Delay: 280 ps · Area: 100.1 µm²
  • proved reference
  • the Pareto front of the proved designs
Lower is better on both axes. The step line joins the proved designs that no other proved design beats on both; baselines are shown for scale. Choose any two numbers to find the best design for your own trade-off. 2 of 3 designs have both numbers (the rest lack one).
every design with all its numbers, by score
designScore (µm²·ns)Area (µm²)Delay (ps)Area (GE)Depth (gates)GatesProof (lines)
band par28.03100.128021.328116159
band_lp reference28.03100.128021.328116161
band_tactics reference–––21.32811638
  • proved reference
  • the Pareto front of the proved designs
Lower is better on both axes. The step line joins the proved designs that no other proved design beats on both; baselines are shown for scale. Choose any two numbers to find the best design for your own trade-off. 3 of 3 designs have both numbers.
every design with all its numbers, by score
designScore (µm²·ns)Area (µm²)Delay (ps)Area (GE)Depth (gates)GatesProof (lines)
band par0.07841.4005621.328116159
band_lp reference0.07841.4005621.328116161
band_tactics reference0.07841.4005621.32811638

Proved references

Proved and accepted designs that ship with the task, written or adapted by the maintainers. They are the first entries, and par, the bar to beat, is the one with the best score (area × time, µm²·ns, from the sky130ASAP7 area and time; a design without a sky130an ASAP7 weighing has no score and comes after, by its extra GE columns). A reference that was also recorded links its record under its name: the record holds that reference's design and proof, matched by the sha256 of both files.

designscore (µm²·ns)area (µm²)time (ps)GE · depthvs parproof linesfiles
band parparOne AND gate per bit: assign y = a & b;.tactics: decide, omega, simprecord: 817c78519b1128.030.0784100.11.4002805621.328 · 1parpar159.sv .lean
band_lp The same circuit, with local parameters in the header (the port widths) and in the body.tactics: decide, omega, simprecord: 341bdd371efb28.030.0784100.11.4002805621.328 · 1±0.0%±0.0%161.sv .lean
band_tactics same design as bandThe same design, byte for byte, proved with the sv_comb tactics (sv_structure, sv_interface, sv_equations) in a quarter of the code lines: the proof the walk-through starts from.tactics: omega, simp, sv_cover, sv_equations, sv_interface, sv_structure–0.0784–1.400–5621.328 · 1–±0.0%38.sv .lean

Baselines

No baselines for this task.