HomeSTA CourseDay 5
DAY 5 · STA FUNDAMENTALS

Liberty Files and Timing Arcs

By EcrioniX · Updated June 2026

Every delay number you see in a timing report comes from a Liberty (.lib) file. Liberty is the standard-cell timing database that tells STA tools how fast each gate switches, what slew rates it produces, and what setup/hold constraints each flip-flop imposes. Understanding how Liberty files are structured — and how STA tools query them — is the difference between guessing at timing results and actually understanding them.

1. What a Liberty file is

A Liberty (.lib) file is a plain-text timing database provided by your standard cell library vendor (e.g., TSMC, Samsung, GlobalFoundries). Every cell in the library — inverters, AND gates, flip-flops, MUXes, memories — has an entry in the .lib file describing its timing, power, and area characteristics.

The STA tool reads the .lib file alongside your gate-level netlist. For every cell instance in the design, the tool looks up that cell’s timing arcs in the Liberty database, queries the appropriate delay given the actual input slew and output load, and uses that delay to compute path arrival times.

A typical 28nm standard cell library has one .lib file per PVT corner — so you might have sc9_ss_0p81v_125c.lib (slow-slow corner), sc9_tt_1p0v_25c.lib (typical), and sc9_ff_1p1v_n40c.lib (fast-fast), plus many more combinations.

Netlist (.v) Gate instances Connectivity Liberty (.lib) Delay tables Timing arcs SDC (.sdc) Clock defs Constraints STA Tool (PrimeTime) Timing report Slack STA Tool Inputs Liberty is the cell timing database — without it, STA cannot compute any delay

2. Liberty file structure

Liberty uses a hierarchical block syntax. The top level is the library block; inside it are cell blocks; inside those are pin blocks; inside pin blocks are timing groups with the actual delay tables.

Liberty file structure — annotated skeleton
/* ── Top-level library block ── */
library (sc9_tt_1p0v_25c) {

  /* Library-level attributes */
  technology             (cmos);
  delay_model            : table_lookup;   /* NLDM */
  time_unit              : "1ns";
  voltage_unit           : "1V";
  capacitive_load_unit   (1, pf);
  nom_process            : 1.0;
  nom_voltage            : 1.0;
  nom_temperature        : 25;

  /* Default output transition (slew) thresholds */
  slew_lower_threshold_pct_rise : 20.0;
  slew_upper_threshold_pct_rise : 80.0;

  /* Operating conditions block */
  operating_conditions (typical) {
    process     : 1.0;
    voltage     : 1.0;
    temperature : 25;
  }

  /* ── Cell block ── */
  cell (AND2X2) {
    area : 4.32;

    /* ── Pin block: output ── */
    pin (Z) {
      direction    : output;
      function     : "(A*B)";
      max_fanout   : 16;

      /* ── Timing arc: A → Z (combinational) ── */
      timing () {
        related_pin      : "A";
        timing_type      : combinational;
        timing_sense     : positive_unate;

        /* Cell delay table (NLDM) */
        cell_rise (delay_template_7x7) {
          index_1 ("0.01,0.02,0.04,0.08,0.16,0.32,0.64"); /* input transition */
          index_2 ("0.001,0.002,0.004,0.008,0.016,0.032,0.064"); /* output cap */
          values (
            "0.021,0.025,0.033,0.048,0.078,0.138,0.258",
            "0.026,0.030,0.038,0.053,0.083,0.143,0.263",
            "0.036,0.040,0.048,0.063,0.093,0.153,0.273",
            ...
          );
        }
        /* rise_transition, cell_fall, fall_transition tables follow */
      }
    }

    /* ── Pin block: clock of internal FF (sequential) ── */
    pin (CK) {
      direction : input;
      clock     : true;
    }
  } /* end cell AND2X2 */

} /* end library */

3. NLDM vs CCS delay models

Liberty supports multiple delay model types. The two most commonly used in STA are NLDM and CCS.

AttributeNLDM (Non-Linear Delay Model)CCS (Composite Current Source)
Model approachPrecharacterised delay + output slew as 2D tables (input_transition × output_cap)Cell modeled as a time-varying current source; captures actual output waveform shape
AccuracyGood for 90nm–28nm; less accurate for steep-slew or receiver-dominated pathsHigh accuracy at 28nm and below; models waveform distortion and receiver dependence
RuntimeFast; bilinear table lookupSlower; requires waveform integration at each receiver
Liberty keyworddelay_model : table_lookupdelay_model : ccs; uses output_current_rise tables
Typical useSynthesis, early STA, RTL sign-off, most 65nm+ flowsPost-layout sign-off at 28nm and below; SI-aware STA

Which model to use?

For most 65nm–28nm sign-off flows, NLDM is accurate enough and is the default. For 16nm/7nm and below — where receiver input capacitance and waveform shape significantly affect timing — CCS (or its ECSM equivalent from Cadence) is required for accurate sign-off. Your foundry PDK will specify which model type to use per node.

4. How the delay lookup works

When STA encounters a cell during path propagation, it needs to know: (a) how long before the output switches after the input switches (cell delay), and (b) how fast the output transitions (output slew, which becomes the next cell’s input transition). Both are in NLDM tables indexed by two variables:

The tool performs bilinear interpolation when the actual values fall between table entries. If the actual input slew or output cap exceeds the table range, the tool extrapolates — which can be less accurate, which is why libraries are typically characterised to cover realistic on-chip ranges.

NLDM delay table — reading example
/* cell_rise table for INV_X1, arc: A → ZN */
cell_rise (delay_template_5x5) {
  /* index_1 = input transition time (ns) */
  index_1 ("0.01, 0.04, 0.10, 0.20, 0.40");
  /* index_2 = output load capacitance (pF) */
  index_2 ("0.001, 0.004, 0.010, 0.020, 0.040");
  values (
  /* cap:  0.001   0.004   0.010   0.020   0.040 */
    "0.018, 0.024, 0.034, 0.053, 0.091",  /* trans=0.01 */
    "0.022, 0.028, 0.038, 0.057, 0.095",  /* trans=0.04 */
    "0.030, 0.036, 0.046, 0.065, 0.103",  /* trans=0.10 */
    "0.043, 0.049, 0.059, 0.078, 0.116",  /* trans=0.20 */
    "0.068, 0.074, 0.084, 0.103, 0.141"   /* trans=0.40 */
  );
}

/* Example lookup:
   Actual input transition = 0.07 ns  (between 0.04 and 0.10)
   Actual output cap       = 0.007 pF (between 0.004 and 0.010)

   Bilinear interpolation:
   - At trans=0.04: delay(0.007) = 0.028 + (0.007-0.004)/(0.010-0.004)*(0.038-0.028) = 0.033
   - At trans=0.10: delay(0.007) = 0.036 + 0.5*0.010 = 0.041
   - Final: 0.033 + (0.07-0.04)/(0.10-0.04)*(0.041-0.033) = 0.037 ns
*/

5. Timing arc types

A timing arc describes the timing relationship between two pins of a cell. Liberty defines several arc types:

Arc typeLiberty keywordDescriptionExample
CombinationalcombinationalData flows from input pin to output pin through combinational logicAND gate: A→Z, B→Z
Rising_edgerising_edgeSequential arc: output changes on rising clock edge (clock-to-Q)DFF: CK→Q
Falling_edgefalling_edgeOutput changes on falling clock edgeNegative-edge DFF: CK→Q
Setup_risingsetup_risingSetup constraint arc: D must be stable before rising CKDFF: D to CK setup
Hold_risinghold_risingHold constraint arc: D must be stable after rising CKDFF: D to CK hold
Three_state_enablethree_state_enableOutput enable arc for tri-state bufferTBUF: OE→Z
Three_state_disablethree_state_disableOutput disable (high-Z) arc for tri-state bufferTBUF: OE→Z (high-Z)

Timing sense

Each arc also carries a timing_sense attribute that describes how the input signal polarity affects the output:

STA uses timing_sense to determine whether to propagate a rising or falling transition through a path, which affects which delay table (cell_rise vs cell_fall) to look up.

6. Sequential arcs — setup and hold

Flip-flops have two special arc types that define their timing constraints. These are different from propagation arcs — they don’t produce delay, they consume margin from the path budget.

Liberty flip-flop: clock-to-Q, setup, and hold arcs
cell (DFFX1) {
  area : 6.48;

  /* Flip-flop state description */
  ff (IQ, IQN) {
    next_state          : "D";
    clocked_on          : "CK";
  }

  /* ── Clock-to-Q arc (propagation) ── */
  pin (Q) {
    direction  : output;
    function   : "IQ";

    timing () {
      related_pin   : "CK";
      timing_type   : rising_edge;     /* triggers on CK rising edge */
      timing_sense  : non_unate;

      cell_rise (delay_template_7x7) {
        /* Q rises after CK: table[input_transition][output_cap] */
        index_1 ("0.01,0.02,...");
        index_2 ("0.001,0.002,...");
        values ( "0.045,0.052,...", ... );
      }
      cell_fall (delay_template_7x7) { ... }
    }
  }

  /* ── Setup arc (D → CK) ── */
  pin (D) {
    direction : input;

    timing () {
      related_pin   : "CK";
      timing_type   : setup_rising;   /* D must be valid before CK rises */

      /* Setup time vs input transition (1D table indexed by D slew) */
      rise_constraint (constraint_template_7x7) {
        index_1 ("0.01,0.02,...");  /* D transition */
        index_2 ("0.01,0.02,...");  /* CK transition */
        values ( "0.041,0.044,...", ... );
      }
      fall_constraint (constraint_template_7x7) { ... }
    }

    /* ── Hold arc (D → CK) ── */
    timing () {
      related_pin   : "CK";
      timing_type   : hold_rising;    /* D must remain valid after CK rises */

      rise_constraint (constraint_template_7x7) { ... }
      fall_constraint (constraint_template_7x7) { ... }
    }
  }
} /* end DFFX1 */

Setup and hold values can be negative

In modern standard cell libraries, hold time values are often negative — this means the data can change slightly before the clock edge and still be captured correctly. STA interprets a negative hold time by requiring a shorter minimum path. Negative hold values are not a mistake; they are the result of the flip-flop’s internal circuitry having a built-in time slack on its data latch path.

7. Timing arc modifiers

Liberty arcs can carry additional attributes that modify how STA handles them:

MUX conditional arcs — when attribute
cell (MUX2X1) {
  pin (Z) {
    direction : output;
    function  : "(S*B) + (!S*A)";

    /* Arc A→Z only active when S=0 */
    timing () {
      related_pin  : "A";
      when         : "!S";
      timing_type  : combinational;
      timing_sense : positive_unate;
      cell_rise    (delay_template_7x7) { ... }
    }

    /* Arc B→Z only active when S=1 */
    timing () {
      related_pin  : "B";
      when         : "S";
      timing_type  : combinational;
      timing_sense : positive_unate;
      cell_rise    (delay_template_7x7) { ... }
    }

    /* Select arc: S→Z (non-unate) */
    timing () {
      related_pin  : "S";
      timing_type  : combinational;
      timing_sense : non_unate;
      cell_rise    (delay_template_7x7) { ... }
    }
  }
}

8. How PrimeTime uses Liberty

The STA tool’s delay computation follows this sequence for every cell in a timing path:

  1. Identify the cell type and look up its Liberty cell entry
  2. Determine the active arc based on timing_type and any when conditions (from set_case_analysis)
  3. Read the input transition at the cell’s input pin (propagated from the previous cell’s output slew table)
  4. Read the output load by summing the wire capacitance (from SPEF) and all receiver input capacitances (from Liberty pin capacitance values)
  5. Interpolate the delay table (cell_rise or cell_fall) at (input_transition, output_load)
  6. Interpolate the transition table (rise_transition or fall_transition) to get the output slew for the next cell
  7. Accumulate: arrival_time += cell_delay + (wire delay from SPEF)

At flip-flop endpoints, the tool uses the setup_rising arc to get the required setup time and subtracts it from the clock arrival to compute the required time. Slack = required time − arrival time.

Liberty is per-corner

One Liberty file represents one operating condition (one PVT corner). For setup analysis you read a slow corner .lib; for hold you read a fast corner .lib. The tool loads multiple .lib files when running MCMM (Multi-Corner Multi-Mode) analysis. Every number in a Liberty table — delays, setup times, hold times — is valid only at the PVT corner it was characterised for.

9. Reading Liberty in practice

PrimeTime — reading Liberty and querying arcs
## Load a Liberty file
read_lib /pdk/tsmc28/lib/sc9_tt_1p0v_25c.lib

## Check which cells are loaded
list_libs

## Query timing arcs for a specific cell
get_lib_attribute sc9_tt_1p0v_25c/AND2X2 cell_footprint
report_lib sc9_tt_1p0v_25c/DFFX1

## Query setup time for a flip-flop at specific slew values
set_lib_attribute sc9_tt_1p0v_25c/DFFX1/D \
  setup_rising rise_constraint

## Report all timing arcs for a cell (from netlist instance)
report_timing -through [get_cells u_adder/FF_result] \
  -delay_type max -nworst 1

## Check if a Liberty arc is being used
get_lib_timing_arcs -from [get_lib_pins sc9/AND2X2/A] \
                    -to   [get_lib_pins sc9/AND2X2/Z]

Day 5 Key Takeaways

Frequently Asked Questions

What is a Liberty file in STA?

A Liberty (.lib) file is the timing database for a standard cell library. It contains cell delay, output slew, setup/hold constraints, and power data for every cell, modelled as lookup tables indexed by input transition time and output capacitance. STA tools read Liberty files to compute cell delays during path analysis.

What is the difference between NLDM and CCS?

NLDM (Non-Linear Delay Model) stores delay as a precomputed 2D table — fast to look up via bilinear interpolation. CCS (Composite Current Source) models the cell output as a time-varying current source, capturing the actual output waveform and receiver-dependent delay with higher accuracy. NLDM is used for 90nm–28nm; CCS is required for accurate sign-off at 16nm and below.

What is a timing arc?

A timing arc is the timing relationship between two pins of a cell. Combinational arcs model input-to-output propagation delay. Sequential arcs model clock-to-Q delay for flip-flops. Setup and hold arcs are constraint arcs that define how much time the data must be stable before/after the clock edge. Three-state arcs model tri-state buffer enable/disable timing.

How does STA look up cell delay from a Liberty table?

The STA tool computes the actual input slew (from the previous cell’s output transition table) and the actual output load (wire cap from SPEF + receiver capacitances from Liberty). It then does bilinear interpolation in the NLDM cell_rise or cell_fall table at those two coordinates to get the exact cell delay and output slew.

Why can hold time in Liberty be negative?

A negative hold time means the flip-flop’s internal latch can correctly capture data that changes slightly before the clock edge. This occurs because the latch’s master stage has a small propagation delay, giving it an effective negative hold window. STA handles negative hold values correctly — it means the minimum path only needs to be slightly longer than the clock-to-Q of the previous flip-flop, not necessarily longer than the entire clock period.

← Previous
Day 4: SDC Constraints