mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-19 05:35:47 +00:00
Prove the three pattern detectors work on unseen inputs, not just the RTL
they were derived from. Because detection is functional (ConstEval
fingerprinting over the reachable input space), correctness is established
per case with equiv_opt -assert (full) or a SAT miter clamped to the
reachable range (non-power-of-two), and detection is confirmed with a
w:*tag* probe.
opt_priokey:
D1-D3 spelling variants (explicit shift-or set, compound derived guard,
accumulator also exported) -- all fire and prove equivalent.
E1-E2 parameter sweep P=2..8, S=4..32.
E3 non-power-of-two S=12 reachable-range equivalence via SAT miter.
E4 same shape under -strict declines to rewrite (formal-flow safety).
F1-F2 near-miss negatives (clear accumulator, multi-hot set) -> no rewrite.
opt_prienc (round-robin):
RR4-RR5 DEPTH sweep 8/32, full sequential equivalence.
RR6 non-power-of-two DEPTH=7 reachable-range equivalence (SAT miter).
RR7 an entirely different spelling (upward wrap-scan, first-hit) of the
same arbiter -- fires and proves equivalent.
RR8 fixed-priority (no rotating pointer) negative.
opt_first_fit_alloc (coalesce):
H1 inline same-category compare (no precomputed matrix) spelling.
H2 different slot/field shape (N=8, NB=8, W=3).
All new cases pass locally; they avoid brittle exact cell-count asserts so
they are robust to upstream optimization drift.
Co-authored-by: Cursor <cursoragent@cursor.com>
583 lines
16 KiB
Text
583 lines
16 KiB
Text
# Tests for opt_priokey
|
|
#
|
|
# The pass detects a serial "priority-by-key" set accumulator: several sources
|
|
# each carry a small key and claim it if no earlier source already did. This
|
|
# elaborates into a chain of dynamic-index reads/writes ($shiftx / $shift) into
|
|
# a wide one-hot "taken" vector, whose depth grows with both the number of
|
|
# sources P and the accumulator width S. Every dynamic read taken[key[j]] is
|
|
# provably equal to the pairwise reduction
|
|
#
|
|
# OR over i<j of ( set_guard[i] & key[i] == key[j] )
|
|
#
|
|
# so the pass replaces each read with that compare reduction and drops the wide
|
|
# dynamic indexing. Correctness of every rewrite is validated by an in-pass
|
|
# ConstEval fingerprint over the reachable key range [0,S).
|
|
#
|
|
# Each group exercises a specific facet:
|
|
# A: formal equivalence across (P,S) shapes (power-of-two S -> full equiv).
|
|
# B: structural win -- the $shiftx chain is gone after the rewrite.
|
|
# C: negative / no-op cases (no false rewrites).
|
|
#
|
|
# Convention: every object the pass emits is named with a `priokey_` suffix, so
|
|
# `select w:*priokey*` is a reliable "did the rewrite fire" probe.
|
|
|
|
# ============================================================================
|
|
# Group A: formal equivalence (equiv_opt -assert)
|
|
# ============================================================================
|
|
|
|
# A1: P=3 sources into a 64-slot accumulator (SW=6, all keys reachable).
|
|
log -header "A1: priority-by-key dedup P=3 S=64 (equiv)"
|
|
log -push
|
|
design -reset
|
|
read_verilog -sv <<EOF
|
|
module t #(parameter int P=3, parameter int S=64, parameter int SW=6)(
|
|
input logic [P-1:0] act,
|
|
input logic [P-1:0][SW-1:0] sel,
|
|
input logic [P-1:0] src,
|
|
output logic [P-1:0] win
|
|
);
|
|
logic [S-1:0] taken;
|
|
always_comb begin
|
|
taken = '0; win = '0;
|
|
for (int i=0;i<P;i++)
|
|
if (act[i] && !taken[sel[i]]) begin
|
|
taken[sel[i]] = 1'b1;
|
|
win[i] = src[i];
|
|
end
|
|
end
|
|
endmodule
|
|
EOF
|
|
hierarchy -top t
|
|
proc
|
|
opt
|
|
check -assert
|
|
equiv_opt -assert opt_priokey
|
|
design -load postopt
|
|
select -assert-min 1 w:*priokey*
|
|
select -assert-count 0 t:$shiftx
|
|
design -reset
|
|
log -pop
|
|
|
|
# A2: P=4 sources into a 16-slot accumulator (SW=4).
|
|
log -header "A2: priority-by-key dedup P=4 S=16 (equiv)"
|
|
log -push
|
|
design -reset
|
|
read_verilog -sv <<EOF
|
|
module t #(parameter int P=4, parameter int S=16, parameter int SW=4)(
|
|
input logic [P-1:0] act,
|
|
input logic [P-1:0][SW-1:0] sel,
|
|
input logic [P-1:0] src,
|
|
output logic [P-1:0] win
|
|
);
|
|
logic [S-1:0] taken;
|
|
always_comb begin
|
|
taken = '0; win = '0;
|
|
for (int i=0;i<P;i++)
|
|
if (act[i] && !taken[sel[i]]) begin
|
|
taken[sel[i]] = 1'b1;
|
|
win[i] = src[i];
|
|
end
|
|
end
|
|
endmodule
|
|
EOF
|
|
hierarchy -top t
|
|
proc
|
|
opt
|
|
check -assert
|
|
equiv_opt -assert opt_priokey
|
|
design -load postopt
|
|
select -assert-min 1 w:*priokey*
|
|
select -assert-count 0 t:$shiftx
|
|
design -reset
|
|
log -pop
|
|
|
|
# A3: P=5 sources into an 8-slot accumulator (SW=3) -- deeper source chain.
|
|
log -header "A3: priority-by-key dedup P=5 S=8 (equiv)"
|
|
log -push
|
|
design -reset
|
|
read_verilog -sv <<EOF
|
|
module t #(parameter int P=5, parameter int S=8, parameter int SW=3)(
|
|
input logic [P-1:0] act,
|
|
input logic [P-1:0][SW-1:0] sel,
|
|
input logic [P-1:0] src,
|
|
output logic [P-1:0] win
|
|
);
|
|
logic [S-1:0] taken;
|
|
always_comb begin
|
|
taken = '0; win = '0;
|
|
for (int i=0;i<P;i++)
|
|
if (act[i] && !taken[sel[i]]) begin
|
|
taken[sel[i]] = 1'b1;
|
|
win[i] = src[i];
|
|
end
|
|
end
|
|
endmodule
|
|
EOF
|
|
hierarchy -top t
|
|
proc
|
|
opt
|
|
check -assert
|
|
equiv_opt -assert opt_priokey
|
|
design -load postopt
|
|
select -assert-min 1 w:*priokey*
|
|
select -assert-count 0 t:$shiftx
|
|
design -reset
|
|
log -pop
|
|
|
|
# ============================================================================
|
|
# Group B: structural win (the dynamic-index chain disappears)
|
|
# ============================================================================
|
|
|
|
# B1: P=6 sources, 64-slot accumulator. Before the rewrite the serial scan uses
|
|
# per-source dynamic reads ($shiftx). After the rewrite those reads are gone,
|
|
# replaced by pairwise $eq comparisons -- the QoR (depth) win.
|
|
log -header "B1: priority-by-key structural, P=6 S=64"
|
|
log -push
|
|
design -reset
|
|
read_verilog -sv <<EOF
|
|
module t #(parameter int P=6, parameter int S=64, parameter int SW=6)(
|
|
input logic [P-1:0] act,
|
|
input logic [P-1:0][SW-1:0] sel,
|
|
input logic [P-1:0] src,
|
|
output logic [P-1:0] win
|
|
);
|
|
logic [S-1:0] taken;
|
|
always_comb begin
|
|
taken = '0; win = '0;
|
|
for (int i=0;i<P;i++)
|
|
if (act[i] && !taken[sel[i]]) begin
|
|
taken[sel[i]] = 1'b1;
|
|
win[i] = src[i];
|
|
end
|
|
end
|
|
endmodule
|
|
EOF
|
|
hierarchy -top t
|
|
proc
|
|
opt
|
|
# Serial baseline: the dynamic-index reads are present.
|
|
select -assert-min 1 t:$shiftx
|
|
opt_priokey
|
|
opt_clean
|
|
# The wide dynamic indexing is gone, replaced by pairwise key comparisons.
|
|
select -assert-count 0 t:$shiftx
|
|
select -assert-min 1 t:$eq
|
|
select -assert-min 1 w:*priokey*
|
|
design -reset
|
|
log -pop
|
|
|
|
# ============================================================================
|
|
# Group C: negative / no-op cases (no false rewrites)
|
|
# ============================================================================
|
|
|
|
# C1: the "taken" vector is a primary input, not a set accumulator rooted at 0.
|
|
# The dynamic read has no traceable set history, so the pass must not fire.
|
|
log -header "C1: non-accumulator dynamic read -> no rewrite"
|
|
log -push
|
|
design -reset
|
|
read_verilog -sv <<EOF
|
|
module t #(parameter int S=64, parameter int SW=6)(
|
|
input logic [S-1:0] taken,
|
|
input logic [SW-1:0] sel,
|
|
output logic hit
|
|
);
|
|
assign hit = taken[sel];
|
|
endmodule
|
|
EOF
|
|
hierarchy -top t
|
|
proc
|
|
opt
|
|
opt_priokey
|
|
select -assert-count 0 w:*priokey*
|
|
design -reset
|
|
log -pop
|
|
|
|
# C2: a plain per-lane passthrough -- no dynamic indexing at all.
|
|
log -header "C2: per-lane passthrough -> no rewrite"
|
|
log -push
|
|
design -reset
|
|
read_verilog -sv <<EOF
|
|
module t #(parameter int P=4)(
|
|
input logic [P-1:0] a,
|
|
input logic [P-1:0] b,
|
|
output logic [P-1:0] y
|
|
);
|
|
assign y = a & b;
|
|
endmodule
|
|
EOF
|
|
hierarchy -top t
|
|
proc
|
|
opt
|
|
opt_priokey
|
|
select -assert-count 0 w:*priokey*
|
|
design -reset
|
|
log -pop
|
|
|
|
# C3: a dynamic write accumulator with NO conflict check -- every source
|
|
# unconditionally sets its key and reads are absent (win is a direct index).
|
|
# There is no taken[]-guarded read chain to rewrite.
|
|
log -header "C3: unconditional writes, no guarded read -> no rewrite"
|
|
log -push
|
|
design -reset
|
|
read_verilog -sv <<EOF
|
|
module t #(parameter int P=3, parameter int S=16, parameter int SW=4)(
|
|
input logic [P-1:0][SW-1:0] sel,
|
|
output logic [S-1:0] taken
|
|
);
|
|
always_comb begin
|
|
taken = '0;
|
|
for (int i=0;i<P;i++)
|
|
taken[sel[i]] = 1'b1;
|
|
end
|
|
endmodule
|
|
EOF
|
|
hierarchy -top t
|
|
proc
|
|
opt
|
|
opt_priokey
|
|
select -assert-count 0 w:*priokey*
|
|
design -reset
|
|
log -pop
|
|
|
|
# ============================================================================
|
|
# Group D: RTL-spelling variants (generalization across surface syntax)
|
|
# ============================================================================
|
|
#
|
|
# Detection is functional (the pass traces the set-accumulator structurally
|
|
# and then ConstEval-validates each read over the reachable key range), so it
|
|
# is independent of how the conflict scan is spelled. Each variant below is a
|
|
# DIFFERENT way to write the same "first source per key wins" resolution; for
|
|
# every one we require both that the rewrite fires (w:*priokey*) and that
|
|
# equiv_opt -assert proves it equivalent to the original elaboration. This is
|
|
# the core generalization claim: unseen but functionally-equivalent RTL is
|
|
# handled, not just the one spelling from the QoR case.
|
|
|
|
# D1: explicit `taken = taken | (1 << sel[i])` set (instead of the bit-select
|
|
# write taken[sel[i]]=1) and a separate `conflict` temporary for the guard.
|
|
log -header "D1: explicit shift-or set + temp guard (equiv + fires)"
|
|
log -push
|
|
design -reset
|
|
read_verilog -sv <<EOF
|
|
module t #(parameter int P=4, S=16, SW=4)(
|
|
input logic [P-1:0] act,
|
|
input logic [P-1:0][SW-1:0] sel,
|
|
output logic [P-1:0] win
|
|
);
|
|
logic [S-1:0] taken;
|
|
logic conflict;
|
|
always_comb begin
|
|
taken = '0; win = '0;
|
|
for (int i=0;i<P;i++) begin
|
|
conflict = taken[sel[i]];
|
|
if (act[i] && !conflict) begin
|
|
win[i] = 1'b1;
|
|
taken = taken | (S'(1) << sel[i]);
|
|
end
|
|
end
|
|
end
|
|
endmodule
|
|
EOF
|
|
hierarchy -top t
|
|
proc
|
|
opt
|
|
check -assert
|
|
equiv_opt -assert opt_priokey
|
|
design -load postopt
|
|
select -assert-min 1 w:*priokey*
|
|
design -reset
|
|
log -pop
|
|
|
|
# D2: compound guard (act[i] & en[i]) -- the per-step guard the pass keys off
|
|
# is a derived net, not a primary input. The fingerprint drives it as a free
|
|
# variable, so proving read == OR(guard & key==read_key) over free guards is
|
|
# strictly stronger than the real (correlated) guards need.
|
|
log -header "D2: compound derived guard (equiv + fires)"
|
|
log -push
|
|
design -reset
|
|
read_verilog -sv <<EOF
|
|
module t #(parameter int P=5, S=32, SW=5)(
|
|
input logic [P-1:0] act,
|
|
input logic [P-1:0] en,
|
|
input logic [P-1:0][SW-1:0] sel,
|
|
output logic [P-1:0] win
|
|
);
|
|
logic [S-1:0] taken;
|
|
always_comb begin
|
|
taken = '0; win = '0;
|
|
for (int i=0;i<P;i++)
|
|
if ((act[i] & en[i]) && !taken[sel[i]]) begin
|
|
taken[sel[i]] = 1'b1;
|
|
win[i] = 1'b1;
|
|
end
|
|
end
|
|
endmodule
|
|
EOF
|
|
hierarchy -top t
|
|
proc
|
|
opt
|
|
check -assert
|
|
equiv_opt -assert opt_priokey
|
|
design -load postopt
|
|
select -assert-min 1 w:*priokey*
|
|
design -reset
|
|
log -pop
|
|
|
|
# D3: the final accumulator state is ALSO a module output. Only the guarded
|
|
# dynamic reads are rewritten; the set-writes that build `taken` are left
|
|
# intact. equiv_opt must still prove the (untouched) taken output and the
|
|
# rewritten win outputs all match.
|
|
log -header "D3: accumulator also exported as output (equiv + fires)"
|
|
log -push
|
|
design -reset
|
|
read_verilog -sv <<EOF
|
|
module t #(parameter int P=4, S=16, SW=4)(
|
|
input logic [P-1:0] act,
|
|
input logic [P-1:0][SW-1:0] sel,
|
|
output logic [P-1:0] win,
|
|
output logic [S-1:0] taken_o
|
|
);
|
|
logic [S-1:0] taken;
|
|
always_comb begin
|
|
taken = '0; win = '0;
|
|
for (int i=0;i<P;i++)
|
|
if (act[i] && !taken[sel[i]]) begin
|
|
taken[sel[i]] = 1'b1;
|
|
win[i] = 1'b1;
|
|
end
|
|
taken_o = taken;
|
|
end
|
|
endmodule
|
|
EOF
|
|
hierarchy -top t
|
|
proc
|
|
opt
|
|
check -assert
|
|
equiv_opt -assert opt_priokey
|
|
design -load postopt
|
|
select -assert-min 1 w:*priokey*
|
|
design -reset
|
|
log -pop
|
|
|
|
# ============================================================================
|
|
# Group E: parameter sweep + non-power-of-two accumulator width
|
|
# ============================================================================
|
|
|
|
# E1: tiny shape P=2 S=4 -- lower edge of the pattern.
|
|
log -header "E1: P=2 S=4 (equiv, edge)"
|
|
log -push
|
|
design -reset
|
|
read_verilog -sv <<EOF
|
|
module t #(parameter int P=2, S=4, SW=2)(
|
|
input logic [P-1:0] act,
|
|
input logic [P-1:0][SW-1:0] sel,
|
|
input logic [P-1:0] src,
|
|
output logic [P-1:0] win
|
|
);
|
|
logic [S-1:0] taken;
|
|
always_comb begin
|
|
taken = '0; win = '0;
|
|
for (int i=0;i<P;i++)
|
|
if (act[i] && !taken[sel[i]]) begin
|
|
taken[sel[i]] = 1'b1; win[i] = src[i];
|
|
end
|
|
end
|
|
endmodule
|
|
EOF
|
|
hierarchy -top t
|
|
proc
|
|
opt
|
|
check -assert
|
|
equiv_opt -assert opt_priokey
|
|
design -load postopt
|
|
select -assert-min 1 w:*priokey*
|
|
design -reset
|
|
log -pop
|
|
|
|
# E2: deep shape P=8 S=32 -- more sources than any QoR case, longer chain.
|
|
log -header "E2: P=8 S=32 (equiv, deep chain)"
|
|
log -push
|
|
design -reset
|
|
read_verilog -sv <<EOF
|
|
module t #(parameter int P=8, S=32, SW=5)(
|
|
input logic [P-1:0] act,
|
|
input logic [P-1:0][SW-1:0] sel,
|
|
input logic [P-1:0] src,
|
|
output logic [P-1:0] win
|
|
);
|
|
logic [S-1:0] taken;
|
|
always_comb begin
|
|
taken = '0; win = '0;
|
|
for (int i=0;i<P;i++)
|
|
if (act[i] && !taken[sel[i]]) begin
|
|
taken[sel[i]] = 1'b1; win[i] = src[i];
|
|
end
|
|
end
|
|
endmodule
|
|
EOF
|
|
hierarchy -top t
|
|
proc
|
|
opt
|
|
check -assert
|
|
equiv_opt -assert opt_priokey
|
|
design -load postopt
|
|
select -assert-min 1 w:*priokey*
|
|
design -reset
|
|
log -pop
|
|
|
|
# E3: NON-power-of-two accumulator S=12 (SW=4, so the key bus spans [0,16) but
|
|
# only [0,12) are valid slots). The default (non-strict) rewrite is guaranteed
|
|
# only over the REACHABLE key range [0,S); it is NOT unconditionally equivalent
|
|
# (reads for keys in [12,16) index out of range). We prove the reachable-range
|
|
# guarantee rigorously with a SAT miter that clamps every key into [0,S) and
|
|
# compares the rewritten copy against an untouched reference (cf. RR2). The
|
|
# rewrite must fire AND agree with the reference for all in-range keys.
|
|
log -header "E3: non-pow2 S=12 reachable-range equivalence (SAT miter)"
|
|
log -push
|
|
design -reset
|
|
read_verilog -sv <<EOF
|
|
module pk_dut #(parameter int P=4, S=12, SW=4)(
|
|
input logic [P-1:0] act,
|
|
input logic [P*SW-1:0] sel_flat,
|
|
output logic [P-1:0] win
|
|
);
|
|
logic [SW-1:0] sel [0:P-1];
|
|
for (genvar g=0; g<P; g++) assign sel[g] = sel_flat[g*SW +: SW];
|
|
logic [S-1:0] taken;
|
|
always_comb begin
|
|
taken = '0; win = '0;
|
|
for (int i=0;i<P;i++)
|
|
if (act[i] && !taken[sel[i]]) begin
|
|
taken[sel[i]] = 1'b1; win[i] = 1'b1;
|
|
end
|
|
end
|
|
endmodule
|
|
EOF
|
|
hierarchy -top pk_dut
|
|
proc
|
|
opt
|
|
design -save pk_gold
|
|
opt_priokey
|
|
select -assert-min 1 w:*priokey*
|
|
opt_clean
|
|
design -save pk_gate
|
|
design -reset
|
|
design -copy-from pk_gold -as pk_ref pk_dut
|
|
design -copy-from pk_gate -as pk_dut pk_dut
|
|
read_verilog -sv <<EOF
|
|
module tb #(parameter int P=4, S=12, SW=4)(
|
|
input logic [P-1:0] act, input logic [P*SW-1:0] sel_raw
|
|
);
|
|
logic [P*SW-1:0] sel_c;
|
|
for (genvar g=0; g<P; g++) begin : clamp
|
|
wire [SW-1:0] k = sel_raw[g*SW +: SW];
|
|
assign sel_c[g*SW +: SW] = (k >= SW'(S)) ? (k - SW'(S)) : k; // into [0,S)
|
|
end
|
|
logic [P-1:0] w1, w2;
|
|
pk_dut #(P,S,SW) u1(.act(act), .sel_flat(sel_c), .win(w1));
|
|
pk_ref #(P,S,SW) u2(.act(act), .sel_flat(sel_c), .win(w2));
|
|
always_comb assert (w1 == w2);
|
|
endmodule
|
|
EOF
|
|
hierarchy -top tb
|
|
flatten
|
|
chformal -lower
|
|
opt -full
|
|
sat -verify -prove-asserts -show-ports tb
|
|
design -reset
|
|
log -pop
|
|
|
|
# E4: SAME non-pow2 S=12 under -strict. Strict validation sweeps the FULL key
|
|
# range and rejects rewrites that only hold via out-of-range don't-cares, so
|
|
# the pass must decline to rewrite. This is the safety mode used by formal
|
|
# synthesis flows: no reliance on out-of-range freedom.
|
|
log -header "E4: non-pow2 S=12 -strict -> no rewrite (safety)"
|
|
log -push
|
|
design -reset
|
|
read_verilog -sv <<EOF
|
|
module t #(parameter int P=4, S=12, SW=4)(
|
|
input logic [P-1:0] act,
|
|
input logic [P-1:0][SW-1:0] sel,
|
|
output logic [P-1:0] win
|
|
);
|
|
logic [S-1:0] taken;
|
|
always_comb begin
|
|
taken = '0; win = '0;
|
|
for (int i=0;i<P;i++)
|
|
if (act[i] && !taken[sel[i]]) begin
|
|
taken[sel[i]] = 1'b1; win[i] = 1'b1;
|
|
end
|
|
end
|
|
endmodule
|
|
EOF
|
|
hierarchy -top t
|
|
proc
|
|
opt
|
|
opt_priokey -strict
|
|
select -assert-count 0 w:*priokey*
|
|
design -reset
|
|
log -pop
|
|
|
|
# ============================================================================
|
|
# Group F: additional near-miss negatives (no false rewrites)
|
|
# ============================================================================
|
|
|
|
# F1: CLEAR accumulator -- `avail` starts all-ones and bits are cleared. The
|
|
# read cone does not bottom out at constant zero, so the accumulator trace
|
|
# fails and nothing is rewritten.
|
|
log -header "F1: clear-accumulator (rooted at all-ones) -> no rewrite"
|
|
log -push
|
|
design -reset
|
|
read_verilog -sv <<EOF
|
|
module t #(parameter int P=4, S=16, SW=4)(
|
|
input logic [P-1:0] act,
|
|
input logic [P-1:0][SW-1:0] sel,
|
|
output logic [P-1:0] win
|
|
);
|
|
logic [S-1:0] avail;
|
|
always_comb begin
|
|
avail = '1; win = '0;
|
|
for (int i=0;i<P;i++)
|
|
if (act[i] && avail[sel[i]]) begin
|
|
avail[sel[i]] = 1'b0; win[i] = 1'b1;
|
|
end
|
|
end
|
|
endmodule
|
|
EOF
|
|
hierarchy -top t
|
|
proc
|
|
opt
|
|
opt_priokey
|
|
select -assert-count 0 w:*priokey*
|
|
design -reset
|
|
log -pop
|
|
|
|
# F2: MULTI-hot set mask -- each source sets two adjacent slots (3 << sel).
|
|
# The set arm is not a single one-hot (1 << key), so decode_onehot_key fails
|
|
# and the accumulator is not recognized as a priority-by-key set chain.
|
|
log -header "F2: multi-hot set mask -> no rewrite"
|
|
log -push
|
|
design -reset
|
|
read_verilog -sv <<EOF
|
|
module t #(parameter int P=3, S=16, SW=4)(
|
|
input logic [P-1:0] act,
|
|
input logic [P-1:0][SW-1:0] sel,
|
|
output logic [P-1:0] win
|
|
);
|
|
logic [S-1:0] taken;
|
|
always_comb begin
|
|
taken = '0; win = '0;
|
|
for (int i=0;i<P;i++)
|
|
if (act[i] && !taken[sel[i]]) begin
|
|
taken = taken | (S'(3) << sel[i]);
|
|
win[i] = 1'b1;
|
|
end
|
|
end
|
|
endmodule
|
|
EOF
|
|
hierarchy -top t
|
|
proc
|
|
opt
|
|
opt_priokey
|
|
select -assert-count 0 w:*priokey*
|
|
design -reset
|
|
log -pop
|