Reading a Yosys Stats Report
Section 2.4 ended on the timing report. Section 2.5 is about reading both halves of the synthesis output, starting with the structural half.
Every run in this module has quoted a cell count and an estimated area without showing where they come from. They come from one command, Yosys’s stat, run automatically at the end of the script from Section 2.2, dumping a summary of the mapped netlist. It looks like noise the first time. It is one of the most information-dense reports in the flow.
The full report, alu8, area strategy
The stat output for the AREA 0 run of alu8 (illustrative, in the structure of real stat output):
=== alu8 ===
Number of wires: 212
Number of wire bits: 612
Number of public wires: 27
Number of public wire bits: 187
Number of memories: 0
Number of memory bits: 0
Number of processes: 0
Number of cells: 146
sky130_fd_sc_hd__a21oi_1 9
sky130_fd_sc_hd__and2_1 7
sky130_fd_sc_hd__buf_1 5
sky130_fd_sc_hd__clkinv_1 1
sky130_fd_sc_hd__conb_1 2
sky130_fd_sc_hd__dfxtp_1 10
sky130_fd_sc_hd__fa_1 8
sky130_fd_sc_hd__inv_1 11
sky130_fd_sc_hd__mux2_1 34
sky130_fd_sc_hd__nand2_1 15
sky130_fd_sc_hd__nor2_1 10
sky130_fd_sc_hd__o21ai_1 12
sky130_fd_sc_hd__xnor2_1 9
sky130_fd_sc_hd__xor2_1 13
Chip area for module '\alu8': 1512.67
Reading it section by section
Wires. Number of wires: 212 counts every internal net Yosys tracks, including intermediate signals that correspond to nothing you named. Number of public wires: 27 is the more useful number for a sanity check: it counts wires that trace back to a named signal in the source (ports and named regs and wires), a rough cross-check against how many named signals the Verilog declares.
Cells, by type. This is the section to read closely, because each line traces to an RTL construct:
| Cell type | Count | Likely RTL origin |
|---|---|---|
dfxtp_1 (D flip-flop) |
10 | result[7:0] (8) + zero (1) + carry_out (1) |
fa_1 (full adder) |
8 | The a + b and a - b arithmetic in the case |
mux2_1 (2:1 mux) |
34 | The 8-way case (op) selecting between operations, per bit |
xor2_1, xnor2_1 |
13, 9 | The XOR operation, plus XOR/XNOR inside comparator and subtractor logic |
and2_1, nand2_1, nor2_1 |
7, 15, 10 | The AND and OR operations and general restructuring |
a21oi_1, o21ai_1 |
9, 12 | Compound AND-OR-invert cells ABC folded multi-gate logic into, per Section 2.1 |
buf_1 |
5 | Fanout buffering where a signal drives enough load to need it |
conb_1 |
2 | Constant 0 and 1 drivers, typically from tied-off or unused bits |
Ten flip-flops matches exactly what the RTL declares as registered outputs. That is a useful sanity check, not a coincidence to skip. If the number had come back as 3 or 40, that mismatch alone would be worth investigating before trusting anything else. A flip-flop count matching the declared registers is the fastest, cheapest check after any synthesis run; a mismatch (extra flops from an accidental latch turned register, or missing flops from a signal optimised away) is a structural problem to catch immediately.
Total cell count and area. Number of cells: 146 and Chip area for module '\alu8': 1512.67 are the two headline numbers Section 2.2 quoted. The area is in the PDK’s native units (square microns for SKY130), summing each cell’s Liberty area field across the netlist.
Do not compare raw cell counts between designs, or between two runs under different strategies, as if cell count alone measured quality. Section 2.2’s comparison showed a smaller count trading directly against timing margin. Cell count and area matter alongside the timing report, never in isolation.
Practice Exercise
A stat report for a supposedly identical rerun of alu8 shows Number of cells: 146 but lists sky130_fd_sc_hd__dfxtp_1 at 9, one fewer than expected. What do you check first, and why is this a bigger concern than a shifted mux or gate count?
Solution
Check which of the three registered outputs (result[7:0], zero, carry_out, ten bits of state) lost its flip-flop, most directly by diffing the netlist’s register names against the previous run, or re-reading the RTL for any change, even one line, in the reset or clocked logic. This matters more than a shifted gate count because combinational cell distribution can legitimately vary between runs through different optimisation choices (as Section 2.2 showed with SYNTH_STRATEGY) without affecting correctness. A missing flip-flop usually means a bit of designed state became combinational, was optimised away as a constant, or was merged incorrectly, any of which is a functional bug rather than a stylistic difference.
Cell counts and area tell you the netlist’s shape. In the next article we go back to the timing side and walk a complete pre-placement OpenSTA report end to end, connecting every field to the setup and hold ideas from the Verilog course.