Liberty .lib & LEF — Complete Study Guide
A structured full-day intensive covering Standard Cell Liberty timing/power models, Library Exchange Format physical abstracts, and hands-on tool integration in Cadence Genus synthesis, Cadence Innovus place-and-route, and AMD Vivado — the three frontends you need to master for production physical design.
Liberty (.lib) File — Complete Reference
The Liberty Reference Manual (IEEE Std 1685) defines a text-based format encoding every electrical characteristic of a standard cell: propagation delay, setup/hold constraints, output slew, and power consumption — all as functions of input slew and output load capacitance.
Why Liberty (.lib) Exists
SPICE simulation of a full chip is orders of magnitude too slow for STA. Instead, foundries characterize each cell at multiple PVT corners and store delay/slew as indexed lookup tables in a .lib file. Synthesis and STA tools read this abstract model — never the actual SPICE transistor netlist.
Data encoded in .lib: propagation delay, output transition (slew), setup/hold time, recovery/removal time, leakage power, dynamic switching power, pin capacitance, Boolean logic function, max-fanout/max-cap constraints.
Foundry PDK IP Vendor Custom Block
(TSMC/GF/...) (ARM/Synopsys) (char'd)
.lib (SS/TT/FF) .lib + LEF .lib + LEF
LEF (tech + cell)
| | |
+---------------------+-------------------+
|
+--------------v--------------+
| Genus Synthesis |<-- RTL (Verilog)
| read_libs / set_db lef |<-- SDC constraints
+--------------+--------------+
| Mapped netlist (.v)
+--------------v--------------+
| Innovus Place & Route |<-- Technology LEF
| loadLefFile / read_libs |<-- Cell LEF
+--------------+--------------+
| GDS + SDF + SPEF
+--------------v--------------+
| Tempus / PrimeTime STA | Sign-off timing
+-----------------------------+
.lib File Anatomy — Top-Level Structure
A .lib file is a hierarchical ASCII text format. The outermost block is library() containing global defaults, then cell() blocks for each standard cell, each containing pin() blocks.
library (my_stdcell_tt_0p8v_25c) { /* Library name encodes corner */
/* === Global Unit Declarations === */
technology (cmos);
delay_model : table_lookup; /* NLDM (most common) */
time_unit : "1ns";
voltage_unit : "1V";
current_unit : "1mA";
leakage_power_unit: "1nW";
capacitive_load_unit (1, pf);
/* === Nominal PVT Corner === */
nom_process : 1.0;
nom_voltage : 0.8; /* 0.8V supply */
nom_temperature : 25.0;
/* === Operating Conditions Block === */
operating_conditions (tt_0p8v_25c) {
process : 1.0;
voltage : 0.8;
temperature : 25.0;
}
default_operating_conditions : tt_0p8v_25c;
/* === Default Net Constraints (DRC limits) === */
default_max_fanout : 20.0;
default_max_transition : 0.5; /* ns max slew */
default_input_pin_cap : 0.0;
/* === Wire Load Model (pre-route estimation) === */
wire_load ("medium") {
resistance : 1.0e-3; /* kOhm/um */
capacitance : 1.0e-4; /* pF/um */
slope : 0.5;
fanout_length (1, 0.5) (2, 1.0) (4, 2.5) (8, 6.0);
}
default_wire_load : "medium";
/* === Lookup Table Index Templates === */
lu_table_template (delay_template_5x5) {
variable_1 : input_net_transition; /* row = input slew */
variable_2 : total_output_net_capacitance; /* col = Cload */
index_1 ("0.01, 0.05, 0.1, 0.2, 0.5"); /* ns breakpoints */
index_2 ("0.001, 0.005, 0.01, 0.05, 0.1"); /* pF breakpoints */
}
/* === Cell Definitions === */
cell (INV_X1) { ... }
cell (NAND2_X1){ ... }
cell (DFF_X1) { ... }
}
| Attribute | Typical Value | Meaning |
|---|---|---|
delay_model | table_lookup | NLDM — 2D bilinear interpolation |
delay_model | ccs | CCS — current source waveform model |
nom_voltage | 0.8 | VDD of this characterization corner |
nom_temperature | 25.0 / 125.0 | Temperature (degC) of this corner |
time_unit | "1ns" or "1ps" | All delay values are in this unit |
capacitive_load_unit | (1,pf) | Load capacitance unit |
Operating Conditions & PVT Corners
A single design must be verified across multiple PVT corners (Process/Voltage/Temperature). Each corner has its own .lib file. Slow corners dominate setup analysis; fast corners dominate hold analysis.
| Corner Name | Process | Voltage | Temp | Used For |
|---|---|---|---|---|
tt_0p8v_25c | Typical | 0.8V (nom) | 25C | Simulation reference |
ss_0p72v_125c | Slow | 0.72V (-10%) | 125C | Setup worst-case |
ff_0p88v_m40c | Fast | 0.88V (+10%) | -40C | Hold worst-case |
ss_0p72v_m40c | Slow | 0.72V | -40C | Hold (leakage worst-case) |
ff_0p88v_125c | Fast | 0.88V | 125C | Leakage / EM check |
create_analysis_view with separate delay corners for setup (SS) and hold (FF) rather than loading both libs into the same mode.Wire Load Models (WLM)
Pre-route, there is no real wire. Wire Load Models estimate net capacitance as a function of fanout count. They are statistical averages for a given die area. Used only during synthesis; replaced by real SPEF parasitics after route.
wire_load ("my_chip_wlm") {
resistance : 2.5e-3; /* kOhm/um */
capacitance : 1.8e-4; /* pF/um linear factor from fanout */
area : 0.0;
slope : 0.8; /* pF added per fanout above table */
/* (fanout_count, estimated_wire_length_um) */
fanout_length (1, 1.0) (2, 2.0) (4, 4.5) (8, 9.0) (16, 20.0);
}
wire_load_selection ("auto_select") {
wire_load_from_area (0, 5000, "small");
wire_load_from_area (5000, 50000, "medium");
wire_load_from_area (50000, 1e9, "large");
}
set_wire_load_mode top or none in Genus and rely on post-route SPEF for signoff. WLMs matter most for initial synthesis QoR estimates.NLDM — 2D Lookup Tables
Non-Linear Delay Model (NLDM) stores cell delay and output transition (slew) as 2D tables indexed by input transition time (row) and output load capacitance (column). STA tools bilinearly interpolate between table entries.
cell (INV_X1) {
area : 0.532;
leakage_power : 0.089;
pin (A) {
direction : input;
capacitance : 0.00481; /* pF input pin cap */
rise_capacitance : 0.00481;
fall_capacitance : 0.00481;
max_transition : 0.5; /* DRC: max allowed input slew */
}
pin (ZN) {
direction : output;
function : "!A"; /* Boolean logic function */
max_capacitance : 0.2; /* DRC: max output load pF */
timing () {
related_pin : "A";
timing_sense : negative_unate; /* rising A => falling ZN */
/* Propagation Delay: A rising => ZN falling */
cell_fall (delay_template_5x5) {
index_1 ("0.01, 0.05, 0.10, 0.20, 0.50"); /* input slew (ns) */
index_2 ("0.001, 0.005, 0.010, 0.050, 0.100"); /* Cload (pF) */
values ( \
"0.012, 0.025, 0.040, 0.082, 0.152", \
"0.030, 0.040, 0.052, 0.090, 0.158", \
"0.055, 0.065, 0.075, 0.112, 0.178", \
"0.105, 0.113, 0.122, 0.158, 0.220", \
"0.255, 0.262, 0.270, 0.304, 0.362" \
);
}
/* Propagation Delay: A falling => ZN rising */
cell_rise (delay_template_5x5) {
index_1 ("0.01, 0.05, 0.10, 0.20, 0.50");
index_2 ("0.001, 0.005, 0.010, 0.050, 0.100");
values ( \
"0.015, 0.030, 0.048, 0.095, 0.175", \
"0.035, 0.048, 0.062, 0.105, 0.183", \
"0.062, 0.074, 0.086, 0.128, 0.204", \
"0.115, 0.126, 0.136, 0.176, 0.248", \
"0.270, 0.280, 0.289, 0.326, 0.394" \
);
}
/* Output Transition (slew): ZN falling */
fall_transition (delay_template_5x5) {
index_1 ("0.01, 0.05, 0.10, 0.20, 0.50");
index_2 ("0.001, 0.005, 0.010, 0.050, 0.100");
values ( \
"0.018, 0.038, 0.060, 0.120, 0.220", \
"0.022, 0.040, 0.062, 0.122, 0.222", \
"0.030, 0.046, 0.066, 0.124, 0.224", \
"0.050, 0.062, 0.080, 0.132, 0.228", \
"0.115, 0.124, 0.136, 0.176, 0.250" \
);
}
/* Output Transition: ZN rising */
rise_transition (delay_template_5x5) { /* ... similar values ... */ }
}
}
}
Tools extrapolate (with a warning) if slew or load is outside the table range.
CCS & ECSM — Current-Source Models
CCS (Composite Current Source) is Synopsys's extension; ECSM (Effective Current Source Model) is Cadence's. Both store the output current waveform enabling more accurate noise and crosstalk delay analysis on the RC wire.
- Delay = scalar from 2D table
- Slew = scalar from 2D table
- Fast to compute
- Less accurate for SI/noise
- Default 28nm+ flows
- Delay = waveform-propagated
- Enables crosstalk noise analysis
- 2-4x slower compute
- Required for <16nm signoff
- Larger .lib file size
delay_model : ccs automatically when CCS libs are loaded. Tempus defaults to CCS for signoff when CCS data is present in the .lib.Timing Arcs & Unateness
Every timing() group defines a timing arc — a directed edge from related_pin to the current output pin. Unateness tells the STA tool which input edge polarity causes which output edge polarity.
| timing_sense | Input Rise | Input Fall | Example Cell |
|---|---|---|---|
positive_unate | Output Rise | Output Fall | BUF, AND, OR |
negative_unate | Output Fall | Output Rise | INV, NAND, NOR |
non_unate | Either | Either | XOR, MUX2 data |
none | — | — | Disabled arc |
/* NAND2_X1: ZN = !(A & B) */
pin (ZN) {
function : "!(A & B)";
timing () { related_pin: "A"; timing_sense: negative_unate; ... }
timing () { related_pin: "B"; timing_sense: negative_unate; ... }
}
/* MUX2: Z = S ? B : A -- non_unate from A/B since S can invert effect */
pin (Z) {
function : "(S & B) | (!S & A)";
timing () { related_pin: "A"; timing_sense: non_unate; ... }
timing () { related_pin: "B"; timing_sense: non_unate; ... }
timing () { related_pin: "S"; timing_sense: non_unate; ... }
}
Sequential Cell Timing Arcs — DFF
cell (DFF_X1) {
ff ("IQ", "IQN") { /* internal state variables */
next_state : "D";
clocked_on : "CK"; /* rising-edge triggered */
}
/* === Setup Constraint: D stable BEFORE CK rising edge === */
pin (D) {
direction : input;
timing () {
timing_type : setup_rising; /* check at CK rise */
related_pin : "CK";
rise_constraint (constraint_template_5x5) {
/* row=CK slew, col=D slew */
values ("0.090, 0.100, 0.115, 0.145, 0.210", ...);
}
fall_constraint (constraint_template_5x5) { ... }
}
timing () {
timing_type : hold_rising;
related_pin : "CK";
rise_constraint (constraint_template_5x5) {
values ("-0.010, -0.005, 0.000, 0.010, 0.030", ...);
}
fall_constraint (constraint_template_5x5) { ... }
}
}
/* === Clock-to-Q (Tco) Propagation Arc === */
pin (Q) {
direction : output;
function : "IQ";
timing () {
timing_type : rising_edge; /* Tco: CK rise => Q change */
related_pin : "CK";
timing_sense : non_unate; /* Q can rise or fall */
cell_rise (delay_template_5x5) { ... }
cell_fall (delay_template_5x5) { ... }
rise_transition(delay_template_5x5) { ... }
fall_transition(delay_template_5x5) { ... }
}
}
/* === Async Reset Arcs (if present) === */
pin (RN) { /* active-low async reset */
timing () { timing_type: recovery_rising; related_pin: "CK"; ... }
timing () { timing_type: removal_rising; related_pin: "CK"; ... }
}
}
Power Modeling — Leakage & Internal Power
cell (INV_X1) {
/* Leakage: state-dependent, one entry per input state */
leakage_power () { when : "A"; value : 0.051; } /* A=1, output low */
leakage_power () { when : "!A"; value : 0.042; } /* A=0, output high */
/* Internal Power: energy consumed per switching event */
pin (A) {
internal_power () {
rise_power (power_template_5x5) { /* A 0->1 transition */
index_1 ("0.01, 0.05, 0.1, 0.2, 0.5"); /* input slew */
index_2 ("0.001, 0.005, 0.010, 0.050, 0.1"); /* Cload */
values ("0.121, 0.125, 0.131, 0.152, 0.198", ...);
}
fall_power (power_template_5x5) { /* A 1->0 transition */
values ("0.108, 0.112, 0.118, 0.140, 0.186", ...);
}
}
}
}
P_switching = alpha * C_load * VDD^2 * f (tool computes from pin cap + activity)
P_leakage: sum of leakage_power() values weighted by state probability
pg_pin — Power/Ground Pins & Multi-Supply
In UPF/CPF low-power flows, pg_pin declarations identify which VDD/VSS rail each cell connects to, enabling multi-VDD domain crossing analysis. Level shifters require two supply pins.
cell (LSHD_1V8_0V8) {
pg_pin (VDD18) {
pg_type : primary_power;
voltage_name: VDD18; /* 1.8V supply domain */
}
pg_pin (VDD08) {
pg_type : primary_power;
voltage_name: VDD08; /* 0.8V supply domain */
}
pg_pin (VSS) {
pg_type : primary_ground;
voltage_name: VSS;
}
pin (A) { direction: input; related_power_pin: "VDD18"; ... }
pin (Z) { direction: output; related_power_pin: "VDD08"; ... }
}
/* Always-On cell: remains powered during domain power-down */
cell (AOBUF_X1) {
pg_pin (VDD) {
pg_type : primary_power;
voltage_name: VDD;
always_on : true; /* stays powered during power-down */
}
...
}
Session 1 Lab Exercises
- Lab 1.1 — Open the SS corner .lib for your PDK INV cell. Find the cell_fall delay for input slew = 0.1 ns, Cload = 0.01 pF. Manually bilinearly interpolate and compare with tool output.
- Lab 1.2 — Identify a DFF cell in the .lib. List all timing arc types (setup, hold, Tco, recovery, removal). Note which are missing and explain why.
- Lab 1.3 — In Genus:
set_db library {ss.lib}, elaborate a design, then runreport_lib INV_X1. Verify timing tables match the .lib file manually. - Lab 1.4 — Find a cell with non_unate timing sense (XOR or MUX). In Tempus, trace which edges are propagated on that arc and explain worst-case slack analysis.
- Lab 1.5 — Compute average leakage for 100 INV_X1 + 50 NAND2_X1 at 50% toggle rate. Compare with
report_power -leakage_onlyin Genus.
LEF (Library Exchange Format) — Complete Reference
LEF defines the physical geometry of each standard cell and the technology layer stack — exactly what P&R needs to position cells, route wires, and prevent DRC violations. LEF is geometry only; it contains no timing or power data.
LEF Purpose, Versions & Two-File Model
Technology LEF — metal stack, via rules, design rules (spacing, width, enclosure). Provided by foundry as part of PDK. Usually: tech.lef
Cell LEF — physical abstract (bounding box, pin locations, obstruction layers) of each cell/macro/IP. Usually: stdcell.lef, sram.lef
| LEF Version | Key Additions | Typical Use |
|---|---|---|
| 5.4 | Basic layers, macros, vias | Legacy 180nm-90nm PDKs |
| 5.5 | Via Rules, Nondefault Rules (NDR) | 65nm - 40nm |
| 5.6 | Site alignment, DFM rules | 28nm |
| 5.7 | Antenna ratios per layer, new DRC rules | 16nm - 7nm |
| 5.8 | Cut class, LEF58 properties (2D spacing) | 7nm - 3nm (current) |
loadLefFile {tech.lef stdcell.lef sram.lef} — Technology LEF must be first in the list.Technology LEF — LAYER Definitions
VERSION 5.8 ; UNITS DATABASE MICRONS 1000 ; /* 1 LEF unit = 1nm; coordinates in nm */ END UNITS /* === Implant / Non-routing layers === */ LAYER DIFF TYPE IMPLANT ; END DIFF LAYER POLY TYPE MASTERSLICE ; END POLY /* === Contact layer (POLY/DIFF to M1) === */ LAYER CONT TYPE CUT ; WIDTH 0.100 ; /* contact size 100nm x 100nm */ SPACING 0.140 ; /* min contact-to-contact spacing */ ENCLOSURE ABOVE POLY 0.060 0.060 ; ENCLOSURE ABOVE DIFF 0.005 0.090 ; END CONT /* === Metal 1 (local, horizontal preferred) === */ LAYER M1 TYPE ROUTING ; DIRECTION HORIZONTAL ; /* preferred routing direction */ PITCH 0.200 ; /* track pitch 200nm */ WIDTH 0.100 ; /* minimum metal width 100nm */ SPACING 0.100 ; /* min edge-to-edge metal spacing 100nm */ MINAREA 0.020 ; /* minimum metal area um^2 */ THICKNESS 0.100 ; /* for RC extraction model */ RESISTANCE RPERSQ 0.038 ; /* Ohm/sq sheet resistance */ CAPACITANCE CPERSQDIST 1.05e-4 ; /* pF/um^2 area cap */ EDGECAPACITANCE 6.0e-5 ; /* pF/um edge fringe cap */ END M1 /* === VIA12 cut layer (M1 to M2) === */ LAYER VIA12 TYPE CUT ; WIDTH 0.120 ; SPACING 0.140 ; ENCLOSURE ABOVE M1 0.040 0.040 ; ENCLOSURE BELOW M2 0.040 0.040 ; END VIA12 /* === Metal 2 (vertical preferred) === */ LAYER M2 TYPE ROUTING ; DIRECTION VERTICAL ; PITCH 0.200 ; WIDTH 0.100 ; SPACING 0.100 ; RESISTANCE RPERSQ 0.034 ; END M2
[M5 horizontal] =========================== Global routing
|VIA45|
[M4 vertical] |||||||||||||||||||||||||||
|VIA34|
[M3 horizontal] =========================== Semi-global
|VIA23|
[M2 vertical] |||||||||||||||||||||||||||
|VIA12|
[M1 horizontal] =========================== Local routing
|CONT |
------Active (DIFF / POLY)------------------
Technology LEF — VIA & VIARULE GENERATE
/* === Single-cut fixed VIA === */
VIA VIA12_1X1 DEFAULT
LAYER VIA12 ;
RECT -0.060 -0.060 0.060 0.060 ; /* cut geometry (um) */
LAYER M1 ;
RECT -0.100 -0.100 0.100 0.100 ; /* bottom metal enclosure */
LAYER M2 ;
RECT -0.100 -0.100 0.100 0.100 ; /* top metal enclosure */
END VIA12_1X1
/* === 2x2 cut array VIA (double via for reliability) === */
VIA VIA12_2X2
LAYER VIA12 ;
RECT -0.200 -0.060 -0.080 0.060 ; /* left cut */
RECT 0.080 -0.060 0.200 0.060 ; /* right cut */
LAYER M1 ;
RECT -0.260 -0.100 0.260 0.100 ;
LAYER M2 ;
RECT -0.260 -0.100 0.260 0.100 ;
END VIA12_2X2
/* === VIARULE GENERATE: router auto-creates arrays === */
VIARULE VIA12_GEN GENERATE
LAYER M1 ;
ENCLOSURE 0.040 0.040 ;
WIDTH 0.100 TO 10.000 ;
LAYER VIA12 ;
RECT -0.060 -0.060 0.060 0.060 ; /* single cut shape */
SPACING 0.200 BY 0.200 ; /* cut pitch (x, y) */
LAYER M2 ;
ENCLOSURE 0.040 0.040 ;
WIDTH 0.100 TO 10.000 ;
END VIA12_GEN
Technology LEF — SPACING Rules & NDR
/* Width-dependent spacing (long-range spacing rule) */
LAYER M3
TYPE ROUTING ;
DIRECTION HORIZONTAL ;
PITCH 0.300 ; WIDTH 0.120 ;
SPACINGTABLE
PARALLELRUNLENGTH 0.000 0.500 1.000 2.000 ; /* wire run length (um) */
WIDTH 0.120 0.120 0.140 0.160 0.200 ; /* spacing vs run length */
WIDTH 0.240 0.160 0.180 0.200 0.240 ; /* wider wire needs more */
WIDTH 0.480 0.200 0.220 0.240 0.280 ;
;
MINSTEP 0.060 INSIDECORNER ;
END M3
/* Non-Default Rule: 2x width + 2x spacing for clock nets */
NONDEFAULTRULE clock_ndr
HARDSPACING ;
LAYER M3 ; WIDTH 0.240 ; SPACING 0.240 ; END
LAYER M4 ; WIDTH 0.240 ; SPACING 0.240 ; END
LAYER M5 ; WIDTH 0.240 ; SPACING 0.240 ; END
VIA VIA12_2X2 ; /* double-via at each layer transition */
VIA VIA23_2X2 ;
END clock_ndr
setNDRRule clock_ndr -nets {CLK*}Cell LEF — MACRO Block
MACRO INV_X1 /* MUST match .lib cell() name */
CLASS CORE ; /* standard cell placed in row */
ORIGIN 0.000 0.000 ; /* always 0,0 for std cells */
FOREIGN INV_X1 0.000 0.000 ; /* GDS cell reference name */
SIZE 0.532 BY 2.400 ; /* WIDTH x HEIGHT in um */
SYMMETRY X Y R90 ; /* legal orientations */
SITE core ; /* row site name from tech LEF */
/* === Input Pin === */
PIN A
DIRECTION INPUT ;
USE SIGNAL ;
PORT
LAYER M1 ;
RECT 0.090 1.800 0.200 2.000 ; /* access rectangle (um) */
END
END A
/* === Output Pin === */
PIN ZN
DIRECTION OUTPUT ;
USE SIGNAL ;
PORT
LAYER M1 ;
RECT 0.350 0.400 0.460 1.200 ;
END
END ZN
/* === Power/Ground Pins (full rail spans) === */
PIN VDD
DIRECTION INOUT ; USE POWER ; SHAPE ABUTMENT ;
PORT
LAYER M1 ;
RECT 0.000 2.200 0.532 2.400 ; /* full top power rail */
END
END VDD
PIN VSS
DIRECTION INOUT ; USE GROUND ; SHAPE ABUTMENT ;
PORT
LAYER M1 ;
RECT 0.000 0.000 0.532 0.200 ; /* full bottom ground rail */
END
END VSS
/* === Obstruction: internal layers blocked to router === */
OBS
LAYER POLY ;
RECT 0.050 0.200 0.480 2.200 ;
LAYER DIFF ;
RECT 0.050 0.280 0.480 2.120 ;
LAYER M1 ;
RECT 0.050 0.200 0.480 2.200 ; /* internal M1 blocked */
END
END INV_X1
Cell LEF — PIN Definition Details
| PIN Keyword | Values | Meaning |
|---|---|---|
DIRECTION | INPUT / OUTPUT / INOUT / FEEDTHRU | Signal direction (informational) |
USE | SIGNAL / POWER / GROUND / CLOCK / TIEOFF / ANALOG / SCAN / RESET | Pin type; affects router treatment |
SHAPE | ABUTMENT / RING / FEEDTHRU | Power pin topology hint |
MUSTJOIN | pin_name | These pins must connect to same net |
ANTENNADIFFAREA | float | Diffusion area for antenna calc |
ANTENNAGATEAREA | float | Gate oxide area for antenna calc |
Cell LEF — OBS (Obstruction Layers)
OBS (Obstruction) blocks tell the router: "this region is internally used — do not route here." Critical for SRAM, IO pads, PLLs with internal routing.
/* SRAM 512x64 macro: entire interior blocked M1-M5 */
OBS
LAYER M1 ;
RECT 0.000 0.000 200.000 100.000 ;
LAYER M2 ;
RECT 0.000 0.000 200.000 100.000 ;
LAYER M3 ;
RECT 0.000 0.000 200.000 100.000 ;
LAYER M4 ;
RECT 0.000 0.000 200.000 100.000 ;
LAYER M5 ;
/* leave channels at edges for power ring connection */
RECT 5.000 0.000 195.000 100.000 ;
END
Antenna Rules in LEF
Antenna Effect: During plasma etch, long floating metal wires accumulate charge. If the metal area / gate area ratio exceeds the foundry limit, the gate oxide can be permanently damaged. LEF specifies allowed antenna ratios per layer, and cell LEF specifies protective diffusion area on input pins.
/* Tech LEF: maximum allowed cumulative antenna ratios */
LAYER M2
TYPE ROUTING ;
ANTENNACUMAREARATIO 1000 ; /* metal area / gate area limit */
ANTENNACUMDIFFSIDEARATIO 800 ;
ANTENNACUMROUTINGPLUSCUT 1200 ;
ANTENNAMODEL OXIDE1 ;
END M2
/* Cell LEF PIN: protective diffusion on input pin */
PIN A
DIRECTION INPUT ;
ANTENNADIFFAREA 0.200 ; /* um^2 diffusion (acts as charge sink) */
ANTENNAGATEAREA 0.048 ; /* gate area this pin connects to */
ANTENNAPARTIALCUTAREA 0.006 ; /* via cut area for cumulative calc */
PORT
LAYER M1 ;
RECT 0.090 1.800 0.200 2.000 ;
END
END A
addAntennaFix -diode_cell ANT_DIODE_X1 -diode_pin ANODE -max_routing_layer M5MACRO CLASS Types & SYMMETRY
| CLASS | Sub-Type | P&R Treatment |
|---|---|---|
CORE | — | Standard cell, placed in row, abuts power rail |
CORE | SPACER | Filler cell, inserted to fill gaps |
CORE | ANTENNACELL | Diode cell for antenna fixing |
CORE | WELLTAP | N-well/P-tap tie cell (auto-inserted at max spacing) |
BLOCK | — | Hard macro (SRAM, PLL, IO pad); not row-placed |
BLOCK | BLACKBOX | IP block, internals not visible to router |
PAD | INPUT/OUTPUT/INOUT/POWER/SPACER | IO pad cells placed on chip boundary ring |
ENDCAP | PRE/POST/TOPLEFT/... | Row end-cap cells for DRC at row boundaries |
COVER | BUMP | Flip-chip C4 bump cell |
.lib vs LEF — What Lives Where
| Data Type | .lib (Liberty) | LEF |
|---|---|---|
| Propagation delay | YES: cell_rise/fall tables | NO |
| Setup / hold time | YES: constraint tables | NO |
| Output slew | YES: transition tables | NO |
| Leakage / internal power | YES: leakage_power / internal_power | NO |
| Boolean function | YES: function : "!(A&B)" | NO |
| Pin capacitance | YES: capacitance : 0.005 | NO |
| Cell bounding box | NO | YES: SIZE w BY h |
| Pin metal geometry | NO | YES: PIN PORT LAYER RECT |
| Obstruction geometry | NO | YES: OBS block |
| Layer stack (metal pitch) | NO | YES: Technology LEF LAYER |
| Via geometry | NO | YES: VIA / VIARULE |
| Antenna ratio limits | NO | YES: ANTENNACUMAREARATIO in LAYER |
| Cell class / symmetry | NO | YES: CLASS, SYMMETRY, SITE |
Session 2 Lab Exercises
- Lab 2.1 — Open your PDK tech.lef. List all routing layers and preferred directions. Calculate minimum track pitch X and Y for M1 and M2. Verify against the PITCH keyword.
- Lab 2.2 — Open the cell LEF for INV_X1. Measure width and height in um. Count PORT rectangles on M1 for each signal pin. Verify every signal pin has at least one M1 rect.
- Lab 2.3 — In Innovus:
loadLefFile {tech.lef stdcell.lef}, thendbget [dbget -p head.lefCells.name INV_X1].pins.name. Verify output matches LEF PIN declarations. - Lab 2.4 — Identify a MACRO CLASS BLOCK (SRAM or PLL) in your LEF. Map which layers are covered by OBS and which have accessible pins. Draw a cross-section sketch.
- Lab 2.5 — After global route in Innovus, run
checkAntennaViolation. Count violations. RunaddAntennaFix. Re-run and report before/after counts.
Tool Integration — Reading .lib and LEF
Every P&R and synthesis tool has specific commands to load .lib and LEF. Small mistakes in loading order or file format can silently corrupt an entire flow. This session covers exact commands, pitfalls, and debug workflows for all three frontends.
Genus Synthesis — read_libs / set_db Flow
## === Genus lib_setup.tcl =====================================
## 1. Set search paths
set_db lib_search_path {
/pdkroot/libs/tt_0p8v_25c/
/pdkroot/libs/ss_0p72v_125c/
/pdkroot/libs/ff_0p88v_m40c/
/ip/sram/lib/
}
## 2. Target library -- cells available for synthesis/mapping
## Provide .lib filenames (not full paths if using lib_search_path)
set_db library {
stdcell_tt_0p8v_25c.lib
sram_512x64_tt_0p8v_25c.lib
}
## 3. Link library -- hierarchical black-box resolution
set_db link_library {
stdcell_tt_0p8v_25c.lib
sram_512x64_tt_0p8v_25c.lib
analog_block_tt.lib
* /* wildcard: also search already-loaded libs */
}
## 4. LEF files (for area estimation and cell height checking)
set_db lef_library {
/pdkroot/lef/tech_5p8.lef
/pdkroot/lef/stdcell.lef
/ip/sram/lef/sram_512x64.lef
}
## 5. Read / elaborate RTL
read_hdl -sv { rtl/top.sv rtl/datapath.sv rtl/ctrl.sv }
elaborate top
## 6. Apply SDC timing constraints
read_sdc constraints/top.sdc
## 7. Synthesize
syn_gen /* generic synthesis */
syn_map /* technology mapping */
syn_opt /* optimization */
## 8. Verify library loading
report_lib -list /* lists all loaded lib names */
report_lib stdcell_tt_0p8v_25c /* detailed info */
report_timing -nworst 10
report_power
## 9. Write outputs
write_hdl > outputs/top_mapped.v
write_sdc > outputs/top_mapped.sdc
set_db library is only correct for MCMM synthesis. In single-mode, use only the target corner (SS for setup analysis). Mixing corners causes incorrect timing.Genus — MCMM Multi-Corner Multi-Mode Setup
## === Genus MCMM Setup ========================================
## Create library sets per corner
create_library_set -name SS_libs \
-libraries { stdcell_ss_0p72v_125c.lib sram_512x64_ss.lib }
create_library_set -name FF_libs \
-libraries { stdcell_ff_0p88v_m40c.lib sram_512x64_ff.lib }
## Create constraint mode
create_constraint_mode -name func_mode -sdc_files { constraints/top.sdc }
## Setup analysis view: SS corner, functional mode
create_delay_corner -name SS_dc \
-library_set SS_libs \
-opcond ss_0p72v_125c
create_analysis_view -name setup_view \
-constraint_mode func_mode \
-delay_corner SS_dc
## Hold analysis view: FF corner
create_delay_corner -name FF_dc \
-library_set FF_libs \
-opcond ff_0p88v_m40c
create_analysis_view -name hold_view \
-constraint_mode func_mode \
-delay_corner FF_dc
## Activate both views
set_analysis_view -setup {setup_view} -hold {hold_view}
## Synthesize
syn_gen -effort high
syn_map -effort high
syn_opt -effort high
## Report per-view results
report_timing -view setup_view -nworst 5
report_timing -view hold_view -nworst 5
Innovus P&R — Loading LEF & Lib Files
## === Innovus init_design.tcl =================================
## 1. LEF: Technology LEF MUST be first, then cell LEFs
set lef_files {
/pdkroot/lef/tech_5p8.lef ;# Technology LEF -- FIRST
/pdkroot/lef/stdcell.lef ;# Standard cell abstracts
/ip/sram/lef/sram_512x64.lef ;# SRAM macro LEF
/io/lef/io_pads.lef ;# IO pad LEF
}
loadLefFile $lef_files
## 2. Liberty for timing analysis
set lib_ss { /pdkroot/libs/ss/stdcell_ss.lib /ip/sram/lib/sram_ss.lib }
set lib_ff { /pdkroot/libs/ff/stdcell_ff.lib /ip/sram/lib/sram_ff.lib }
## 3. Read mapped netlist from Genus
read_netlist outputs/top_mapped.v
## 4. Read timing constraints
read_sdc outputs/top_mapped.sdc
## 5. Create MCMM views
create_library_set -name SS_libs -timing [list {*}$lib_ss]
create_library_set -name FF_libs -timing [list {*}$lib_ff]
create_constraint_mode -name func_mode -sdc_files {outputs/top_mapped.sdc}
create_delay_corner -name SS_dc -library_set SS_libs \
-opcond_library stdcell_ss -opcond ss_0p72v_125c
create_delay_corner -name FF_dc -library_set FF_libs \
-opcond_library stdcell_ff -opcond ff_0p88v_m40c
create_analysis_view -name setup_av -constraint_mode func_mode -delay_corner SS_dc
create_analysis_view -name hold_av -constraint_mode func_mode -delay_corner FF_dc
set_analysis_view -setup {setup_av} -hold {hold_av}
## 6. Initialize design (commits all loaded data)
init_design
Innovus — LEF Debug Techniques
## === LEF inspection commands =================================
## List all loaded cells from LEF
dbget head.allCells.name
## Get cell properties
set cell [dbget head.allCells.name INV_X1 -p]
dbget $cell.width
dbget $cell.height
dbget $cell.class
## List all pins and their layer/geometry
foreach pin [dbget $cell.terms] {
set nm [dbget $pin.name]
foreach shape [dbget $pin.shapes] {
puts "$nm layer:[dbget $shape.layer.name] rect:[dbget $shape.rect]"
}
}
## Check OBS geometry
foreach obs [dbget $cell.obstructions] {
puts "OBS layer:[dbget $obs.layer.name] rect:[dbget $obs.rect]"
}
## Query technology LEF layers
dbget head.lefLayers.name
set m1 [dbget head.lefLayers.name M1 -p]
dbget $m1.minWidth ; dbget $m1.pitch ; dbget $m1.direction
## Check lib/lef cell name consistency
set lib_cells [get_db lib_cells */INV_X1]
set lef_cells [dbget head.allCells.name]
foreach lc $lib_cells {
set cn [lindex [split [get_db $lc .name] /] end]
if { $cn ni $lef_cells } { puts "MISSING in LEF: $cn" }
}
| LEF Error | Root Cause | Fix |
|---|---|---|
Undefined layer X | Cell LEF loaded before Tech LEF | Always load tech.lef first |
MACRO not found | Cell in netlist has no LEF MACRO | Add missing cell to cell LEF |
Overlapping pins | PIN PORT rect overlaps OBS | Adjust OBS to exclude pin access area |
Cell height mismatch | LEF SIZE HEIGHT not a multiple of row height | Fix HEIGHT to exact row height multiple |
SITE not found | Cell LEF references undefined site | Add SITE block to tech LEF |
AMD Vivado — IP-XACT, Liberty & XDC
Vivado targets Xilinx/AMD FPGAs — it does NOT read foundry .lib files. Instead it uses:
1. IP-XACT (component.xml): XML metadata wrapping a Vivado IP, including bus interfaces, parameters, and links to XDC constraint files.
2. XDC (Xilinx Design Constraints): Timing constraints in SDC-like format. Vivado's equivalent of .sdc applied to the FPGA primitive timing database (built into the tool).
3. Device timing database: AMD embeds timing models for every FPGA primitive (LUT, FF, DSP48, BRAM, etc.) internally — equivalent to .lib but not user-visible.
## === Vivado: Package custom IP block ==========================
## Create IP project
create_project my_ip ./ip_project -part xczu3eg-sfvc784-1-e
## Add RTL sources
add_files -norecurse rtl/my_block.v
add_files -fileset constrs_1 -norecurse constraints/my_block.xdc
## Package IP (creates IP-XACT component.xml)
ipx::package_project -root_dir ./my_ip_packaged \
-vendor mycompany -library user -taxonomy /UserIP
## Set IP-XACT metadata
set ip [ipx::current_core]
set_property NAME my_custom_block $ip
set_property VERSION 1.0 $ip
set_property DISPLAY_NAME "My Custom Block" $ip
## Save
ipx::save_core $ip
## === XDC Timing Constraints (my_block.xdc) ====================
## Clock definition
create_clock -period 10.000 -name sys_clk [get_ports clk]
## Generated clock from MMCM
create_generated_clock -name div2_clk \
-source [get_pins mmcm_inst/CLKIN1] \
-divide_by 2 [get_pins mmcm_inst/CLKOUT0]
## I/O timing
set_input_delay -clock sys_clk -max 2.0 [get_ports data_in*]
set_input_delay -clock sys_clk -min -0.5 [get_ports data_in*]
set_output_delay -clock sys_clk -max 1.5 [get_ports data_out*]
## Exceptions
set_false_path -from [get_clocks sys_clk] -to [get_clocks fast_clk]
set_multicycle_path -setup 2 -from [get_cells slow_data_reg*]
set_multicycle_path -hold 1 -from [get_cells slow_data_reg*]
set_false_path -from [get_ports rst_n]
## Physical constraints (equivalent of LEF SITE/placement)
set_property LOC RAMB36_X0Y0 [get_cells bram_inst]
set_property PACKAGE_PIN T14 [get_ports led[0]]
set_property IOSTANDARD LVCMOS33 [get_ports {led[*]}]
set_input_delay/set_output_delay in XDC to model timing at the interface..lib & LEF Quality Impact on QoR
| Problem | Root Cause | Symptom | Fix |
|---|---|---|---|
| Post-route timing worse than post-synth | WLM too optimistic | Positive pre-route, negative post-route slack | Use pessimistic WLM or run with real SPEF immediately |
| Setup fails only at SS corner | Wrong lib loaded (TT instead of SS) | WNS=0 in one mode, -2ns in another | Verify report_operating_conditions |
| Hold degraded after buffer insertion | Wrong hold buffer timing arc | Hold WNS degrades during ECO | Use dedicated hold bufs; verify hold arcs in .lib |
| Placement density too high | LEF SIZE too small | Router congestion, DRC in OBS | Re-characterize SIZE from actual GDS |
| Router cannot connect pin | LEF PIN PORT missing/blocked | Unconnected pin in DRC | Verify OBS vs PIN overlap; add accessible PORT |
| Power exceeds budget by 30% | Leakage from wrong state in .lib | report_power inflated | Verify leakage_power(when) covers all states |
Common .lib Debug Techniques
## === Genus: library verification ============================
report_lib -list ;# all loaded libs
report_operating_conditions ;# active corner
get_db [get_db lib_cells */INV_X1] .area
get_db [get_db lib_cells */INV_X1] .total_leakage_power
## Check timing arc data
set arc [get_db lib_timing_arcs {stdcell_tt/INV_X1:A->ZN}]
get_db $arc .timing_sense
get_db [get_db $arc .cell_fall_table] .values
## === Tempus: signoff timing debug ============================
read_db post_route.dat
read_spef outputs/top.spef
read_sdc constraints/top.sdc
## Report with lib interpolation details
report_timing -path_type full -input_pins -nets \
-lib_lookup -lib_lookup_details > timing_debug.rpt
## Check for missing constraints
check_timing -all_clocks -verbose > check_timing.log
| .lib Error | Likely Cause | Action |
|---|---|---|
Cannot find cell X | Name mismatch between netlist and .lib | Check cell() block name vs netlist module name |
Extrapolating timing table | Slew or Cload outside index range | Fix DRC violations (max_slew, max_cap) or extend table |
No timing arc from A to Z | Missing timing() group or wrong timing_sense | Re-check .lib characterization for that pin pair |
Negative setup time | Re-characterization bug in setup table | Validate SPICE simulation for that corner |
Undefined operating condition | opcond name mismatch | Match default_operating_conditions name exactly |
Common LEF Debug Techniques
## === Verify LEF after loading =================================
## Check all technology layers
foreach layer [dbget head.lefLayers] {
puts "[dbget $layer.name] type=[dbget $layer.type] \
width=[dbget $layer.minWidth]"
}
## Verify cell count
puts "Loaded cells: [llength [dbget head.allCells]]"
## Check placement site consistency
foreach cell [dbget head.stdCells] {
if { [dbget $cell.site.name] ne "core" } {
puts "Wrong site: [dbget $cell.name]"
}
}
## Run DRC checks
verifyConnectivity -type all -error 1000 > connectivity.rpt
verifyGeometry -minSpacing -minWidth -minArea > geometry.rpt
checkAntennaViolation -report antenna.rpt
## Fix antennas automatically
addAntennaFix -diode_cell ANT_DIODE_X1 -diode_pin ANODE \
-max_routing_layer M5 -no_add_jumper false
## Debug an unrouted net
set net [dbget head.nets.name my_signal -p]
puts "Unrouted: [dbget $net.isUnrouted]"
puts "Pins: [dbget $net.instTerms.term.name]"
Session 3 Lab Exercises
- Lab 3.1 (Genus) — Synthesize a small RTL using SS corner. Switch to TT and re-synthesize. Compare: cell count, area, WNS, TNS. Document differences.
- Lab 3.2 (Genus MCMM) — Set up 2-view MCMM (SS for setup, FF for hold). Run
syn_opt. Report setup WNS and hold WNS per view. Observe how the tool balances both. - Lab 3.3 (Innovus) — Load an Innovus DB with tech LEF intentionally loaded LAST (wrong order). Observe error messages. Fix the order. Document what changed.
- Lab 3.4 (Innovus) — After global route, run
verifyGeometry+checkAntennaViolation. Count violations. RunaddAntennaFix. Report before/after counts. - Lab 3.5 (Vivado) — Package a simple 8-bit counter as IP using
ipx::package_project. Add XDC with one clock constraint and one false path. Verify in Vivado timing report that both constraints apply.
Knowledge Check — 20 Questions
Click an answer option to reveal the explanation. Target: 16/20 before moving on.