patch notes · #225–26 September

#2 · 132 SystemVerilog probes run through the product, every stage checked

In numbers. Before #2, test/run.sh passed 51 checks, and the 43 probes of the 2509 measurement lived outside the repo, run by a script that called yosys directly (33 of 43 synthesized). After: test/run.sh passes 178, fails 0, and counts 87 known gaps apart; its probe section runs 132 probes through the CLI itself. Synthesis 69/132, all four stages 30/132, and 29 of the 111 probes Vivado supports pass all four: the other 82 are our gap. 17 probes build a bitstream whose netlist fails: 15 do something else (a silent wrong), and 2 (35, an MMCM, and 97, a block RAM) have no simulation model to check them against. The product did not change in #2 (bin/ and templates/ are the same as before); #3 and #4 are scored against these numbers. Seven break rounds sent 195 reports; every one was reproduced (one of round 7's in part), seven side claims inside them did not hold (below), and what was not fixed here is listed with the update that owns it. Every probe, with its construct, Vivado's status, the source and the stage that fails, is listed under "Every probe" below.

What a student may write is now part of the test suite. test/sv/ holds 132 probes, one construct each: design.sv (one probe has design.v) with module top, tb.sv with module tb that prints PASS, sometimes a .svh, a .mem, a package, interface, submodule or netlist-form module in its own .sv, or the lab's own Basys3_Master.xdc with only some pins uncommented (96b; 93's one design file is counter.sv, as its lab has it). 43 came from the 2509 measurement (svprobe); the comments that named a student and a student's file are gone. 8 were added in the first break round, 18 in the second, 23 in the third, 8 in the fourth, 15 in the fifth, 8 in the sixth and 9 in the seventh (below), for cases the 43 did not cover. Every probe goes through four stages, all of them through bin/dewfpga and templates/Makefile, in a temp folder that holds only the probe's sources:

test/sv/expect.tsv has one row per probe: the construct, whether Vivado accepts it, the source for that, what each stage does today, and what the student sees. test/sv/run.sh fails on any difference, in both directions: a stage that stops passing, and a stage that starts passing without the table saying so. It also fails on a row without a source, on a file:line in the today column that no stage printed, and on a message the today column quotes ('...' or "...") that no stage printed word for word (round 4). It prints four numbers: synthesis, all four stages, Vivado-supported probes that pass all four, and known gaps. A known gap does what the table says, but either Vivado supports it and a stage fails, or its bitstream builds while its netlist fails (a silent wrong).

test/run.sh runs it and prints one line per probe: PASS, GAP (counted on its own, not as a pass; it does not fail the run) or FAIL. A probe that fails where Vivado refuses the code, or where what Vivado does is unverified, is a PASS, unless its bitstream builds from a netlist that fails: that silent wrong is a GAP whatever Vivado does (03, 03b, 05 and 39 are unverified and gaps; this said PASS until round 5, and so did test/run.sh's header). CI runs the same and keeps the rows as the sv-results artifact. With the measured yosys and iverilog, when #3 or #4 closes a gap the run fails until expect.tsv records the new result, so every change in these numbers is an edit of the table. With another yosys (CI installs 0.68+post) a stage that starts passing is only a note, so the table is updated from a local run.

Found on the way: the CLI's top finder misses an array of instances. inv u_inv [3:0] (...) is in UG901's list of supported Verilog, and it compiles through the CLI. What fails is the automatic top: the scanner does not read inv u_inv [3:0] ( as an instance, so inv looks like a second top, and dewfpga bit prints 2 modules could be the top (nothing instantiates them): inv, top. Name it: dewfpga bit inv, which names the wrong one. dewfpga bit top builds it (4 LUT), and so does plain dewfpga bit when the file is named top.sv. The old runner called yosys directly and never saw this, so synthesis through the product is 32/43, not the 33/43 the plan started from. The fix is #4's.

The Vivado column, checked row by row. Sources: UG901 v2023.2 (chapter, table, page), UG953 v2022.2 (the 7-series primitive guide), and Vivado logs from public CS223 lab repos. A quoted log line keeps the message; the student's module and signal names are replaced by a description. A forum is marked as a weak source. The 132: 111 supported, 3 not supported, 18 unverified (the 123 of round 6: 105, 3, 15; the 115 of round 5: 99, 3, 13; the 100 of round 4: 84, 3, 13). Changes from the 2509 measurement:

Tried, and why it changed.

Break round 1. Three independent breakers (a student who writes what Vivado accepts, a mutation tester, a regression reader) ran against #2 and sent 38 reports; some are the same break seen by two or three of them. Every one was reproduced in a scratch folder. Two side claims inside them did not hold as written: one breaker counted 20 probes hidden behind passed 94, and the table has 18 (43 minus the 25 that passed all four; 13 of them Vivado-supported, as the breaker said); another's aside, that CI's golden check would also miss every LUT INIT zeroed before nextpnr, came from reading test/run.sh, and it was not run under CI's yosys 0.68 (not verified). What changed:

Tried, and dropped:

Found and left to later updates (reproduced, not fixed here):

Break round 2. The same three kinds of breaker ran against the tree after round 1 and sent 30 reports; two of them are the same break (13b). Each was run in a scratch folder: all 30 reproduced. Fixed here:

Tried, and dropped:

Found and left to later updates (reproduced, not fixed here):

Break round 3. The same three kinds of breaker ran against the tree after round 2 and sent 25 reports. Each was run in a scratch folder: all 25 reproduced. Fixed here:

Tried, and dropped:

Found and left to later updates (reproduced, not fixed here):

Break round 4. The same three kinds of breaker ran against the tree after round 3 and sent 23 reports; two of them are the same break (a netlist that lost its reset), so 22 breaks. Each was run in a scratch folder: all 22 reproduced. (This said "sent 22 reports" until the final count.) A first attempt at this round stopped halfway (a network outage); its eqv.py rewrite and eight probe drafts were checked here, one draft was rewritten (81) and the rest were finished. Fixed here:

Tried, and dropped:

Found and left to later updates (reproduced, not fixed here):

Break round 5. The same three kinds of breaker ran against the tree after round 4 and sent 22 reports. Each was run in a scratch folder: all 22 reproduced. Two side claims inside them did not: that a course project hits the same eqv.py bug through a wire named message (grep -rlE 'message' over the corpus .sv and .v files, also without case: 0 files; the Lab 4 shape the fix covers was found in one repo's logs and is the case regport), and that the Vivado 2021.2 lab writes its range-only port in an always_ff (it is an always_comb, as 08c's source says). A first attempt at this round stopped before it changed anything (a network outage). The eight probe folders a round-4 attempt had left without rows (13c, 18c, 21b, 22c, 22d, 22e, 64b, 81) already had their rows when this round started: 100 folders, 100 rows, and the runner's folder check agreed. Fixed here:

Tried, and dropped:

Found and left to later updates (reproduced, not fixed here):

Break round 6. The same three kinds of breaker ran against the tree after round 5 and sent 36 reports. Each was run in a scratch folder: all 36 reproduced (a mutation report by its mutation and the checks that could catch it, not by a full suite run each; one had a moved line: the lenient-verdict mutation is on test/run.sh line 130, not 126). A first attempt at this round stopped before it changed anything (a network outage). The eight probe folders the task named as lacking rows (13c, 18c, 21b, 22c, 22d, 22e, 64b, 81) have had their rows since round 4: 115 folders, 115 rows. Fixed here:

Tried, and dropped:

Found and left to later updates (reproduced, not fixed here):

Break round 7. The same three kinds of breaker ran against the tree after round 6 and sent 21 reports. Each was run in a scratch folder: 20 reproduced as written and one in part (the port-line comment, below); a mutation report by its mutation and the cases or checks that could catch it, not by a full suite run each. Three side claims did not hold (below). A first attempt at this round stopped before it changed anything (a network outage). The eight probe folders the task named as lacking rows (13c, 18c, 21b, 22c, 22d, 22e, 64b, 81) have had their rows since round 4, as round 6 found too: 123 folders and 123 rows before this round, 132 and 132 after. Fixed here:

Side claims that did not hold:

Tried, and dropped:

Found and left to later updates (reproduced, not fixed here):

What the breakers tried that held. Every round, the breakers also reported what they tried and could not break. Those runs are part of the evidence, so they are listed here, round by round.

Tests. test/run.sh: 51 passed, 0 failed before #2 (78 s); passed 94, failed 0 after #2's first draft (228 s). After break round 1: passed 86, failed 0, known gaps 23 (356 s). After break round 2: passed 99, failed 0, known gaps 41 (305 s). After break round 3: passed 119, failed 0, known gaps 56 (409 s). After break round 4: passed 138, failed 0, known gaps 63 (556 s). After break round 5: passed 148, failed 0, known gaps 77 (474 s). After break round 6: passed 166, failed 0, known gaps 82 (533 s; the final run of that round, 528 s, the same). After break round 7: passed 178, failed 0, known gaps 87 (583 s). The 178 are the 51 from before, 4 hygiene checks, 24 checks of the probe runner itself, 54 checks of eqv.py and eqv.sh, and the 45 probes that are not known gaps (round 4: 63 stopped being a gap and the 8 new probes were all gaps; round 5: of the 15 new probes, 14 are gaps and 84 passes; round 6: of the 8 new probes, 5 are gaps, and 63b, 91 and 92 pass; round 7: of the 9 new probes, 5 are gaps, and 31b, 95, 98 and 99 pass). The final run on 26 September, after these notes were written: passed 178, failed 0, known gaps 87 (582 s), the same (evidence below).

The four stages today, before #3 and #4 change anything:

rtl synth netlist bit
pass, the 43 from 2509 35 32 27 32
pass, the 51 after round 1 37 35 28 35
pass, all 69 49 38 30 37
fail, all 69 20 31 8 32
not run (no netlist), all 69 31
pass, all 92 60 47 37 44
fail, all 92 32 45 10 48
not run (no netlist), all 92 45
pass, all 100 62 52 39 49
fail, all 100 38 48 13 51
not run (no netlist), all 100 48
pass, all 115 68 57 42 53
fail, all 115 47 58 15 62
not run (no netlist), all 115 58
pass, all 123 75 62 45 57
fail, all 123 48 61 17 66
not run (no netlist), all 123 61
pass, all 132 84 69 49 60
fail, all 132 48 63 20 72
not run (no netlist), all 132 63

Every probe. The 132 folders of test/sv, from the final run's rows (they equal expect.tsv). Per probe: the id, Vivado's status (supported, not supported, unverified), the verdict (ok: does what the table says and is not a known gap; gap: a known gap), the stages that fail, the runner's note if any, the construct, and where the Vivado status comes from. "Vivado 2020.1 log" is a Vivado log in a public CS223 (or CS-224) lab repo or in the course's example project, quoted in expect.tsv without the student's names; UG901 is the Vivado synthesis guide, UG953 the 7-series primitive guide. expect.tsv holds the full quote for every source and what the student sees today. Summary: 45 ok, 87 gap; 111 supported, 3 not supported, 18 unverified.

01_latch_comb                supported     gap  fails: synth, bit (netlist not run)
    always_comb with an if and no else (a latch is inferred)
    source: Vivado 2020.1 log; UG901 v2023.2 p.84
02_unnamed_inst              supported     gap  fails: rtl, synth, bit (netlist not run)
    module instance with no instance name: inv(sw[0], led[0]);
    source: Vivado 2020.1 log
03_async_reset_nonconst      unverified    gap  fails: netlist
    always_ff @(posedge clk or posedge btnC) if (btnC) q <= sw[3:0]; (async load from a signal)
    source: UG901 v2023.2 p.81-82
03b_async_reset_selfref      unverified    gap  fails: netlist
    a button used as an async 'reset' that loads cnt+1 (the button-as-clock counter)
    source: UG901 v2023.2 p.81-82
04_dual_edge                 unverified    ok   fails: synth, bit (netlist not run)
    always @(posedge clk or negedge clk) cnt <= cnt + 1;
    source: UG901 v2023.2 p.81; forum posts (weak source)
05_two_block_driver          unverified    gap  fails: netlist
    one reg written from two always blocks on different edges (posedge btnU / posedge btnC)
    source: forum posts (weak source)
06_missing_end_default       not supported ok   fails: rtl, synth, bit (netlist not run)
    a case item's begin (S2: begin) never closed before default: (invalid code; a typo seen in a
    CS223 lab)
    source: IEEE 1800-2017 A.6.7
07_enum_packed_array         supported     ok   passes all four
    packed array of enums: statetype [1:0] state, nextstate;
    source: Vivado 2020.1 log; UG901 v2023.2 p.285
08_port_dir_inherit          supported     ok   passes all four
    ANSI port inheriting its direction: output [6:0] seg, logic dp, (the course's seven-segment
    file)
    source: Vivado 2020.1 log
08b_port_dir_comment         supported     gap  fails: synth, bit (netlist not run)
    the course's port line (output [6:0] seg, logic dp) with comments in the port list: one after
    seg, one with a ';' in it
    source: Vivado 2020.1 log; IEEE 1800-2017 5.4
08c_port_dir_inherit_proc    supported     gap  fails: rtl
    the course's port line shape with a range only, written in an always block: output logic [6:0]
    seg, [3:0] an; with an set in an always_comb
    source: Vivado 2021.2 log; IEEE 1800-2017 23.2.2.3; slang
09_always_procs              supported     ok   passes all four
    always_ff / always_comb / always_latch
    source: UG901 v2023.2 p.286
10_enum_fsm                  supported     ok   passes all four
    typedef enum FSM with an explicit base type and with the default (int), plus a light_t'(l+1)
    cast
    source: UG901 v2023.2 p.285
11_enum_methods              supported     gap  fails: synth, bit (netlist not run)
    enum methods s.first() / s.next() / s.last()
    source: UG901 v2023.2 p.285
12_struct_packed             supported     ok   passes all four
    typedef struct packed, nested, member read and write
    source: UG901 v2023.2 p.285
12b_struct_assign_pattern    supported     gap  fails: rtl, synth, bit (netlist not run)
    named assignment pattern '{hi: x, lo: y} and '{default: 0}
    source: UG901 v2023.2 p.286
12c_struct_array_var_index   supported     gap  fails: synth, bit (netlist not run)
    a packed array of structs indexed by a signal, then a member select: cars[sw[15]].x
    source: UG901 v2023.2 p.285, p.287
13_arrays_multidim           supported     ok   passes all four
    packed 2-D, unpacked, unpacked 2-D arrays, for (int i..) in always_comb
    source: UG901 v2023.2 p.285
13b_unpacked_array_port      supported     gap  fails: synth, bit (netlist not run)
    an unpacked array as a module port: input logic [3:0] v [0:3]
    source: UG901 v2023.2 p.161, p.162, p.164; UG901 v2022.2 p.160-162; IEEE 1800-2017 A.1.3
13c_unpacked_array_concat    supported     gap  fails: rtl, synth, bit (netlist not run)
    an unpacked array concatenation: assign arr = {sw[3:0], sw[7:4]}; to logic [3:0] arr [0:1]
    source: UG901 v2023.2 p.286
13d_packed_2d_var_index      supported     gap  fails: rtl
    note: netlist: testbench only, iverilog cannot compile the RTL
    a packed 2-D array indexed by a variable, then a bit or part select: grid[i][j] <= ... in a
    loop, grid[sw[13:12]][3:1]
    source: UG901 v2023.2 p.285; Vivado 2019.1 log
14_params                    supported     ok   passes all four
    typed parameters, one depending on another, localparam, #(.W(8),.K(3)) and positional #(4)
    source: UG901 v2023.2 p.288
15_generate                  supported     ok   passes all four
    generate for with genvar (named block), for (genvar j..) with if-generate, case-generate
    source: UG901 v2023.2 p.288
16_func_task                 supported     ok   passes all four
    function automatic with a loop, plain function, task automatic called in always_comb
    source: UG901 v2023.2 p.287
16b_func_return              supported     gap  fails: synth, bit (netlist not run)
    'return expr;' inside a function
    source: UG901 v2023.2 p.287
16c_while_loop               supported     gap  fails: synth, bit (netlist not run)
    while loop in an always block (UG901 example)
    source: UG901 v2023.2 p.257, p.258
17_clog2_bits_cast           supported     ok   passes all four
    $clog2 in a localparam and a range, $bits, size cast 4'(expr)
    source: UG901 v2023.2 p.240, p.285
18_unique_priority           supported     ok   passes all four
    unique case / priority casez
    source: UG901 v2023.2 p.287, p.279; UG901 v2022.2 p.290
18b_unique_priority_if       supported     gap  fails: rtl
    note: netlist: testbench only, iverilog cannot compile the RTL
    unique if / priority if
    source: UG901 v2023.2 p.287
18c_unique0_if               supported     gap  fails: rtl
    note: netlist: testbench only, iverilog cannot compile the RTL
    unique0 if: an if/else if chain where no branch may match
    source: UG901 v2023.2 p.287
19_casez_casex               supported     ok   passes all four
    casez with ? wildcards, casex
    source: UG901 v2023.2 p.279
20_inside                    not supported ok   fails: rtl, synth, bit (netlist not run)
    set membership: x inside {1,3,[8:10]} and case (x) inside
    source: UG901 v2023.2 p.287; UG901 v2022.2 Table 8-1
21_incdec_assignops          supported     ok   passes all four
    x++ and x += in always_comb, k++ inside always_ff, for (int i..;i++) with c++
    source: UG901 v2023.2 p.286
21b_assign_in_expr           supported     gap  fails: rtl
    note: netlist: testbench only, iverilog cannot compile the RTL
    an assignment within an expression: a = (b = sw[3:0]) + 4'd1; in always_comb
    source: UG901 v2023.2 p.286
22_interface_modport         supported     gap  fails: rtl
    note: netlist: testbench only, iverilog cannot compile the RTL
    interface with two modports, modport-typed module ports (sum_if.prod bus)
    source: UG901 v2023.2 p.288, p.283-284
22b_interface_own_file       supported     gap  fails: rtl, synth, bit (netlist not run)
    an interface declared in its own file (sum_if.sv), generic interface ports
    source: UG901 v2023.2 p.288
22c_interface_ports          supported     gap  fails: netlist
    an interface with ports, interface cnt_if(input logic clk, input logic en), holding a counter;
    top reads c.q
    source: UG901 v2023.2 p.288
22d_interface_array          supported     gap  fails: netlist
    an array of interfaces: pair_if p [0:1] (); p[0].d and p[1].d driven and read in top
    source: UG901 v2023.2 p.288
22e_modport_expression       supported     gap  fails: rtl, synth, bit (netlist not run)
    a modport expression: modport lo (input .nib(data[3:0])); a submodule reads b.nib
    source: UG901 v2023.2 p.288; IEEE 1800-2017 25.5.4; slang
22f_interface_member_access  supported     gap  fails: netlist
    an interface without ports whose members the module that instantiates it drives and reads:
    add_if bus (); assign bus.a = sw[7:0]; ... led = bus.s
    source: UG901 v2023.2 p.288, p.282
23_package_import            supported     gap  fails: synth, bit (netlist not run)
    package (enum, parameter, localparam, function) + import pkg::*; inside the module + pkg::NAME
    source: UG901 v2023.2 p.288, p.284
23b_package_file_import      supported     gap  fails: synth, bit (netlist not run)
    the same package with import pkg::*; at file level, using an imported typedef
    source: UG901 v2023.2 p.288, p.284
23c_package_own_file         supported     gap  fails: rtl, netlist
    a package in its own file (pkg.sv), referenced as cfg_pkg::NAME
    source: UG901 v2023.2 p.288
23d_package_header_import    supported     gap  fails: rtl, synth, bit (netlist not run)
    import in the module header: module top import pkg::*; (...)
    source: UG901 v2023.2 p.288
23e_package_export           supported     gap  fails: synth, bit (netlist not run)
    a package that exports a name it imported: package p2; import p1::K; export p1::K; endpackage,
    and import p2::* in the module
    source: UG901 v2023.2 p.288
24_preproc_include           supported     ok   passes all four
    `include of a .svh, `define with arguments, `ifdef/`ifndef/`else, +: part select
    source: UG901 v2023.2 p.239
25_port_conn_dotstar         supported     ok   passes all four
    .* and .name implicit port connections
    source: UG901 v2023.2 p.281-282, p.287
26_inst_array                supported     gap  fails: synth, bit (netlist not run)
    array of instances: inv u_inv [3:0] (.a(sw[3:0]), .y(led[3:0]));
    source: UG901 v2023.2 p.239
27_readmemh_rom              supported     ok   passes all four
    ROM from initial $readmemh("rom.mem") with async and sync read
    source: UG901 v2023.2 p.240, p.155, p.177
28_dist_ram                  supported     ok   passes all four
    RAM: sync write, async read (distributed RAM, -nobram)
    source: UG901 v2023.2 p.114
29_shift_reg_srl             supported     ok   passes all four
    32-deep shift register (SRL) + dynamic tap sr[sw[8:4]]
    source: UG901 v2023.2 p.88, p.91
30_mult_signed               supported     ok   passes all four
    signed 8x8 multiply, >>> arithmetic shift, signed compare, $signed
    source: UG901 v2023.2 p.94, p.286, p.240
31_reset_styles              supported     ok   passes all four
    sync active-high reset, async active-low reset (negedge rst_n), async set to a nonzero constant
    source: UG901 v2023.2 p.81, p.82
31b_negedge_set              supported     ok   passes all four
    registers on the falling edge with no start value: a counter with a synchronous set (FDSE_1) and
    a bit with an asynchronous preset (FDPE_1), both reset from two switches
    source: UG901 v2023.2 p.81
32_clkdiv_7seg               supported     ok   passes all four
    clock divider making a derived clock (always_ff @(posedge slow)) + 4-digit 7-seg multiplexing +
    hex ROM via case
    source: Vivado 2020.1 log; UG901 v2023.2 p.81
33_tristate_pmod             supported     gap  fails: netlist
    inout JA: JA[0] = oe ? d : 1'bz and read back; JA[7:1] = 'z, JA[1] read as input
    source: UG901 v2023.2 p.86; UG953 v2022.2 p.386
33b_inout_read_only          supported     ok   passes all four
    inout pin only read (never assigned 'z) + one bidirectional pin
    source: UG901 v2023.2 p.86; UG953 v2022.2 p.386
33c_tristate_submodule_port  supported     gap  fails: netlist, bit
    the textbook's tristate buffer module (assign y = en ? a : 4'bz) instantiated four times, each
    driving one nibble of an output tri [15:0] port
    source: UG901 v2023.2 p.86
34_bufg                      supported     gap  fails: rtl
    UNISIM primitive instantiation: BUFG
    source: UG901 v2023.2 p.231-232; UG953 v2022.2 p.266
35_mmcm                      supported     gap  fails: rtl, netlist
    UNISIM MMCME2_BASE (100 to 50 MHz) + BUFG
    source: UG953 v2022.2 p.459; UG901 v2023.2 p.232
36_keep_attr                 supported     ok   passes all four
    (* keep = "true" *) and (* dont_touch = "true" *) on internal nets
    source: UG901 v2023.2 p.51, p.59
37_var_init                  unverified    ok   passes all four
    register power-up value: logic [3:0] cnt = 5; and initial c2 = 9;
    source: UG901 v2023.2 p.244, p.251, p.155
37b_decl_init_expr           unverified    gap  fails: netlist
    a variable declared with an initializer that reads inputs: logic [3:0] sum = sw[3:0] + sw[7:4];
    (meant as an adder)
    source: UG901 v2023.2 p.286, p.244; IEEE 1800-2017 6.8
38_gate_primitives           supported     gap  fails: rtl
    note: netlist: testbench only, iverilog cannot compile the RTL
    gate primitives (not, and, or, xor) driving logic variables and an output logic port
    source: Vivado 2015.2 log; UG901 v2023.2 p.242
39_undeclared_name           unverified    gap  fails: rtl, netlist
    a typo: an undeclared name on the right of an assign (summ for sum)
    source: IEEE 1800-2017 6.10
40_display_module_name       supported     gap  fails: rtl, synth, bit (netlist not run)
    a module named display next to a $display call in a design module
    source: IEEE 1800-2017 A.1.2; UG901 v2023.2 p.239
40b_module_name_in_string    supported     gap  fails: rtl, synth, bit (netlist not run)
    a module name and ( inside a $display string in a design module: $display("counter (u_cnt)
    wrapped") next to module counter
    source: UG901 v2023.2 p.239; IEEE 1800-2017 5.9
41_wildcard_equality         supported     gap  fails: synth, bit (netlist not run)
    wildcard equality: sw[7:0] ==? 8'b1??0_??01 and !=?
    source: UG901 v2023.2 p.286
42_streaming_concat          not supported ok   fails: rtl, synth, bit (netlist not run)
    streaming concatenation: {<<{sw[7:0]}} (bit reverse) and {<<4{sw[15:8]}}
    source: UG901 v2023.2 p.287, p.286; UG901 v2022.2 p.289
43_foreach_loop              supported     gap  fails: synth, bit (netlist not run)
    foreach over an unpacked array in always_comb
    source: UG901 v2023.2 p.287, p.280
44_do_while_loop             supported     gap  fails: synth, bit (netlist not run)
    do ... while in always_comb, twice: a popcount, and a loop whose condition is false on entry
    (its body still runs once, which tells do-while from while)
    source: UG901 v2023.2 p.287, p.280
45_break                     supported     gap  fails: synth, bit (netlist not run)
    break out of a for loop in always_comb (lowest set bit)
    source: UG901 v2023.2 p.280, p.287
46_continue                  unverified    ok   fails: synth, bit (netlist not run)
    continue in a for loop in always_comb (count of set bits)
    source: UG901 v2023.2 p.287
47_type_param                supported     gap  fails: synth, bit (netlist not run)
    type parameter: module inv_t #(parameter type T = logic [3:0]), overridden with #(.T(logic
    [7:0]))
    source: UG901 v2023.2 p.285
48_iff_event                 unverified    ok   fails: rtl, synth, bit (netlist not run)
    iff event qualifier: always_ff @(posedge clk iff sw[15])
    source: UG901 v2023.2 p.286; IEEE 1800-2017 9.4.2.3; slang; UG901 v2022.2 p.288
49_default_arg               supported     gap  fails: synth, bit (netlist not run)
    function argument with a default value, called without it
    source: UG901 v2023.2 p.287
50_arg_by_name               supported     gap  fails: synth, bit (netlist not run)
    function arguments bound by name, in another order: diff(.b(x), .a(y))
    source: UG901 v2023.2 p.287
51_unpacked_param_array      supported     gap  fails: rtl, synth, bit (netlist not run)
    an unpacked array localparam set with an assignment pattern: localparam logic [6:0] SEGS [0:3] =
    '{...}
    source: UG901 v2023.2 p.285, p.286
51b_packed_param_array       supported     gap  fails: rtl, synth, bit (netlist not run)
    a packed 2-D localparam as a lookup table: localparam logic [3:0][6:0] SEG = {...}; seg =
    SEG[sw[1:0]];
    source: UG901 v2023.2 p.285
51c_packed_param_typedef     supported     gap  fails: rtl, netlist
    the same lookup table with its type named first: typedef logic [3:0][6:0] tab_t; localparam
    tab_t SEG = {...};
    source: UG901 v2023.2 p.285
52_internal_tristate         supported     gap  fails: netlist, bit
    an internal tri bus with two tristate drivers taking turns (the textbook's mux from tristate
    buffers)
    source: UG901 v2023.2 p.86
53_async_reset_sync_clear    supported     gap  fails: synth, bit (netlist not run)
    async reset ORed with a synchronous clear: always_ff @(posedge clk, posedge btnC) if (btnC ||
    btnU) q <= 0;
    source: Vivado 2021.2 log
54_use_before_decl           supported     gap  fails: rtl
    note: netlist: testbench only, iverilog cannot compile the RTL
    a name used before its declaration: assign led[0] = stop; logic stop;
    source: Vivado 2017.3 log
55_enum_conditional          unverified    ok   fails: rtl
    note: netlist: testbench only, iverilog cannot compile the RTL
    a conditional between two values of one enum: next = sw[0] ? RUN : IDLE;
    source: UG901 v2023.2 p.285; slang
56_unit_scope_enum           supported     gap  fails: synth, bit (netlist not run)
    typedef enum {S0, S1, S2} outside the module (compilation-unit scope), with the textbook's state
    names
    source: UG901 v2023.2 p.270, p.285
56b_unit_typedef_file        supported     gap  fails: rtl, synth, bit (netlist not run)
    a typedef at file scope in a file of its own (types.sv holds only typedef enum ... state_t;),
    used by the design's module
    source: UG901 v2023.2 p.270
57_ready_module_netlist      supported     gap  fails: rtl, synth, bit (netlist not run)
    a course 'ready module' in netlist form in its own file ((* keep_hierarchy *), \<const0>, GND,
    LUT2), instantiated by the design
    source: Vivado 2017.3 log
58_hier_name                 supported     gap  fails: netlist
    a hierarchical name that reads a submodule's signal: assign led[1:0] = u_fsm.state;
    source: UG901 v2023.2 p.239, p.288
59_isunknown                 supported     gap  fails: netlist
    $isunknown(sw) in a design (a real signal is never x, so it is 0)
    source: UG901 v2023.2 p.240
60_pass_by_ref               supported     gap  fails: rtl, synth, bit (netlist not run)
    a function with a ref argument: function automatic void inc(ref logic [3:0] x)
    source: UG901 v2023.2 p.287
61_enum_range                supported     gap  fails: synth, bit (netlist not run)
    enum ranges: typedef enum {S[3]} (S0, S1, S2) and {T[5:7]} (T5, T6, T7)
    source: UG901 v2023.2 p.285
62_type_operator             supported     gap  fails: rtl, synth, bit (netlist not run)
    the type operator: var type(a) b;
    source: UG901 v2023.2 p.285
63_real_cast                 unverified    ok   fails: synth, bit (netlist not run)
    a real localparam cast to int: localparam int INC = int'(STEP); (2.6 rounds to 3)
    source: UG901 v2023.2 p.285, p.273, p.286
63b_real_localparam_expr     unverified    ok   fails: synth, bit (netlist not run)
    a real literal in a localparam used in an expression: localparam MAX = 1e1; ... count == MAX - 1
    (a lab writes 50e6)
    source: UG901 v2023.2 p.285, p.273, p.286
64_unpacked_struct           supported     gap  fails: rtl, synth, bit (netlist not run)
    an unpacked struct: typedef struct { logic [3:0] a; logic [3:0] b; } (no packed)
    source: UG901 v2023.2 p.285
64b_unpacked_union           supported     gap  fails: rtl, synth, bit (netlist not run)
    an unpacked union: typedef union { logic [7:0] byte_v; logic [3:0] nib; } (no packed), one
    member written and read
    source: UG901 v2023.2 p.286
65_stream_unpack             supported     gap  fails: rtl, synth, bit (netlist not run)
    streaming concatenation as the target of an assignment: {>>{a, b}} = sw[7:0];
    source: UG901 v2023.2 p.287
66_alias                     unverified    ok   fails: rtl, synth, bit (netlist not run)
    alias a = b; (two nets made one)
    source: UG901 v2023.2 p.286; UG901 v2022.2 p.288-289
67_array_compare             supported     gap  fails: rtl, synth, bit (netlist not run)
    equality of two whole unpacked arrays: a == b, a != b
    source: UG901 v2023.2 p.285, p.286
68_array_slice               supported     gap  fails: rtl, synth, bit (netlist not run)
    a slice of an unpacked array: b = a[2:3];
    source: UG901 v2023.2 p.285
69_disable                   supported     gap  fails: synth, bit (netlist not run)
    disable of a named block to leave a loop (the lowest switch that is up)
    source: UG901 v2023.2 p.238
70_wor_wand                  supported     gap  fails: bit
    a wor and a wand net, two drivers each
    source: UG901 v2023.2 p.238
71_array_copy                supported     gap  fails: rtl
    note: netlist: testbench only, iverilog cannot compile the RTL
    one whole unpacked array assigned to another in always_ff: b <= a;
    source: UG901 v2023.2 p.285
72_void_func_outputs         supported     gap  fails: rtl
    note: netlist: testbench only, iverilog cannot compile the RTL
    a void function that returns through output arguments
    source: UG901 v2023.2 p.287
73_array_arg                 supported     gap  fails: rtl
    note: netlist: testbench only, iverilog cannot compile the RTL
    an unpacked array as a function argument
    source: UG901 v2023.2 p.285
74_verilog2005_file          supported     gap  fails: rtl, synth, bit (netlist not run)
    a .v design file with bit and final as names (keywords in SystemVerilog, names in Verilog 2005)
    source: UG901 v2023.2 p.269
75_timing_not_met            supported     gap  fails: bit
    a design that misses 100 MHz: a 14-bit value turned into four registered decimal digits (a long
    divide chain)
    source: Vivado 2015.2 log
76_implicit_net              supported     ok   passes all four
    names the standard declares implicitly: a net from a port connection (.y(w)) and one from the
    left of an assign (assign eq = ...)
    source: Vivado 2021.2 log; IEEE 1800-2017 6.10
77_initial_from_signal       unverified    ok   fails: synth, bit (netlist not run)
    an initial block that reads a signal: initial num = sw; (seen in a CS223 lab)
    source: UG901 v2023.2 p.251, p.244
78_keep_hierarchy            supported     gap  fails: rtl, synth, bit (netlist not run)
    (* keep_hierarchy = "yes" *) on a module, spaced as in UG901
    source: UG901 v2023.2 p.60
79_keep_hierarchy_nospace    supported     ok   passes all four
    the same attribute written without spaces: (*keep_hierarchy="yes"*) (yosys keeps the submodule)
    source: UG901 v2023.2 p.60
80_async_reset_trailing      unverified    ok   fails: synth, bit (netlist not run)
    an always_ff with an async reset and a statement after its if/else (d <= q; runs on the reset
    edge too)
    source: UG901 v2023.2 p.81-82
81_finish_in_design          supported     gap  fails: rtl, netlist
    note: the CLI took counter for the top
    a design module that calls $finish in a simulation check (always @(posedge clk) if (...)
    $finish;), its submodule's ports named as the XDC's (counter.sv)
    source: UG901 v2023.2 p.239, p.240
82_file_tasks_in_design      supported     gap  fails: synth, bit (netlist not run)
    file tasks left in a design module: $fopen, $fdisplay and $fwrite (a debug trace)
    source: UG901 v2023.2 p.239
83_realtobits                supported     gap  fails: rtl, synth, bit (netlist not run)
    $realtobits and $bitstoreal in localparams (a real turned into its IEEE 754 bits and back)
    source: UG901 v2023.2 p.240
84_repeat_const              supported     ok   passes all four
    a repeat loop with a constant count in always_comb (count the switches that are up)
    source: UG901 v2023.2 p.238
85_bitstream_cast            supported     gap  fails: rtl, synth, bit (netlist not run)
    a bitstream cast to an unpacked array: q = quad_t'(sw[7:0]); with typedef logic [3:0] quad_t
    [0:1]
    source: UG901 v2023.2 p.285
86_extern_module             supported     gap  fails: rtl, synth, bit (netlist not run)
    an extern module declaration ahead of the module: extern module inv4(input logic [3:0] a, output
    logic [3:0] y);
    source: UG901 v2023.2 p.287
87_config                    supported     gap  fails: synth, bit (netlist not run)
    a config declaration next to the design: config cfg; design work.top; default liblist work;
    endconfig
    source: UG901 v2023.2 p.239, p.288
88_class_static              supported     gap  fails: rtl, synth, bit (netlist not run)
    a class used for its static function, called as util::rev(sw[3:0]) (no object is made)
    source: UG901 v2023.2 p.288
89_clkdiv_slow_logic         supported     gap  fails: bit
    a clock divider's output clocks more logic than 100 MHz allows (four decimal digits of a 14-bit
    value on the slow clock); the XDC has no create_clock, as the course's master XDC arrives
    source: Vivado 2015.2 to 2021.2 routed timing reports (11 lab runs)
90_elab_warning_initial      supported     gap  fails: synth, bit (netlist not run)
    a parameter check in an initial block: initial if (N < 8) $warning(...)
    source: UG901 v2023.2 p.286, p.241
91_submodule_own_file        supported     ok   passes all four
    a design split over two files: top in design.sv, its submodule counter in counter.sv (the usual
    lab layout)
    source: UG901 v2023.2 p.270
92_display_in_design         supported     ok   passes all four
    a $display debug print left in a clocked design module: if (q == 4'd15) $display("wrapped");
    source: UG901 v2023.2 p.239
93_two_roots_file_name       supported     gap  fails: netlist
    note: the CLI took counter for the top
    two modules nothing instantiates, in one file named after one of them (counter.sv: the plain
    counter, and the board version the project names as its top)
    source: Vivado 2015.2 logs of two CS223 Lab 4 projects (.xpr and runme.log)
94_power_var_base            supported     gap  fails: bit
    a variable raised to a constant power: assign led = sw[7:0] ** 2;
    source: UG901 v2023.2 p.278, p.249
95_empty_submodule           unverified    ok   fails: netlist, bit
    a submodule declared with its ports and no body (a lab part not written yet), its output used
    source: none (no Vivado log; UG901 is silent)
96_port_one_bit_vector       supported     gap  fails: bit
    a port declared [N-1:0] with N = 1: a vector of one bit, numbered 0
    source: UG901 v2023.2 p.285; IEEE 1800-2017 7.4
96b_port_offset_range        supported     gap  fails: bit
    ports numbered from 1: input logic [4:1] sw, with the lab's own XDC (sw[1] to sw[4] only)
    source: UG901 v2023.2 p.285; IEEE 1800-2017 7.4
97_ram_style_block           supported     gap  fails: netlist
    UG901's RAM_STYLE attribute: (* ram_style = "block" *) on a 256-byte memory
    source: UG901 v2023.2 p.64
98_module_named_primitive    unverified    ok   fails: synth, bit (netlist not run)
    a student's module named like a Xilinx primitive: module INV (GND, VCC and MUXF7 too)
    source: UG901 v2023.2 p.232 (the guide is silent on the name)
99_string_parameter          unverified    ok   fails: synth, bit (netlist not run)
    a parameter of type string: parameter string INIT_FILE = "digits.mem" (a ROM's $readmemh file)
    source: UG901 v2023.2 p.285, p.238, p.247, p.232

Does the suite catch breakage? Each mutation below was made in a scratch copy and reverted.

Evidence.

$ test/sv/run.sh
test/sv: 51 probes, yosys 0.69+post, iverilog 13.0
  gap  01_latch_comb                rtl pass  synth fail  netlist -     bit fail
  gap  03_async_reset_nonconst      rtl pass  synth pass  netlist fail  bit pass
  ok   07_enum_packed_array         rtl pass  synth pass  netlist pass  bit pass
  gap  18b_unique_priority_if       rtl fail  synth pass  netlist pass  bit pass   note: netlist: testbench only, iverilog cannot compile the RTL
  ...
synthesis 35/51, all four stages 24/51, Vivado-supported probes passing all four stages 23/42, known gaps 23
matches expect.tsv: 51/51                                  (226 s)

$ PATH=<yowasp yosys 0.68 shim>:$PATH test/sv/run.sh
test/sv: 51 probes, yosys 0.68, iverilog 13.0  (expect.tsv was measured with yosys 0.69+post, iverilog 13.0: only regressions and new silent wrongs fail)
synthesis 35/51, all four stages 24/51, Vivado-supported probes passing all four stages 23/42, known gaps 23
matches expect.tsv: 51/51

$ SV_OUT=rows.tsv test/run.sh          (from a scratch folder; rows.tsv is there afterwards, 2279 bytes)
== probe runner (test/sv/run.sh on a copy, one probe each)
  PASS a build output left in a probe folder is not reused
  PASS a new silent wrong fails with any yosys
  PASS an unexpected pass fails with the measured yosys
  PASS a row without a Vivado source is refused
  PASS a wrong line in the latch error is caught
== SystemVerilog probes (test/sv)
  GAP  sv 01_latch_comb: rtl pass, synth fail, netlist -, bit fail
  ...
  PASS sv 07_enum_packed_array: rtl pass, synth pass, netlist pass, bit pass
  ...
passed 86, failed 0, known gaps 23

The same new checks run against the tree before this round: the old personal-path grep misses the
planted line, student names FAIL, stale top_sim FAIL (the run said "rtl pass"), new silent wrong FAIL (the
run said "note: ..." and exit 0), empty source FAIL, latch line FAIL. The unexpected-pass check passes
there too: it guards the runner's exact mode, which was already right.

The breaker's LUT flip in 30's netlist (32'd2720070586 -> 32'd2686516154); the old testbench printed PASS:
tb on the netlist: FAIL: >>>, $signed or signed < (sw=1410 seg=0000010, want sh=1 a<b=1)
EQV FAIL: 128 of 1507328 compared output bits differ between the RTL and the netlist

Round 2:

$ test/run.sh                                     (from a scratch folder, SV_OUT=rows-final.tsv)
== probe runner (test/sv/run.sh on a copy, one probe each)
  PASS a testbench that prints FAIL is an rtl fail
  PASS a probe folder without a row is refused
  PASS a bit run without top.bit is a bit fail
  PASS a vivado column its source does not back is refused
  PASS a probe that stops matching expect.tsv fails this suite
  PASS the verdict of each row is checked, not trusted
  PASS eqv.py: an equal netlist passes
  PASS eqv.py: a fault only on led[15] is caught
  PASS eqv.py: a fault only at sw=0000 is caught
  PASS eqv.py: a clocked fault only at sw=ffff is caught
  PASS eqv.py: a clocked fault only at sw=7fff is caught
  PASS eqv.py: a fault after 200 cycles is caught
== SystemVerilog probes (test/sv)
  GAP  sv 13b_unpacked_array_port: rtl pass, synth fail, netlist -, bit fail
  GAP  sv 52_internal_tristate: rtl pass, synth pass, netlist fail, bit fail
  PASS sv 55_enum_conditional: rtl fail, synth pass, netlist pass, bit pass (note: netlist: testbench only, iverilog cannot compile the RTL)
  GAP  sv 57_ready_module_netlist: rtl fail, synth fail, netlist -, bit fail
  ...
  synthesis 38/69, all four stages 24/69, Vivado-supported probes passing all four stages 23/60, known gaps 41
passed 99, failed 0, known gaps 41                          (305 s)

$ PATH=<yowasp yosys 0.68 shim>:$PATH test/sv/run.sh
test/sv: 69 probes, yosys 0.68, iverilog 13.0  (expect.tsv was measured with yosys 0.69+post, ...)
synthesis 38/69, all four stages 24/69, Vivado-supported probes passing all four stages 23/60, known gaps 41
matches expect.tsv: 69/69                                   (the row check on these rows: 28 passed, 0 failed, 41 gaps)

$ test/sv/eqv_check.sh <case>, with round 1's eqv.py and with mutations of the new one
round 1's eqv.py   equal ok   msb ok    zero RED  ones RED  dense RED  deep ok
compare bit 0      equal ok   msb RED   zero ok   ones ok   dense ok   deep ok
16 cycles          equal ok   msb ok    zero ok   ones ok   dense RED  deep RED
no corner values   equal ok   msb ok    zero ok   ones RED  dense RED  deep ok

The breakers' flips, round 1's eqv.py then the new one:
  sw=0000 only:  EQV PASS: 1048576 output bits compared   ->  EQV MISMATCH ... led[0] rtl 1, netlist 0; inputs sw=0000
  21 at ffff:    EQV PASS: 262024 output bits compared    ->  EQV MISMATCH ... led[11] rtl 0, netlist 1; inputs btnC=0 sw=ffff
  21 at 7fff:    (passed 4096 cycles)                     ->  EQV MISMATCH ... led[11] rtl 1, netlist 0; inputs btnC=0 sw=7fff

Mutations, each on a copy of the fixed tree, and the check that goes red:
  runner writes ok for bad          a probe that stops matching expect.tsv fails this suite
  row check files bad as gap        the verdict of each row is checked, not trusted
  row check drops the stage compare the verdict of each row is checked, not trusted
  row check ignores the exit code   the verdict of each row is checked, not trusted
  rtl without grep PASS             a testbench that prints FAIL is an rtl fail
  silent wrong not a gap            sv 05_two_block_driver: the runner says ok, but ... make it gap
  folder/row check removed          a probe folder without a row is refused
  synth read from the exit code     sv 52_internal_tristate: synth fail, expected pass
  bit without top.bit               a bit run without top.bit is a bit fail
  vivado column check removed       a vivado column its source does not back is refused
  student-name regex gutted         student-name check sees a quoted name
  eqv: bit 0 only / 16 cycles / walk from 1 / no corner values    eqv.py: msb / deep, dense / zero / ones, dense
The fixed tree without a mutation: all 13 of those checks pass.

Before and after, on the tree the breakers had:
  13b                                    PASS sv 13b_unpacked_array_port  ->  GAP  sv 13b_unpacked_array_port
  runner ok-for-bad + 14 broken          PASS sv 14_params, exit 0        ->  FAIL sv 14_params: the runner says ok, but its stages ... differ from expect.tsv
  silent wrong not a gap                 PASS sv 03_async_reset_nonconst  ->  FAIL sv 03_async_reset_nonconst: the runner says ok, but ... make it gap

Round 3:

$ GITHUB_STEP_SUMMARY=summary.md SV_OUT=rows-final.tsv test/run.sh      (from a scratch folder)
== probe runner (test/sv/run.sh on a copy, one probe each)
  PASS a netlist that differs from its RTL fails, with any yosys
  PASS a testbench FAIL on the netlist fails, with any yosys
  PASS the runner checks leave CI's step summary alone
  ...
  PASS eqv.py: a fault only at sw=1234 is caught
  PASS eqv.py: a clocked fault only at sw=0100 is caught
  PASS eqv.py: a fault only while btnC is pressed is caught
  PASS eqv.py: an undriven (z) output is caught
  PASS eqv.py: an x output is caught
  PASS eqv.py: a register with INIT x starts at 0, as on the board
  PASS eqv.py: a start-value difference before the reset is apart
  PASS eqv.py: a kept submodule named as the RTL's passes
  PASS eqv.py: a fault inside a kept submodule is caught
== SystemVerilog probes (test/sv)
  GAP  sv 58_hier_name: rtl pass, synth pass, netlist fail, bit pass
  GAP  sv 59_isunknown: rtl pass, synth pass, netlist fail, bit pass
  GAP  sv 75_timing_not_met: rtl pass, synth pass, netlist pass, bit fail
  PASS sv 79_keep_hierarchy_nospace: rtl pass, synth pass, netlist pass, bit pass
  ...
  synthesis 47/92, all four stages 26/92, Vivado-supported probes passing all four stages 25/77, known gaps 56
passed 119, failed 0, known gaps 56                          (409 s)
$ cat summary.md                                              (one line; 8 before)
SystemVerilog probes (yosys 0.69+post, iverilog 13.0): synthesis 47/92, all four stages 26/92, ...

$ PATH=<yowasp yosys 0.68 shim>:$PATH test/sv/run.sh       (CI's yosys; brew untouched)
test/sv: 92 probes, yosys 0.68, iverilog 13.0  (expect.tsv was measured with yosys 0.69+post, ...)
synthesis 47/92, all four stages 26/92, Vivado-supported probes passing all four stages 25/77, known gaps 56
matches expect.tsv: 92/92                                    (the only notes: 8 "testbench only")
$ PATH=<the same shim>:$PATH test/sv/eqv_check.sh <each of the 15 cases>: 15 of 15 as expected

eqv.py mutations, each on a copy, and the eqv_check.sh cases that go red:
  exhaustive walk off (EXHAUSTIVE_BITS = 0)    walk
  no mostly-zeros values                        sparse
  no mostly-ones values                         dense
  buttons never pressed                         button
  a z counted as unknown                        zout
  an x counted as unknown                       xout
  INITs left x (no board start)                 init, xstart
  no start-value excuse                         xstart
  every 0/1 difference excused                  msb, zero, walk, ones, dense, sparse, deep, button, hierfault
  the excuse without its 0/1 test               xout
  only top renamed                              hier, hierfault
  cell types not renamed                        hierfault
  compare bit 0 only                            msb, zout, xout
  16 cycles                                     dense, sparse, deep
  walk from 1                                   zero
  no corner values                              ones, dense, sparse
The fixed eqv.py: all 15 cases pass.

The runner, and the checks that go red:
  netlist-vs-RTL comparison deleted (CI mode)   FAIL a netlist that differs from its RTL fails, with any yosys
  testbench PASS dropped from the netlist stage FAIL a testbench FAIL on the netlist fails, with any yosys
  the summary check on the round-2 tree         FAIL the runner checks leave CI's step summary alone (PASS now)
  the port-line note one line down              ok 08 on the round-2 tree -> BAD 08_port_dir_inherit ... expect.tsv says design.sv:2, no stage printed it

Before and after:
  79 on the round-2 tree   BAD 79_keep_hierarchy_nospace ... net_eqv.v:3: error: 'inv' has already been declared in this scope.  ->  ok
  the undriven led[4]      EQV PASS: 983040 output bits compared, all equal (65536 more were x in the netlist only)  ->  EQV MISMATCH at 3000 (gray): led[4] rtl 0, netlist x; inputs sw=0000
  55's 48 LUT flips        the old testbench passes 23 of the 36 that change the netlist  ->  the new one passes 0

Round 4:

$ GITHUB_STEP_SUMMARY=<absolute path> SV_OUT=rows-final.tsv test/run.sh      (from a scratch folder)
== static
  PASS student-name check sees a quoted name
== probe runner (test/sv/run.sh on a copy, one probe each)
  PASS the score line is counted again from the rows
  PASS a message the today column quotes is checked
  PASS a file:line of a .v file is checked
  ...
  PASS eqv.py: a packed array of enums with no start value is started
  PASS eqv.py: a 1-bit enum with no start value is started
  PASS eqv.py: a netlist that lost its reset is caught
  PASS eqv.py: a re-encoded state machine is compared after one reset
  PASS eqv.py: ports named x, mode, seed, r, n, v, k do not clash with the bench
  ...
== SystemVerilog probes (test/sv)
  PASS sv 07_enum_packed_array: rtl pass, synth pass, netlist pass, bit pass
  GAP  sv 13c_unpacked_array_concat: rtl fail, synth fail, netlist -, bit fail
  GAP  sv 18c_unique0_if: rtl fail, synth pass, netlist pass, bit pass (note: netlist: testbench only, iverilog cannot compile the RTL)
  GAP  sv 22c_interface_ports: rtl pass, synth pass, netlist fail, bit pass
  GAP  sv 22d_interface_array: rtl pass, synth pass, netlist fail, bit pass
  PASS sv 63_real_cast: rtl pass, synth fail, netlist -, bit fail
  GAP  sv 81_finish_in_design: rtl fail, synth pass, netlist fail, bit pass (note: the CLI took counter for the top)
  ...
  synthesis 52/100, all four stages 26/100, Vivado-supported probes passing all four stages 25/84, known gaps 63
passed 138, failed 0, known gaps 63                          (556 s)
$ cat summary.md                                              (GITHUB_STEP_SUMMARY=<absolute path>; one line)
SystemVerilog probes (yosys 0.69+post, iverilog 13.0): synthesis 52/100, all four stages 26/100, Vivado-supported probes passing all four stages 25/84, known gaps 63
$ PATH=<yowasp yosys 0.68 shim>:$PATH test/sv/run.sh <the 100, in four runs>          (CI's yosys; brew untouched)
test/sv: 25 probes, yosys 0.68, iverilog 13.0  (expect.tsv was measured with yosys 0.69+post, ...)
matches expect.tsv: 25/25, 25/25, 25/25, 24/25    BAD 75_timing_not_met ... expect.tsv quotes 'ERROR: timing not met: 33.61 MHz (FAIL at 100.00 MHz)', no stage printed it
after the rewording, 75 under both:  gap  75_timing_not_met  rtl pass  synth pass  netlist pass  bit fail
$ PATH=<the same shim>:$PATH test/sv/eqv_check.sh <each of the 30 cases>: 30 of 30 as expected
$ GITHUB_STEP_SUMMARY=<absolute path> test/sv/run.sh 07_enum_packed_array 81_finish_in_design; cat <that file>
SystemVerilog probes (yosys 0.69+post, iverilog 13.0): synthesis 2/2, all four stages 1/2, Vivado-supported probes passing all four stages 1/2, known gaps 1

$ test/sv/eqv_check.sh <case>, round 3's eqv.py (its argument count only widened) and today's
                 round 3                                                        today
names            eqv.sv:12: error: 'r' has already been declared in this scope.  EQV PASS: 98304 output bits compared, all equal
lostreset        EQV PASS: 262136 ... (31956 more differed only while a register had no start value)   EQV FAIL: 33108 of 262144 ...
lostinit         EQV PASS: 196608 ... (35328 more differed only while ...)       EQV FAIL: 35328 of 196608 ...
(the other 27 cases give the same verdict with both; they pin what round 3 left unpinned, below)

eqv.py mutations, each on a copy, and the eqv_check.sh cases that go red:
  no reset press before the first compare      recode
  every start value 0                          fillset fillaset
  no start values in the RTL                   xstart pkenum enum1
  LDPE starts at 1                             ldpe ldfill
  FDSE starts at 0                             fdse fillset
  FDPE starts at 0                             fillaset
  a latch's start taken from its preset        ldfill
  buttons out of the exhaustive walk           cbutton
  inout pins never driven from outside         ioread iofloat
  inout pins not compared                      iofloat
  512 cycles / 3999 cycles                     deep / deep
  buttons never pressed after the start        button
  netlist INITs left x                         init fdse ldpe ldfill xstart fillset fillaset pkenum enum1
  only top renamed                             hierfault
  every register set bit by bit (07's crash)   pkenum enum1
  a 1-bit enum not started                     enum1
Today's eqv.py: all 30 cases as expected.

The product's netlists with every reset/set pin that is not a constant tied to 0 (tb.sv on it; round 3's bench; today's):
  09  tb FAIL  EQV PASS: 262132 output bits compared, all equal (31956 more ...)   EQV MISMATCH at 28000 (data): led[0] rtl 0, netlist 1
  10  tb FAIL  EQV PASS: 262140 ... (20140 more ...)                               EQV MISMATCH at 28000 (data): led[4] rtl 0, netlist 1
  21  tb FAIL  EQV PASS: 262120 ... (96886 more ...)                               EQV MISMATCH at 28000 (data): led[0] rtl 0, netlist 1
  31  tb FAIL  EQV PASS: 262092 ... (96814 more ...)                               EQV MISMATCH at 28000 (data): led[0] rtl 0, netlist 1
  32  tb FAIL  EQV PASS: 196608 ... (46705 more ...)                               EQV MISMATCH at 36000 (posedg): an[0] rtl 0, netlist 1
  34  tb FAIL  EQV PASS: 196604 ... (24440 more ...)                               EQV MISMATCH at 14000 (btns): led[0] rtl 0, netlist 1

The runner and test/run.sh's row check over 07, 01, 52, 70, each with a mutated runner:
  round 3's tree, supported probes all counted as passing   passed 1, failed 0 (the line says 4/4)
  today, the same                                           FAIL sv: test/sv/run.sh says '... passing all four stages 4/4, known gaps 3', its rows make it '... 1/4, known gaps 3'
  today, synthesis counted from the bit stage               FAIL sv: test/sv/run.sh says 'synthesis 1/4, ...', its rows make it 'synthesis 3/4, ...'
  today, no mutation                                        passed 1, failed 0, known gaps 3

The latch advice replaced with 'something went wrong.':
  round 3's runner   gap  01_latch_comb   rtl pass  synth fail  netlist -  bit fail          matches expect.tsv: 1/1
  today's runner     BAD  01_latch_comb   ... expect.tsv quotes 'Give q a default value at the top of the block.', no stage printed it
Each mutation on a copy, the new check that goes red (all four green on round 3's suite):
  the backquote dropped from the student-name pattern   FAIL student-name check sees a quoted name
  .v dropped from the runner's file:line pattern        FAIL a file:line of a .v file is checked
  the runner's quote check removed                      FAIL a message the today column quotes is checked
  the runner counts every supported probe               FAIL sv: test/sv/run.sh says ... (the full run's row check, above)

81 with a runner that reads only top.json (round 3's), and today's:
  BAD  81_finish_in_design   rtl fail  synth fail  netlist -     bit fail   synth fail, expected pass; netlist -, expected fail; bit fail, expected pass
  gap  81_finish_in_design   rtl fail  synth pass  netlist fail  bit pass   note: the CLI took counter for the top

Round 5:

$ GITHUB_STEP_SUMMARY=<absolute path> SV_OUT=rows-final.tsv test/run.sh      (from a scratch folder)
== static
  PASS shellcheck                                                (now also test/sv/eqv.sh)
== error paths
  PASS unnamed instance -> line and fix                          (now also 'Write:  sub u_sub(')
== probe runner (test/sv/run.sh on a copy, one probe each)
  PASS a vivado value other than supported, not supported, unverified is refused
  PASS a message the today column quotes in double quotes is checked
  PASS eqv.py: an output lost only between a button change and the clock edge is caught
  PASS eqv.py: a register with an asynchronous reset starts in the RTL as on the board
  PASS eqv.py: a latch with no start value starts at 0 in the RTL, as on the board
  PASS eqv.py: a reset value of 0011 starts each bit as its FDSE or FDRE does
  PASS eqv.sh: a submodule's register with no start value is started in the RTL
  PASS eqv.sh: a fault in a submodule's register with no start value is caught
  PASS eqv.py: a register that feeds a submodule's port is started by its own name
== SystemVerilog probes (test/sv)
  GAP  sv 08c_port_dir_inherit_proc: rtl fail, synth pass, netlist pass, bit pass
  GAP  sv 51c_packed_param_typedef: rtl fail, synth pass, netlist fail, bit pass
  PASS sv 84_repeat_const: rtl pass, synth pass, netlist pass, bit pass
  ...
  synthesis 57/115, all four stages 27/115, Vivado-supported probes passing all four stages 26/99, known gaps 77
passed 148, failed 0, known gaps 77                          (474 s)
$ cat summary.md                                              (one line)
SystemVerilog probes (yosys 0.69+post, iverilog 13.0): synthesis 57/115, all four stages 27/115, Vivado-supported probes passing all four stages 26/99, known gaps 77
$ PATH=<yowasp yosys 0.68 shim>:$PATH test/sv/run.sh <the 15 new probes>     (CI's yosys; brew untouched)
test/sv: 15 probes, yosys 0.68, iverilog 13.0  (expect.tsv was measured with yosys 0.69+post, ...)
matches expect.tsv: 15/15                                     (52 s)
$ PATH=<the same shim>:$PATH test/sv/eqv_check.sh <each of the 37 cases>: 37 of 37 as expected (111 s)
$ test/sv/run.sh <the 115, in four runs of 29, 29, 29 and 28>
matches expect.tsv: 29/29, 29/29, 29/29, 28/28          (124 s, 105 s, 51 s, 55 s)

The breaker's probe 90_reg_to_port (register n feeds a submodule's port D; top also has a register D):
  round 4's runner   BAD  90_reg_to_port   rtl pass  synth pass  netlist fail  bit pass   netlist fail, expected pass
                              net:    eqv.sv:20: error: 'eqv_rtl.A1.D' is not a valid l-value for a procedural assignment.
  today's runner     ok   90_reg_to_port   rtl pass  synth pass  netlist pass  bit pass

The breaker's divider in a submodule, the product's netlist of a copy that counts down:
  round 4's runner, its eqv() as it is        EQV FAIL: 26112 of 196608 compared output bits differ between the RTL and the netlist
  round 4's runner, its eqv() without flatten EQV PASS: 147456 output bits compared, all equal
  today's eqv.sh                              EQV FAIL: 26112 of 196608 compared output bits differ between the RTL and the netlist

eqv mutations, each on a copy; the cases that go red. Round 4's tree ran its 30 cases plus the breakers' 4
(mealyb, xstarta, xstartl, fillasym added to it); today's tree runs its 37:
                                                    round 4's tree              today
  no compare after the buttons change (eqv.py)      mealyb (the 30: none)       mealyb
  async-reset flip-flops not started (eqv.py)       xstarta (the 30: none)      xstarta
  latches not started (eqv.py)                      xstartl (the 30: none)      xstartl
  reset value bits in the other order (eqv.py)      fillasym (the 30: none)     fillasym
  no flatten in the RTL register listing            none (it was in run.sh)     subfault (it is in eqv.sh)
  no proc in the RTL register listing (eqv.sh)                                  25 cases, subreg subfault regport among them
  the always block's module not looked at first                                 subreg subfault regport
  eqv.py --netlist skipped (INITs left x, modules not renamed)                   17 cases
Today's tree without a mutation: all 37 cases as expected (21 s).

The runner checks on a copy of today's tree with the breakers' runner mutations:
  "..." quotes not read from the today column   FAIL st_fixtext    (the run: gap 02_unnamed_inst ... matches expect.tsv: 1/1)
  the vivado value check removed                FAIL st_vivvalue   (the run: ok 01_latch_comb ... matches expect.tsv: 1/1)
On round 4's tree the same two mutations left the suite green: 02 'matches expect.tsv: 1/1' with the fix
text gone from the CLI, 01 'ok' with its column written 'Supported'.

The new probes' testbenches, each on a correct design and on one with its construct broken:
  08c  the line bit rewrites, iverilog   PASS    an = 4'b1110 for two digits          FAIL: sw=0100 an=1110 seg=1111111
  12c  iverilog                          PASS    .x and .y swapped                     FAIL: sw=0001 led=0001
  13d  yosys-slang netlist               PASS    sw[4*j + i] in the loop               FAIL: sw=0101 led=5005 want=1101
  13d  yosys-slang netlist               PASS    the two read indices swapped          FAIL: sw=1010 led=0010 want=1010
  23e  iverilog / yosys-slang            PASS    K = 6                                 FAIL: sw=0000 led=0006 (both)
  33c  iverilog                          PASS    4'b0 instead of 4'bz                  FAIL: sw=0000 led=0000
  40b  iverilog                          PASS    the counter steps by 2                FAIL: after 1 edges led=a5a2
  51b  yosys-slang netlist               PASS    two table entries swapped             FAIL: sw=0002 seg=0110000
  51c  yosys-slang netlist               PASS    two table entries swapped             FAIL: sw=0002 seg=0110000
  82   iverilog                          PASS    q + sw[4:1]                           FAIL: cycle 0 led=0002 want=4
  83   yosys-slang netlist               PASS    $realtobits(3.5)                      FAIL: sw=0000 led=400a
  83   yosys-slang netlist               PASS    $bitstoreal of 1.0                    FAIL: sw=0000 led=4000
  84   iverilog                          PASS    repeat (7)                            FAIL: sw=da80 led=da00
  85   yosys-slang netlist               PASS    quad_t [1:0] instead of [0:1]         FAIL: sw=c201 led=c201
  86   yosys-slang netlist               PASS    y = a                                 FAIL: sw=0000 led=0000
  87   iverilog                          PASS    the byte swap undone                  FAIL: sw=3c00 led=3c00
  88   yosys-slang netlist               PASS    rev returns a                         FAIL: sw=0101 led=0101

51c, the product's netlist and yosys-slang's, sw = 0 to 3 (the table: 1000000 1111001 0100100 0110000):
  dewfpga bit    pnr ok: 0 LUT, 0 FF ...    seg 0000000 0000000 0000000 0000000
  yosys-slang                               seg 1000000 1111001 0100100 0110000

Round 6:

$ GITHUB_STEP_SUMMARY=<absolute path> SV_OUT=rows-final.tsv test/run.sh      (from a scratch folder)
== static
  PASS student-name check sees a quoted name                     (now a quoted name after each of 10 words)
== probe runner (test/sv/run.sh on a copy, one probe each)
  PASS an unexpected pass in a row is not trusted with the measured yosys
  PASS a message the today column quotes second is checked
  PASS a file:line the today column names second is checked
  PASS a comparison that fails with exit 1 is a netlist fail
  PASS eqv.py: a register whose slice a wire names is started by its own name
  PASS eqv.py: a register with an alias wire that sorts first is started by its own name
  PASS eqv.py: 1-bit enums of a submodule and of the file are started
  PASS eqv.py: a 2-bit enum the netlist starts in a state the RTL never has is caught
  PASS eqv.py: a LUT RAM that powers up with the wrong contents is caught
  PASS eqv.py: an output lost only between a switch change and the clock edge is caught
  PASS eqv.sh: a bench that does not compile while the RTL does is a FAIL
  PASS eqv.sh: a package in its own file that sorts after the design is compiled first
  PASS eqv.py: a bench that compares nothing is a FAIL
  PASS eqv.py: a netlist one clock off at the start, as dewfpga sim shows it, passes
  PASS eqv.py: a netlist that mixes two starts in one compare is caught
== SystemVerilog probes (test/sv)
  GAP  sv 22f_interface_member_access: rtl pass, synth pass, netlist fail, bit pass
  GAP  sv 37b_decl_init_expr: rtl pass, synth pass, netlist fail, bit pass
  GAP  sv 44_do_while_loop: rtl pass, synth fail, netlist -, bit fail
  GAP  sv 56b_unit_typedef_file: rtl fail, synth fail, netlist -, bit fail
  PASS sv 63b_real_localparam_expr: rtl pass, synth fail, netlist -, bit fail
  GAP  sv 89_clkdiv_slow_logic: rtl pass, synth pass, netlist pass, bit fail
  GAP  sv 90_elab_warning_initial: rtl pass, synth fail, netlist -, bit fail
  PASS sv 91_submodule_own_file: rtl pass, synth pass, netlist pass, bit pass
  PASS sv 92_display_in_design: rtl pass, synth pass, netlist pass, bit pass
  ...
  synthesis 62/123, all four stages 29/123, Vivado-supported probes passing all four stages 28/105, known gaps 82
passed 166, failed 0, known gaps 82                          (533 s; rows-final.tsv has 123 rows)
$ cat summary.md                                              (one line)
SystemVerilog probes (yosys 0.69+post, iverilog 13.0): synthesis 62/123, all four stages 29/123, Vivado-supported probes passing all four stages 28/105, known gaps 82
$ test/sv/run.sh <the 123, in four runs of 31, 31, 31 and 30>
matches expect.tsv: 31/31, 31/31, 31/31, 30/30          (136 s, 114 s, 39 s, 73 s)
synthesis 19+23+8+12 = 62/123, all four stages 12+12+0+5 = 29/123, supported and all four 28/105, known gaps 82
$ PATH=<yowasp yosys 0.68 shim>:$PATH test/sv/run.sh <the 8 new probes and the 6 changed rows>     (CI's yosys)
test/sv: 14 probes, yosys 0.68, iverilog 13.0  (expect.tsv was measured with yosys 0.69+post, ...)
matches expect.tsv: 14/14                                     (63b's crash quote removed first: 13/14 with it)
$ PATH=<the same shim>:$PATH test/sv/eqv_check.sh <each of the 48 cases>: 48 of 48 as expected (152 s)

The breakers' netlists, round 5's eqv.sh, then today's:
  Gray counter (6 FDRE)   EQV FAIL: 9 of 36864 compared output bits differ between the RTL and the netlist
                          EQV PASS: 36864 output bits compared, all equal (at 9 compares to the RTL as dewfpga sim starts it, ...)
  enum in a submodule     EQV FAIL: the RTL compiles but the equivalence bench does not   (Unable to bind `eqv_rtl.OFF')
                          EQV PASS: 196608 output bits compared, all equal
  wire low = led[3:0]     EQV FAIL: the RTL compiles but the equivalence bench does not   ('eqv_rtl.low' is not a valid l-value)
                          EQV PASS: 262144 output bits compared, all equal
The breakers' netlists that have to fail, today's bench (the excuse passes none of them):
  enum state 11 at power-up   EQV FAIL: 2 of 196608 compared output bits differ between the RTL and the netlist
  28's RAM all ones           EQV FAIL: 4096 of 262144 compared output bits differ between the RTL and the netlist
  led[0] a constant 1         EQV FAIL: 3609 of 196608 compared output bits differ between the RTL and the netlist

The new eqv_check cases on round 5's eqv.py and eqv.sh (red = the case does not give its verdict):
  regslice alias enum1sub romstart                          red (the first three: the bench does not compile;
                                                            romstart: EQV FAIL: 21501 of 196608)
  enumstart memstart datasw nobench pkgfile nothing mixstart as expected (they pin what round 5 already did)

eqv mutations on a copy of today's tree, and the cases that go red (48 cases; none without a mutation):
  12 the multi-bit enum start deleted                  enumstart
  13 memories not started                              memstart
  14 no data compare with a clock                      enumstart datasw
  15 eqv.sh's bench guard removed                      nobench
  18 the assigned_in fallback removed                  regslice alias enum1sub
  22 the packages-first order removed                  pkgfile
  23 "nothing compared" no longer a FAIL               nothing
  the sim-start excuse removed                         romstart
  the excuse per bit, not per compare                  mixstart
  an x in the sim-start copy excuses                   subfault enumstart memstart
  the 1-bit enum item named in top's scope             enum1sub
  assigned_in reads whole lines, not columns           alias enum1sub
On round 5's tree the breakers' seven (12 to 23) each left all 37 cases green.

Runner mutations on a copy of today's tree, the old checks that could see them, and the new one:
  only a row's first quote is checked        PASS st_latchtext, PASS st_fixtext, FAIL st_quote2
  only a row's first file:line is checked    PASS st_latchline, PASS st_vfile, FAIL st_line2
  any eqv.sh failure is a skip (-ne 0)       PASS st_eqvpin, FAIL st_eqvexit
  sv_rows always lenient (exact=0)           PASS st_verdicts, PASS st_score, FAIL st_exact
  the name check's words cut to module       FAIL st_names

Product and probe mutations, the probe that goes BAD:
  sim compiles only the first design file    BAD 91_submodule_own_file  rtl fail, expected pass   (tb.sv:7: error: Unknown module type: top)
  delete t:$print dropped                    BAD 92_display_in_design   bit fail, expected pass   (no Bels remaining of type '$print')
  44's two do-while loops written as while   BAD 44_do_while_loop       rtl fail, expected pass
Before, no probe could see the first two (only 57 has two design files, and the CLI stops it; 40, 40b
and 81 never hand their $display to yosys); the breakers' full runs with them: passed 144, failed 0.
44 with its one loop written as while matched expect.tsv (gap, 1/1).

-noautowire, every probe read with and without it (hierarchy, proc): 22, 22b, 22c, 22d, 22f, 23c, 39, 58, 76
change; 63b crashes either way.

The new probes' testbenches, on the RTL (iverilog) and with one edit:
  89   PASS    d1 without % 10                       FAIL: value 9999: led=9979, want 9999
  89   PASS    the slow clock never toggles          FAIL: value 9999: led=0000, want 9999
  90   PASS    N = 5                                 FAIL: sw=0010 led=0010, want 0000
  63b  PASS    MAX = 1.2e1                           FAIL: after 10 edges led=0000
  37b  PASS    wire instead of logic (continuous)    FAIL: led follows sw (sw=0101 led=0001, was 0000): an initializer runs once
  22f  PASS    s = a - b                             FAIL: sw=0100 led=00ff
  91   PASS    the counter steps by 2                FAIL: after 1 edges sw=5e81 led=5e83
  92   PASS    the counter steps by 2                FAIL: after 1 edges sw=5e81 led=5e82
  56b  PASS    RUN goes back to IDLE                 FAIL: after 2 edges led=0000, want 2
  44   PASS    the second loop written as while      FAIL: do-while popcount, and a body that runs once (sw=8000 led=0001 want 1, 1)

Round 6's final run, 26 September (the tree after round 6):

$ GITHUB_STEP_SUMMARY=<absolute path> SV_OUT=rows-final.tsv test/run.sh      (from a scratch folder)
== static
  PASS shellcheck
  PASS no personal paths
  PASS personal-path check sees test/sv/run.sh
  PASS no names from student code in expect.tsv
  PASS student-name check sees a quoted name
  ...
== probe runner (test/sv/run.sh on a copy, one probe each)          71 PASS: 23 runner checks, 48 eqv checks
  ...
== SystemVerilog probes (test/sv)                                    41 PASS, 82 GAP, 0 FAIL
  GAP  sv 01_latch_comb: rtl pass, synth fail, netlist -, bit fail
  ...
  PASS sv 92_display_in_design: rtl pass, synth pass, netlist pass, bit pass
  synthesis 62/123, all four stages 29/123, Vivado-supported probes passing all four stages 28/105, known gaps 82

passed 166, failed 0, known gaps 82
real 527,76                                                           (exit 0; rows-final.tsv has 123 rows)
$ cat summary.md                                                      (one line)
SystemVerilog probes (yosys 0.69+post, iverilog 13.0): synthesis 62/123, all four stages 29/123, Vivado-supported probes passing all four stages 28/105, known gaps 82

$ PATH=<yowasp yosys 0.68 shim>:$PATH SV_OUT=<chunk>.tsv test/sv/run.sh <25 ids>     (CI's yosys; brew untouched; 5 runs)
test/sv: 25 probes, yosys 0.68, iverilog 13.0  (expect.tsv was measured with yosys 0.69+post, iverilog 13.0: only regressions and new silent wrongs fail)
matches expect.tsv: 25/25, 25/25, 25/25, 25/25, 23/23        (175 s, 149 s, 129 s, 61 s, 131 s; 0 BAD)
synthesis 14+16+14+6+12 = 62/123, all four stages 9+8+7+0+5 = 29/123,
Vivado-supported all four 9+8+6+0+5 = 28 of 20+24+19+21+21 = 105, known gaps 14+16+15+21+16 = 82
notes: 11 "netlist: testbench only, iverilog cannot compile the RTL", 1 "the CLI took counter for the top"
$ diff <the native rows, id to bit> <the 0.68 rows, id to bit>                          (identical, 123 rows)
$ PATH=<the same shim>:$PATH test/sv/eqv_check.sh <each of the 48 cases>
as expected: 48 of 48; red: none                              (151 s)
$ readlink /opt/homebrew/bin/dewfpga; yosys -V
<the repo>/bin/dewfpga
Yosys 0.69+post (git sha1 143eb14f9cc55d6f8927e68523b0c9d2166ed02c, ...)

Round 7:

$ GITHUB_STEP_SUMMARY=<absolute path> SV_OUT=rows-final.tsv test/run.sh      (from a scratch folder)
== static
  PASS personal-path check sees test/run.sh                         (new)
== probe runner (test/sv/run.sh on a copy, one probe each)
  PASS a testbench that prints PASS while dewfpga sim exits 1 is an rtl fail      (new)
  PASS the score line is counted again from the rows                (now also: no score line, 'Synthesis ...')
  PASS eqv.py: a wrong netlist that matches sim's x-optimistic copy at some compares is caught
  PASS eqv.py: a netlist that shows only what sim shows while its register is x is caught
  PASS eqv.py: an x in sim's copy excuses no x in the netlist
  PASS eqv.py: a reset on a switch is pressed first, like a button
  PASS eqv.sh: a register that shares its variable with an assign is started
  PASS eqv.py: an FDSE_1 and an FDPE_1 with INIT x start at 1, as on the board
== SystemVerilog probes (test/sv)
  PASS sv 31b_negedge_set: rtl pass, synth pass, netlist pass, bit pass
  GAP  sv 93_two_roots_file_name: rtl pass, synth pass, netlist fail, bit pass (note: the CLI took counter for the top)
  GAP  sv 94_power_var_base: rtl pass, synth pass, netlist pass, bit fail
  PASS sv 95_empty_submodule: rtl pass, synth pass, netlist fail, bit fail
  GAP  sv 96_port_one_bit_vector: rtl pass, synth pass, netlist pass, bit fail
  GAP  sv 96b_port_offset_range: rtl pass, synth pass, netlist pass, bit fail
  GAP  sv 97_ram_style_block: rtl pass, synth pass, netlist fail, bit pass
  PASS sv 98_module_named_primitive: rtl pass, synth fail, netlist -, bit fail
  PASS sv 99_string_parameter: rtl pass, synth fail, netlist -, bit fail
  ...
  synthesis 69/132, all four stages 30/132, Vivado-supported probes passing all four stages 29/111, known gaps 87
passed 178, failed 0, known gaps 87                          (583 s; exit 0; rows-final.tsv has 132 rows, 178 PASS, 87 GAP, 0 FAIL)
  final run, after every file but these notes was written: the same, 582 s, the same 132 rows
$ cat summary.md                                              (one line)
SystemVerilog probes (yosys 0.69+post, iverilog 13.0): synthesis 69/132, all four stages 30/132, Vivado-supported probes passing all four stages 29/111, known gaps 87
$ SV_OUT=<chunk>.tsv test/sv/run.sh <the 132, in five runs of 27, 27, 27, 27 and 24>
matches expect.tsv: 27/27, 27/27, 27/27, 27/27, 24/24                (the first 118 s)
synthesis 15+19+13+10+12 = 69/132, all four stages 10+11+4+1+4 = 30/132,
Vivado-supported all four 10+11+3+1+4 = 29 of 22+26+21+23+19 = 111, known gaps 15+15+20+22+15 = 87
(the rows, id to bit, equal those of the full run)
$ PATH=<yowasp yosys 0.68 shim>:$PATH test/sv/run.sh <the 9 new probes and 13d>     (CI's yosys; brew untouched)
test/sv: 10 probes, yosys 0.68, iverilog 13.0  (expect.tsv was measured with yosys 0.69+post, ...)
matches expect.tsv: 10/10
$ PATH=<the same shim>:$PATH SV_OUT=<chunk>.tsv test/sv/run.sh <the 132, in the same five runs>
matches expect.tsv: 27/27, 27/27, 27/27, 27/27, 24/24        (193 s, 186 s, 115 s, 113 s, 117 s; 0 BAD)
synthesis 69/132, all four stages 30/132, Vivado-supported all four 29/111, known gaps 87 (the same sums)
notes: 11 "netlist: testbench only, iverilog cannot compile the RTL", 2 "the CLI took counter for the top"
$ diff <the native rows, id to bit> <the 0.68 rows, id to bit>                          (identical, 132 rows)
$ PATH=<the same shim>:$PATH test/sv/eqv_check.sh <each of the 54 cases>
as expected: 54 of 54; red: none                              (172 s)

The breakers' netlists, round 6's eqv.sh, then today's:
  digit counter, one LUT bit flipped   EQV PASS: 196608 output bits compared, all equal (at 3072 compares to the RTL as dewfpga sim starts it, ...)
                                       EQV FAIL: 3072 of 196608 compared output bits differ between the RTL and the netlist
  digit counter lost (led = 1111)      EQV PASS: 196608 output bits compared, all equal (at 9216 compares to the RTL as dewfpga sim starts it, ...)
                                       EQV FAIL: 9216 of 196608 compared output bits differ between the RTL and the netlist
  one-hot FSM, reset on sw[15]         EQV FAIL: 10 of 196608 compared output bits differ between the RTL and the netlist
                                       EQV PASS: 196608 output bits compared, all equal
  the same, reset on btnC              EQV PASS: 262144 output bits compared, all equal          (both)
  counter on led[3:0], assign the rest EQV FAIL: the RTL compiles but the equivalence bench does not
                                       EQV PASS: 262144 output bits compared, all equal
  the corpus Gray counter (6 FDRE)     EQV PASS: 36864 output bits compared, all equal (at 9 compares to the RTL as dewfpga sim starts it, ...)
                                       EQV PASS: 36864 output bits compared, all equal
  counter with no start, led[3:0] x    EQV FAIL: 49152 of 196608 compared output bits differ between the RTL and the netlist   (both)
  negedge set counter (FDSE_1, INIT x) EQV PASS: 196608 output bits compared, all equal          (both)

The new eqv_check cases on round 6's eqv.py and eqv.sh:
  simflip   red   EQV PASS: 196608 output bits compared, all equal (at 3072 compares ...)
  simlost   red   EQV PASS: 196608 output bits compared, all equal (at 9216 compares ...)
  swreset   red   EQV FAIL: 10 of 196608 compared output bits differ between the RTL and the netlist
  partassign red  EQV FAIL: the RTL compiles but the equivalence bench does not
  xhold negset    as expected (they pin what round 6 already did)
All 48 old cases on today's eqv.py and eqv.sh before the five were changed: 48 of 48 as expected (40 s).

eqv mutations on a copy of today's tree, and the cases that go red (54 cases; none without a mutation):
  the x test dropped from the sim copy's rule                   xhold
  STARTS_AT_1 without FDSE_1 and FDPE_1                         negset
  reset values ignored (every register started at 0)           fillset fillaset fillasym
      (the same with their resets still on sw[15]: all five green, the press hides the start)
  the sim copy counted as resolved from the start               simlost romstart
  the excuse per compare again                                  simflip simlost
  the excuse removed                                            romstart
  switch resets not pressed                                     swreset
  no bit-by-bit start (--bits ignored)                          partassign

Runner and test/run.sh mutations, the check that sees each:
  the rtl stage's exit code not required        st_rtlexit: PASS on the runner, FAIL on the mutant
                                                (the runner on 07 with the planted $error: BAD 07_enum_packed_array rtl fail)
  the runner prints no score line               sv_rows: 'test/sv/run.sh printed no score line, its rows make it
                                                'synthesis 1/2, ...'', fail=1 (round 6's sv_rows: fail=0)
  a home-folder path appended to test/run.sh    round 6's personal_paths: 0 lines; today's: 1 (test/run.sh:469)

13d's testbench, all 432 single-bit LUT INIT flips of the product's netlist, in one simulation (408 s):
  caught 414 of 432 (the breaker's count with the old testbench: 308)
  the 18 left: LUT _32_ (it drives led[12]) bits 6 7 12 13 14 15 18 19 22 23 24 25 26 27 28 29 30 31
  input combinations of _32_ that never occur, every grid value x every row and column (1048576 cases, 7 s):
                   6 7 12 13 14 15 18 19 22 23 24 25 26 27 28 29 30 31
  the breaker's flip (LUT 3, bit 27): old testbench PASS, new FAIL: grid=84f5 sw=c45a led=54f5 want=44f5

The new probes' testbenches, on the RTL (iverilog) and with one edit:
  93   PASS    the plain counter as top                FAIL: after 1 clocks led=1, want 0
  94   PASS    sw[7:0] ** 3                            FAIL: sw=0002 led=8 want 4
  94   PASS    sw[7:0] * 2                             FAIL: sw=0001 led=2 want 1
  95   PASS    led = {sw[14:0], b}                     FAIL: sw=0001 led=000X
  96   PASS    assign led = sw                         FAIL: 2 of 2
  96b  PASS    assign led = sw                         FAIL: 16 of 16
  97   PASS    writes the address, not the data        FAIL: address 0 led=0000
  97   PASS    reads the next address                  FAIL: address 0 led=000a
  98   PASS    INV passes a through                    FAIL: sw=0000 led=0000
  99   PASS    the ROM read at ~a                      FAIL: address 0 led=00a6
  31b  PASS    posedge instead of negedge              FAIL: the rising edge moved q: led=0000
  31b  PASS    the set loads 0                         FAIL: the set on the falling edge: led=0000
  31b  PASS    the preset loads 0                      FAIL: the preset, before any edge: led=0003

Measured apart for the new rows:
  93 as lab4.sv        ERROR: 2 modules could be the top (nothing instantiates them): counter, top. Name it:  dewfpga bit counter
  corpus 061 (its own XDC)   pnr ok: 6 LUT, 6 FF, 830.56 MHz (PASS at 100.00 MHz); the plain counter's .bit, exit 0, no 'top module:' line
  94 with 16'd3 ** sw[2:0]   the same 'no Bels remaining of type '$pow'' and 'does not fit'
  94 with 2 ** sw[3:0]       pnr ok: 16 LUT, 0 FF;   with sw[7:0] * sw[7:0]: pnr ok: 0 LUT, 0 FF (a DSP48E1)
  95 with b unused           pnr ok: 0 LUT, 0 FF, no clocked paths, timing not applicable
  96, nextpnr-xilinx on the product's top.json: Constraining 'led' to site 'IOB_X0Y3', 'sw' to 'IOB_X0Y11'
      (the sites of led[0] and sw[0] in a 16-bit design)
  96b, the same with its own XDC: exit 0, sw[1] to sw[4] on IOB_X0Y12, Y10, Y9, Y7 (the sites of sw[1] to sw[4])
  97 with rom_style = "block" on an initialized ROM: RAMB18E1: 1/150, pnr ok: 0 LUT, 0 FF, no clocked paths
  98 as GND, VCC, MUXF7: cells_sim.v:28, :24, :342: ERROR: Re-definition of module ...;  as BUF: pnr ok: 1 LUT
  99 untyped: pnr ok: 7 LUT, 0 FF; its netlist: the testbench PASS, EQV PASS: 1048576 output bits compared, all equal

The port-line fix (check_xdc.py --fix-ports) on eight placements of a comment, 1 = the line was fixed:
  // a comment after seg,  at the end of the seg, line                1   (the comment itself ends in a comma)
  // the segments          at the end of the seg, line                0
  // ...                   on a line of its own between the two       0
  /* ... */                on a line of its own between the two       0
  /* ... */                between seg, and logic dp on one line      0
  /* ; ... */              after seg,                                 0
  // ...                   after logic dp,                            1
  /* ... */                before the comma after seg                 1

Not verified.

Not done here.


previous: #1 The CLI and the guide say the same thing
next: #3 Silent wrongs stop the build
This entry in the full list
The commands this entry names: dewfpga sim · dewfpga bit · dewfpga flash
Every SystemVerilog construct measured so far, next to what Vivado does: the probes, stage by stage