Inside a cross body, binsof selects a slice of the product matrix. binsof(cp.bin_name) picks every cell whose cp coordinate is that bin: a full row or column.
binsof(cp) intersect {values} picks the cells whose cp bin contains any of the listed values. Selection is by value overlap, not by bin name.
The listing below is not run in this course's checks: the open simulators do not count covergroups, so the lesson's bench counts it with the bins model.
// not-run: Verilator 5.048 ignores covergroups (COVERIGN) and Icarus 13 has none; the bins model counts it
covergroup cg @(posedge clk iff valid);
cp_op : coverpoint opcode { bins add = {OP_ADD}; bins sub = {OP_SUB};
bins mul = {OP_MUL}; bins div = {OP_DIV}; }
cp_len : coverpoint burst_len { bins single = {1}; bins short_b = {[2:4]};
bins long_b = {[5:16]}; }
x_op_len : cross cp_op, cp_len {
// Select by bin name: the whole div row (3 cells -> 1 named bin)
bins div_any = binsof(cp_op.div);
// Select by value: any len bin containing 1..2 (single and short_b)
bins short_ops = binsof(cp_len) intersect {[1:2]};
// AND of selections: exactly the <div, long_b> cell
bins div_long = binsof(cp_op.div) && binsof(cp_len.long_b);
// OR of selections: union of the mul row and the div row
bins muldiv = binsof(cp_op.mul) || binsof(cp_op.div);
// Negation: every cell NOT in the add row
bins not_add = !binsof(cp_op.add);
}
endgroupSelection | Cells | Which |
|---|---|---|
| 3 | The div row |
| 8 | The single and short_b columns: 2 overlaps short_b, so the whole column joins |
| 1 |
|
| 6 | The mul and div rows: |
| 9 | Every row but add: |
Form | Selects | Set meaning |
|---|---|---|
binsof(cp.bin) | Whole row or column of that bin | Base selection |
binsof(cp) intersect {vals} | Every source bin overlapping the values | Value filter |
A && B | Cells in both selections | Narrows |
A || B | Cells in either selection | Widens |
!A | Cells outside the selection | Inverts |
A named cross bin built from a selection is one bin, no matter how many cells it covers. It closes when any cell in its selection is hit.
A named bin absorbs the auto cells it selects. Every other auto cell stays in the goal. To make the goal exactly the named bins, add an ignore_bins catch-all over the complement.
The listing below is not run in this course's checks, for the same reason.
// not-run: Verilator 5.048 ignores covergroups (COVERIGN) and Icarus 13 has none; the bins model counts it
x_op_len : cross cp_op, cp_len {
// ONE bin: closes when ANY div cell is hit.
// It absorbs the 3 div cells; the other 9 auto cells stay.
bins div_any = binsof(cp_op.div);
}
// Goal: 1 named bin + 9 auto cells = 10 bins.
x_div_cells : cross cp_op, cp_len {
// Cross bins have no [] array form. To grade each div cell,
// name each one:
bins div_single = binsof(cp_op.div) && binsof(cp_len.single);
bins div_short = binsof(cp_op.div) && binsof(cp_len.short_b);
bins div_long = binsof(cp_op.div) && binsof(cp_len.long_b);
// Catch-all: drop every other cell, so the goal is these 3 bins.
ignore_bins rest = !binsof(cp_op.div);
}Prefer binsof(cp.bin) over value lists when the bin already names the intent. Name selection survives value renumbering inside the bin.
A named cross bin is one bin, so one hit anywhere closes it. Cross bins have no [] form. Leave those cells to the auto product, which grades each cell, or declare one named bin per cell.
10 goal bins: the named bin plus the 9 auto cells it does not select. Add an ignore_bins catch-all if the goal should be the named bin alone.
The bench builds each selection from this lesson with the bins model and counts its cells, then sends one <div,long_b> sample through three crosses: one with all five selections as named bins, one with div_any alone, and one with a named bin per div cell plus the catch-all.
binsof(cp_len) intersect {[1:2]} select, and what goal does div_any alone leave?8 cells, because intersect selects every bin that overlaps the values, and 2 lies in short_b. div_any alone leaves a goal of 10: itself plus the 9 auto cells it does not select. The one sample also hits 4 of the 5 overlapping named bins at once.
// uses: covmodel
// binsof selections over the 4 x 3 cross: how many cells each one picks, and the goal they leave.
module tb_binsof;
cm_point cp_op = new("cp_op"), cp_len = new("cp_len");
cm_cross x_sel, x_any, x_cells;
initial begin
int n_hit = 0;
cp_op.add("add", 0, 0); cp_op.add("sub", 1, 1); cp_op.add("mul", 2, 2); cp_op.add("div", 3, 3);
cp_len.add("single", 1, 1); cp_len.add("short_b", 2, 4); cp_len.add("long_b", 5, 16);
x_sel = new("x_op_len", cp_op, cp_len);
x_sel.add_bin("div_any", x_sel.sel("div", "")); // binsof(cp_op.div)
x_sel.add_bin("short_ops", x_sel.sel_values('{1, 2}, 1)); // binsof(cp_len) intersect {[1:2]}
x_sel.add_bin("div_long", x_sel.sel_and(x_sel.sel("div", ""), x_sel.sel("", "long_b"))); // &&
x_sel.add_bin("muldiv", x_sel.sel_or(x_sel.sel("mul", ""), x_sel.sel("div", ""))); // ||
x_sel.add_bin("not_add", x_sel.sel_not(x_sel.sel("add", ""))); // !
foreach (x_sel.nb_name[n]) $display(" %-10s cells: %0d", x_sel.nb_name[n], x_sel.count(x_sel.nb_cells[n]));
// One named bin and nothing else: the 9 cells it does not select stay as auto bins.
x_any = new("x_any", cp_op, cp_len);
x_any.add_bin("div_any", x_any.sel("div", ""));
// One named bin per div cell, and an ignore_bins catch-all for the rest.
x_cells = new("x_div_cells", cp_op, cp_len);
x_cells.add_bin("div_single", x_cells.sel("div", "single"));
x_cells.add_bin("div_short", x_cells.sel("div", "short_b"));
x_cells.add_bin("div_long", x_cells.sel("div", "long_b"));
x_cells.ignore(x_cells.sel_not(x_cells.sel("div", ""))); // ignore_bins rest = !binsof(cp_op.div);
// A single sample: div with a 9-beat burst.
cp_op.sample(3); cp_len.sample(9); x_sel.sample(); x_any.sample(); x_cells.sample();
foreach (x_sel.nb_hits[n]) if (x_sel.nb_hits[n] != 0) n_hit++;
$display(" one <div,long_b> sample hit %0d of the overlapping named bins", n_hit);
x_any.report(); x_cells.report();
if (x_sel.count(x_sel.nb_cells[1]) != 8 || n_hit != 4 || x_any.n_bins() != 10 || x_cells.n_bins() != 3 || x_any.nb_hits[0] != 1)
$fatal(1, "FAIL: selection math");
$display("PASS: intersect took whole columns (8 cells), div_any left a 10-bin goal, the catch-all left 3");
$finish;
end
endmodule div_any cells: 3
short_ops cells: 8
div_long cells: 1
muldiv cells: 6
not_add cells: 9
one <div,long_b> sample hit 4 of the overlapping named bins
cross x_any: 10.00% (1 of 10 bins)
div_any 1
hole: <add, single>
hole: <add, short_b>
hole: <add, long_b>
hole: <sub, single>
hole: <sub, short_b>
hole: <sub, long_b>
hole: <mul, single>
hole: <mul, short_b>
hole: <mul, long_b>
cross x_div_cells: 33.33% (1 of 3 bins)
div_single 0 <- hole
div_short 0 <- hole
div_long 1
PASS: intersect took whole columns (8 cells), div_any left a 10-bin goal, the catch-all left 3Counted with the course's bins model (rich/coverage/cov_model.sv, listed on the Coverage hub) on Verilator 5.048 (--binary --timing) on 2026-10-18; every bench printed the PASS line shown. Verilator 5.048 parses covergroups with a COVERIGN warning and ignores their bins, and Icarus 13 has none, so each covergroup listing is marked not run and its bench counts the same bins with the model.
intersect {[1:2]} took 8 cells, div_any alone left a 10-bin goal, the ignore_bins catch-all left 3, and one sample hit 4 overlapping named bins at once.