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

Fair N-client arbiter, clocked and reactive arbiter

At most one grant per cycle, only to a requester, someone whenever anyone requests, and a requester that asks N cycles in a row granted within them.

open for submissions clocked, reactive scored at N = 8

Par
2175µm²·nsrr_mask · 769.5 µm² × 2.83 ns
Record
2175µm²·nsrr_mask · 769.5 µm² × 2.83 ns
Under par
0%
Par
5.642µm²·nsrr_mask · 12.160 µm² × 0.464 ns
Record
5.642µm²·nsrr_mask · 12.160 µm² × 0.464 ns
Under par
0%

Score

ASAP7 · area × time · µm²·ns · lower is better
arbiter: the score of each entry by date1 entry 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.200021002200230026 Oct2 Nov9 Novdate enteredscore (µm²·ns) · lower is betterpar: rr_mask, 2175 µm²·nsPAR2175 · provedthe best score so farrr_mask · proved reference · par · 2026-11-05T18:53:43Z · Score: 2175 µm²·ns · Area: 769.5 µm² · Time: 2826 ps
arbiter: the score of each entry by date1 entry 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.2000220026 Oct2 Nov9 Novdate enteredscore (µm²·ns) · lower is betterpar: rr_mask, 2175 µm²·nsPARthe best score so farrr_mask · proved reference · par · 2026-11-05T18:53:43Z · Score: 2175 µm²·ns · Area: 769.5 µm² · Time: 2826 ps
  • proved reference
  • the best score so far
  • par
Score = area × time: the sky130 cell area of the scored netlist in µm² (flip-flops included) times the register-to-register clock period in ns, one decision per cycle, 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. The clock period (what score/ppa.py calls the register-to-register period) is the longest path from an input or a flip-flop to an output or a flip-flop (clock-to-Q and setup included), so paths from the inputs and to the outputs count too, not only the paths between two flip-flops. 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-11-05rr_maskproved reference · par2175769.5 µm² × 2.83 ns
arbiter: the score of each entry by date1 entry 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.5.25.45.65.866.226 Oct2 Nov9 Novdate enteredscore (µm²·ns) · lower is betterpar: rr_mask, 5.642 µm²·nsPAR5.642 · provedthe best score so farrr_mask · proved reference · par · 2026-11-05T18:53:43Z · Score: 5.642 µm²·ns · Area: 12.160 µm² · Time: 464 ps
arbiter: the score of each entry by date1 entry 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.5.5626 Oct2 Nov9 Novdate enteredscore (µm²·ns) · lower is betterpar: rr_mask, 5.642 µm²·nsPARthe best score so farrr_mask · proved reference · par · 2026-11-05T18:53:43Z · Score: 5.642 µm²·ns · Area: 12.160 µm² · Time: 464 ps
  • proved reference
  • the best score so far
  • par
Score = area × time: the ASAP7 cell area of the scored netlist in µm² (flip-flops included) times the register-to-register clock period in ns, one decision per cycle, 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). The clock period (what score/ppa.py calls the register-to-register period) is the longest path from an input or a flip-flop to an output or a flip-flop (clock-to-Q and setup included), so paths from the inputs and to the outputs count too, not only the paths between two flip-flops. 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-11-05rr_maskproved reference · par5.64212.160 µm² × 0.464 ns

Give the grant to at most one of N requesters per cycle, only to one that asks, to someone whenever anyone asks, and never let a requester ask N cycles in a row without being granted. This is svGolf's first reactive task: a controller that runs for ever, specified by a safety property on every cycle and a bounded response over the whole input trace, with no assumption about the requesters. The proof covers every N with 1 ≤ N and N·N < 2^31; the score is taken at N = 8.

The design is clocked by clk alone, on its rising edge, with the synchronous reset rst: no asynchronous process, and clk is never read as data. The grant is registered, a Moore output: a clock edge samples req, and the grant it decides is on gnt for the whole next clock period, so a grant follows its request by one cycle. No output may depend combinationally on an input. The claims hold from every power-up value of every register, the first reset included, so a register that is never reset may only hold a value that does not matter; no construct may create an unknown value, and a register that is never loaded is refused. Run-time / % ** are banned. Any fair policy is allowed (round-robin pointer or mask, rotating priority, a tree, a matrix), so the task is the policy and its state, which the score prices. The bound N is tight: no design can serve every persistent requester within N - 1 cycles.

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.

arbiter.sv
module arbiter #(parameter int N = 8) (
  input  logic         clk, rst,
  input  logic [N-1:0] req,
  output logic [N-1:0] gnt
);
portdirectionwidth (bits)
clkinput1
rstinput1
reqinputN
gntoutputN

The trusted statement #

A proof must establish the task's trusted statement, the constant SvGolf.Tasks.Arbiter.Statement of Spec.lean (module tasks.arbiter.Spec). The proved references meet it. The last tab, what does not count, lists the designs the checker rejects.

Properties

STATEMENT
Statement
/-- **The challenge statement**: the task at every `N` in range with the response bound `N - 1`
(G4: `N` consecutive requests are granted at least once). -/
abbrev Statement (sem : Nat → LeanModels.Sv.Design2) : Prop :=
  task.Statement sem (fun N => N - 1)
svgolf/tasks/arbiter/Spec.leanOpen 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.

  • a13_async.sv (attack, stopped at source): A round-robin with an asynchronous reset: the reset is synchronous on this task, and the source check refuses the second event.

    the design, with its comments left out
    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 or posedge rst) begin
        if (rst) begin
          gnt <= '0;
          mask <= '1;
        end else begin
          gnt <= pick;
          if (pick != '0) mask <= ~((pick << 1) - 1'b1);
        end
      end
    endmodule
    
  • m004_wide_req.sv (attack, stopped at extract): The reference with its request port one bit wider than the task's: right grants on the wrong interface, so no proof can exist; refused when the checker compares the ports, before any other stage.

    the design, with its comments left out
    module arbiter #(parameter int N = 8) (
      input  logic         clk, rst,
      input  logic [N-0: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
    
  • m007_wide_gnt.sv (attack, stopped at extract): The reference with its grant port one bit wider than the task's, the extra bit never set: refused when the checker compares the ports.

    the design, with its comments left out
    module arbiter #(parameter int N = 8) (
      input  logic         clk, rst,
      input  logic [N-1:0] req,
      output logic [N-0: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
    
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.

  • bit_ring.sv (negative, stopped at solution): A correct round-robin behind a test of a 2-state ring that is never reset: fair from the power-up value 0, where a simulator starts it, and fixed priority for ever from all ones.

    the design, with its comments left out
    module arbiter #(parameter int N = 8) (
      input  logic         clk, rst,
      input  logic [N-1:0] req,
      output logic [N-1:0] gnt
    );
      bit [31:0] u;
      logic [N-1:0] mask, mreq, pick, fix;
      always_ff @(posedge clk) u <= {u[30:0], u[31]};
      always_comb begin
        mreq = req & mask;
        pick = (mreq != '0) ? (mreq & (~mreq + 1'b1)) : (req & (~req + 1'b1));
        fix = req & (~req + 1'b1);
      end
      always_ff @(posedge clk) begin
        if (rst) begin
          gnt <= '0;
          mask <= '1;
        end else begin
          if (&u) gnt <= fix;
          else gnt <= pick;
          if (pick != '0) mask <= ~((pick << 1) - 1'b1);
        end
      end
    endmodule
    
  • reset_edge.sv (negative, stopped at solution): A correct round-robin behind a flag that the reset sets from a register's power-up value: from all ones the first segment after the reset is fixed priority.

    the design, with its comments left out
    module arbiter #(parameter int N = 8) (
      input  logic         clk, rst,
      input  logic [N-1:0] req,
      output logic [N-1:0] gnt
    );
      logic [31:0] u;
      logic bad;
      logic [N-1:0] mask, mreq, pick, fix;
      always_comb begin
        mreq = req & mask;
        pick = (mreq != '0) ? (mreq & (~mreq + 1'b1)) : (req & (~req + 1'b1));
        fix = req & (~req + 1'b1);
      end
      always_ff @(posedge clk) begin
        if (rst) begin
          u <= '0;
          if (&u) bad <= 1'b1;
          else bad <= 1'b0;
          gnt <= '0;
          mask <= '1;
        end else begin
          u <= {u[30:0], ~(u[31] ^ u[21] ^ u[1] ^ u[0])};
          if (bad) gnt <= fix;
          else gnt <= pick;
          if (pick != '0) mask <= ~((pick << 1) - 1'b1);
        end
      end
    endmodule
    
Rejected after scoring

These get through the proof stages and are rejected by scoring or by the post-synthesis check.

  • a16_xopt.sv (attack, stopped at score): A correct round-robin behind a test of a register that only holds itself: synthesis removes the register and builds fixed priority, a simulator stays fair, and from the power-up value 0 the design is fixed priority too. The checker refuses a register that is never loaded.

    the design, with its comments left out
    module arbiter #(parameter int N = 8) (
      input  logic         clk, rst,
      input  logic [N-1:0] req,
      output logic [N-1:0] gnt
    );
      logic u;
      logic [N-1:0] mask, mreq, pick, fix;
      always_ff @(posedge clk) u <= u;
      always_comb begin
        mreq = req & mask;
        pick = (mreq != '0) ? (mreq & (~mreq + 1'b1)) : (req & (~req + 1'b1));
        fix = req & (~req + 1'b1);
      end
      always_ff @(posedge clk) begin
        if (rst) begin
          gnt <= '0;
          mask <= '1;
        end else begin
          if (!u) gnt <= fix;
          else gnt <= pick;
          if (pick != '0) mask <= ~((pick << 1) - 1'b1);
        end
      end
    endmodule
    
  • a01_never.sv (attack, stopped at postsynth): Never grant: nobody is served when someone requests.

    the design, with its comments left out
    module arbiter #(parameter int N = 8) (
      input  logic         clk, rst,
      input  logic [N-1:0] req,
      output logic [N-1:0] gnt
    );
      always_ff @(posedge clk) gnt <= '0;
    endmodule
    
  • a02_everyone.sv (attack, stopped at postsynth): Grant every requester: two clients hold the grant at once.

    the design, with its comments left out
    module arbiter #(parameter int N = 8) (
      input  logic         clk, rst,
      input  logic [N-1:0] req,
      output logic [N-1:0] gnt
    );
      always_ff @(posedge clk) gnt <= rst ? '0 : req;
    endmodule
    
  • a03_zero.sv (attack, stopped at postsynth): Always grant client 0: a grant to a client that does not ask, and the others starve.

    the design, with its comments left out
    module arbiter #(parameter int N = 8) (
      input  logic         clk, rst,
      input  logic [N-1:0] req,
      output logic [N-1:0] gnt
    );
      always_ff @(posedge clk) gnt <= rst ? '0 : 1;
    endmodule
    
  • a04_fixed.sv (attack, stopped at postsynth): Fixed priority, the lowest requester wins: every cycle is legal, but a persistent high requester starves.

    the design, with its comments left out
    module arbiter #(parameter int N = 8) (
      input  logic         clk, rst,
      input  logic [N-1:0] req,
      output logic [N-1:0] gnt
    );
      always_ff @(posedge clk) gnt <= rst ? '0 : (req & (~req + 1'b1));
    endmodule
    
  • a05_ring.sv (attack, stopped at postsynth): A free-running token ring that ignores the requests: it grants clients that do not ask.

    the design, with its comments left out
    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] tok;
      always_ff @(posedge clk) begin
        if (rst) begin
          tok <= 1;
          gnt <= '0;
        end else begin
          tok <= (tok << 1) | (tok >> (N - 1));
          gnt <= tok;
        end
      end
    endmodule
    
  • a06_tdma.sv (attack, stopped at postsynth): Time division: a token ring gated by the requests is fair but idles while someone waits.

    the design, with its comments left out
    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] tok;
      always_ff @(posedge clk) begin
        if (rst) begin
          tok <= 1;
          gnt <= '0;
        end else begin
          tok <= (tok << 1) | (tok >> (N - 1));
          gnt <= tok & req;
        end
      end
    endmodule
    
  • a07_late.sv (attack, stopped at postsynth): A correct round-robin decision delivered one cycle late: it answers the previous cycle's requests.

    the design, with its comments left out
    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
      logic [N-1:0] q;
      always_ff @(posedge clk) begin
        if (rst) begin
          gnt <= '0;
          q <= '0;
          mask <= '1;
        end else begin
          q <= pick;
          gnt <= q;
          if (pick != '0) mask <= ~((pick << 1) - 1'b1);
        end
      end
    endmodule
    
  • a08_sticky.sv (attack, stopped at postsynth): A sticky round-robin: the priority stays with the granted client, so a persistent requester keeps it.

    the design, with its comments left out
    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'b1);
        end
      end
    endmodule
    
  • a09_rotate_pow2.sv (attack, stopped at postsynth): Rotating priority whose counter wraps at the next power of two: right at N = 8, wrong at N = 3 and 5.

    the design, with its comments left out
    module arbiter #(parameter int N = 8) (
      input  logic         clk, rst,
      input  logic [N-1:0] req,
      output logic [N-1:0] gnt
    );
      localparam int PW = (N > 1) ? $clog2(N) : 1;
      logic [PW-1:0] p;
      logic [2**PW-1:0] reqp, pickp;
      logic [PW:0] s;
      logic [PW-1:0] idx;
      logic [N-1:0] pick;
      logic found;
      always_comb begin
        reqp = '0;
        reqp[N-1:0] = req;
        pickp = '0;
        found = 1'b0;
        s = '0;
        idx = '0;
        for (int k = 0; k < N; k++) begin
          s = p + k;
          idx = (s >= N) ? s - N : s;
          if (!found && reqp[idx]) begin
            pickp[idx] = 1'b1;
            found = 1'b1;
          end
        end
        pick = pickp[N-1:0];
      end
      always_ff @(posedge clk) begin
        if (rst) begin
          gnt <= '0;
          p <= '0;
        end else begin
          gnt <= pick;
          p <= p + 1'b1;
        end
      end
    endmodule
    
  • a10_mealy_last.sv (attack, stopped at postsynth): A correct registered grant behind a combinational output that copies the requests whenever they change: every snapshot is right, the wire is not.

    the design, with its comments left out
    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
      logic [N-1:0] g, last;
      always_ff @(posedge clk) begin
        last <= req;
        if (rst) begin
          g <= '0;
          mask <= '1;
        end else begin
          g <= pick;
          if (pick != '0) mask <= ~((pick << 1) - 1'b1);
        end
      end
      assign gnt = (req == last) ? g : req;
    endmodule
    
  • a11_noreset.sv (attack, stopped at postsynth): A round-robin whose grant register has no reset: out of reset it still shows its power-up value or its last grant.

    the design, with its comments left out
    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
        gnt <= pick;
        if (rst) mask <= '1;
        else if (pick != '0) mask <= ~((pick << 1) - 1'b1);
      end
    endmodule
    
  • a12_stale_mask.sv (attack, stopped at postsynth): A mask round-robin that forgets to update the mask on the wrap-around grant: a requester starves.

    the design, with its comments left out
    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;
      logic wrap;
      always_comb begin
        mreq = req & mask;
        wrap = (mreq == '0);
        pick = !wrap ? (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 && !wrap) mask <= ~((pick << 1) - 1'b1);
        end
      end
    endmodule
    
  • a14_mealy_rr.sv (attack, stopped at postsynth): A combinational round-robin with the mask registered, no output register: the grant moves with the requests within a cycle.

    the design, with its comments left out
    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;
      always_comb begin
        mreq = req & mask;
        gnt = (mreq != '0) ? (mreq & (~mreq + 1'b1)) : (req & (~req + 1'b1));
      end
      always_ff @(posedge clk) begin
        if (rst) mask <= '1;
        else if (gnt != '0) mask <= ~((gnt << 1) - 1'b1);
      end
    endmodule
    
  • a15_half_rate.sv (attack, stopped at postsynth): A round-robin that arbitrates every other cycle: requesters wait while nobody is granted.

    the design, with its comments left out
    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
      logic t;
      always_ff @(posedge clk) begin
        if (rst) begin
          gnt <= '0;
          mask <= '1;
          t <= 1'b0;
        end else begin
          t <= !t;
          gnt <= t ? pick : '0;
          if (t && pick != '0) mask <= ~((pick << 1) - 1'b1);
        end
      end
    endmodule
    
  • a17_timebomb.sv (attack, stopped at postsynth): A correct round-robin for 4095 cycles after a reset and fixed priority after that: only a long run without a reset shows it.

    the design, with its comments left out
    module arbiter #(parameter int N = 8) (
      input  logic         clk, rst,
      input  logic [N-1:0] req,
      output logic [N-1:0] gnt
    );
      logic [11:0] age;
      logic [N-1:0] mask, mreq, pick, fix;
      always_comb begin
        mreq = req & mask;
        pick = (mreq != '0) ? (mreq & (~mreq + 1'b1)) : (req & (~req + 1'b1));
        fix = req & (~req + 1'b1);
      end
      always_ff @(posedge clk) begin
        if (rst) begin
          gnt <= '0;
          mask <= '1;
          age <= '0;
        end else begin
          if (age != '1) age <= age + 1'b1;
          if (age == '1) gnt <= fix;
          else gnt <= pick;
          if (pick != '0) mask <= ~((pick << 1) - 1'b1);
        end
      end
    endmodule
    
Spec.lean, verbatim (171 lines)
import SvGolf.TaskReact

/-!
# Task `arbiter`: a fair N-client arbiter
# (TRUSTED text, final, decided 2026-11-07; written 2026-11-05, txtask-v2's rules 2026-11-06; the reactive kind `ReactTask`, `SvGolf/TaskReact.lean`)

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

```systemverilog
module arbiter #(parameter int N = 8) (
  input  logic         clk, rst,
  input  logic [N-1:0] req,
  output logic [N-1:0] gnt
);
```

## What the statement says (`Statement sem`)

For every `N` with `1 ≤ N` and `N·N < 2^31`, the design `sem N`:

1. has exactly the ports above, and no two declarations of one name (`Interface`);
2. is clocked by `clk` alone with no asynchronous reset, never reads `clk` as data (`ClockedBy clk
   none`), has no combinational path from an input port to an output port (`MooreOut`), and
   terminates from every power-up state under every schedule and known stimulus (`TerminatesPU`);
3. has no construct that can create an `x` from known operands (`XSafe`, txtask-v2's rule 3);
4. from EVERY power-up state (every register and variable, 2-state ones included, starts at some
   0/1 value, one value per signal), under every schedule, on every known stimulus, in every
   completed run, at every RESET RELEASE `c1` (the entry `c1 - 1` asserts `rst`) and for every list
   `x0 :: xs` of request vectors that the entries `c1 - 1, c1, c1 + 1, …` drive (the reset entry,
   then the entries with `rst` = 0), the snapshots `c1 - 1, c1, c1 + 1, …` show known grant vectors
   `y0, ys[0], ys[1], …` with
   * **G0, reset**: `y0 = 0` (no grant comes out of reset);
   * **G1, mutual exclusion**: every `ys[j]` has at most one bit set;
   * **G2, no spurious grant**: a bit of `ys[j]` is set only if the same bit of `xs[j]` is;
   * **G3, work conservation**: `xs[j] ≠ 0` implies `ys[j] ≠ 0`;
   * **G4, bounded fairness** with `K = N - 1`: if requester `i` requests at all `N` entries
     `j, …, j + N - 1` of the segment, then `ys[j + k]` grants `i` for some `k ≤ N - 1`.

The grant in snapshot `c` answers the request of entry `c` (the one the edge of cycle `c`
samples); by `MooreOut` it is what the requesters see on `gnt` for the whole next clock period,
while they drive entry `c + 1`. So a requester learns of its grant one period after it asserts its
request: a REGISTERED (Moore) arbiter, like verilog-axis `arbiter.v` (`grant_reg`), or a Mealy one
(OpenTitan `prim_arbiter_tree`) behind one output register.

## Decided 2026-11-05 (the study's defaults; reasons in `README.md`)

* Moore observation (`MooreOut`), from the kind.
* Safety (G1 to G3, per cycle: the ghost state is `Unit`) and bounded response (G4) with the bound
  `K = N - 1` fixed here, not declared by the golfer: no design can beat it (`bound_tight`, among the
  task's kernel-checked refutations, `tests/arbiter/negative/`), so a declared `K` would be a dead column.
* No environment assumption beyond reset and known inputs.
* "Any fair" policy: the statement pins fairness, not a grant order.
* Scored at `N = 8` (`task.json`).

## Why it cannot be satisfied vacuously or gamed (the kind's list, `SvGolf/TaskReact.lean`, plus)

* **Request-ignoring designs.** The free-running token ring that is SYNTCOMP-minimal for the
  simple and round-robin arbiter families grants without requests (G2), the time-sliced ring
  gated by the requests wastes slots (G3), grant-everyone breaks G1, never-grant breaks G3 and G4,
  fixed priority starves (G4). The task's refutations (`tests/arbiter/negative/`) refute four of them
  by kernel-evaluated runs.
* **The Mealy phantom.** Register `last <= req` and drive `gnt = (req == last) ? g : req` from a
  correct registered grant `g`: every snapshot shows `g`, while in silicon `gnt = req` whenever
  `req` changes, which breaks mutual exclusion. `MooreOut` rejects it (`mealy_refuted`).
* **Unknown and unreset values** (rules 2 and 3). The claims hold from every power-up state, so a
  design may keep an unreset register only where its value does not matter. A correct round-robin
  behind `if (~u)` on a never-reset, self-holding `u` fails G4 from the power-up `u = 0`
  (`xopt_refuted`); behind `if (&u)` on a never-reset 2-state rotating ring `u`, from `u` all ones
  (`ring_refuted`; ls-sv's `x` start would have made `u` 0 for ever); and with a flag set at the
  first reset edge from the pre-reset `&u`, from `u` all ones (`reset_edge_refuted`). These runs
  are ls-sv's: that the scored netlist agrees with them on defined values (obligation C) is
  SAMPLED by the post-synthesis check, not proved. Yosys keeps such a register as a flop that
  powers up to some value, and the checker refuses a never-loaded one (`u <= u`) where the pinned
  flow removes its flip-flop while reads of it remain (it resolves each read separately).
* **Never-reset grant flops.** G0 requires a KNOWN zero at every reset snapshot, from every
  power-up.

## What it does NOT pin, on purpose

* which requester wins (any policy meeting G4 is legal: round-robin pointer, mask, rotating
  priority, matrix/LRU), and the state encoding (one-hot mask, binary pointer, matrix);
* the grant of a requester that drops its request before `N` consecutive requests: the reference
  round-robin itself starves a requester that asks at every other entry (measured, `README.md`),
  so a stronger form would reject every round-robin;
* anything while `rst` = 1 except the reset snapshot, and anything before the first reset.
-/

namespace SvGolf

open LeanModels.Sv

namespace Tasks.Arbiter

/-- At most one bit of `g` is set (one-hot or zero). -/
def AtMostOne {N : Nat} (g : BitVec N) : Prop :=
  ∀ i j, g.getLsbD i = true → g.getLsbD j = true → i = j

/-- **One cycle of arbitration**: `gnt` grants at most one requester (G1), only a requester of
`req` (G2), and someone whenever anyone requests (G3). Together: `gnt = 0` if `req = 0`, else `gnt`
is one bit of `req`. -/
def Grants {N : Nat} (req gnt : BitVec N) : Prop :=
  AtMostOne gnt ∧ (∀ i, gnt.getLsbD i = true → req.getLsbD i = true) ∧ (req ≠ 0#N → gnt ≠ 0#N)

/-- **The task.** The ghost state is trivial (the safety property is per cycle); the obligations
are the requesters `i < N`: requesting triggers, being granted responds. -/
def task : ReactTask Nat where
  inRange N := 1 ≤ N ∧ N * N < 2 ^ 31
  clk := "clk"
  rst := "rst"
  inputs N := [("req", N)]
  outputs N := [("gnt", N)]
  atReset N := fun (g, ()) => g = 0#N
  Ghost _ := Unit
  ginit _ := ()
  gnext _ _ _ _ := ()
  safe _ _ := fun (r, ()) (g, ()) => Grants r g
  Obl N := Fin N
  trig _ i := fun (r, ()) => r.getLsbD i.val = true
  resp _ i := fun (g, ()) => g.getLsbD i.val = true

/-- **The challenge statement**: the task at every `N` in range with the response bound `N - 1`
(G4: `N` consecutive requests are granted at least once). -/
abbrev Statement (sem : Nat → LeanModels.Sv.Design2) : Prop :=
  task.Statement sem (fun N => N - 1)

/-! ## Sanity checks on the statement's data (proved; they add nothing to the trusted base) -/

/-- The scoring point `N = 8` and the probe points are in range; `N = 0` is not, nor any `N` with
`N·N ≥ 2^31` (a matrix arbiter declares `N·N` bits). -/
example : task.inRange 1 ∧ task.inRange 2 ∧ task.inRange 3 ∧ task.inRange 8 ∧
    ¬ task.inRange 0 ∧ ¬ task.inRange 46341 := by
  simp [task]

/-- The port names are distinct. -/
example : ["clk", "rst", "req"].Nodup ∧ "gnt" ∉ ["clk", "rst", "req"] := by decide

/-- `Grants` with the bit indices bounded by `N` (bits at `i ≥ N` read `false`): decidable on
concrete vectors. -/
theorem grants_iff {N : Nat} {r g : BitVec N} : Grants r g ↔
    (∀ i, i < N → ∀ j, j < N → g.getLsbD i = true → g.getLsbD j = true → i = j) ∧
    (∀ i, i < N → g.getLsbD i = true → r.getLsbD i = true) ∧ (r ≠ 0#N → g ≠ 0#N) := by
  constructor
  · rintro ⟨h1, h2, h3⟩
    exact ⟨fun i _ j _ hi hj => h1 i j hi hj, fun i _ hi => h2 i hi, h3⟩
  · rintro ⟨h1, h2, h3⟩
    exact ⟨fun i j hi hj => h1 i (BitVec.lt_of_getLsbD hi) j (BitVec.lt_of_getLsbD hj) hi hj,
      fun i hi => h2 i (BitVec.lt_of_getLsbD hi) hi, h3⟩

/-- A one-hot grant of a requester is a legal arbitration; so is no grant without requests. -/
example : Grants (0b1011#4) (0b0010#4) ∧ Grants (0#4) (0#4) :=
  ⟨grants_iff.2 (by decide), grants_iff.2 (by decide)⟩

/-- The trivial answers are not legal arbitrations: grant everyone (G1), grant client 0 always
(G2), never grant (G3). -/
example : ¬ Grants (0b11#2) (0b11#2) ∧ ¬ Grants (0b00#2) (0b01#2) ∧ ¬ Grants (0b01#2) (0b00#2) :=
  ⟨fun h => absurd (grants_iff.1 h) (by decide), fun h => absurd (grants_iff.1 h) (by decide),
    fun h => absurd (grants_iff.1 h) (by decide)⟩

/-- **Fixed priority starves** (G4 at `N = 2`, `K = 1`): both clients request twice in a row and
client 0 is granted both times, so the segment's guarantee fails for client 1. -/
example : ¬ task.Guar 2 1 [(0b11#2, ()), (0b11#2, ())] (0#2, ()) [(0b01#2, ()), (0b01#2, ())] := by
  rintro ⟨-, -, hr⟩
  obtain ⟨i, y, hi, hy, hg⟩ := hr (⟨1, by decide⟩ : Fin 2) 0 (by decide) (fun i x hi hx => by
    have : i = 0 ∨ i = 1 := by omega
    rcases this with rfl | rfl <;> (have hx' := Option.some.inj hx; subst hx'; exact rfl))
  have : i = 0 ∨ i = 1 := by omega
  rcases this with rfl | rfl <;> (have hy' := Option.some.inj hy; subst hy'; exact Bool.false_ne_true hg)

end Tasks.Arbiter

end SvGolf

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.arbiter.Specsvgolf/tasks/arbiter/Spec.leantask statement17121c83d684dee

How to participate #

  1. Write a circuit with the task's exact interface.
  2. Prove in Lean 4 that it meets the trusted statement; Start a new design, below, gives the route, and 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.

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.

Start from the reference pair under Files, rr_mask, a complete and accepted one: copy it, from the same directory:

shell
cp tasks/arbiter/reference/rr_mask.sv solution.sv
cp tasks/arbiter/reference/rr_mask.lean Solution.lean

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 (Start a new design, below, gives the route), then check the pair and record it (steps 2 and 3):

shell
# the golfing loop, no Lean: area and period, about a second
python3.12 score/ppa.py solution.sv --task tasks/arbiter \
    --seq --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/arbiter solution.sv --unproved \
    --stage-dir stage
# 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/arbiter solution.sv Solution.lean
# 3. record it: the whole check again, full and sandboxed
python3.12 leaderboard/leaderboard.py add --task arbiter \
    --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 arbiter/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.

The golfing loop and step 1, the first two commands above. The first command weighs the design through the clocked flow (--seq; without it ppa.py refuses the flip-flops): the area and the register-to-register period, with the critical path (--path). The second runs every stage that needs no proof: the clocked source rules, the check that no construct can create an x, the never-loaded register check, the score, and the reactive post-synthesis check, which drives the scored netlist through reset segments and one long run without a reset and holds every grant to the statement's G0 to G4 and the Moore sample. A wrong policy is named there, with the cycle, before any proof. It leaves the design staged in stage/ for probe files (PROVING.md, section 0). The sv_comb tactics are for combinational tasks: --tactics does not read a clocked design.

score/ppa.py is the inner loop of golfing; its ranked numbers are area_um2_sky130 and delay_ps_sky130 in what it prints. It runs only the source gate and the pinned flow: 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. Step 1 does, still without a proof.

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

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

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

Your Solution.lean imports it and proves Goal, as the skeleton in Start a new design (The proof in detail) shows. 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 (in namespace Submission, theorem Submission.solution : Submission.Goal) are fixed.

Step 3 writes your record's three files (.json, .sv and .lean, named by the record's hash) to leaderboard/data/arbiter/, 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 rr_mask: 2175 µm²·ns (769.5 µm² × 2.83 ns).

  1. ⚑
    par proved reference
    2175769.5 µm² × 2.83 ns

No submissions yet. Par, the bar to beat, is the proved reference rr_mask: 5.642 µm²·ns (12.160 µm² × 0.464 ns).

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

At a glance

top module
arbiter
parameters
N in range 1 <= N, N*N < 2^31
scoring point
N = 8
depth budget
none
banned run-time operators
/ % **

Only run-time / % ** are banned: a zero divisor or a negative exponent makes an unknown value from known operands, which ls-sv carries into decisions and synthesis builds as a defined value. Comparisons, additions and shifts are an arbiter's own tools; the score prices the policy and its state.

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)

Start a new design

The route: an invariant and a rank, ReactTask.satisfiedAt_of_rank (PROVING.md, section 20; reference/rr_mask.lean is a complete proof, 487 code lines). The reduction in SvGolf/React.lean turns the statement at one N into facts about ONE clock cycle, six arguments:

  1. Interface: the ports in order and distinct declaration names (rfl, and decide on the names);
  2. Disciplined: ClockedBy clk none (a simp over the processes) and MooreOut, by mooreOut_of_combTargets when no always_comb writes an output;
  3. TerminatesPU, by TerminatesPU.of_invariant from the clock step;
  4. a ReactTask.RankModel: the clock step in closed form (its CycleModel: a Shape of the snapshots and the one-cycle Step), an invariant Inv of the snapshots from a reset on, the grant out it shows, a rank per requester at most N - 1, the RESET obligation (gnt = 0, from any state of the shape) and the STEP obligation (the grant meets Grants, the invariant holds again, and every requester that asks is granted or its rank drops). For a mask round-robin the invariant is "the mask is a thermometer" and the rank is the requester's cyclic distance from the mask's edge;
  5. the shape at every power-up state (powerUp_cons once per declaration);
  6. XSafe, by simp with xsafeB.
The proof in detailLay the design out so the proof stays short · The skeleton · Library lemmas that exist today

Lay the design out so the proof stays short:

  • register the grant: when no always_comb writes gnt, MooreOut is one simp (mooreOut_of_combTargets), and a design whose output moves with req between two edges is rejected by the post-synthesis check before the proof;
  • reset every register whose value matters: the claims hold from every power-up value, the first reset edge included, and a register that only holds itself (u <= u) is refused;
  • keep the combinational logic in one always_comb block computed from signals it does not write (the reference's block reads req and mask; it reads mreq only after writing it): ls-sv's closed-form clock step covers flip-flop-only designs, and a design with combinational logic proves its own settle, which for such a block is two passes (the reference's settle_rr: the first computes the block, the second changes nothing);
  • for XSafe, the loaded design's &, |, ^, ==, != operands and ?: arms at one width, and a run-time index whose every value is in range (a k-bit index into at least 2^k elements): req[(p + k) % N] is refused, so scan a copy of req padded to 2^$clog2(N) bits, as tests/arbiter/designs/rotate.sv does;
  • what ls-sv does not read yet: casts (N'(1), 32'(p): write the literal 1), unique and priority (refused by the source gate), declarations inside a generate block (refused at the design stage, which is where a tree arbiter that declares its nodes there stops today), and instances over unpacked arrays (refused by the extractor).

The skeleton (reference/rr_mask.lean is it, filled in for the mask round-robin):

import Submission.Design
import SvGolf.React
import SvGolf.RoundRobin

namespace Submission
open LeanModels.Sv SvGolf

-- 1. agreement: `design.sem N = myD N`, a hand-built Design2 (sv2_inst_simp)
-- 2. one cycle in closed form, from any values: the comb settle, the edge, the commit
-- 3. the cycle on known values: after a reset, and after an entry with rst = 0

noncomputable def model (N : Nat) (hN : 1 ≤ N) :
    Tasks.Arbiter.task.RankModel N (N - 1) (design.sem N) where
  -- the CycleModel: Shape, Step, init, cycle, shape
  -- then Inv, out, shows, rank, rank_le, reset, step

theorem solution : Goal := by
  intro N hN
  obtain ⟨hN1, -⟩ := hN
  exact Tasks.Arbiter.task.satisfiedAt_of_rank (my_interface N hN1) (my_disciplined N hN1)
    (my_terminates N hN1) (model N hN1) (fun st h => my_powerUp N hN1 st h) (my_xsafe N hN1)

end Submission

#print axioms solution must show propext, Classical.choice and Quot.sound only.

Library lemmas that exist today:

  • SvGolf.React: ReactTask.satisfiedAt_of_rank (the reduction), ReactTask.RankModel, ReactTask.responds_of_rank (the window argument, used inside the reduction), ReactTask.snapshots_known, mooreOut_of_combTargets;
  • SvGolf.RoundRobin, for every width: the lowest set bit (IsLow, getLsbD_isolate, isolate_eq_twoPow, isolate_eq_zero: x & (~x + 1) is its one-hot), the thermometer above a one-hot (getLsbD_thermo, Thermo, thermo_allOnes), the mask round-robin's pick, next, pick_eq_zero, pick_sub, pick_atMostOne and its one-step theorem step (the next mask is a thermometer, and a requester that loses gets strictly closer to the edge in the cyclic distance dist, dist_le: at most N - 1);
  • SvGolf.SeqV2: TerminatesPU.of_invariant, powerUp_cons, powerUp_nil.

A pointer, rotating-priority, tree or matrix policy uses the reduction and the lowest-set-bit lemmas, with its own invariant and rank: the pick/next/step lemmas describe the mask policy.

Compare the designs

ASAP7 · any two numbers · lower is better
arbiter: area against depth1 design by Depth (gates) (x) and Area (GE) (y); lower is better on both. The table under the chart lists the same numbers.180190200161718Depth (gates)Area (GE) · lower is betterthe Pareto front of the proved designsrr_mask · proved reference · par · 2026-11-05T18:53:43Z · Score: 2175 µm²·ns · Depth: 17 gates · Area: 188.979 GE
arbiter: area against depth1 design by Depth (gates) (x) and Area (GE) (y); lower is better on both. The table under the chart lists the same numbers.180190200161718Depth (gates)Area (GE) · lower is betterthe Pareto front of the proved designsrr_mask · proved reference · par · 2026-11-05T18:53:43Z · Score: 2175 µm²·ns · Depth: 17 gates · Area: 188.979 GE
  • 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. 1 of 1 designs have both numbers.
every design with all its numbers, by score
designScore (µm²·ns)Area (µm²)Time (ps)Flip-flopsArea (GE)Depth (gates)GatesProof (lines)
rr_mask par2175769.5282616188.97917103487
arbiter: area against depth1 design by Depth (gates) (x) and Area (GE) (y); lower is better on both. The table under the chart lists the same numbers.180190200161718Depth (gates)Area (GE) · lower is betterthe Pareto front of the proved designsrr_mask · proved reference · par · 2026-11-05T18:53:43Z · Score: 5.642 µm²·ns · Depth: 17 gates · Area: 188.979 GE
arbiter: area against depth1 design by Depth (gates) (x) and Area (GE) (y); lower is better on both. The table under the chart lists the same numbers.180190200161718Depth (gates)Area (GE) · lower is betterthe Pareto front of the proved designsrr_mask · proved reference · par · 2026-11-05T18:53:43Z · Score: 5.642 µm²·ns · Depth: 17 gates · Area: 188.979 GE
  • 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. 1 of 1 designs have both numbers.
every design with all its numbers, by score
designScore (µm²·ns)Area (µm²)Time (ps)Flip-flopsArea (GE)Depth (gates)GatesProof (lines)
rr_mask par5.64212.16046416188.97917103487

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
rr_mask parparA registered mask round-robin: the lowest requester above the last grant wins, else the lowest requester; proved for every number of clients.tactics: decide, omega, simprecord: 84da5a4152db21755.642769.512.1602826464188.979 · 17parpar487.sv .lean

Baselines

No baselines for this task.