All sections
The cards come in more than one shape: a command to explain, and real tool output to read. A missed card returns later in the round and starts the schedule over. A card answered correctly moves up the schedule and next appears after 1, 3, 7, then 21 days. Keys 1 to 4 choose an option, h shows a hint, and Enter moves on. A hint keeps the card where it is on the schedule. An ordering card is answered by clicking its items in order, and one wrong click ends it. Time values are in nanoseconds. Progress is stored in this browser.
All 53 cards in this deck, with answers
-
time_unit : "1ns"; capacitive_load_unit (1,ff); voltage_unit : "1V"; current_unit : "1mA";Declares the units that every value in the library is expressed in.
Hint: Every number later in the file is bare. Ask what these lines are for.
A delay of 0.02 in this file means 0.02 ns, and a capacitance of 1.14 means 1.14 fF. Mixing libraries whose units differ is a classic way to get timing that is wrong by a factor of a thousand, which is why
report_unitsexists. Liberty reference -
'delay_model : table_lookup;'Says delays come from characterized tables rather than an equation.
Hint: Ask what the alternative would be, and which one a modern library uses.
The older
generic_cmosmodel computed delay from a formula, which is too crude below about 130 nm.table_lookupstores measured values against input transition and output load, which is the NLDM (Non-Linear Delay Model). Current-source models such as CCS (Composite Current Source) add more data alongside these tables. Liberty reference -
nom_process : 1.00; nom_voltage : 1.10; nom_temperature : 25.00; operating_conditions (typical) { ... }Records the process, voltage, and temperature the library was characterized at.
Hint: Ask what would have to change for the same cells to need a second file.
One Liberty file is one corner. A design that must work from a low to a high voltage and over a temperature range needs several files, and sign-off analyses them together. Derating scales around these values; it does not replace them. Liberty reference
-
'default_max_transition : 0.198535;'The transition limit used for any pin that does not declare its own.
Hint: The word default says where it applies. Ask what can override it.
Library-level defaults exist for transition, capacitance, and fanout, and a pin may declare a tighter one. Here the value matches the largest transition index in the tables, which is the usual choice: beyond the characterized range the delay would be extrapolated. Liberty reference
-
cell (DFF_X1) { drive_strength : 1; area : 4.522000;The cell's area in library units, and its relative drive strength.
Hint: Ask which of the two numbers a floorplanner can use directly.
Area is what
report_design_areaadds up, and it is the number utilization is computed from. Drive strength is the relative label that appears in the cell's name as_X1; the real drive capability is in the delay tables. Liberty reference -
ff ("IQ" , "IQN") { next_state : "D"; clocked_on : "CK"; }Declares the cell as sequential, naming its state and what clocks it.
Hint: Ask what this tells a timer that a list of pins and arcs could not.
The group names the internal state (
IQand its complement), what the next state is (D), and which pin clocks it (CK). That is how a timer knows the cell breaks timing paths rather than passing them through, and where its checks belong. Latches use alatchgroup instead. Liberty reference -
pg_pin(VDD) { voltage_name : VDD; pg_type : primary_power; }Declares the cell's supply pins and which is power and which ground.
Hint: Ask which tools need to know about a cell's supply pins.
Power intent needs this: a cell with two supplies, such as a level shifter or a retention flop, declares each one and what it is for. Signal pins then refer to them through
related_power_pin, which ties a pin's characterization to the supply it was measured against. Liberty reference -
pin (D) { direction : input; capacitance : 1.140290; rise_capacitance : 1.140290; fall_capacitance : 1.062342;The load this input presents to its driver, in library units.
Hint: Ask who pays for this number: the cell itself, or whatever drives it.
Every load pin adds its capacitance to the net, which is what makes the driver slower. It is why upsizing a cell can hurt: the bigger cell presents a bigger load to the stage before it. Separate rise and fall values exist because the input's capacitance depends on which way it is switching. Liberty reference
-
timing () { related_pin : "CK"; timing_type : hold_rising;An arc from CK to this pin, holding a hold check on the rising edge.
Hint: Two attributes: one names the other end of the arc, one names its kind.
A
timinggroup lives inside the pin it ends at, andrelated_pinsays where it starts.timing_typesays what kind of arc it is: a combinational delay, an edge-triggered delay, or a check such assetup_risingorhold_rising. Liberty reference -
'timing_sense : negative_unate;'A rising input makes the output fall, as in an inverter.
Hint: Ask what happens to the output when the input rises.
Unateness tells the timer which output edge to propagate for a given input edge.
positive_unatepreserves direction,negative_unateinverts it, andnon_unate, as in an exclusive-OR gate, means both must be considered. It is also why a clock through such a gate needsset_sense. Liberty reference -
timing () { related_pin : "A1"; when : "!A2"; timing_sense : negative_unate;This arc applies only while A2 is low, as a NAND's other input must be.
Hint: The condition names another pin. Ask when this arc is the one that applies.
A gate's delay from one input depends on what the others are doing, so a library can hold several arcs for the same pin pair with different conditions. The timer picks the one whose condition can hold, and case analysis can make that choice definite. Liberty reference
-
sdf_cond : "A2 == 1'b0";The same condition written for an SDF (Standard Delay Format) file.
Hint: Compare it with `when`: same idea, different consumer.
whenis the condition the timer uses;sdf_condis the same condition in the syntax an SDF (Standard Delay Format) writer needs, so that annotated delays land on the right arc. They should agree, and a mismatch shows up as unannotated arcs. Liberty reference -
cell_rise (Timing_7_7) { index_1 ("0.00117378, 0.00472397, ..."); /* input transition */ index_2 ("0.365616, 1.893040, ..."); /* output load */ values ("0.0189, 0.0247, ...", ...);Delay against input transition and output load.
Hint: Two indexes, one grid of values. Ask what each axis is.
The grid is characterized, so a real value is interpolated on it. These are the two things a cell's delay depends on most. A real value between grid points is interpolated, and outside the grid it is extrapolated, which is why the limits exist. The template name says the grid's size, here seven by seven. Liberty reference
-
cell_rise (...) cell_fall (...) rise_transition (...) fall_transition (...)Delay and output slew, each for a rising and a falling output.
Hint: Two are delays. Ask what the other two are for.
A stage's output slew is the next stage's input transition, so the transition tables are what let delay propagate along a path. Rise and fall are characterized separately because the pull-up and pull-down networks are not identical. Liberty reference
-
lu_table_template (Timing_7_7) { variable_1 : input_net_transition; variable_2 : total_output_net_capacitance; index_1 (...); index_2 (...); }Names a reusable grid, so each table lists only its values.
Hint: Ask why a library would name a grid instead of repeating it.
Hundreds of cells share the same axes, so the axes are declared once and referenced by name.
variable_1andvariable_2say what the axes mean, which is how a reader knows whether index 1 is transition or load. Liberty reference -
output_current_rise () { vector (...) { ... } }The driver's current over time, not a single delay value.
Hint: Ask what this gives a delay calculator that a single delay number cannot.
The receiving waveform is computed from that current. CCS (Composite Current Source) models the driver as a current source rather than a single delay, which matters when the load is resistive enough that the received waveform is not a simple ramp. The library is much larger, and the older NLDM (Non-Linear Delay Model) tables usually remain alongside. Liberty reference
-
timing_type : setup_rising; timing_type : hold_rising;Checks against the rising clock edge: one a setup, one a hold.
Hint: Both mention the rising edge. Ask whose edge it is.
The edge in the name is the active clock edge at the related pin. A falling-edge flop uses
setup_fallingandhold_falling. The values themselves are constraint tables, indexed by the data and clock transitions rather than by load. Liberty reference -
timing_type : recovery_rising; timing_type : removal_rising;The checks on an asynchronous pin's release relative to the clock.
Hint: Ask which pin these checks belong to; it is not the data pin.
Asserting a reset needs no timing: the flop resets whenever it arrives. Releasing it does, because a release too close to the clock edge leaves the flop metastable. Recovery is the setup-like check on the release and removal the hold-like one. Liberty reference
-
fall_constraint (Hold_3_3) { index_1 ("..."); /* related pin transition */ index_2 ("..."); /* constrained pin transition */A setup or hold value indexed by the clock and data transitions.
Hint: Compare the axes with a delay table's. Ask what replaced the load.
A check depends on how sharp both edges are, not on what the pin drives, so load does not appear. A slow clock edge makes setup worse, which is one reason clock slew is held tight. Liberty reference
-
pin (ZN) { direction : output; max_capacitance : 0.150479; max_transition : 0.198535;The limits this output declares, which design-rule repair must meet.
Hint: These sit on an output pin. Ask who has to respect them.
Beyond these values the tables no longer cover the cell's behaviour.
repair_designbuffers or upsizes to meet them, andreport_check_types -max_slew -max_capacitancereports what remains. SDC (Synopsys Design Constraints) can tighten them but not relax them. Liberty reference -
cell_leakage_power : 79.112308; leakage_power () { when : "!CK & !D & !Q & QN"; value : 73.812310; }An average leakage, plus the leakage in each specific logic state.
Hint: One number, then several. Ask why leakage would depend on a condition.
Which transistors are off depends on the state the cell is in, so leakage does too. Power analysis uses the state-dependent values with the probabilities it has for each state, falling back to the average when it has none. Liberty reference
-
internal_power () { related_pin : "A"; rise_power (Power_7_7) { ... } }The energy the cell itself spends when it switches.
Hint: Ask which of the three kinds of power this is, given that it sits in the library.
This is the internal part of switching power. It splits in two: charging the external load, which the tool computes from the net, and the cell's own internal cost, which only the library can know. The tables are indexed like delay tables, so a slower input costs more internal power. Liberty reference
-
'related_pg_pin : "VDD";'Ties this data to the supply it was characterized against.
Hint: Ask why a table would need to name a supply at all.
A multi-supply cell, such as a level shifter, has values that depend on which supply is meant. Naming the supply keeps power intent and timing consistent, and it is how a tool knows what happens when one supply is switched off. Liberty reference
-
What does this tell you about the cell, before any timing is read?
report excerpt
cell (DFF_X1) { drive_strength : 1; ff ("IQ" , "IQN") { next_state : "D"; clocked_on : "CK"; } area : 4.522000;It is sequential: the ff group gives its state and its clock.Hint: One group here only appears on a certain kind of cell.
The
ffgroup marks the cell as a flip-flop, names the internal state IQ and its complement, says the next state comes from D, and says CK clocks it.areais in library units and feeds utilization;drive_strengthis the relative label that appears in the cell's name. Liberty reference -
Which check is this, and between which two pins?
report excerpt
pin (D) { direction : input; related_power_pin : "VDD"; related_ground_pin : "VSS"; capacitance : 1.140290; fall_capacitance : 1.062342; rise_capacitance : 1.140290; timing () { related_pin : "CK"; timing_type : hold_rising; fall_constraint(Hold_3_3) { index_1 ("0.00117378,0.0449324,0.198535");A hold check on D against the rising edge of CK.Hint: Look at related_pin and timing_type together, and note which pin group they sit in.
The group sits inside
pin (D), so the check is on D;related_pinnames CK as the reference andtiming_typesays it is a hold check on the rising edge. The values come as a constraint table indexed by the two pins' transitions, not by load. Liberty reference -
Why does this cell have more than one leakage value?
report excerpt
cell_leakage_power : 79.112308; leakage_power () { when : "!CK & !D & !Q & QN"; value : 73.812310; } leakage_power () { when : "!CK & !D & Q & !QN"; value : 77.650980; } leakage_power () { when : "!CK & D & !Q & QN";Leakage depends on the state the cell is holding.Hint: Read the when conditions: they describe the cell's state, not an event.
Which transistors are off depends on the stored state and the inputs, so each state leaks differently.
cell_leakage_poweris the average used when the state probabilities are unknown;report_poweruses the state-dependent values when it has activity data. Liberty reference -
A delay table in this library holds the value 0.0189. What is that?
report excerpt
delay_model : table_lookup; in_place_swap_mode : match_footprint; library_features (report_delay_calculation,report_power_calculation); /* Units Attributes */ time_unit : "1ns"; leakage_power_unit : "1nW"; voltage_unit : "1V"; current_unit : "1mA"; pulling_resistance_unit : "1kohm"; capacitive_load_unit (1,ff);
0.0189 nanoseconds, since the library's time unit is 1 ns.Hint: The file declares its units once, at the top.
Values in Liberty are bare numbers, and the header says what they mean: time in nanoseconds, capacitance in femtofarads, power in nanowatts here. A tool reporting in different units converts on the way out, which
report_unitsshows. Liberty reference -
slew_lower_threshold_pct_rise : 30.00 ; slew_upper_threshold_pct_rise : 70.00 ; input_threshold_pct_rise : 50.00 ; output_threshold_pct_rise : 50.00 ;Where on a waveform a delay and a transition are measured.
Hint: A delay is measured between two points on two waveforms. These name the points.
Delay runs from the 50 percent point of the input to the 50 percent point of the output, and a transition is the time between the 30 and 70 percent points. Two libraries measured at different thresholds describe the same silicon with different numbers, so they cannot be mixed without care. Liberty reference
-
slew_derate_from_library : 1.00 ;How to scale a threshold-to-threshold transition to the full swing.
Hint: The tables hold a slew measured between thresholds, not a full swing.
A transition measured between the 30 and 70 percent points covers 40 percent of the swing, so a library characterized that way may carry a derate of 0.4. Nangate45 carries 1.00, meaning its values are already what the timer should use. A wrong value scales every transition, and through them every delay. Liberty reference
-
voltage_map (VDD,1.10); voltage_map (VSS,0.00);The voltage on each supply rail the cells refer to by name.
Hint: Each cell names its rails by name. Ask what turns a name into a number.
Every cell's
pg_pingroups name a rail, such as VDD or VSS, and this is where those names are given values. It matters most when a design runs several supplies, because the timer has to know which pin sits on which rail before it can check a level shifter or an always-on path. Liberty reference -
wire_load("5K_hvratio_1_1") { capacitance : 1.774000e-01; resistance : 3.571429e-03; fanout_length( 1, 1.7460 ); fanout_length( 2, 3.9394 ); } default_wire_load : "5K_hvratio_1_1" ;A guess at a net's length, and so its parasitics, from its fanout.
Hint: Before a design is placed, nobody knows a net's length. Ask what stands in.
A net with two loads is assumed to be 3.9 units long, which times the resistance and capacitance gives an estimate. It is a pre-layout stand-in only, and it is thrown away once real parasitics are extracted into SPEF (Standard Parasitic Exchange Format). Physical synthesis replaced it with placement-based estimates. Liberty reference
-
NangateOpenCellLibrary_typical.lib NangateOpenCellLibrary_typical.dbThe same library as readable text and as a compiled binary.
Hint: Both hold the same library. Ask what differs, and which one you can read.
Commercial tools compile Liberty into a binary that loads faster and hides the source. Open tools read the text form, which is why every excerpt in this deck can be quoted. A very large library is often shipped compressed instead, and
read_libertyaccepts that directly. Liberty reference -
pin (ZN) { direction : output; function : "!((A1 A2) + B)"; }The logic the output performs on the inputs, as a boolean expression.
Hint: Read the operators: a space, a plus, and an exclamation mark.
A space means and, a plus means or, an exclamation mark means not, and a circumflex means exclusive or. This is what lets a tool swap one cell for an equivalent one, and what a formal equivalence check compares the netlist against. Liberty reference
-
default_fanout_load : 1.000000; pin (A) { fanout_load : 1.000000; }The unit a fanout limit counts, which need not be one per pin.
Hint: A fanout limit counts something. Ask what unit it counts in.
A
max_fanoutof 10 means the sum of the fanout loads on the net must not exceed 10, and a heavy input can declare more than 1. It is a technology-independent stand-in for capacitance, used during synthesis before real loads are known. Liberty reference -
dont_useA mark that keeps a cell in the library but out of the design.
Hint: The library ships a cell, but this project must not have it placed.
Teams exclude cells for many reasons: poor yield, high leakage, a hold buffer reserved for repair, or a cell the foundry has withdrawn. The library may carry the attribute, and the flow can add its own with
set_dont_use. A cell already placed is not removed, which is why the list is set before synthesis. Liberty reference -
latch ("IQ" , "IQN") { data_in : "D"; enable : "G"; }A level-sensitive latch, open while its enable is active.
Hint: Compare the keywords with the ones a flip-flop uses.
A flip-flop declares
next_stateandclocked_on; a latch declaresdata_inandenable, and that difference is how the timer knows to allow time borrowing rather than to check a single edge. The two names in parentheses are the internal state and its complement. Liberty reference -
ff ("IQ" , "IQN") { next_state : "D"; clocked_on : "CK"; preset : "!SN"; }An asynchronous set, active when the SN pin is low.
Hint: One of these lines does not mention the clock.
A
presetorclearexpression acts without the clock, which is why the arcs on such a pin are recovery and removal rather than setup and hold. A cell with both needsclear_preset_var1to say what the outputs do when both are asserted at once. Liberty reference -
pin (Z) { function : "A"; three_state : "EN"; }The output goes high impedance unless the enable is asserted.
Hint: Ask what this output does when EN is low.
The cell has a third state besides high and low, so the timer needs arcs for turning the driver on and off. Those appear as
three_state_enableandthree_state_disablearcs, and the design has to guarantee that two drivers on the same net are never enabled together. Liberty reference -
statetable ("CK E SE","IQ") { table : "L L L : - : L , \ L L H : - : H , \ L H L : - : H , \ H - - : - : N " ; } clock_gating_integrated_cell : latch_posedge_precontrol;A clock gate whose enable is latched while the clock is low.
Hint: Look at the last row: what does the cell do while the clock is high?
Latching the enable while the clock is low stops a late enable from chopping the clock pulse. The attribute tells the tools this is a clock gate rather than ordinary logic, so
set_clock_gating_checkapplies and the clock tree can be built through it. TheSEinput keeps the gate transparent during scan shift. Liberty reference -
cell (SDFF_X1) { ff ("IQ" , "IQN") { next_state : "(D & !SE) | (SI & SE)"; clocked_on : "CK"; } }A flip-flop with the scan multiplexer built into the cell.
Hint: Read the next-state expression: it has a choice in it.
Scan insertion swaps ordinary flops for these, which is why the netlist grows and every register gets two more pins. The multiplexer sits on the data path, so it costs setup time on every functional path, not only during test. Liberty reference
-
pin (Q) { timing () { related_pin : "CK"; } }An arc from CK to Q, since the arc belongs to the pin holding it.
Hint: The group sits inside one pin and names another.
Every arc is read this way: the enclosing pin is the endpoint, and
related_pinis the start. The same shape carries both delays and checks, so atiminggroup inside a data pin naming a clock is a setup or hold check, while one inside an output is a delay. Liberty reference -
timing_type : combinational; timing_type : rising_edge; timing_type : preset; timing_type : three_state_enable;Four kinds of arc, from plain logic to a clocked or enabling one.
Hint: Ask what each one tells the timer about when the arc is active.
combinationalis a plain propagation,rising_edgefires only on a rising clock,presetis an asynchronous path to the output, and the tristate types turn a driver on or off. The type decides which edges the timer pairs and which checks it looks for. Liberty reference -
timing () { related_pin : "CK"; timing_type : min_pulse_width; fall_constraint(Pulse_width_3) { index_1 ("0.00117378,0.0449324,0.198535"); values ("0.075346,0.087068,0.198733"); } }The shortest the clock may stay low, given how sharp its edges are.
Hint: The values are times, and the axis is a transition. Ask what has to last that long.
A pulse shorter than this may not be captured at all. The constraint grows with a slower clock transition, from 0.075 nanoseconds at a sharp edge to 0.199 at the slowest, which is one reason the clock network is held to a tight transition limit.
set_min_pulse_widthcan tighten it. Liberty reference -
index_1 ("0.00117378,...,0.198535"); index_2 ("0.365616,...,23.4"); /* a load of 40 is asked for */The tool extrapolates, which is far less trustworthy than interpolating.
Hint: The value asked for is past the end of the axis.
Inside the grid the tool interpolates between characterized points, which is accurate. Outside it, the straight-line continuation can be badly wrong, which is why a driver loaded far past its
max_capacitancegives delays nobody should trust, and why the limit exists. Liberty reference -
cell_rise (Timing_7_7) { index_1 ("0.0012, ... , 0.1985"); /* input transition */ index_2 ("0.3656, ... , 23.40"); /* output load */ values ("0.0189,0.0243,...", \ "0.0221,0.0276,..."); }One string per input transition, each holding the values across the loads.
Hint: There is one string per value of one axis. Ask which axis.
Rows follow
index_1and columns followindex_2, so reading a table by hand means counting into the right string. Getting the order backwards is a classic error when a library is written by a script rather than a characterization tool. Liberty reference -
ocv_sigma_cell_rise (Timing_7_7) { sigma_type : early; values ( ... ); }How much this delay varies, per cell rather than by a flat derate.
Hint: The ordinary table holds one delay. Ask what this one adds.
A single derate factor over-margins long paths and under-margins short ones. LVF (Liberty Variation Format) stores a standard deviation beside every delay and constraint, so a timer can combine variation along the path statistically. It multiplies the library's size, which is why not every library ships it. Liberty reference
-
rise_constraint (Hold_3_3) { values ("-0.012, -0.009, -0.004"); }The data may change slightly before the edge and still be captured.
Hint: A hold requirement is a time the data must stay stable after the edge.
Negative values are normal and come from the delays inside the cell: the clock reaches the internal latch after the data does. They make hold easier to meet. Negative setup values also occur, and both are why hold repair must read the library rather than assume zero. Liberty reference
-
default_max_transition : 0.198535; /* library */ pin (ZN) { max_transition : 0.30; } /* cell pin */ set_max_transition 0.15 [current_design]The tightest of the three applies at that pin.
Hint: Three sources set the same limit. Ask which one a tool obeys.
A cell that can genuinely take a slower edge says so on its pin. A project that wants a sharper edge than any cell requires sets it in the constraints. Design-rule repair works to whichever is smallest at that pin, so a stray global constraint can create work nobody asked for. Liberty reference
-
internal_power () { related_pin : "A"; rise_power (Power_7_7) { index_1 (" ... "); /* input transition */ index_2 (" ... "); /* output load */ } }The energy the cell spends inside itself, per transition.
Hint: Same two axes as a delay table. Ask why the load appears at all.
Internal energy is what the cell spends inside itself, mostly the brief current that flows through both transistor stacks while the input crosses. It grows with the input transition. The energy delivered into the load is counted separately as switching power, so the two are not double counted. Liberty reference
-
cell_leakage_power : 79.112308; leakage_power () { when : "!A1 & !A2"; value : 86.94; }The single value is used when no state is known, the conditional ones when it is.
Hint: The timer may not know what state the cell is in.
With switching activity annotated, a tool weights each state by how long the cell spends in it. Without it, the plain value stands, usually an average over states. The spread between states can be large, which is why a design held in a deliberate low-leakage state at idle saves real power. Liberty reference
-
What kind of cell is this, and what does the timer allow it to do?
report excerpt
cell (DLH_X1) { latch ("IQ" , "IQN") { data_in : "D"; enable : "G"; } area : 2.660000; }A transparent latch, so late data can borrow time through it.Hint: Compare the group's keywords against a flip-flop's.
The
latchgroup withdata_inandenableis the signature. While G is active the cell is transparent, so the timer checks the data against the closing edge and permits borrowing up to the limit set byset_max_time_borrow. The two names are the state and its complement. Liberty reference -
This cell's state table ends with the row "H - - : - : N". What does that row say?
report excerpt
statetable ("CK E SE","IQ") { table : "L L L : - : L ,\ L L H : - : H ,\ L H L : - : H ,\ L H H : - : H ,\ H - - : - : N " ; } clock_gating_integrated_cell : latch_posedge_precontrol;While the clock is high the cell holds its state, whatever the enables do.Hint: The three inputs are CK, E, and SE, and N is not a logic level.
Nmeans no change. The enable is captured only while the clock is low, so a late enable cannot cut a pulse that has already started. That is the whole point of an integrated clock gating cell, and the reasonset_clock_gating_checktimes the enable against the opposite edge. Liberty reference -
The clock reaching this pin has a transition of about 0.045 nanoseconds. What does this table then require?
report excerpt
timing () { related_pin : "CK"; timing_type : min_pulse_width; fall_constraint(Pulse_width_3) { index_1 ("0.00117378,0.0449324,0.198535"); values ("0.075346,0.087068,0.198733"); } }The clock must stay low for at least 0.087 nanoseconds.Hint: Find 0.045 on the axis and read the value beneath it.
It is a fall constraint, so it governs the low phase, and 0.0449 is the second point on the axis, giving 0.087068. A sharper edge would need only 0.075. This is why a clock with a degraded transition can fail a pulse width check that a clean one passes at the same frequency. Liberty reference