diff --git a/include/sta/Liberty.hh b/include/sta/Liberty.hh index 7ebdc882..253927c8 100644 --- a/include/sta/Liberty.hh +++ b/include/sta/Liberty.hh @@ -88,6 +88,12 @@ constexpr int scale_factor_pvt_count = int(ScaleFactorPvt::unknown) + 1; enum class TableTemplateType { delay, power, output_current, ocv }; constexpr int table_template_type_count = int(TableTemplateType::ocv) + 1; +enum class LevelShifterType { HL, LH, HL_LH }; + +enum class SwitchCellType { coarse_grain, fine_grain }; + +//////////////////////////////////////////////////////////////// + void initLiberty(); void @@ -117,6 +123,8 @@ timingSenseString(TimingSense sense); TimingSense timingSenseOpposite(TimingSense sense); +//////////////////////////////////////////////////////////////// + class LibertyLibrary : public ConcreteLibrary { public: @@ -145,6 +153,7 @@ public: void setNominalVoltage(float voltage); float nominalTemperature() const { return nominal_temperature_; } void setNominalTemperature(float temperature); + void setScaleFactors(ScaleFactors *scales); // Add named scale factor group. void addScaleFactors(ScaleFactors *scales); @@ -159,6 +168,7 @@ public: int tr_index, const LibertyCell *cell, const Pvt *pvt) const; + void setWireSlewDegradationTable(TableModel *model, RiseFall *rf); TableModel *wireSlewDegradationTable(const RiseFall *rf) const; @@ -173,8 +183,10 @@ public: float defaultInputPinCap() const { return default_input_pin_cap_; } void setDefaultInputPinCap(float cap); + float defaultOutputPinCap() const { return default_output_pin_cap_; } void setDefaultOutputPinCap(float cap); + float defaultBidirectPinCap() const { return default_bidirect_pin_cap_; } void setDefaultBidirectPinCap(float cap); @@ -196,6 +208,7 @@ public: bool &exists) const; void setDefaultBidirectPinRes(const RiseFall *rf, float value); + void defaultOutputPinRes(const RiseFall *rf, // Return values. float &res, @@ -206,12 +219,15 @@ public: void defaultMaxSlew(float &slew, bool &exists) const; void setDefaultMaxSlew(float slew); + void defaultMaxCapacitance(float &cap, bool &exists) const; void setDefaultMaxCapacitance(float cap); + void defaultMaxFanout(float &fanout, bool &exists) const; void setDefaultMaxFanout(float fanout); + void defaultFanoutLoad(// Return values. float &fanout, bool &exists) const; @@ -248,7 +264,6 @@ public: Wireload *defaultWireload() const; WireloadSelection *findWireloadSelection(const char *name) const; WireloadSelection *defaultWireloadSelection() const; - void addWireload(Wireload *wireload); WireloadMode defaultWireloadMode() const; void setDefaultWireloadMode(WireloadMode mode); @@ -405,6 +420,14 @@ public: void setIsPad(bool is_pad); bool isLevelShifter() const { return is_level_shifter_; } void setIsLevelShifter(bool is_level_shifter); + LevelShifterType levelShifterType() const { return level_shifter_type_; } + void setLevelShifterType(LevelShifterType level_shifter_type); + bool isIsolationCell() const { return is_isolation_cell_; } + void setIsIsolationCell(bool is_isolation_cell); + bool alwaysOn() const { return always_on_; } + void setAlwaysOn(bool always_on); + SwitchCellType switchCellType() const { return switch_cell_type_; } + void setSwitchCellType(SwitchCellType switch_cell_type); bool interfaceTiming() const { return interface_timing_; } void setInterfaceTiming(bool value); bool isClockGateLatchPosedge() const; @@ -537,7 +560,10 @@ protected: bool is_memory_; bool is_pad_; bool is_level_shifter_; - bool has_internal_ports_; + LevelShifterType level_shifter_type_; + bool is_isolation_cell_; + bool always_on_; + SwitchCellType switch_cell_type_; bool interface_timing_; ClockGateType clock_gate_type_; TimingArcSetSeq timing_arc_sets_; @@ -571,6 +597,7 @@ protected: float leakage_power_; bool leakage_power_exists_; LibertyPgPortMap pg_port_map_; + bool has_internal_ports_; private: friend class LibertyLibrary; @@ -713,6 +740,19 @@ public: void setIsClockGateOutPin(bool is_clk_gate_out); bool isPllFeedbackPin() const { return is_pll_feedback_pin_; } void setIsPllFeedbackPin(bool is_pll_feedback_pin); + + bool isolationCellDataPin() const { return isolation_cell_data_pin_; } + void setIsolationCellDataPin(bool isolation_cell_data_pin); + + bool isolationCellEnablePin() const { return isolation_cell_enable_pin_; } + void setIsolationCellEnablePin(bool isolation_cell_enable_pin); + + bool levelShifterDataPin() const { return level_shifter_data_pin_; } + void setLevelShifterDataPin(bool level_shifter_data_pin); + + bool switchPin() const { return switch_pin_; } + void setSwitchPin(bool switch_pin); + // Has register/latch rise/fall edges from pin. bool isRegClk() const { return is_reg_clk_; } void setIsRegClk(bool is_clk); @@ -789,6 +829,10 @@ protected: bool is_clk_gate_enable_pin_:1; bool is_clk_gate_out_pin_:1; bool is_pll_feedback_pin_:1; + bool isolation_cell_data_pin_:1; + bool isolation_cell_enable_pin_:1; + bool level_shifter_data_pin_:1; + bool switch_pin_:1; bool is_disabled_constraint_:1; private: diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index e87ba253..a92cb98f 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -891,7 +891,10 @@ LibertyCell::LibertyCell(LibertyLibrary *library, is_memory_(false), is_pad_(false), is_level_shifter_(false), - has_internal_ports_(false), + level_shifter_type_(LevelShifterType::HL_LH), + is_isolation_cell_(false), + always_on_(false), + switch_cell_type_(SwitchCellType::fine_grain), interface_timing_(false), clock_gate_type_(ClockGateType::none), has_infered_reg_timing_arcs_(false), @@ -901,7 +904,8 @@ LibertyCell::LibertyCell(LibertyLibrary *library, ocv_derate_(nullptr), is_disabled_constraint_(false), leakage_power_(0.0), - leakage_power_exists_(false) + leakage_power_exists_(false), + has_internal_ports_(false) { liberty_cell_ = this; } @@ -1038,11 +1042,35 @@ LibertyCell::LibertyCell::setIsPad(bool is_pad) } void -LibertyCell::LibertyCell::setIsLevelShifter(bool is_level_shifter) +LibertyCell::setIsLevelShifter(bool is_level_shifter) { is_level_shifter_ = is_level_shifter; } +void +LibertyCell::setLevelShifterType(LevelShifterType level_shifter_type) +{ + level_shifter_type_ = level_shifter_type; +} + +void +LibertyCell::setIsIsolationCell(bool is_isolation_cell) +{ + is_isolation_cell_ = is_isolation_cell; +} + +void +LibertyCell::setAlwaysOn(bool always_on) +{ + always_on_ = always_on; +} + +void +LibertyCell::setSwitchCellType(SwitchCellType switch_cell_type) +{ + switch_cell_type_ = switch_cell_type; +} + void LibertyCell::setInterfaceTiming(bool value) { @@ -1898,6 +1926,10 @@ LibertyPort::LibertyPort(LibertyCell *cell, is_clk_gate_enable_pin_(false), is_clk_gate_out_pin_(false), is_pll_feedback_pin_(false), + isolation_cell_data_pin_(false), + isolation_cell_enable_pin_(false), + level_shifter_data_pin_(false), + switch_pin_(false), is_disabled_constraint_(false) { liberty_port_ = this; @@ -2351,6 +2383,30 @@ LibertyPort::setIsPllFeedbackPin(bool is_pll_feedback_pin) is_pll_feedback_pin_ = is_pll_feedback_pin; } +void +LibertyPort::setIsolationCellDataPin(bool isolation_cell_data_pin) +{ + isolation_cell_data_pin_ = isolation_cell_data_pin; +} + +void +LibertyPort::setIsolationCellEnablePin(bool isolation_cell_enable_pin) +{ + isolation_cell_enable_pin_ = isolation_cell_enable_pin; +} + +void +LibertyPort::setLevelShifterDataPin(bool level_shifter_data_pin) +{ + level_shifter_data_pin_ = level_shifter_data_pin; +} + +void +LibertyPort::setSwitchPin(bool switch_pin) +{ + switch_pin_ = switch_pin; +} + void LibertyPort::setPulseClk(RiseFall *trigger, RiseFall *sense) diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index 4fd2fbe0..44777696 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -164,6 +164,7 @@ LibertyReader::defineAttrVisitor(const char *attr_name, void LibertyReader::defineVisitors() { + // Library defineGroupVisitor("library", &LibertyReader::beginLibrary, &LibertyReader::endLibrary); defineAttrVisitor("time_unit", &LibertyReader::visitTimeUnit); @@ -281,6 +282,7 @@ LibertyReader::defineVisitors() defineAttrVisitor("wire_load_from_area", &LibertyReader::visitWireloadFromArea); + // Cells defineGroupVisitor("cell", &LibertyReader::beginCell, &LibertyReader::endCell); defineGroupVisitor("scaled_cell", &LibertyReader::beginScaledCell, @@ -293,9 +295,14 @@ LibertyReader::defineVisitors() defineAttrVisitor("is_memory", &LibertyReader::visitIsMemory); defineAttrVisitor("is_pad", &LibertyReader::visitIsPad); defineAttrVisitor("is_level_shifter", &LibertyReader::visitIsLevelShifter); + defineAttrVisitor("level_shifter_type", &LibertyReader::visitLevelShifterType); + defineAttrVisitor("is_isolation_cell", &LibertyReader::visitIsIsolationCell); + defineAttrVisitor("always_on", &LibertyReader::visitAlwaysOn); + defineAttrVisitor("switch_cell_type", &LibertyReader::visitSwitchCellType); defineAttrVisitor("interface_timing", &LibertyReader::visitInterfaceTiming); defineAttrVisitor("scaling_factors", &LibertyReader::visitScalingFactors); + // Pins defineGroupVisitor("pin", &LibertyReader::beginPin,&LibertyReader::endPin); defineGroupVisitor("bus", &LibertyReader::beginBus,&LibertyReader::endBus); defineGroupVisitor("bundle", &LibertyReader::beginBundle, @@ -337,6 +344,15 @@ LibertyReader::defineVisitors() &LibertyReader::visitIsPllFeedbackPin); defineAttrVisitor("signal_type", &LibertyReader::visitSignalType); + defineAttrVisitor("isolation_cell_data_pin", + &LibertyReader::visitIsolationCellDataPin); + defineAttrVisitor("isolation_cell_enable_pin", + &LibertyReader::visitIsolationCellEnablePin); + defineAttrVisitor("level_shifter_data_pin", + &LibertyReader::visitLevelShifterDataPin); + defineAttrVisitor("switch_pin", &LibertyReader::visitSwitchPin); + + // Register/latch defineGroupVisitor("ff", &LibertyReader::beginFF, &LibertyReader::endFF); defineGroupVisitor("ff_bank", &LibertyReader::beginFFBank, &LibertyReader::endFFBank); @@ -2502,6 +2518,58 @@ LibertyReader::visitIsLevelShifter(LibertyAttr *attr) } } +void +LibertyReader::visitLevelShifterType(LibertyAttr *attr) +{ + if (cell_) { + const char *level_shifter_type = getAttrString(attr); + if (stringEq(level_shifter_type, "HL")) + cell_->setLevelShifterType(LevelShifterType::HL); + else if (stringEq(level_shifter_type, "LH")) + cell_->setLevelShifterType(LevelShifterType::LH); + else if (stringEq(level_shifter_type, "HL_LH")) + cell_->setLevelShifterType(LevelShifterType::HL_LH); + else + libWarn(900, attr, "level_shifter_type must be HL, LH, or HL_LH"); + } +} + +void +LibertyReader::visitIsIsolationCell(LibertyAttr *attr) +{ + if (cell_) { + bool is_isolation_cell, exists; + getAttrBool(attr, is_isolation_cell, exists); + if (exists) + cell_->setIsIsolationCell(is_isolation_cell); + } +} + +void +LibertyReader::visitAlwaysOn(LibertyAttr *attr) +{ + if (cell_) { + bool always_on, exists; + getAttrBool(attr, always_on, exists); + if (exists) + cell_->setAlwaysOn(always_on); + } +} + +void +LibertyReader::visitSwitchCellType(LibertyAttr *attr) +{ + if (cell_) { + const char *switch_cell_type = getAttrString(attr); + if (stringEq(switch_cell_type, "coarse_grain")) + cell_->setSwitchCellType(SwitchCellType::coarse_grain); + else if (stringEq(switch_cell_type, "fine_grain")) + cell_->setSwitchCellType(SwitchCellType::fine_grain); + else + libWarn(901, attr, "switch_cell_type must be coarse_grain or fine_grain"); + } +} + void LibertyReader::visitInterfaceTiming(LibertyAttr *attr) { @@ -3223,65 +3291,25 @@ LibertyReader::visitPulseClock(LibertyAttr *attr) void LibertyReader::visitClockGateClockPin(LibertyAttr *attr) { - if (cell_) { - bool value, exists; - getAttrBool(attr, value, exists); - if (exists) { - LibertyPortSeq::Iterator port_iter(ports_); - while (port_iter.hasNext()) { - LibertyPort *port = port_iter.next(); - port->setIsClockGateClockPin(value); - } - } - } + visitPortBoolAttr(attr, &LibertyPort::setIsClockGateClockPin); } void LibertyReader::visitClockGateEnablePin(LibertyAttr *attr) { - if (cell_) { - bool value, exists; - getAttrBool(attr, value, exists); - if (exists) { - LibertyPortSeq::Iterator port_iter(ports_); - while (port_iter.hasNext()) { - LibertyPort *port = port_iter.next(); - port->setIsClockGateEnablePin(value); - } - } - } + visitPortBoolAttr(attr, &LibertyPort::setIsClockGateEnablePin); } void LibertyReader::visitClockGateOutPin(LibertyAttr *attr) { - if (cell_) { - bool value, exists; - getAttrBool(attr, value, exists); - if (exists) { - LibertyPortSeq::Iterator port_iter(ports_); - while (port_iter.hasNext()) { - LibertyPort *port = port_iter.next(); - port->setIsClockGateOutPin(value); - } - } - } + visitPortBoolAttr(attr, &LibertyPort::setIsClockGateOutPin); } void LibertyReader::visitIsPllFeedbackPin(LibertyAttr *attr) { - if (cell_) { - bool value, exists; - getAttrBool(attr, value, exists); - if (exists) { - LibertyPortSeq::Iterator port_iter(ports_); - while (port_iter.hasNext()) { - LibertyPort *port = port_iter.next(); - port->setIsPllFeedbackPin(value); - } - } - } + visitPortBoolAttr(attr, &LibertyPort::setIsPllFeedbackPin); } void @@ -3302,6 +3330,47 @@ LibertyReader::visitSignalType(LibertyAttr *attr) } } +void +LibertyReader::visitIsolationCellDataPin(LibertyAttr *attr) +{ + visitPortBoolAttr(attr, &LibertyPort::setIsolationCellDataPin); +} + +void +LibertyReader::visitIsolationCellEnablePin(LibertyAttr *attr) +{ + visitPortBoolAttr(attr, &LibertyPort::setIsolationCellEnablePin); +} + +void +LibertyReader::visitLevelShifterDataPin(LibertyAttr *attr) +{ + visitPortBoolAttr(attr, &LibertyPort::setLevelShifterDataPin); +} + +void +LibertyReader::visitSwitchPin(LibertyAttr *attr) +{ + visitPortBoolAttr(attr, &LibertyPort::setSwitchPin); +} + +void +LibertyReader::visitPortBoolAttr(LibertyAttr *attr, + LibertyPortBoolSetter setter) +{ + if (cell_) { + bool value, exists; + getAttrBool(attr, value, exists); + if (exists) { + LibertyPortSeq::Iterator port_iter(ports_); + while (port_iter.hasNext()) { + LibertyPort *port = port_iter.next(); + (port->*setter)(value); + } + } + } +} + //////////////////////////////////////////////////////////////// void diff --git a/liberty/LibertyReaderPvt.hh b/liberty/LibertyReaderPvt.hh index cd6a99c6..663f35f5 100644 --- a/liberty/LibertyReaderPvt.hh +++ b/liberty/LibertyReaderPvt.hh @@ -56,6 +56,7 @@ typedef Vector LibertyFuncSeq; typedef Vector TimingGroupSeq; typedef Vector InternalPowerGroupSeq; typedef Vector LeakagePowerGroupSeq; +typedef void (LibertyPort::*LibertyPortBoolSetter)(bool value); class LibertyReader : public LibertyGroupVisitor { @@ -182,7 +183,11 @@ public: virtual void visitIsMacro(LibertyAttr *attr); virtual void visitIsMemory(LibertyAttr *attr); virtual void visitIsPad(LibertyAttr *attr); - void visitIsLevelShifter(LibertyAttr *attr); + virtual void visitIsLevelShifter(LibertyAttr *attr); + virtual void visitLevelShifterType(LibertyAttr *attr); + virtual void visitIsIsolationCell(LibertyAttr *attr); + virtual void visitAlwaysOn(LibertyAttr *attr); + virtual void visitSwitchCellType(LibertyAttr *attr); virtual void visitInterfaceTiming(LibertyAttr *attr); virtual void visitScalingFactors(LibertyAttr *attr); virtual void visitCellLeakagePower(LibertyAttr *attr); @@ -233,6 +238,12 @@ public: virtual void visitSignalType(LibertyAttr *attr); EarlyLateAll *getAttrEarlyLate(LibertyAttr *attr); virtual void visitClock(LibertyAttr *attr); + virtual void visitIsolationCellDataPin(LibertyAttr *attr); + virtual void visitIsolationCellEnablePin(LibertyAttr *attr); + virtual void visitLevelShifterDataPin(LibertyAttr *attr); + virtual void visitSwitchPin(LibertyAttr *attr); + void visitPortBoolAttr(LibertyAttr *attr, + LibertyPortBoolSetter setter); virtual void beginScalingFactors(LibertyGroup *group); virtual void endScalingFactors(LibertyGroup *group);