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 / arbiter / record

Record 84da5a4152db

reference: par, not an entryreference: par, not an entry scored at N = 8

Recorded by the maintainers from the proved reference rr_mask: its design and its proof rr_mask.lean (487 code lines). A registered mask round-robin: the lowest requester above the last grant wins, else the lowest requester; proved for every number of clients. The record shows that reference passing the whole checker. It is par, the bar to beatpar, the bar to beat, not a player's entry, and it is not ranked among the submissions (proved references).

Area

769.49µm²

769.4880 µm² exactly

vs par
this design is par
cells
103
flops
16
repair
0 buffers, 0 tie cells
GE
188.979 extra

Performance · time

2 826ps

the register-to-register period, one decision per cycle: the latest arrival at an output, or at a flip-flop's D plus setup, ideal clock

vs par
this design is par
Fmax-eq.
353.9 MHz derived
critical path
15 cells
unit depth
17 extra

Score · area × time

2175µm²·ns

769.4880 µm² × 2 826 ps

vs par
this design is par
board
par, the bar to beat: never ranked

No other player has a ranked record on arbiter yet: the beats and matches lines come with the first one.

how these numbers are measured and compared

Area: sky130 A0′, the repaired netlist.

Area, time and score are ranked (the leaderboard orders by the score); a number tagged extra, derived or research is shown, never ranked. Fmax-equivalent = 10⁶ / time in ps, for comparison with sites that quote Fmax.

The field is the ranked records of arbiter's other players at this revision (0 players, 0 records), never the references, the baselines or a rejected design; advisory, recomputed at every build, never stored in a record and never used by the ranking.

This design is the only one with sky130 numbers on this page, so the cards have no “on this page” or “Pareto” row.

Area

12.160µm²

12.15972 µm² exactly

vs par
this design is par
cells
138
flops
16
repair
0 buffers, 0 tie cells
GE
188.979 extra

Performance · time

464ps

the register-to-register period, one decision per cycle: the latest arrival at an output, or at a flip-flop's D plus setup, ideal clock

vs par
this design is par
Fmax-eq.
2155.2 MHz derived
unit depth
17 extra

Score · area × time

5.642µm²·ns

12.15972 µm² × 464 ps

vs par
this design is par
board
par, the bar to beat: never ranked

No other player has a ranked record on arbiter yet: the beats and matches lines come with the first one.

how these numbers are measured and compared

Area: ASAP7 A0′ (asap7_a0_v1), the same scored netlist, each gate its least-area ASAP7 build, repaired by buffering. ASAP7: a predictive 7 nm library, never fabricated; no wires, like sky130's score (how ASAP7 is scored, and its quirks).

Area, time and score order this view's board (by the score); the records' ranked score is sky130's, the default view; a number tagged extra, derived or research is shown, never ranked. Fmax-equivalent = 10⁶ / time in ps, for comparison with sites that quote Fmax.

The field is the ranked records of arbiter's other players at this revision (0 players, 0 records), never the references, the baselines or a rejected design; advisory, recomputed at every build, never stored in a record and never used by the ranking.

This design is the only one with ASAP7 numbers on this page, so the cards have no “on this page” or “Pareto” row.

The sources

rr_mask.svdownload
// Task `arbiter`: the reference (own code, 2026-11-04; proved for every N >= 1, rr_mask.lean, 2026-11-05). A registered
// round-robin arbiter, the textbook mask form: `mask` marks the clients above the last grant; the lowest
// masked requester wins, else the lowest requester (the wrap). Moore: gnt is a flop (the one comb block
// computes the pick from req and the mask and drives no output). Fair within N cycles: if
// client i requests and loses, the winner lies between the last grant and i, so i's cyclic distance from
// the mask's edge drops (the ranking of tasks/arbiter/README.md (e)).
// Why own code and not a real-world design (MEASURED 2026-11-05): the adapted OpenTitan prim_arbiter_tree
// (tests/arbiter/designs/arbiter_ot.sv) declares variables and localparams inside its generate blocks, which
// ls-sv does not instantiate yet; verilog-axis arbiter.v instantiates priority_encoder twice (hierarchy) over
// unpacked arrays. tasks/arbiter/README.md, "The reference".
module arbiter #(parameter int N = 8) (
  input  logic         clk, rst,
  input  logic [N-1:0] req,
  output logic [N-1:0] gnt
);
  logic [N-1:0] mask, mreq, pick;
  always_comb begin
    mreq = req & mask;
    pick = (mreq != '0) ? (mreq & (~mreq + 1'b1)) : (req & (~req + 1'b1));
  end
  always_ff @(posedge clk) begin
    if (rst) begin
      gnt <= '0;
      mask <= '1;
    end else begin
      gnt <= pick;
      if (pick != '0) mask <= ~((pick << 1) - 1'b1);
    end
  end
endmodule
rr_mask.lean (487 code lines)
import Submission.Design
import LeanModels.Sv.Gen2
import LeanModels.Sv.Hier2Gen
import LeanModels.Sv.Known2
import LeanModels.Sv.Mono2
import LeanModels.Sv.SeqFamily
import SvGolf.Seq
import SvGolf.React
import SvGolf.RoundRobin

/-!
# Reference solution for task `arbiter`: the registered mask round-robin, every `N ≥ 1`

`reference/rr_mask.sv` (own code; the real-world candidates wait on ls-sv, `tasks/arbiter/README.md` (j)) keeps
`gnt` and a thermometer `mask` in one `always_ff`, and computes the pick in one `always_comb`: the lowest
requester among `req & mask`, else the lowest requester. Proved for every `N ≥ 1` (`N` stays a variable)
through `ReactTask.satisfiedAt_of_rank` (`SvGolf/React.lean`):

1. **Agreement** (`rr_sem_eq`): `design.sem N` is the hand-built `rrD N` (`sv2_inst_simp`; the comb
   block's self-read guard by `comb_admits`). One proof-side lemma, `inst_ne_fill`: `x != '0` lowers at
   `x`'s width. `sv2_inst_simp` alone stops there, because ls-sv's private `maxW2` has a simp lemma for two
   known widths only (`maxW2_some`) and a fill has none (`tasks/arbiter/README.md` F11).
2. **One cycle in closed form** (`rr_cycle`, any values, `x` included): the inputs applied, the comb settle
   (one pass computes the block, a second changes nothing: `settle_rr`), the edge (`ff_run`), the commit
   (`commit_ff`), the comb settle again. `Terminates2` and the shape follow (`rr_terminates`). ls-sv's
   clock-step library has this closed form for FF-only designs only (`cycleStep2_ffOnly`); a design with a
   comb process proves its own settle here (README F10).
3. **The cycle on known values** (`rrNext_reset`, `rrNext_run`): from a reset, `gnt = 0` and `mask` all
   ones; otherwise `gnt = pick req mask` and `mask` the thermometer above the pick
   (`SvGolf.RoundRobin.pick`, `next`).
4. **The rank model** (`model`): the invariant `ArbInv` (every signal but `clk` known, the mask a
   thermometer with edge `e`), the outputs `gnt`, the rank of client `i` its cyclic distance from the edge
   (`RoundRobin.dist`, at most `N - 1`). Safety is `pick_grants`; progress is `RoundRobin.step`: a
   requester that loses gets strictly closer to the edge.
5. **Every power-up** (txtask-v2's rule 2, 2026-11-06): every power-up state of `rrD N` has the shape
   (`rr_powerUp`, by `powerUp_cons` once per declaration), so the rank model's claim holds from each,
   and termination from each (`rr_terminates`, `TerminatesPU.of_invariant`). The reset lemma already
   held from ANY state of the shape, so nothing else changed.
6. **Structure**: `Interface` (`rfl` on `rrD`, the names distinct by `decide`), `ClockedBy clk none`,
   `MooreOut` (no comb process writes an output: `mooreOut_of_combTargets`), and rule 3 (`rr_xsafe`,
   `xsafeB` by `simp`: equal operand widths, no division, no dynamic index).
-/

namespace Submission

open LeanModels.Sv SvGolf

/-! ## 1. Agreement: the loaded family is the hand-built `rrD` -/

/-- The `N`-bit fills `'0`, `'1` and the literal `1'b1`. -/
abbrev z0 (N : Nat) : LVec := LVec.replicate N .l0
abbrev z1 (N : Nat) : LVec := LVec.replicate N .l1
abbrev one1 : LVec := ⟨#[.l1]⟩

/-- The `always_comb` body: `mreq = req & mask; pick = (mreq != '0) ? lowbit(mreq) : lowbit(req)`. -/
def combBody (N : Nat) : Stmt2 :=
  .block #[
    .blockingAssign (.ident "mreq") (.binary .and (.ident "req") (.ident "mask")),
    .blockingAssign (.ident "pick")
      (.ternary (.binary .ne (.ident "mreq") (.lit (z0 N)))
        (.binary .and (.ident "mreq") (.binary .add (.unary .bnot (.ident "mreq")) (.resize N (.lit one1))))
        (.binary .and (.ident "req") (.binary .add (.unary .bnot (.ident "req")) (.resize N (.lit one1)))))]

/-- The `always_ff` body: reset, else `gnt <= pick` and the mask above the pick. -/
def ffBody (N : Nat) : Stmt2 :=
  .block #[
    .ifStmt (.ident "rst")
      (.block #[.nbaAssign (.ident "gnt") (.lit (z0 N)), .nbaAssign (.ident "mask") (.lit (z1 N))])
      (some (.block #[.nbaAssign (.ident "gnt") (.ident "pick"),
        .ifStmt (.binary .ne (.ident "pick") (.lit (z0 N)))
          (.nbaAssign (.ident "mask") (.unary .bnot (.binary .sub
            (.binary (.shl false) (.ident "pick") (.lit (LVec.ofInt 32 1))) (.resize N (.lit one1)))))
          none]))]

/-- The comb process. -/
def combP (N : Nat) : Process2 := .alwaysComb (combBody N)

/-- The flop process. -/
def ffP (N : Nat) : Process2 := .alwaysFF "clk" (ffBody N)

/-- The declarations at width `n`. -/
def rrDeclsW (n : Nat) : List Decl :=
  [{ name := "clk", width := 1, isInput := true }, { name := "rst", width := 1, isInput := true },
   { name := "req", width := n, isInput := true }, { name := "gnt", width := n, isOutput := true },
   { name := "mask", width := n }, { name := "mreq", width := n }, { name := "pick", width := n }]

/-- **The hand-built design** at `N`. -/
def rrD (N : Nat) : Design2 where
  name := "arbiter"
  decls := (rrDeclsW N).toArray
  processes := #[combP N, ffP N]

def rrScope (N : Int) : IEnv := { vals := [("N", N)], pwidths := [("N", 32)] }

def rrEnv (N : Int) : IEnv := { rrScope N with dims := dimTable (rrScope N) design.pdesign.decls }

theorem rr_paramEnv (N : Int) : design.pdesign.paramEnv2 [N] = .ok (rrEnv N) := rfl

def rrElems : List (String × Nat) := ["clk", "rst", "req", "gnt", "mask", "mreq", "pick"].map (·, 1)

theorem rr_decls (N : Int) :
    buildDecls (rrEnv N) design.pdesign.decls = .ok (rrDeclsW ((N - 1).natAbs + 1)) := by
  simp [design.pdesign, buildDecls, instDecl, PType.width_packed_cons, PDim.width, evalInt,
    rrEnv, rrScope, List.lookup, rrDeclsW, Gen2.except_ok_bind]

theorem rr_elems (N : Int) : buildElems (rrEnv N) design.pdesign.decls = .ok rrElems := by
  simp [design.pdesign, buildElems, PType.width_packed_cons, PDim.width, evalInt, rrEnv,
    rrScope, List.lookup, rrElems, Gen2.except_ok_bind]

/-- The instantiation environment. -/
abbrev rrE (N : Nat) : IEnv := (rrEnv N).withDecls (rrDeclsW N)

/-- The source bodies of the two processes. -/
def combT : PStmt := match design.pdesign.processes with
  | [.alwaysComb b, _] => b
  | _ => .block []

def ffT : PStmt := match design.pdesign.processes with
  | [_, .alwaysFF _ b] => b
  | _ => .block []

theorem rr_procs_src : design.pdesign.processes = [.alwaysComb combT, .alwaysFF "clk" ffT] := rfl

/-- `x != '0` lowers at the width of `x` (the fill takes the comparison's width). Stated with the
width lookup itself, so that `sv2_inst_simp` meets no `max` of a width and the fill's none. -/
theorem inst_ne_fill (E : IEnv) (el : List (String × Nat)) (n : String) (b : Logic) :
    instExpr2 E el none (.binary (.m0 .ne) (.ident n) (.fill b)) =
      .binary .ne (fitExpr2 E el (E.widths.lookup n) (.ident n))
        (fitExpr2 E el (E.widths.lookup n) (.fill b)) := by
  simp only [instExpr2, selfWidth2]
  cases E.widths.lookup n <;> rfl

macro "rr_inst_simp" : tactic => `(tactic| sv2_inst_simp [↓ inst_ne_fill, evalSized, ctype, evalAt,
  ctypeList, evalAtList, SymBinOp.constClass, PExpr.pushedTarget, PExpr.readsSignal, PExpr.readsSignalList,
  Gen2.except_pure, instStmt2, instStmts2, design.pdesign, rrEnv, rrScope, rrDeclsW, rrElems, combT, ffT,
  combBody, ffBody, dimTable, dimTableStep, PType.width_packed_cons, PDim.width, ctxOpWidth2, rigidMax2,
  PExpr.ctxPropagates, PExpr.constLeaf, PExpr.negGenvarWidened, LVec.width, divOperandWidth2,
  instDivOperand2, fitDivOperand2, *])

theorem comb_inst (N : Nat) (hN : 1 ≤ N) : instStmt2 (rrE N) rrElems combT = combBody N := by
  have h0 : (0 : Int) < N := by omega
  rr_inst_simp
  try and_intros
  all_goals first | rfl | (change fitExpr2 _ _ (some N) _ = _; rr_inst_simp) | skip

theorem ff_inst (N : Nat) (hN : 1 ≤ N) : instStmt2 (rrE N) rrElems ffT = ffBody N := by
  have h0 : (0 : Int) < N := by omega
  rr_inst_simp
  try and_intros
  all_goals first | rfl | (change fitExpr2 _ _ (some N) _ = _; rr_inst_simp) | skip

/-- The comb block's self-read guard admits the body at every `N` (every read the walk compares is
on another signal than the bits written after it). -/
theorem comb_admits (N : Nat) : (combBody N).combAdmits (fun n => (rrE N).widths.lookup n) = true := by
  simp [Stmt2.combAdmits, combBody, Stmt2.combViol, Stmt2.listCombViol, Stmt2.mayW,
    Stmt2.listMayW, Stmt2.mustW, Lhs2.mayW, Lhs2.mustW, Lhs2.rdW, Expr2.rdW, CombGuard.readsViol,
    CombGuard.whole, CombGuard.BWin.inter, CombGuard.BWin.sub, CombGuard.BWin.subAll, List.lookup,
    rrDeclsW]

theorem rr_static (N : Nat) (hN : 1 ≤ N) :
    design.pdesign.processes.map (instProcess2 (rrE N) rrElems) = [combP N, ffP N] := by
  rw [rr_procs_src]
  simp only [List.map_cons, List.map_nil, instProcess2, comb_inst N hN, ff_inst N hN,
    combGuardProc_of_admits (comb_admits N), combP, ffP]

theorem rr_instantiate2 (N : Nat) (hN : 1 ≤ N) :
    design.pdesign.instantiate2 [(N : Int)] (PDesign.surfaceFuel [(N : Int)]) =
      .ok (design.pdesign.assemble2 (rrEnv N) (rrDeclsW N) rrElems []) := by
  have hd := rr_decls N
  rw [Lib.natAbs_sub_one_add_one hN] at hd
  exact PDesign.instantiate2_of_ok rfl (rr_paramEnv _) hd (rr_elems _)
    (by simp [design.pdesign])

theorem rr_processes (N : Nat) (hN : 1 ≤ N) :
    (design.pdesign.instantiateD2 [(N : Int)]).processes.toList = [combP N, ffP N] := by
  rw [PDesign.instantiateD2_of_ok (rr_instantiate2 N hN), PDesign.assemble2_processes,
    rr_static N hN]
  simp [design.pdesign]

theorem rr_driversOk (N : Nat) :
    driversOk design.pdesign.declNames design.pdesign.inputNames [combP N, ffP N] = true := by
  first
  | (simp [driversOk, driverWins, Process2.drvWins, Process2.procWins, Process2.procWrites,
      Process2.exclusive, Process2.exclClash, Process2.procWinsOn, procExclusiveOk,
      drvWinsDisjoint, DrvWin.overlaps, Stmt2.drvWins, Stmt2.drvWinsOpt, Stmt2.drvWinsList,
      Lhs2.drvWins, combP, combBody, ffP, ffBody, design.pdesign, PDesign.declNames, PDesign.inputNames]; done)
  | rfl

/-- **The loaded family is `rrD`**, at every `N ≥ 1`. -/
theorem rr_sem_eq (N : Nat) (hN : 1 ≤ N) : design.sem N = rrD N := by
  have h1 : design.sem N = design.pdesign.instantiateD2 [(N : Int)] := by
    show design.pdesign.instantiateGD2 [(N : Int)] = _
    exact PDesign.instantiateGD2_of_driversOk (by rw [rr_processes N hN]; exact rr_driversOk N)
  rw [h1, PDesign.instantiateD2_of_ok (rr_instantiate2 N hN)]
  simp only [PDesign.assemble2, rr_static N hN, rrD]
  simp [design.pdesign]

/-! ## 2. One cycle, in closed form (any values, `x` included) -/

/-- The seven signals of `rrD`, in declaration order. -/
def SS (ck r q g m mr pk : LVec) : SvState :=
  [("clk", ck), ("rst", r), ("req", q), ("gnt", g), ("mask", m), ("mreq", mr), ("pick", pk)]

theorem apply_rr (N : Nat) (e : SvState) (ck r q g m mr pk : LVec) :
    applyInputs2 (rrD N) e (SS ck r q g m mr pk) =
      SS (appIn e "clk" ck) (appIn e "rst" r) (appIn e "req" q) g m mr pk := by
  unfold applyInputs2
  rw [← Array.foldl_toList]
  cases h1 : SvState.lookup e "clk" <;> cases h2 : SvState.lookup e "rst" <;>
    cases h3 : SvState.lookup e "req" <;>
    simp [rrD, rrDeclsW, SS, appIn, h1, h2, h3, SvState.set]

/-- A write of a full-width part at bit `0` is the part. -/
theorem insertAt_zero_full (v p : LVec) (h : p.width = v.width) : v.insertAt 0 p = p := by
  apply LVec.ext_getElem?
  intro i
  simp only [LVec.insertAt, Array.getElem?_ofFn]
  by_cases hi : i < v.width
  · have hp : i < p.bits.size := by simp only [LVec.width] at h hi; omega
    rw [dif_pos hi, Array.getElem?_eq_getElem hp]
    simp [h, hi, Array.getElem?_eq_getElem hp]
  · have hp : p.bits.size ≤ i := by simp only [LVec.width] at h hi; omega
    rw [dif_neg hi, Array.getElem?_eq_none hp]

theorem width_resizeU' (v : LVec) (w : Nat) : (v.resizeU w).width = w := by
  simp [LVec.resizeU, LVec.width]

/-- The pick the comb block computes from `req` and `mreq`. -/
def pickV (N : Nat) (q mr : LVec) : LVec :=
  LVec.ternary (.ofLogic (mr.neLogical (z0 N))) (mr.and (mr.not.add (one1.resizeU N)))
    (q.and (q.not.add (one1.resizeU N)))

/-- `mreq` after the comb block. -/
def MRv (q m mr : LVec) : LVec := (q.and m).resizeU mr.width

/-- `pick` after the comb block. -/
def PKv (N : Nat) (q m mr pk : LVec) : LVec := (pickV N q (MRv q m mr)).resizeU pk.width

/-- The state after the comb block. -/
def combS (N : Nat) (ck r q g m mr pk : LVec) : SvState :=
  SS ck r q g m (MRv q m mr) (PKv N q m mr pk)

theorem MRv_width (q m mr : LVec) : (MRv q m mr).width = mr.width := width_resizeU' _ _
theorem PKv_width (N : Nat) (q m mr pk : LVec) : (PKv N q m mr pk).width = pk.width :=
  width_resizeU' _ _

theorem comb_run (N F : Nat) (hF : 20 ≤ F) (ck r q g m mr pk : LVec) :
    runCombProcess2 F (SS ck r q g m mr pk) (combP N) = .ok (combS N ck r q g m mr pk) := by
  obtain ⟨f, rfl⟩ : ∃ f, F = f + 20 := ⟨F - 20, by omega⟩
  simp [combP, combBody, combS, MRv, PKv, pickV, runCombProcess2, execStmt2, execStmts2, evalExpr2,
    resolveLhs2, readSignal, SS, SvState.lookup, SvState.set, insertAt_zero_full]

theorem choose_single (σ : ScheduleOracle) (k i : Nat) : σ.choose k [i] = [i] :=
  List.perm_singleton.mp (σ.choose_perm k [i])

/-- **The comb settle**: one pass computes the block, a second pass changes nothing. -/
theorem settle_rr (N : Nat) (σ : ScheduleOracle) (F k : Nat) (hF : 24 ≤ F) (ck r q g m mr pk : LVec) :
    ∃ k', combSettle2 (rrD N) σ F (SS ck r q g m mr pk) k = .ok (combS N ck r q g m mr pk, k') := by
  have hci : (rrD N).combIndices = [0] := rfl
  have hp0 : (rrD N).processes[0]? = some (combP N) := rfl
  have hpass : ∀ f', 20 ≤ f' → ∀ (ck r q g m mr pk : LVec) (j : Nat),
      combPass2 (rrD N) f' (SS ck r q g m mr pk) (σ.choose j (rrD N).combIndices) =
        .ok (combS N ck r q g m mr pk) := by
    intro f' hf' ck r q g m mr pk j
    rw [hci, choose_single]
    simp only [combPass2, hp0, comb_run N f' hf', Res.ok_bind]
  have hidem : combS N ck r q g m (MRv q m mr) (PKv N q m mr pk) = combS N ck r q g m mr pk := by
    simp only [combS, MRv, PKv, width_resizeU']
  have hpass2 : ∀ f', 20 ≤ f' → ∀ j, combPass2 (rrD N) f' (combS N ck r q g m mr pk)
      (σ.choose j (rrD N).combIndices) = .ok (combS N ck r q g m mr pk) := by
    intro f' hf' j
    show combPass2 (rrD N) f' (SS ck r q g m (MRv q m mr) (PKv N q m mr pk)) _ = _
    rw [hpass f' hf', hidem]
  obtain ⟨f, rfl⟩ : ∃ f, F = f + 24 := ⟨F - 24, by omega⟩
  rw [combSettle2.eq_2, hpass (f + 23) (by omega)]
  simp only [Res.ok_bind]
  by_cases hb : (combS N ck r q g m mr pk == SS ck r q g m mr pk) = true
  · rw [if_pos hb]; exact ⟨_, rfl⟩
  · rw [if_neg hb, combSettle2.eq_2, hpass2 (f + 22) (by omega)]
    simp only [Res.ok_bind]
    rw [beq_self_eq_true, if_pos rfl]
    exact ⟨_, rfl⟩

/-- `pick != '0`, the mask-update condition. -/
def NZ (N : Nat) (pk : LVec) : Bool := (LVec.ofLogic (pk.neLogical (z0 N))).condTrue

/-- The next mask `~((pick << 1) - 1)`. -/
def MaskV (N : Nat) (pk : LVec) : LVec :=
  ((pk.shl (LVec.ofInt 32 1)).sub (one1.resizeU N)).not

/-- The flop updates of a cycle, from the pre-edge `rst`, `gnt`, `mask` and `pick`. -/
def ffQ (N : Nat) (r g m pk : LVec) : NbaQueue2 :=
  if r.condTrue then [("gnt", 0, (z0 N).resizeU g.width), ("mask", 0, (z1 N).resizeU m.width)]
  else ("gnt", 0, pk.resizeU g.width) ::
    (if NZ N pk then [("mask", 0, (MaskV N pk).resizeU m.width)] else [])

theorem ff_run (N F : Nat) (hF : 30 ≤ F) (ck r q g m mr pk : LVec) :
    runEdgeProcess2 F (SS ck r q g m mr pk) [] (ffP N) = .ok (SS ck r q g m mr pk, ffQ N r g m pk) := by
  obtain ⟨f, rfl⟩ : ∃ f, F = f + 30 := ⟨F - 30, by omega⟩
  unfold ffQ NZ
  by_cases h1 : r.condTrue = true <;>
    by_cases h2 : (LVec.ofLogic (pk.neLogical (LVec.ofBitVec (0#N)))).condTrue = true <;>
    simp [ffP, ffBody, MaskV, runEdgeProcess2, execStmt2, execStmts2, evalExpr2, resolveLhs2, readSignal, SS,
      SvState.lookup, evalBinOp, h1, h2]

/-- `gnt` after the edge. -/
def Gv (N : Nat) (r g pk : LVec) : LVec :=
  if r.condTrue then (z0 N).resizeU g.width else pk.resizeU g.width

/-- `mask` after the edge. -/
def Mv (N : Nat) (r m pk : LVec) : LVec :=
  if r.condTrue then (z1 N).resizeU m.width else if NZ N pk then (MaskV N pk).resizeU m.width else m

theorem commit_ff (N : Nat) (ck r q g m mr pk : LVec) :
    commitNba2 (SS ck r q g m mr pk) (ffQ N r g m pk) = SS ck r q (Gv N r g pk) (Mv N r m pk) mr pk := by
  unfold ffQ Gv Mv
  by_cases h1 : r.condTrue = true <;> by_cases h2 : NZ N pk = true <;>
    simp [h1, h2, commitNba2, SS, SvState.lookup, SvState.set, insertAt_zero_full]

/-- **One cycle of `rrD`**, in closed form: the inputs, the comb block, the edge, the commit,
the comb block again. -/
def rrNext (N : Nat) (e : SvState) (ck r q g m mr pk : LVec) : SvState :=
  combS N (appIn e "clk" ck) (appIn e "rst" r) (appIn e "req" q)
    (Gv N (appIn e "rst" r) g (PKv N (appIn e "req" q) m mr pk))
    (Mv N (appIn e "rst" r) m (PKv N (appIn e "req" q) m mr pk))
    (MRv (appIn e "req" q) m mr) (PKv N (appIn e "req" q) m mr pk)

theorem rr_cycle (N : Nat) (σ : ScheduleOracle) (e : SvState) (ck r q g m mr pk : LVec)
    (kk F : Nat) (hF : 64 ≤ F) :
    ∃ k', cycleStep2 (rrD N) σ F e (SS ck r q g m mr pk) kk = .ok (rrNext N e ck r q g m mr pk, k') := by
  have hF' : 24 ≤ F := by omega
  obtain ⟨k1, h1⟩ := settle_rr N σ F kk hF' (appIn e "clk" ck) (appIn e "rst" r) (appIn e "req" q)
    g m mr pk
  obtain ⟨k2, h2⟩ := settle_rr N σ F (k1 + 1) hF' (appIn e "clk" ck) (appIn e "rst" r)
    (appIn e "req" q) (Gv N (appIn e "rst" r) g (PKv N (appIn e "req" q) m mr pk))
    (Mv N (appIn e "rst" r) m (PKv N (appIn e "req" q) m mr pk))
    (MRv (appIn e "req" q) m mr) (PKv N (appIn e "req" q) m mr pk)
  have hE : edgePass2 (rrD N) F (combS N (appIn e "clk" ck) (appIn e "rst" r) (appIn e "req" q) g m mr pk)
      [] (σ.choose k1 (rrD N).edgeIndices) =
      .ok (combS N (appIn e "clk" ck) (appIn e "rst" r) (appIn e "req" q) g m mr pk,
        ffQ N (appIn e "rst" r) g m (PKv N (appIn e "req" q) m mr pk)) := by
    rw [show (rrD N).edgeIndices = [1] from rfl, choose_single]
    simp only [edgePass2, combS, show (rrD N).processes[1]? = some (ffP N) from rfl,
      ff_run N F (by omega), Res.ok_bind]
  have hC : commitNba2 (combS N (appIn e "clk" ck) (appIn e "rst" r) (appIn e "req" q) g m mr pk)
      (ffQ N (appIn e "rst" r) g m (PKv N (appIn e "req" q) m mr pk)) =
      SS (appIn e "clk" ck) (appIn e "rst" r) (appIn e "req" q)
        (Gv N (appIn e "rst" r) g (PKv N (appIn e "req" q) m mr pk))
        (Mv N (appIn e "rst" r) m (PKv N (appIn e "req" q) m mr pk))
        (MRv (appIn e "req" q) m mr) (PKv N (appIn e "req" q) m mr pk) :=
    commit_ff N _ _ _ g m _ _
  have hre : ∀ a b, (rrD N).resetIndices a b = [] := fun _ _ => rfl
  refine ⟨k2, ?_⟩
  simp only [cycleStep2, apply_rr, h1, Res.ok_bind, Res.pure_eq, hre, hE, hC, h2] <;> rfl

/-! ## 3. The state shape, initially and through a cycle -/

/-- The states the design can be in: the seven signals, the registers and nets `N` bits wide. -/
def Shp (N : Nat) (st : SvState) : Prop :=
  ∃ ck r q g m mr pk, st = SS ck r q g m mr pk ∧ g.width = N ∧ m.width = N ∧ mr.width = N ∧ pk.width = N

theorem width_xVec (w : Nat) : (LVec.xVec w).width = w := by
  simp [LVec.xVec, LVec.replicate, LVec.width]

theorem rr_init (N : Nat) : Shp N (initState2 (rrD N)) :=
  ⟨LVec.xVec 1, LVec.xVec 1, LVec.xVec N, LVec.xVec N, LVec.xVec N, LVec.xVec N, LVec.xVec N, rfl,
    width_xVec N, width_xVec N, width_xVec N, width_xVec N⟩

theorem Gv_width (N : Nat) (r g pk : LVec) : (Gv N r g pk).width = g.width := by
  unfold Gv; split <;> exact width_resizeU' _ _

theorem Mv_width (N : Nat) (r m pk : LVec) : (Mv N r m pk).width = m.width := by
  unfold Mv
  split
  · exact width_resizeU' _ _
  · split
    · exact width_resizeU' _ _
    · rfl

theorem rrNext_shp {N : Nat} {e : SvState} {ck r q g m mr pk : LVec} (hg : g.width = N)
    (hm : m.width = N) (hmr : mr.width = N) (hpk : pk.width = N) :
    Shp N (rrNext N e ck r q g m mr pk) :=
  ⟨_, _, _, _, _, _, _, rfl, by rw [Gv_width, hg], by rw [Mv_width, hm],
    by rw [MRv_width, MRv_width, hmr], by rw [PKv_width, PKv_width, hpk]⟩

/-- One cycle from a state of the shape. -/
def Stp (N : Nat) (e prev st : SvState) : Prop :=
  ∃ ck r q g m mr pk, prev = SS ck r q g m mr pk ∧
    (g.width = N ∧ m.width = N ∧ mr.width = N ∧ pk.width = N) ∧ st = rrNext N e ck r q g m mr pk

/-! ## 4. The cycle on known values -/

theorem one_resize {N : Nat} : one1.resizeU N = LVec.ofBitVec (1#N) := by
  have h : one1 = LVec.ofBitVec (BitVec.ofBool true) := LVec.ofLogic_l1
  rw [h, LVec.resizeU_ofBitVec]
  congr 1
  apply BitVec.eq_of_getLsbD_eq
  intro i hi
  simp [hi]

theorem ofInt_one : LVec.ofInt 32 1 = LVec.ofBitVec (1#32) := by
  first | decide | simp [LVec.ofInt] | rfl

/-- `<<` of known vectors (a known shift amount) is `BitVec`'s left shift by the amount's value. -/
theorem shl_ofBitVec {w v : Nat} (x : BitVec w) (y : BitVec v) :
    (LVec.ofBitVec x).shl (LVec.ofBitVec y) = LVec.ofBitVec (x <<< y.toNat) := by
  rw [LVec.eq_ofBitVec_iff]
  refine ⟨by simp [LVec.shl, LVec.shiftAmount?, LVec.width]; exact LVec.width_ofBitVec x, fun i hi => ?_⟩
  simp only [LVec.shl, LVec.shiftAmount?, LVec.toNat?_ofBitVec, Array.getElem?_ofFn,
    LVec.width_ofBitVec, hi, dite_true, BitVec.getLsbD_shiftLeft]
  by_cases h : i < y.toNat
  · simp [h, Logic.ofBool]
  · have h2 : i - y.toNat < w := by omega
    simp [h, h2, LVec.getElem?_ofBitVec]

theorem mr_val {N : Nat} (x m : BitVec N) (mr : LVec) (hmr : mr.width = N) :
    MRv (LVec.ofBitVec x) (LVec.ofBitVec m) mr = LVec.ofBitVec (x &&& m) := by
  simp [MRv, hmr]

theorem pickV_val {N : Nat} (x s : BitVec N) :
    pickV N (LVec.ofBitVec x) (LVec.ofBitVec s) =
      LVec.ofBitVec (if s = 0#N then x &&& (~~~x + 1#N) else s &&& (~~~s + 1#N)) := by
  unfold pickV
  rw [one_resize]
  by_cases h : s = 0#N <;>
    simp [h, LVec.add_ofBitVec]

theorem pk_val {N : Nat} (x m : BitVec N) (mr pk : LVec) (hmr : mr.width = N)
    (hpk : pk.width = N) :
    PKv N (LVec.ofBitVec x) (LVec.ofBitVec m) mr pk = LVec.ofBitVec (RoundRobin.pick x m) := by
  unfold PKv RoundRobin.pick
  rw [mr_val x m mr hmr, pickV_val, hpk, LVec.resizeU_ofBitVec, BitVec.setWidth_eq]

theorem NZ_val {N : Nat} (p : BitVec N) : NZ N (LVec.ofBitVec p) = decide (p ≠ 0#N) := by
  by_cases h : p = 0#N <;> simp [NZ, h]

theorem MaskV_val {N : Nat} (p : BitVec N) :
    MaskV N (LVec.ofBitVec p) = LVec.ofBitVec (~~~((p <<< 1) - 1#N)) := by
  unfold MaskV
  rw [ofInt_one, shl_ofBitVec, one_resize, LVec.sub_ofBitVec, LVec.not_ofBitVec]
  simp

theorem Gv_reset {N : Nat} {g : LVec} (pk : LVec) (hg : g.width = N) :
    Gv N (knownBit true) g pk = LVec.ofBitVec 0#N := by
  simp [Gv, hg]

theorem Mv_reset {N : Nat} {m : LVec} (pk : LVec) (hm : m.width = N) :
    Mv N (knownBit true) m pk = LVec.ofBitVec (BitVec.allOnes N) := by
  simp [Mv, hm]

theorem Gv_run {N : Nat} {g : LVec} (p : BitVec N) (hg : g.width = N) :
    Gv N (knownBit false) g (LVec.ofBitVec p) = LVec.ofBitVec p := by
  simp [Gv, hg]

theorem Mv_run {N : Nat} (x mk : BitVec N) :
    Mv N (knownBit false) (LVec.ofBitVec mk) (LVec.ofBitVec (RoundRobin.pick x mk)) =
      LVec.ofBitVec (RoundRobin.next x mk) := by
  unfold Mv RoundRobin.next
  rw [condTrue_knownBit, NZ_val, MaskV_val]
  by_cases h : RoundRobin.pick x mk = 0#N <;> simp [h]

theorem rrNext_reset {N : Nat} {e : SvState} {ck r q g m mr pk : LVec} {x : BitVec N}
    (hb : BitIs e "rst" true) (hq : SvState.lookup e "req" = some (LVec.ofBitVec x))
    (hg : g.width = N) (hm : m.width = N) (hmr : mr.width = N) (hpk : pk.width = N) :
    rrNext N e ck r q g m mr pk = SS (appIn e "clk" ck) (knownBit true) (LVec.ofBitVec x)
      (LVec.ofBitVec 0#N) (LVec.ofBitVec (BitVec.allOnes N))
      (LVec.ofBitVec (x &&& BitVec.allOnes N))
      (LVec.ofBitVec (RoundRobin.pick x (BitVec.allOnes N))) := by
  have hr : appIn e "rst" r = knownBit true := BitIs.appIn_eq hb r
  have hq' : appIn e "req" q = LVec.ofBitVec x := by simp only [appIn, hq, Option.getD_some]
  unfold rrNext combS
  rw [hr, hq', Gv_reset _ hg, Mv_reset _ hm,
    mr_val x _ (MRv (LVec.ofBitVec x) m mr) (by rw [MRv_width, hmr]),
    pk_val x _ (MRv (LVec.ofBitVec x) m mr) (PKv N (LVec.ofBitVec x) m mr pk)
      (by rw [MRv_width, hmr]) (by rw [PKv_width, hpk])]

theorem rrNext_run {N : Nat} {e : SvState} {ck r q g m mr pk : LVec} {x mk : BitVec N}
    (hb : BitIs e "rst" false) (hq : SvState.lookup e "req" = some (LVec.ofBitVec x))
    (hm : m = LVec.ofBitVec mk) (hg : g.width = N) (hmr : mr.width = N) (hpk : pk.width = N) :
    rrNext N e ck r q g m mr pk = SS (appIn e "clk" ck) (knownBit false) (LVec.ofBitVec x)
      (LVec.ofBitVec (RoundRobin.pick x mk)) (LVec.ofBitVec (RoundRobin.next x mk))
      (LVec.ofBitVec (x &&& RoundRobin.next x mk))
      (LVec.ofBitVec (RoundRobin.pick x (RoundRobin.next x mk))) := by
  subst hm
  have hr : appIn e "rst" r = knownBit false := BitIs.appIn_eq hb r
  have hq' : appIn e "req" q = LVec.ofBitVec x := by simp only [appIn, hq, Option.getD_some]
  unfold rrNext combS
  rw [hr, hq', pk_val x mk mr pk hmr hpk, mr_val x mk mr hmr, Gv_run _ hg, Mv_run,
    mr_val x _ (LVec.ofBitVec (x &&& mk)) (LVec.width_ofBitVec _),
    pk_val x _ (LVec.ofBitVec (x &&& mk)) (LVec.ofBitVec (RoundRobin.pick x mk))
      (LVec.width_ofBitVec _) (LVec.width_ofBitVec _)]

/-! ## 5. The rank model -/

/-- The known `N`-bit value of signal `n` (`0`-filled where unknown; read only in invariant states). -/
def bvOf (N : Nat) (n : String) (st : SvState) : BitVec N :=
  BitVec.ofNat N ((SvState.lookup st n).getD (LVec.xVec N)).toNat

theorem bvOf_gnt {N : Nat} {ck r q m mr pk : LVec} {g : BitVec N} :
    bvOf N "gnt" (SS ck r q (LVec.ofBitVec g) m mr pk) = g := by
  simp [bvOf, SS, SvState.lookup, BitVec.ofNat_toNat]

theorem bvOf_mask {N : Nat} {ck r q g mr pk : LVec} {mk : BitVec N} :
    bvOf N "mask" (SS ck r q g (LVec.ofBitVec mk) mr pk) = mk := by
  simp [bvOf, SS, SvState.lookup, BitVec.ofNat_toNat]

theorem SS_mask {ck r q g m mr pk ck' r' q' g' m' mr' pk' : LVec}
    (h : SS ck r q g m mr pk = SS ck' r' q' g' m' mr' pk') : m = m' := by
  simp only [SS, List.cons.injEq, Prod.mk.injEq, true_and, and_true] at h
  exact h.2.2.2.2.1

open Classical in
/-- The edge of a thermometer mask (`0` for any other vector). -/
noncomputable def edgeOf {N : Nat} (mk : BitVec N) : Nat :=
  if h : ∃ e, RoundRobin.Thermo mk e then Classical.choose h else 0

theorem edgeOf_eq {N : Nat} {mk : BitVec N} {e : Nat} (h : RoundRobin.Thermo mk e) : edgeOf mk = e := by
  have hex : ∃ e, RoundRobin.Thermo mk e := ⟨e, h⟩
  unfold edgeOf
  rw [dif_pos hex]
  exact (Classical.choose_spec hex).unique h

/-- **The invariant** of the snapshots from a reset on: every signal but `clk` known, the mask a
thermometer, `mreq` and `pick` the comb block's values. -/
def ArbInv (N : Nat) (st : SvState) : Prop :=
  ∃ (ck : LVec) (b : Bool) (x g mk : BitVec N) (e : Nat),
    st = SS ck (knownBit b) (LVec.ofBitVec x) (LVec.ofBitVec g) (LVec.ofBitVec mk)
      (LVec.ofBitVec (x &&& mk)) (LVec.ofBitVec (RoundRobin.pick x mk)) ∧ RoundRobin.Thermo mk e

theorem pick_grants {N : Nat} (x mk : BitVec N) : Tasks.Arbiter.Grants x (RoundRobin.pick x mk) :=
  ⟨fun _ _ hi hj => RoundRobin.pick_atMostOne hi hj, fun _ hi => RoundRobin.pick_sub hi,
    fun hx h => hx (RoundRobin.pick_eq_zero.1 h)⟩

/-- **The rank model** of the reference at `N`, with the response bound `N - 1`. -/
noncomputable def model (N : Nat) (hN : 1 ≤ N) :
    Tasks.Arbiter.task.RankModel N (N - 1) (design.sem N) where
  Shape := Shp N
  Step := Stp N
  init := by rw [rr_sem_eq N hN]; exact rr_init N
  cycle := by
    rintro σ F e prev k st k' ⟨ck, r, q, g, m, mr, pk, rfl, hw⟩ hc
    rw [rr_sem_eq N hN] at hc
    obtain ⟨k2, h2⟩ := rr_cycle N σ e ck r q g m mr pk k 64 (Nat.le_refl _)
    exact ⟨ck, r, q, g, m, mr, pk, rfl, hw, (Prod.mk.inj (cycleStep2_det hc h2)).1⟩
  shape := by
    rintro e prev st - ⟨ck, r, q, g, m, mr, pk, -, ⟨hg, hm, hmr, hpk⟩, rfl⟩
    exact rrNext_shp hg hm hmr hpk
  Inv := fun _ st => ArbInv N st
  out := fun st => (bvOf N "gnt" st, ())
  shows := by
    rintro - st ⟨ck, b, x, g, mk, e, rfl, -⟩
    show SvState.lookup _ "gnt" = some (LVec.ofBitVec (bvOf N "gnt" _)) ∧ True
    rw [bvOf_gnt]
    exact ⟨by simp [SS, SvState.lookup], trivial⟩
  rank := fun o st => RoundRobin.dist N (edgeOf (bvOf N "mask" st)) o.val
  rank_le := by
    rintro o - st ⟨ck, b, x, g, mk, e, rfl, hth⟩
    show RoundRobin.dist N (edgeOf (bvOf N "mask" _)) o.val ≤ N - 1
    rw [bvOf_mask, edgeOf_eq hth]
    exact RoundRobin.dist_le hth.1 o.isLt
  reset := by
    rintro e prev st ⟨x, ⟨⟩⟩ - ⟨ck, r, q, g, m, mr, pk, -, ⟨hg, hm, hmr, hpk⟩, rfl⟩ hb hx
    have hq : SvState.lookup e "req" = some (LVec.ofBitVec x) := hx.1
    rw [rrNext_reset hb hq hg hm hmr hpk]
    refine ⟨⟨_, true, x, 0#N, BitVec.allOnes N, 0, rfl, RoundRobin.thermo_allOnes N⟩, ?_⟩
    show bvOf N "gnt" _ = 0#N
    rw [bvOf_gnt]
  step := by
    rintro e prev st - ⟨x, ⟨⟩⟩ - ⟨ck, r, q, g, m, mr, pk, rfl, ⟨hg, hm, hmr, hpk⟩, rfl⟩
      ⟨ck', b', xp, gp, mk, ed, hprev, hth⟩ hb hx
    have hq : SvState.lookup e "req" = some (LVec.ofBitVec x) := hx.1
    have hmm : m = LVec.ofBitVec mk := SS_mask hprev
    have hmask : bvOf N "mask" (SS ck r q g m mr pk) = mk := by rw [hmm, bvOf_mask]
    rw [rrNext_run hb hq hmm hg hmr hpk]
    obtain ⟨e', hth', hprog⟩ := RoundRobin.step (x := x) hth
    refine ⟨⟨_, false, x, _, _, e', rfl, hth'⟩, ?_, fun o ho => ?_⟩
    · show Tasks.Arbiter.Grants x (bvOf N "gnt" _)
      rw [bvOf_gnt]
      exact pick_grants x mk
    · have ho' : x.getLsbD o.val = true := ho
      by_cases hp : (RoundRobin.pick x mk).getLsbD o.val = true
      · left
        show (bvOf N "gnt" _).getLsbD o.val = true
        rw [bvOf_gnt]
        exact hp
      · right
        show RoundRobin.dist N (edgeOf (bvOf N "mask" _)) o.val <
          RoundRobin.dist N (edgeOf (bvOf N "mask" _)) o.val
        rw [bvOf_mask, hmask, edgeOf_eq hth', edgeOf_eq hth]
        exact hprog o.val o.isLt ho' (by simpa using hp)

/-! ## 6. Structure, and the statement -/

theorem rr_interface (N : Nat) (hN : 1 ≤ N) : Tasks.Arbiter.task.Interface N (design.sem N) := by
  rw [rr_sem_eq N hN]
  exact ⟨rfl, rfl, by show (["clk", "rst", "req", "gnt", "mask", "mreq", "pick"] : List String).Nodup; decide⟩

theorem rr_moore (N : Nat) : MooreOut (rrD N) := by
  apply mooreOut_of_combTargets
  · simp [rrD, rrDeclsW, Design2.outputNames, Design2.inputNames]
  · simp [rrD, combP, combBody, ffP, ffBody, Process2.isCombPhase, processTargets, stmtTargets, stmtListTargets,
      stmtOptTargets, lhsTargets, Design2.outputNames, rrDeclsW]

theorem rr_disciplined (N : Nat) (hN : 1 ≤ N) : Tasks.Arbiter.task.Disciplined (design.sem N) := by
  rw [rr_sem_eq N hN]
  refine ⟨⟨by simp [Tasks.Arbiter.task, rrD, rrDeclsW, Design2.inputNames], fun p hp => ?_⟩, rr_moore N⟩
  have hm : p = combP N ∨ p = ffP N := by simpa [rrD] using hp
  rcases hm with rfl | rfl <;>
    simp [Tasks.Arbiter.task, combP, combBody, ffP, ffBody, edgeClock, asyncReset, processDataNames, stmtNames,
      stmtOptNames, stmtListNames, lhsNames, exprNames, Process2.isEdgePhase]

/-- **Every power-up state has the shape** (txtask-v2's rule 2): the seven signals in declaration
order, each at its declared width. -/
theorem rr_powerUp (N : Nat) : ∀ st, PowerUp (rrD N) st → Shp N st := by
  intro st h
  have h' : st.map Prod.fst = (rrDeclsW N).map Decl.name ∧
      ∀ b ∈ st.zip (rrDeclsW N), b.1.2.width = b.2.width ∧ b.1.2.allKnown = true := h
  rw [rrDeclsW] at h'
  obtain ⟨ck, r1, rfl, -, -, h1⟩ := powerUp_cons.mp h'
  obtain ⟨r, r2, rfl, -, -, h2⟩ := powerUp_cons.mp h1
  obtain ⟨q, r3, rfl, -, -, h3⟩ := powerUp_cons.mp h2
  obtain ⟨g, r4, rfl, hg, -, h4⟩ := powerUp_cons.mp h3
  obtain ⟨m, r5, rfl, hm, -, h5⟩ := powerUp_cons.mp h4
  obtain ⟨mr, r6, rfl, hmr, -, h6⟩ := powerUp_cons.mp h5
  obtain ⟨pk, r7, rfl, hpk, -, h7⟩ := powerUp_cons.mp h6
  obtain rfl := powerUp_nil.mp h7
  exact ⟨ck, r, q, g, m, mr, pk, rfl, hg, hm, hmr, hpk⟩

theorem rr_terminates (N : Nat) (hN : 1 ≤ N) : TerminatesPU (design.sem N) := by
  rw [rr_sem_eq N hN]
  refine TerminatesPU.of_invariant (Shp N) (rr_powerUp N) (fun σ => ⟨64, ?_⟩) ?_
  · rintro e _ kk ⟨ck, r, q, g, m, mr, pk, rfl, hg, hm, hmr, hpk⟩
    obtain ⟨k', h⟩ := rr_cycle N σ e ck r q g m mr pk kk 64 (Nat.le_refl _)
    exact ⟨_, _, h, rrNext_shp hg hm hmr hpk⟩
  · first
    | rfl
    | simp [rrD, combP, combBody, ffP, ffBody, Process2.hasQualifiedCase, Stmt2.hasQualifiedCase,
        Stmt2.listHasQualifiedCase]

theorem one1_allKnown : one1.allKnown = true := by
  rw [show one1 = LVec.ofBitVec (BitVec.ofBool true) from LVec.ofLogic_l1]
  exact LVec.allKnown_ofBitVec _
theorem one1_width : one1.width = 1 := rfl

/-- **Rule 3**: no construct of the design can create an `x` from known operands (every operand
pair of `&`, `!=`, `?:` has one width; no division, no dynamic index). -/
theorem rr_xsafe (N : Nat) (hN : 1 ≤ N) : XSafe (design.sem N) := by
  rw [rr_sem_eq N hN]
  simp [XSafe, xsafeB, rrD, rrDeclsW, combP, ffP, combBody, ffBody, xsProc, xsStmt, xsStmts, xsOpt,
    xsLhs, xsWidth, binW, sigWidth, ofInt_one, one1_allKnown, one1_width]

/-- **The reference satisfies the arbiter statement**, at every `N` in range. -/
theorem solution : Goal := by
  intro N hN
  obtain ⟨hN1, -⟩ := hN
  exact Tasks.Arbiter.task.satisfiedAt_of_rank (rr_interface N hN1) (rr_disciplined N hN1)
    (rr_terminates N hN1) (model N hN1)
    (fun st h => rr_powerUp N st (by rw [rr_sem_eq N hN1] at h; exact h)) (rr_xsafe N hN1)

/--
info: 'Submission.solution' depends on axioms: [propext, Classical.choice, Quot.sound]
-/
#guard_msgs (whitespace := lax) in
#print axioms solution

end Submission

The netlist

The netlist card shows the sky130 weighing (its cells, its critical path): the ASAP7 view changes the overview above, not this card.

Schematic

drawn at N = 4

Drawn at N = 4, a display instance; scored at N = 8. Only this drawing and the notes under it are at the smaller size: the critical path, the cells and every other number on this page are the scored netlist's.

_0__reg[0] · sky130_fd_sc_hd__dfxtp_1 dfxtp_1 D Q _0__reg[1] · sky130_fd_sc_hd__dfxtp_1 dfxtp_1 D Q _0__reg[2] · sky130_fd_sc_hd__dfxtp_1 dfxtp_1 D Q _0__reg[3] · sky130_fd_sc_hd__dfxtp_1 dfxtp_1 D Q _41_ · sky130_fd_sc_hd__nand2_1 nand2_1 _42_ · sky130_fd_sc_hd__nand2_1 nand2_1 _43_ · sky130_fd_sc_hd__nand2_1 nand2_1 _44_ · sky130_fd_sc_hd__and2_1 and2_1 _45_ · sky130_fd_sc_hd__and2_1 and2_1 _46_ · sky130_fd_sc_hd__nor2b_1 nor2b_1 _47_ · sky130_fd_sc_hd__and2_1 and2_1 _48_ · sky130_fd_sc_hd__or2_1 or2_1 _49_ · sky130_fd_sc_hd__nand2_1 nand2_1 _50_ · sky130_fd_sc_hd__nor2_1 nor2_1 _51_ · sky130_fd_sc_hd__nand2b_1 nand2b_1 _52_ · sky130_fd_sc_hd__nor2b_1 nor2b_1 _53_ · sky130_fd_sc_hd__nand2_1 nand2_1 _54_ · sky130_fd_sc_hd__and2_1 and2_1 _55_ · sky130_fd_sc_hd__nor2_1 nor2_1 _56_ · sky130_fd_sc_hd__nand2_1 nand2_1 _57_ · sky130_fd_sc_hd__nor2_1 nor2_1 _58_ · sky130_fd_sc_hd__and2_1 and2_1 _59_ · sky130_fd_sc_hd__nand2_1 nand2_1 _60_ · sky130_fd_sc_hd__and2_1 and2_1 _61_ · sky130_fd_sc_hd__nor2_1 nor2_1 _62_ · sky130_fd_sc_hd__nor2b_1 nor2b_1 _63_ · sky130_fd_sc_hd__nand2_1 nand2_1 _64_ · sky130_fd_sc_hd__nand2_1 nand2_1 _65_ · sky130_fd_sc_hd__nand2_1 nand2_1 _66_ · sky130_fd_sc_hd__nor2_1 nor2_1 _67_ · sky130_fd_sc_hd__and2_1 and2_1 _68_ · sky130_fd_sc_hd__and2_1 and2_1 _69_ · sky130_fd_sc_hd__and2_1 and2_1 _70_ · sky130_fd_sc_hd__and2_1 and2_1 _71_ · sky130_fd_sc_hd__or2_1 or2_1 _72_ · sky130_fd_sc_hd__nand2_1 nand2_1 _73_ · sky130_fd_sc_hd__nor2b_1 nor2b_1 _74_ · sky130_fd_sc_hd__nand2_1 nand2_1 _75_ · sky130_fd_sc_hd__nand2_1 nand2_1 _76_ · sky130_fd_sc_hd__nor2b_1 nor2b_1 _77_ · sky130_fd_sc_hd__nand2_1 nand2_1 _78_ · sky130_fd_sc_hd__and2_1 and2_1 _79_ · sky130_fd_sc_hd__nor2_1 nor2_1 _80_ · sky130_fd_sc_hd__nand2_1 nand2_1 gnt_reg[0] · sky130_fd_sc_hd__dfxtp_1 dfxtp_1 D Q gnt_reg[1] · sky130_fd_sc_hd__dfxtp_1 dfxtp_1 D Q gnt_reg[2] · sky130_fd_sc_hd__dfxtp_1 dfxtp_1 D Q gnt_reg[3] · sky130_fd_sc_hd__dfxtp_1 dfxtp_1 D Q clk gnt req rst 0 1 2 3 0 3 1 2

It is the same design through the same pinned flow at a smaller size (ppa.py --param), so that what it does can be seen: 48 cells here, 103 at the scoring point. The register-to-register critical path at N = 4 (11 cells, ending at the flip-flop input _05_ falling; a period of 1 869 ps there) is in the accent colour. Drawn by netlistsvg with svGolf's sky130 skin (derived from netlistsvg's default skin, as the drawing is: MIT licence, Copyright (c) 2016 Neil Turley, the notice): one symbol per cell function, the cell above it, the instance on hover; nor2b and nand2b are drawn with the bubble on their inverted input. The cells of the path are listed under Critical path, each a link to the cell here.

The netlist at N = 4: 48 cells, 15 nand2_1, 11 and2_1, 8 dfxtp_1, 6 nor2_1, 5 nor2b_1, 2 or2_1, 1 nand2b_1. There (measured, not ranked): 357.84 µm², 1 869 ps. Open the drawing on its own (SVG, 32.4 KB) to pan and zoom it with the browser's own controls.

Critical path

at N = 8 · scored

The path the ranked register-to-register period ends on, at the scoring point N = 8: 16 nets, 15 cells, to the flip-flop input _009_ falling; the period, 2 826 ps, is the last arrival plus that flip-flop's setup time (ideal clock). Each row is a net of the repaired netlist with the arrival and the transition the STA computed there (NLDM tables, the larger transition carried; no wires). The first row is a flip-flop's Q: its arrival is the flop's clock-to-Q delay after the clock edge. From ppa.py --path (critical_path_timing); the instance names are the scored netlist's, not the schematic's (drawn at a smaller size).

In the schematic, drawn at N = 4, the critical path is 11 cells to the flip-flop input _05_ falling (a period of 1 869 ps there); each cell is a link to it in the drawing:

  1. \_0_[0]
  2. _41_ nand2_1
  3. _44_ and2_1
  4. _46_ nor2b_1
  5. _47_ and2_1
  6. _53_ nand2_1
  7. _54_ and2_1
  8. _67_ and2_1
  9. _68_ and2_1
  10. _69_ and2_1
  11. _70_ and2_1
  12. _71_ or2_1
  13. _05_ flip-flop D
#netedgedriven bycellarrival (ps)transition (ps)stage (ps)
0\_0_[1]riseflop Q–314.659.1
1_037_fall_094_nand2_1362.633.548.0
2_038_fall_095_and2_1512.740.1150.1
3_039_fall_096_and2_1665.640.1152.9
4_040_fall_097_and2_1818.440.0152.8
5_042_fall_099_nor2b_1945.337.2126.9
6_043_fall_100_and2_11 097.040.1151.7
7_044_fall_101_and2_11 249.740.0152.7
8_045_fall_102_and2_11 452.190.8202.4
9_050_fall_108_mux2_11 779.761.6327.6
10_080_fall_145_and2_11 937.536.4157.8
11_081_fall_146_nor2b_12 059.033.6121.5
12_082_fall_147_and2_12 204.536.3145.5
13_086_fall_151_and2_12 374.176.9169.6
14_087_fall_152_and2_12 530.229.7156.1
15_009_fall_153_or2_12 718.142.8187.9

Cells

at N = 8 · scored

the cells of the repaired netlist, by area8 bars; the table beside the chart lists the same numbers.dfxtp_1: 320.31 µm² (µm² · 16 cells)dfxtp_1320.31 µm² · 16 cellsand2_1: 162.66 µm² (µm² · 26 cells)and2_1162.66 µm² · 26 cellsnand2_1: 120.12 µm² (µm² · 32 cells)nand2_1120.12 µm² · 32 cellsnor2b_1: 75.07 µm² (µm² · 12 cells)nor2b_175.07 µm² · 12 cellsnand2b_1: 37.54 µm² (µm² · 6 cells)nand2b_137.54 µm² · 6 cellsnor2_1: 30.03 µm² (µm² · 8 cells)nor2_130.03 µm² · 8 cellsor2_1: 12.51 µm² (µm² · 2 cells)or2_112.51 µm² · 2 cellsmux2_1: 11.26 µm² (µm² · 1 cell)mux2_111.26 µm² · 1 cell
The area of each cell type in the repaired A0′ netlist, at the scoring point: the count times the cell's area in the pinned liberty. Their sum is the ranked area.
cellcountµm² eachµm² in allshare
dfxtp_11620.0192320.307241.6%
and2_1266.2560162.656021.1%
nand2_1323.7536120.115215.6%
nor2b_1126.256075.07209.8%
nand2b_166.256037.53604.9%
nor2_183.753630.02883.9%
or2_126.256012.51201.6%
mux2_1111.260811.26081.5%
total103769.4880

Repair (buffer_trees_v1): 0 buffers on 0 nets, 0 tie cells, 1 weighing round; nothing is resized.

Legality: worst load 0.107 × max_capacitance, worst transition 0.118 × max_transition; 0 timing-table reads outside the characterized grid.

the gate mix of the extra GE column (the pinned GE table, score/ge_seq.json)
gate mix: cells of each type in the scored netlist8 bars; the table beside the chart lists the same numbers.NAND: 32 cells (32.000 GE)NAND32 32.000 GEAND: 26 cells (34.658 GE)AND26 34.658 GEDFF_P: 16 cells (85.328 GE)DFF_P16 85.328 GEANDNOT: 12 cells (15.996 GE)ANDNOT12 15.996 GENOR: 8 cells (8.000 GE)NOR8 8.000 GEORNOT: 6 cells (7.998 GE)ORNOT6 7.998 GEOR: 2 cells (2.666 GE)OR2 2.666 GEMUX: 1 cell (2.333 GE)MUX1 2.333 GE
Cells by type; area is the count weighted by the pinned GE table.
cellcountGE eachGE total
NAND321.00032.000
AND261.33334.658
DFF_P165.33385.328
ANDNOT121.33315.996
NOR81.0008.000
ORNOT61.3337.998
OR21.3332.666
MUX12.3332.333
total103188.979

The record

task
arbiter
player
svgolf-reference
assisted by
Claude (Anthropic)
submitted
2026-11-09
notes
reference solution
scoring point
N = 8
design
rr_mask.sv sha256 f8b02272b7f264d935673b0fa5522fbfb877bdf2985b5c1ad27b861b3a5de784
proof
rr_mask.lean sha256 e082faec9a4fd3c5c00c4ebadace2e3d3007e320a0b5f886b2d4e23c8bc52004: the proof of the reference rr_mask (rr_mask.lean, 487 code lines)
canonical text
sha256 b0bbcf311076bbbb383739ead07fde6ae639ee5deb284c643b1e943ab7d0af67
record hash
84da5a4152db28e4aed74c6cb7f37ec329dc636a4433aff3946fc34e6f60453b
downloads
84da5a4152db.sv 84da5a4152db.lean 84da5a4152db.json

The proof

code lines
487
build time
4.26 s
axioms
Classical.choice, Quot.sound, propext
tactics seen
decide, omega, simp
imports
Submission.Design, LeanModels.Sv.Gen2, LeanModels.Sv.Hier2Gen, LeanModels.Sv.Known2, LeanModels.Sv.Mono2, LeanModels.Sv.SeqFamily, SvGolf.Seq, SvGolf.React, SvGolf.RoundRobin

Checker and flow

Checked under the pinned flow of this site's boards.

Yosys
Yosys 0.53 (git sha1 53c22ab7c0ced80861c7536c5dae682c30fb5834, clang++ 17.0.0 -fPIC -O3)
Verilator
Verilator 5.042 2025-11-02 rev UNKNOWN.REV
Lean toolchain
leanprover/lean4:v4.33.0-rc1
svGolf revision
7fb4c3d844e0911b67cb6657e9dfdac8741e72d3
lean-surfaces revision
7fb4c3d844e0911b67cb6657e9dfdac8741e72d3
canonicalization script
bbd11227d45dc1365f27597fd45c565fe721ba2648450588fc4fd983d00b367b
scoring script
c3874dbfc85921a87df6eacdfc6b2c9a0e2b34edd5738951e0d8bdb51f4558b2
GE table
0a1aa1147b6916efa4a41e03aa3c8c70e68c1e3fd7a0e9c9a3cbc177edefd1f6
extractor
4930696021c588c75dc890034c534c95560ad9a28a4955b87d1f8d68b5edbc0c
canonical RTLIL
a60960b454b2b36f8f70de80cc69bd944808d6b5f553fb2dd66f21c1507c372a
the checker's files (sha256)
filesha256
check.pyb0c939438a765c2ffeb679721c83ced6213c0a96bfef84759948d3857db9f431
check/Comparator.lean936f97636d6256374eaa4435d03321eeff29e22f808a72c7781375ab648600e8
check/SvEval.leanfb51d72510b515460866c2798aad3c6f55295536e627b92854c3580af215bb91
check/clocked_rules.py73856a45905724544247ad29042bdc2f1778271ec07b15cdb3a5f214685165c1
check/envelope.py076db01a9791bcc25ee84e9b0033604a4b675f00b212eab0c864078e6a4748b7
check/postsynth.pydd89805f9e8335ab15d6bb753eea76865bce47e84ccffa7e7280c91da8131d23
lakefile.tomlf35a88404367d22906effc14d644aac9a9cad47dfd3b704ea8fec88acfaf9c4d
lean-toolchain62c2d9c0fc1ec4c67e151c11eff41ca004ef38e179cf9476c230406e6defedef
score/banlist.pyf18c14c23a14d55db63e202f42cc424dc84c1dd1c337f132ad60859dc9d5d33a
score/canon.ysbbd11227d45dc1365f27597fd45c565fe721ba2648450588fc4fd983d00b367b
score/fourstate.py95332451ae3754226fb87b46027385b46a91121e7eb9ae25b302bce756d90475
score/ge.json6a29196a3f4b58241f4c9af650c9141e4632b737214d563a11ba142a725c4bea
score/ge_seq.json0a1aa1147b6916efa4a41e03aa3c8c70e68c1e3fd7a0e9c9a3cbc177edefd1f6
score/ppa.py912031912c3e3f6790725161753e95415df34846bd8c27dde3eb707747ddbcbe
score/ppa_mapped.ys93547b343dbac135737e98516b1004a780e1cf2f579e1bd7fed82c908c6d4125
score/ppa_mapped_pins.json4b8688ba3f4d67681658e5944afe878592adf588cd416a8b47597ebe06deb045
score/ppa_pins.jsond66a6086a37a97f5985266057051979fb6a8a3c557d3ef9c42acc1b5e41502d8
score/score.py71d2e3b82f8813ec64a58f0a46909ca23dfab377db44eda6f294b713f45ae781
score/srcgate.py11952f61058051c9e8de91a801b672d07e66a29308e978156c04ffd9f0dbef45
score/svgolf.ysea58219d8ef14c3bad265218ee266ccdb709ac9d4dc5258edc34d51ee83a0445
score/svgolf_seq.ysc3874dbfc85921a87df6eacdfc6b2c9a0e2b34edd5738951e0d8bdb51f4558b2

Post-synthesis check

At each point below, the check ran the scored netlist and ls-sv's reading of the design 8 times, once per seed, each run from a power-up state and through a seeded stimulus of 24 segments: a reset entry, then entries with rst = 0, the last segment a long run without a reset. On every cycle of every run the netlist's outputs met the task's guarantee, and the outputs sampled just before each rising edge equalled the snapshot before (the Moore sample). Where the two runs start from the same state (seed 0, the all-zeros power-up, unless the pinned flow turned a register into a constant 1) the netlist's outputs equalled ls-sv's bit for bit; from two different power-ups a correct design may answer differently, and ls-sv's outputs met the guarantee too. The check found no mismatch. The stimulus is a sample of the input traces: a guard against the two tools disagreeing, not a proof.

mode
full
points
N = 3, N = 5, N = 8 (the scoring point)
seeds
8 seeds per point: seed 0 from the all-zeros power-up, every other one from a random power-up drawn from its seed (below)
stimulus
24 segments per seed
clock cycles
1 687 035 in all
mismatches
0
salted
no (the default empty salt: anyone can run this exact stimulus again)
scored netlist
sha256 e072fb19e91c79f0adcdfa0ef3709731d0c642bc4c38b853cbedd53cc6f85d0e
pointseedsclock cyclessegmentsmismatchesnetlist sha256
N = 38561 4351920c5d0e3505f40
N = 58562 04619202903b644d97e
N = 88563 5541920e072fb19e91c
every seed's run (24)

A seed's draw is sha256(salt, task, point, seed) (its first 12 digits below; check/postsynth.py seed_draw). Everything random in the seed's run comes from it: the stimulus, ls-sv's power-up (zeros for seed 0, else seed:<k>) and the netlist's Verilator randSeed, which the all-zeros power-up of seed 0 does not use.

pointseedls-sv power-upnetlist randSeedclock cyclessegmentsdraw
N = 30zeros5169352770 1912491e7bd9c85d2
N = 31seed:7789121772795600815146716594170 19424ff4494b3cb58
N = 32seed:1449055636464940080250706024170 134246e9e9dab38e7
N = 33seed:5524233232498431859131096919470 2132459f4eb1b3a7f
N = 34seed:16777839557804680643145142960470 16624b70ed7f8dc34
N = 35seed:2322128566058997970185055502470 185249fd37805cb9e
N = 36seed:7311075774938213980206163703470 185245854ccc01bce
N = 37seed:12684631304222669956115463237170 16724b8adc5781f9d
N = 50zeros192418111570 21824a2926a835c5a
N = 51seed:1190229300534884153239187881470 2642497821ffe52f8
N = 52seed:931506634852399523242231497070 201241687ae38eb15
N = 53seed:606945942918223950411296329070 262244a4508272d7d
N = 54seed:10194850246807243092205836077070 24824f52d4d97d7b8
N = 55seed:1759472881929067588312012374870 2622432c058f0e81e
N = 56seed:1822507396591165559087777676170 31024a4d17808209a
N = 57seed:626324533183261850484138820570 28124fb8ef5561734
N = 80zeros29569015770 50724ed6b3ddc4f33
N = 81seed:1510559514096927918155102980370 4232467b30be23a85
N = 82seed:1301062456188687467925170491370 59724751e5f9acdad
N = 83seed:18261098257774128044120355642370 45424fbdd7938d96b
N = 84seed:14402032186337480843161670584070 415244beefbb0c098
N = 85seed:966029803194144696651046455270 39824726e04a4aefc
N = 86seed:6798390078260723393145038547970 38524e009927d95a5
N = 87seed:1496864636506506966438687479470 3752442dcc9951d74

Area against time

µm² × ps · lower left is better · ASAP7
arbiter: this design's sky130 area against time, among the task's designs1 design by sky130 area (µm²) (x) and time (ps) (y), this one ringed; lower left is better. The table under the chart lists the same numbers.2700280029003000720740760780800820sky130 area (µm²)time (ps) · lower is betterpar's score: area × time = 2175 µm²·nsthe Pareto front of the entriesthis design · rr_mask · proved reference · par · 2026-11-05T18:53:43Z · Score: 2175 µm²·ns · Area: 769.5 µm² · Time: 2826 psthis design · par
arbiter: this design's sky130 area against time, among the task's designs1 design by sky130 area (µm²) (x) and time (ps) (y), this one ringed; lower left is better. The table under the chart lists the same numbers.2700280029003000750800sky130 area (µm²)time (ps) · lower is betterpar's score: area × time = 2175 µm²·nsthe Pareto front of the entriesthis design · rr_mask · proved reference · par · 2026-11-05T18:53:43Z · Score: 2175 µm²·ns · Area: 769.5 µm² · Time: 2826 psthis design · par
  • proved reference
  • the Pareto front of the entries
  • this design
  • par's score: area × time = 2175 µm²·ns
sky130 area (x) against the ranked time (y); lower left is better on both. The step line is the Pareto front of the entries (the proved references and the players' ranked records); a design under par's score curve has a better score than par. Baselines are drawn for scale: scored, never proved. Every design is in view.
the designs as numbers, by score
designkindarea (µm²)time (ps)score (µm²·ns)
rr_mask · this designproved reference · par769.492 8262175
arbiter: this design's ASAP7 area against time, among the task's designs1 design by ASAP7 area (µm²) (x) and time (ps) (y), this one ringed; lower left is better. The table under the chart lists the same numbers.44046048011.51212.513ASAP7 area (µm²)time (ps) · lower is betterpar's score: area × time = 5.642 µm²·nsthe Pareto front of the entriesthis design · rr_mask · proved reference · par · 2026-11-05T18:53:43Z · Score: 5.642 µm²·ns · Area: 12.160 µm² · Time: 464 psthis design · par
arbiter: this design's ASAP7 area against time, among the task's designs1 design by ASAP7 area (µm²) (x) and time (ps) (y), this one ringed; lower left is better. The table under the chart lists the same numbers.44046048011.51212.513ASAP7 area (µm²)time (ps) · lower is betterpar's score: area × time = 5.642 µm²·nsthe Pareto front of the entriesthis design · rr_mask · proved reference · par · 2026-11-05T18:53:43Z · Score: 5.642 µm²·ns · Area: 12.160 µm² · Time: 464 psthis design · par
  • proved reference
  • the Pareto front of the entries
  • this design
  • par's score: area × time = 5.642 µm²·ns
ASAP7 area (x) against the ASAP7 time (y); lower left is better on both. The step line is the Pareto front of the entries (the proved references and the players' ranked records); a design under par's score curve has a better score than par. Baselines are drawn for scale: scored, never proved. Every design is in view.
the designs as numbers, by score
designkindarea (µm²)time (ps)score (µm²·ns)
rr_mask · this designproved reference · par12.1604645.642

Reproduce and verify

From svgolf/, with the pinned tools (reproduce a score lists them):

shell
# the ranked numbers, at the scoring point (from svgolf/, with the pinned Yosys and liberty)
# a clocked task: the clocked flow, --seq (the time is the register-to-register period)
python3.12 score/ppa.py tasks/arbiter/reference/rr_mask.sv --task tasks/arbiter --seq --path \
    --json out.json --netlist scored.v --repaired-netlist repaired.v

Expect, in out.json:

score.rtlil_sha256
a60960b454b2b36f8f70de80cc69bd944808d6b5f553fb2dd66f21c1507c372a
ppa.netlist_sha256
e072fb19e91c79f0adcdfa0ef3709731d0c642bc4c38b853cbedd53cc6f85d0e
ppa.repair.netlist_sha256
54e9b0edaecf4e3c51a9b662f32499c955f2ccb7db4f1e9647c3ba25d0050792
ppa.area_e4um2_sky130
7694880
ppa.delay_ps_sky130
2826

The schematic and the critical-path data are site/schematics/arbiter/f8b02272b7f264d9.json and its .svg, written by site/gen_schematics.py (the display instance is ppa.py ... --param N=4 --repaired-netlist, drawn by netlistsvg 1.0.2; repaired netlist sha256 287f30177c1e33bc…).

From svgolf/, with the pinned tools (reproduce a score lists them):

shell
# the ASAP7 view's numbers, at the scoring point (from svgolf/, with the pinned Yosys; once:
# python3.12 score/ppa.py --pdk asap7 --fetch-liberty, the five pinned ASAP7 files into score/lib/asap7/)
python3.12 score/ppa.py tasks/arbiter/reference/rr_mask.sv --task tasks/arbiter --seq --pdk asap7 --no-mapped \
    --json out.json

Expect, in out.json:

ppa.netlist_sha256
e072fb19e91c79f0adcdfa0ef3709731d0c642bc4c38b853cbedd53cc6f85d0e
ppa.repair.netlist_sha256
35b5e4557491b5cd59938c64b6398742f05c14168f684945f444942c7ddd2992
ppa.area_e5um2_asap7
1215972
ppa.delay_ps_asap7
464

leaderboard/asap7/arbiter.json keeps these numbers; python3.12 leaderboard/leaderboard.py asap7 --rescore --task arbiter weighs every design of the task again and compares, bit for bit.

Verify the record

Download the three files, then from svgolf/:

shell
# re-run the whole check on this record's files (the cost of the original check)
H=84da5a4152db28e4aed74c6cb7f37ec329dc636a4433aff3946fc34e6f60453b
mkdir -p rec/arbiter && cp "$H.json" "$H.sv" "$H.lean" rec/arbiter/
python3.12 leaderboard/leaderboard.py verify --data-dir rec --task arbiter --full

verify --offline checks only the hashes and the arithmetic; plain verify also rescores the design (no Lean; seconds for most designs, a minute or more for the largest), on sky130 and on ASAP7.