Each library cell carries an area in library units of the teaching library. The report multiplies each count by its cell area and adds the parts.
Cell | Area (library units) |
|---|---|
NAND2 | 2 |
NOR2 | 2 |
INV | 1 |
These units belong to course.lib, a fictional teaching library. They measure relative cell cost, never a real process.
Mapping replaces generic gates with library cells. The script below synthesises the three-gate example, maps it to course.lib, and proves no generic gate remains.
read_verilog <<EOV
module top(input a, b, c, d, output y);
wire n1, n2;
assign n1 = a & b;
assign n2 = c & d;
assign y = n1 | n2;
endmodule
EOV
read_liberty -lib course.lib
hierarchy -check -top top
synth -top top
abc -liberty course.lib
select -assert-none t:$_AND_
select -assert-none t:$_OR_
check
stat -liberty course.lib
log PASS: mapped netlist holds library cells onlySynthesis lowers the coarse cells to generic gates, and abc maps those to course.lib. After abc, no generic gate remains. The block below is an illustrative layout, numbers invented for this lesson.
illustrative layout, numbers invented for this lesson (an example block, never tool output):
NAND2: count 12 x area 2 = 24 units
NOR2: count 4 x area 2 = 8 units
INV: count 6 x area 1 = 6 units
DFF: count 8 x area 8 = 64 units
total = 24 + 8 + 6 + 64
= 102 area unitsThe design below instantiates two NAND2 cells and one NOR2 cell directly. Its script pins the counts, and the calc block adds the area by hand.
read_verilog <<EOV
module NAND2(input a, b, output y);
assign y = ~(a & b);
endmodule
module NOR2(input a, b, output y);
assign y = ~(a | b);
endmodule
module top(input a, b, c, d, output y);
wire n1, n2;
NAND2 g1 (.a(a), .b(b), .y(n1));
NAND2 g2 (.a(c), .b(d), .y(n2));
NOR2 g3 (.a(n1), .b(n2), .y(y));
endmodule
EOV
hierarchy -check -top top
select -assert-count 2 t:NAND2
select -assert-count 1 t:NOR2
check
stat
log PASS: two NAND2 and one NOR2 instantiate as writtencourse.lib areas: NAND2 2 units, NOR2 2 units (teaching library, not a process)
gate list: 2 NAND2, 1 NOR2
NAND2 part = 2 x 2 = 4 units
NOR2 part = 1 x 2 = 2 units
total = 4 + 2 = 6 area units
NAND2 share = 4 / 6 = 66.67%
NOR2 share = 2 / 6 = 33.33%
66.67 + 33.33 = 100.00The program below repeats the addition and checks the shares. It passes only when the total is 6 units and the shares sum to 100.
import sys
AREAS = {"NAND2": 2, "NOR2": 2}
COUNTS = {"NAND2": 2, "NOR2": 1}
def close(got, want):
return abs(got - want) < 0.005
total = 0
for cell in COUNTS:
total = total + COUNTS[cell] * AREAS[cell]
parts = {}
for cell in COUNTS:
parts[cell] = COUNTS[cell] * AREAS[cell] / total * 100.0
bad = 0
if total != 6:
print("FAIL: total area is " + str(total) + " want 6")
bad = 1
if not close(parts["NAND2"], 66.67):
print("FAIL: NAND2 share is " + str(parts["NAND2"]))
bad = 1
if not close(parts["NOR2"], 33.33):
print("FAIL: NOR2 share is " + str(parts["NOR2"]))
bad = 1
if not close(parts["NAND2"] + parts["NOR2"], 100.0):
print("FAIL: shares do not sum to 100")
bad = 1
if bad != 0:
sys.exit(1)
print("PASS: area 6 units with shares 66.67 and 33.33")An area total counts cell area only. It knows nothing about wire area, which depends on placement and routing that run later.
Library units compare only within one library. The companion nand_only.lib holds only INV, BUF and NAND2, so the same RTL mapped there gives a different total.
NAND2 takes 4 units (66.67%) and NOR2 takes 2 units (33.33%). The shares sum to 100.00.
Wire area and placement effects. The report counts cell area in library units only.