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.

SourceLiberty is the format that carries a cell library's timing and power. These cards are checked against the Nangate45 library that OpenROAD-flow-scripts ships, and the excerpts are quoted from it. Liberty is a Synopsys format whose specification is licensed; the behaviour described here is what the open timer OpenSTA implements, and answers link to its command reference. Reference: the OpenSTA command reference (Liberty on GitHub).
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_units exists. 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_cmos model computed delay from a formula, which is too crude below about 130 nm. table_lookup stores 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_area adds 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 (IQ and 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 a latch group 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 timing group lives inside the pin it ends at, and related_pin says where it starts. timing_type says what kind of arc it is: a combinational delay, an edge-triggered delay, or a check such as setup_rising or hold_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_unate preserves direction, negative_unate inverts it, and non_unate, as in an exclusive-OR gate, means both must be considered. It is also why a clock through such a gate needs set_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.

    when is the condition the timer uses; sdf_cond is 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_1 and variable_2 say 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_falling and hold_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_design buffers or upsizes to meet them, and report_check_types -max_slew -max_capacitance reports 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 ff group 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. area is in library units and feeds utilization; drive_strength is 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_pin names CK as the reference and timing_type says 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_power is the average used when the state probabilities are unknown; report_power uses 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_units shows. 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_pin groups 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.db
    The 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_liberty accepts 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_fanout of 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_use
    A 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_state and clocked_on; a latch declares data_in and enable, 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 preset or clear expression 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 needs clear_preset_var1 to 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_enable and three_state_disable arcs, 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_check applies and the clock tree can be built through it. The SE input 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_pin is the start. The same shape carries both delays and checks, so a timing group 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.

    combinational is a plain propagation, rising_edge fires only on a rising clock, preset is 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_width can 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_capacitance gives 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_1 and columns follow index_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 latch group with data_in and enable is 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 by set_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.

    N means 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 reason set_clock_gating_check times 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