A library the mapper cannot read might as well not exist. This lesson reads course.lib end to end: the script instantiates all fifteen cells once, and the stat report below is the recorded listing, one row per cell with areas straight from the report. Two tables are copied exactly from the file along the way, the INV and NAND2 rise tables, so every later lookup has a ground truth to point at.
The course library is a small fictional library called course, kept in course.lib. A second library, nand_only.lib, holds only INV, BUF, and NAND2 at the same areas, and the mapping lesson prices the difference.
The script reads course.lib so its fifteen cells become known modules, instantiates each once, and asks stat -liberty for the histogram. Each select line pins one count: one row per cell, areas straight from the recorded report.
read_liberty -lib course.lib
read_verilog <<EOV
module top(input a, b, c, s, d, clk, rn, output [14:0] y);
INV g0(.A(a), .Y(y[0]));
BUF g1(.A(a), .Y(y[1]));
NAND2 g2(.A(a), .B(b), .Y(y[2]));
NOR2 g3(.A(a), .B(b), .Y(y[3]));
AND2 g4(.A(a), .B(b), .Y(y[4]));
OR2 g5(.A(a), .B(b), .Y(y[5]));
NAND3 g6(.A(a), .B(b), .C(c), .Y(y[6]));
NOR3 g7(.A(a), .B(b), .C(c), .Y(y[7]));
XOR2 g8(.A(a), .B(b), .Y(y[8]));
XNOR2 g9(.A(a), .B(b), .Y(y[9]));
AOI21 g10(.A(a), .B(b), .C(c), .Y(y[10]));
OAI21 g11(.A(a), .B(b), .C(c), .Y(y[11]));
MUX2 g12(.A(a), .B(b), .S(s), .Y(y[12]));
DFF g13(.D(d), .CLK(clk), .Q(y[13]));
DFFR g14(.D(d), .CLK(clk), .RN(rn), .Q(y[14]));
endmodule
EOV
hierarchy -check -top top
tee -o stat_all.txt stat -liberty course.lib
select -assert-count 1 t:INV
select -assert-count 1 t:BUF
select -assert-count 1 t:NAND2
select -assert-count 1 t:NOR2
select -assert-count 1 t:AND2
select -assert-count 1 t:OR2
select -assert-count 1 t:NAND3
select -assert-count 1 t:NOR3
select -assert-count 1 t:XOR2
select -assert-count 1 t:XNOR2
select -assert-count 1 t:AOI21
select -assert-count 1 t:OAI21
select -assert-count 1 t:MUX2
select -assert-count 1 t:DFF
select -assert-count 1 t:DFFR
check
log PASS: all fifteen teaching-library cells instantiate with listed areasFifteen rows, one per cell kind, each with count 1. The two flop cells cost the most: DFF at 8 units and DFFR at 10, against 1 to 5 for every combinational cell. The recorded table shows it.
Cell | Function (exact from course.lib) | Count (recorded) | Area (recorded) |
|---|---|---|---|
AND2 |
| 1 | 3 |
AOI21 |
| 1 | 3 |
BUF |
| 1 | 2 |
DFF |
| 1 | 8 |
DFFR |
| 1 | 10 |
INV |
| 1 | 1 |
MUX2 |
| 1 | 5 |
NAND2 |
| 1 | 2 |
NAND3 |
| 1 | 3 |
NOR2 |
| 1 | 2 |
NOR3 |
| 1 | 3 |
OAI21 |
| 1 | 3 |
OR2 |
| 1 | 3 |
XNOR2 |
| 1 | 5 |
XOR2 |
| 1 | 5 |
Read the shape of the menu: INV 1, BUF 2, NAND2 and NOR2 at 2, AND2 and wider gates at 3, XOR and mux structures 5, flops 8 and 10. This price list is why XOR-heavy logic costs more against the three-cell library: the recorded 4-bit adder in mapping-in-yosys comes out at about 1.12x, area 66 against 59, because sums that take one 5-unit XOR2 each are rebuilt from several 2-unit NAND2 cells.
Each delay table repeats the template axes: index_1 is input_net_transition, the rows, and index_2 is total_output_net_capacitance, the columns. Both axes of the teaching library read 0.01, 0.1. The INV rise table below is copied exactly from course.lib, where it stands as values("0.05,0.07","0.08,0.11"): first string, first row; values across a string run across the loads.
Input slew (rows) / output load (cols) | 0.01 | 0.1 |
|---|---|---|
0.01 | 0.05 | 0.07 |
0.1 | 0.08 | 0.11 |
Read the second row as carefully as the first: the slow-slew row reads 0.08 and 0.11 ns. One digit moves every lookup touching that corner, so check each values string entry by entry before interpolating.
The NAND2 rise table stands in course.lib as values("0.08,0.1","0.11,0.14") on both the A and B arcs, read row by row: slew 0.1 with load 0.01 is 0.11, and slew 0.01 with load 0.1 is 0.10.
Input slew (rows) / output load (cols) | 0.01 | 0.1 |
|---|---|---|
0.01 | 0.08 | 0.10 |
0.1 | 0.11 | 0.14 |
Both tables are nanoseconds by the file header, so 0.11 is 110 ps. Fall tables match rise on every arc here, and all output-slew tables read values("0.02,0.04","0.04,0.08"). Real libraries vary per arc and direction; this one stays symmetric so the lessons can concentrate on the lookup.
Read a cell the way the mapper does: area for the price, pin functions and capacitances for compute and load, one timing group per arc for speed. NAND2 has one group per input pin; DFF replaces output arcs with constraint groups on D against CLK plus clock-to-output, printed in full in the flops lesson.
Timing sense tells the tool which input direction matters, arc by arc as course.lib lists it: negative_unate on both NAND2 arcs, positive_unate on both AND2 arcs, non_unate on both XOR2 arcs (A and B) and on all three MUX2 arcs (data A, data B, and select S). The mapper uses it to propagate the right slew through each stage.
The second script instantiates one NAND2 and runs stat without -liberty. Counts survive, because the design still holds the cell. Areas vanish, because no library prices them: structure comes from the RTL, cost from the library.
read_liberty -lib course.lib
read_verilog <<EOV
module top(input a, b, output y);
NAND2 g1(.A(a), .B(b), .Y(y));
endmodule
EOV
hierarchy -check -top top
tee -o stat_nolib.txt stat
select -assert-count 1 t:NAND2
check
log PASS: stat without a library counts the cell but reports no areaThe recorded plain report, shown below, counts one NAND2 and prints no area line at all: no zero, no total. The recorded library report above prices the same cell at 2 units. When a stat report shows counts but no area line, check whether -liberty named the right file before doubting the netlist.
4. Printing statistics.
=== top ===
+----------Local Count, excluding submodules.
|
3 wires
3 wire bits
3 public wires
3 public wire bits
3 ports
3 port bits
1 cells
1 NAND20.11 ns from the second string of values("0.08,0.1","0.11,0.14"). The first string is the fast-slew row at 0.01, so the second string is slew 0.1, and its first entry is load 0.01.
That structure comes from the RTL and cost comes from the library. The count survives without -liberty; the area needs the file.
Every number and picture on this page comes from Yosys 0.69 runs of the two scripts shown, recorded by the course checker (scripts/tools/run-rtl-testbenches.mjs with COURSE=synth): all fifteen cells instantiated once with a stat -liberty histogram, plus one NAND2 with a plain stat report. Tables and functions are copied exactly from scripts/tools/synth-libs/course.lib.