library(rr_generic) {
  delay_model : table_lookup;
  time_unit : "1ns";
  voltage_unit : "1V";
  current_unit : "1mA";
  pulling_resistance_unit : "1kohm";
  capacitive_load_unit(1,pf);
  input_threshold_pct_rise : 50;
  input_threshold_pct_fall : 50;
  output_threshold_pct_rise : 50;
  output_threshold_pct_fall : 50;
  slew_lower_threshold_pct_rise : 20;
  slew_lower_threshold_pct_fall : 20;
  slew_upper_threshold_pct_rise : 80;
  slew_upper_threshold_pct_fall : 80;

  lu_table_template(delay_template) {
    variable_1 : input_net_transition;
    variable_2 : total_output_net_capacitance;
    index_1("0.01, 0.10");
    index_2("0.01, 0.10");
  }

  /* RTL-T2.143: setup/hold constraint tables may NOT reuse delay_template —
     input_net_transition / total_output_net_capacitance are invalid axes for
     a constraint arc, so OpenSTA warned "unsupported model axis", dropped the
     DFF D-pin arcs, left every endpoint unconstrained, and report_checks
     found no paths (the vacuous verdict T2.130/T2.142 now refuse). Constraint
     tables index on the related (clock) and constrained (data) pin
     transitions instead. */
  lu_table_template(constraint_template) {
    variable_1 : related_pin_transition;
    variable_2 : constrained_pin_transition;
    index_1("0.01, 0.10");
    index_2("0.01, 0.10");
  }

  cell(INV) {
    area : 1;
    pin(A) { direction : input; capacitance : 0.01; }
    pin(Y) {
      direction : output;
      function : "!A";
      timing() {
        related_pin : "A";
        timing_sense : negative_unate;
        cell_rise(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        cell_fall(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        rise_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
        fall_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
      }
    }
  }

  cell(BUF) {
    area : 1;
    pin(A) { direction : input; capacitance : 0.01; }
    pin(Y) {
      direction : output;
      function : "A";
      timing() {
        related_pin : "A";
        timing_sense : positive_unate;
        cell_rise(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        cell_fall(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        rise_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
        fall_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
      }
    }
  }

  /* RTL-T2.178: a Boolean function does not imply a Liberty delay arc.
     Every mapped combinational input must name a related_pin, otherwise
     OpenSTA stops the timing graph at that cell's input pin. */
  cell(AND2) {
    area : 2;
    pin(A) { direction : input; capacitance : 0.01; }
    pin(B) { direction : input; capacitance : 0.01; }
    pin(Y) {
      direction : output;
      function : "A & B";
      timing() {
        related_pin : "A B";
        timing_sense : positive_unate;
        cell_rise(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        cell_fall(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        rise_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
        fall_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
      }
    }
  }

  cell(OR2) {
    area : 2;
    pin(A) { direction : input; capacitance : 0.01; }
    pin(B) { direction : input; capacitance : 0.01; }
    pin(Y) {
      direction : output;
      function : "A | B";
      timing() {
        related_pin : "A B";
        timing_sense : positive_unate;
        cell_rise(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        cell_fall(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        rise_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
        fall_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
      }
    }
  }

  cell(NAND2) {
    area : 2;
    pin(A) { direction : input; capacitance : 0.01; }
    pin(B) { direction : input; capacitance : 0.01; }
    pin(Y) {
      direction : output;
      function : "!(A & B)";
      timing() {
        related_pin : "A B";
        timing_sense : negative_unate;
        cell_rise(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        cell_fall(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        rise_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
        fall_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
      }
    }
  }

  cell(NOR2) {
    area : 2;
    pin(A) { direction : input; capacitance : 0.01; }
    pin(B) { direction : input; capacitance : 0.01; }
    pin(Y) {
      direction : output;
      function : "!(A | B)";
      timing() {
        related_pin : "A B";
        timing_sense : negative_unate;
        cell_rise(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        cell_fall(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        rise_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
        fall_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
      }
    }
  }

  cell(XOR2) {
    area : 3;
    pin(A) { direction : input; capacitance : 0.01; }
    pin(B) { direction : input; capacitance : 0.01; }
    pin(Y) {
      direction : output;
      function : "A ^ B";
      timing() {
        related_pin : "A B";
        timing_sense : non_unate;
        cell_rise(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        cell_fall(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        rise_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
        fall_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
      }
    }
  }

  cell(XNOR2) {
    area : 3;
    pin(A) { direction : input; capacitance : 0.01; }
    pin(B) { direction : input; capacitance : 0.01; }
    pin(Y) {
      direction : output;
      function : "!(A ^ B)";
      timing() {
        related_pin : "A B";
        timing_sense : non_unate;
        cell_rise(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        cell_fall(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        rise_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
        fall_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
      }
    }
  }

  cell(MUX2) {
    area : 3;
    pin(A) { direction : input; capacitance : 0.01; }
    pin(B) { direction : input; capacitance : 0.01; }
    pin(S) { direction : input; capacitance : 0.01; }
    pin(Y) {
      direction : output;
      function : "(S & B) | (!S & A)";
      timing() {
        related_pin : "A B S";
        timing_sense : non_unate;
        cell_rise(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        cell_fall(delay_template) { values("0.02, 0.03", "0.03, 0.04"); }
        rise_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
        fall_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
      }
    }
  }

  cell(DFF) {
    area : 4;
    ff(IQ, IQN) {
      clocked_on : "CLK";
      next_state : "D";
    }
    pin(CLK) {
      direction : input;
      clock : true;
      capacitance : 0.01;
    }
    pin(D) {
      direction : input;
      capacitance : 0.01;
      timing() {
        related_pin : "CLK";
        timing_type : setup_rising;
        rise_constraint(constraint_template) { values("0.05, 0.05", "0.05, 0.05"); }
        fall_constraint(constraint_template) { values("0.05, 0.05", "0.05, 0.05"); }
      }
      timing() {
        related_pin : "CLK";
        timing_type : hold_rising;
        rise_constraint(constraint_template) { values("0.01, 0.01", "0.01, 0.01"); }
        fall_constraint(constraint_template) { values("0.01, 0.01", "0.01, 0.01"); }
      }
    }
    pin(Q) {
      direction : output;
      function : "IQ";
      timing() {
        related_pin : "CLK";
        timing_type : rising_edge;
        cell_rise(delay_template) { values("0.05, 0.06", "0.06, 0.07"); }
        cell_fall(delay_template) { values("0.05, 0.06", "0.06, 0.07"); }
        rise_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
        fall_transition(delay_template) { values("0.01, 0.02", "0.02, 0.03"); }
      }
    }
  }
}
