Module 2: Logic Synthesis ยท 2.5 Synthesis Reports

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.

โ† Why Synthesis-Stage Timing Is Optimistic Reading a Pre-Placement Timing Report โ†’