Generic Cells Versus Standard Cells
The first article in this section said synthesis optimises structure before choosing parts. This one shows what that looks like in the tool.
Open a raw Yosys netlist right after synth runs, before abc touches it, and you see gates that exist in no PDK: $_AND_, $_MUX_, $_DFF_P_. No fab can build a $_AND_. It is Yosys’s internal shorthand. So why does synthesis pass through a stage full of fictional gates before producing anything a fab could use?
Two libraries, two purposes
Yosys works with two different notions of cell:
- Generic cells: Yosys’s own internal, technology-independent primitives (
$_AND_,$_OR_,$_NOT_,$_MUX_,$_DFF_P_and so on). They exist purely as a representation for the optimiser. They have no area, no delay and no pin capacitance, only Boolean or register semantics and a name. - Standard cells: the physical cells a specific PDK provides, each backed by a Liberty timing model and a LEF footprint (both in Section 2.3).
sky130_fd_sc_hd__nand2_1is a standard cell.$_AND_is not.
The synth pass and its family of sub-passes (opt, techmap, flatten and friends) do all their restructuring and logic-level optimisation in terms of generic cells. Only the final abc -liberty <path-to-.lib> call, the technology mapping from the first article, converts generic cells into standard cells selected from the Liberty file you hand it.
Why not optimise directly on real cells?
Because doing the heavy optimisation against real cells would tie every decision to one library and make every pass more complicated for no benefit. Two reasons the separation pays:
- Technology independence. The same generic optimisation works whether the target is SKY130, another open PDK, or an FPGA’s LUT fabric. The restructuring passes (constant propagation, redundancy elimination,
ifandcaseflattening, the sharing decisions from the previous article) do not need to know what the final cells look like. Mapping is a separate, swappable final step. - Simpler optimisation. “Is this restructuring an improvement?” is a much simpler question when every generic gate counts as equally cheap. Once real area and delay from a Liberty file enter, every decision becomes a cost trade, which is better solved once, by ABC, during dedicated mapping than repeatedly during every earlier pass.
This is the “structure first, parts second” idea from the first article, seen from the implementation side. Structure is decided against a fictional, cost-free library; parts are chosen against the real one, once, at the end.
Generic output next to mapped output
A small AND-OR-INVERT function, y = NOT((a AND b) OR c), at both stages. First, Yosys’s generic netlist (abbreviated, in the style of a write_verilog dump of the pre-abc design):
module \aoi_example(a, b, c, y);
wire _00_;
wire _01_;
$_AND_ _g1_ (
.A(a), .B(b), .Y(_00_)
);
$_OR_ _g2_ (
.A(_00_), .B(c), .Y(_01_)
);
$_NOT_ _g3_ (
.A(_01_), .Y(y)
);
endmodule
Note the cell names, $_AND_, $_OR_, $_NOT_: internal shorthand with no area or timing. Now the same design after abc -liberty sky130_fd_sc_hd.lib:
module \aoi_example(a, b, c, y);
sky130_fd_sc_hd__and2_1 _g1_ (
.A(a), .B(b), .X(_00_)
);
sky130_fd_sc_hd__or2_1 _g2_ (
.A(_00_), .B(c), .X(_01_)
);
sky130_fd_sc_hd__inv_1 _g3_ (
.A(_01_), .Y(y)
);
endmodule
Or, and this is the realistic outcome since the SKY130 library contains a compound AND-OR-INVERT cell for exactly this function, ABC may cover the whole three-gate structure with one cell:
module \aoi_example(a, b, c, y);
sky130_fd_sc_hd__a21oi_1 _g1_ (
.A1(a), .A2(b), .B1(c), .Y(y)
);
endmodule
a21oi reads as “2-input AND, OR, invert”, the three-gate function collapsed into one physical cell with better area and delay than three discrete gates. This is the covering choice mapping exists to make, and it is only possible because the PDK offers that compound cell, which previews the next section: what is in a standard cell library, and how synthesis knows what each cell costs.
Do not be alarmed by $_DFF_P_ and similar names in early-stage output; those are generic cells from before mapping, not a missing-library error. A $-prefixed cell in the final netlist after abc has run is the real red flag (Section 2.5’s checklist): it usually means some logic failed to map.
Practice Exercise
You are handed a post-synthesis netlist and asked to confirm it is fully mapped. Grepping for cell types you see sky130_fd_sc_hd__nand2_1, sky130_fd_sc_hd__inv_1, sky130_fd_sc_hd__dfxtp_1, and one line reading $_DFF_P_. What does the last line tell you, and what do you do next?
Solution
A $_DFF_P_ surviving into what should be the final netlist means at least one flip-flop was never mapped; it is still a generic Yosys cell, not a real sky130_fd_sc_hd__dfxtp_1. This is not cosmetic: a generic cell has no layout, no LEF footprint and no Liberty timing, so nothing downstream (placement, routing, STA) can do anything with it. Go back to the synthesis log and check whether dfflibmap, the step that maps generic flip-flops to the library’s sequential cells, ran and completed without errors. A skipped or failed dfflibmap is the most common cause of a stray unmapped flip-flop.
Section 2.1 covered the ideas behind mapping. In the next article, Section 2.2 puts them to work: the actual Yosys script OpenLane runs, command by command, on the course’s reference ALU.