// OpenSTA, Static Timing Analyzer // Copyright (c) 2024, Parallax Software, Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #pragma once #include #include "MinMax.hh" #include "RiseFallMinMax.hh" #include "ConcreteLibrary.hh" #include "RiseFallValues.hh" #include "MinMaxValues.hh" #include "Transition.hh" #include "Delay.hh" #include "LibertyClass.hh" namespace sta { class WriteTimingModel; class LibertyCellIterator; class LibertyCellPortIterator; class LibertyCellPortBitIterator; class LibertyCellPgPortIterator; class LibertyPortMemberIterator; class ModeValueDef; class TestCell; class PatternMatch; class LatchEnable; class Report; class Debug; class LibertyBuilder; class LibertyReader; class OcvDerate; class TimingArcAttrs; class InternalPowerAttrs; class LibertyPgPort; class StaState; class Corner; class Corners; class DcalcAnalysisPt; class DriverWaveform; typedef Map TableTemplateMap; typedef Vector TableTemplateSeq; typedef Map BusDclMap; typedef Vector BusDclSeq; typedef Map ScaleFactorsMap; typedef Map WireloadMap; typedef Map WireloadSelectionMap; typedef Map OperatingConditionsMap; typedef Map PortToSequentialMap; typedef Vector TimingArcSetSeq; typedef Set TimingArcSetMap; typedef Map LibertyPortPairTimingArcMap; typedef Vector InternalPowerSeq; typedef Map PortInternalPowerSeq; typedef Vector LeakagePowerSeq; typedef Map LibertyPortTimingArcMap; typedef Map ScaledCellMap; typedef Map ScaledPortMap; typedef Map ModeDefMap; typedef Map ModeValueMap; typedef Map LatchEnableMap; typedef Vector LatchEnableSeq; typedef Map OcvDerateMap; typedef Vector InternalPowerAttrsSeq; typedef Map SupplyVoltageMap; typedef Map LibertyPgPortMap; typedef Map DriverWaveformMap; typedef Vector DcalcAnalysisPtSeq; enum class ClockGateType { none, latch_posedge, latch_negedge, other }; enum class DelayModelType { cmos_linear, cmos_pwl, cmos2, table, polynomial, dcm }; enum class ScanSignalType { enable, enable_inverted, clock, clock_a, clock_b, input, input_inverted, output, output_inverted, none }; enum class ScaleFactorPvt { process, volt, temp, unknown }; constexpr int scale_factor_pvt_count = int(ScaleFactorPvt::unknown) + 1; enum class TableTemplateType { delay, power, output_current, capacitance, 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 deleteLiberty(); ScaleFactorPvt findScaleFactorPvt(const char *name); const char * scaleFactorPvtName(ScaleFactorPvt pvt); ScaleFactorType findScaleFactorType(const char *name); const char * scaleFactorTypeName(ScaleFactorType type); bool scaleFactorTypeRiseFallSuffix(ScaleFactorType type); bool scaleFactorTypeRiseFallPrefix(ScaleFactorType type); bool scaleFactorTypeLowHighSuffix(ScaleFactorType type); // Timing sense as a string. const char * timingSenseString(TimingSense sense); // Opposite timing sense. TimingSense timingSenseOpposite(TimingSense sense); //////////////////////////////////////////////////////////////// class LibertyLibrary : public ConcreteLibrary { public: LibertyLibrary(const char *name, const char *filename); virtual ~LibertyLibrary(); LibertyCell *findLibertyCell(const char *name) const; LibertyCellSeq findLibertyCellsMatching(PatternMatch *pattern); // Liberty cells that are buffers. LibertyCellSeq *buffers(); LibertyCellSeq *inverters(); DelayModelType delayModelType() const { return delay_model_type_; } void setDelayModelType(DelayModelType type); void addBusDcl(BusDcl *bus_dcl); BusDcl *findBusDcl(const char *name) const; BusDclSeq busDcls() const; void addTableTemplate(TableTemplate *tbl_template, TableTemplateType type); TableTemplate *findTableTemplate(const char *name, TableTemplateType type); TableTemplateSeq tableTemplates() const; float nominalProcess() const { return nominal_process_; } void setNominalProcess(float process); float nominalVoltage() const { return nominal_voltage_; } 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); ScaleFactors *findScaleFactors(const char *name); ScaleFactors *scaleFactors() const { return scale_factors_; } float scaleFactor(ScaleFactorType type, const Pvt *pvt) const; float scaleFactor(ScaleFactorType type, const LibertyCell *cell, const Pvt *pvt) const; float scaleFactor(ScaleFactorType type, int rf_index, const LibertyCell *cell, const Pvt *pvt) const; void setWireSlewDegradationTable(TableModel *model, RiseFall *rf); TableModel *wireSlewDegradationTable(const RiseFall *rf) const; float degradeWireSlew(const RiseFall *rf, float in_slew, float wire_delay) const; // Check for supported axis variables. // Return true if axes are supported. static bool checkSlewDegradationAxes(const TablePtr &table); 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); void defaultIntrinsic(const RiseFall *rf, // Return values. float &intrisic, bool &exists) const; void setDefaultIntrinsic(const RiseFall *rf, float value); // Uses defaultOutputPinRes or defaultBidirectPinRes based on dir. void defaultPinResistance(const RiseFall *rf, const PortDirection *dir, // Return values. float &res, bool &exists) const; void defaultBidirectPinRes(const RiseFall *rf, // Return values. float &res, bool &exists) const; void setDefaultBidirectPinRes(const RiseFall *rf, float value); void defaultOutputPinRes(const RiseFall *rf, // Return values. float &res, bool &exists) const; void setDefaultOutputPinRes(const RiseFall *rf, float value); 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; void setDefaultFanoutLoad(float load); // Logic thresholds. float inputThreshold(const RiseFall *rf) const; void setInputThreshold(const RiseFall *rf, float th); float outputThreshold(const RiseFall *rf) const; void setOutputThreshold(const RiseFall *rf, float th); // Slew thresholds (measured). float slewLowerThreshold(const RiseFall *rf) const; void setSlewLowerThreshold(const RiseFall *rf, float th); float slewUpperThreshold(const RiseFall *rf) const; void setSlewUpperThreshold(const RiseFall *rf, float th); // The library and delay calculator use the liberty slew upper/lower // (measured) thresholds for the table axes and value. These slews // are scaled by slew_derate_from_library to get slews reported to // the user. // slew(measured) = slew_derate_from_library * slew(table) // measured is from slew_lower_threshold to slew_upper_threshold float slewDerateFromLibrary() const; void setSlewDerateFromLibrary(float derate); Units *units() { return units_; } const Units *units() const { return units_; } Wireload *findWireload(const char *name) const; void setDefaultWireload(Wireload *wireload); Wireload *defaultWireload() const; WireloadSelection *findWireloadSelection(const char *name) const; WireloadSelection *defaultWireloadSelection() const; void addWireload(Wireload *wireload); WireloadMode defaultWireloadMode() const; void setDefaultWireloadMode(WireloadMode mode); void addWireloadSelection(WireloadSelection *selection); void setDefaultWireloadSelection(WireloadSelection *selection); OperatingConditions *findOperatingConditions(const char *name); OperatingConditions *defaultOperatingConditions() const; void addOperatingConditions(OperatingConditions *op_cond); void setDefaultOperatingConditions(OperatingConditions *op_cond); // AOCV // Zero means the ocv depth is not specified. float ocvArcDepth() const; void setOcvArcDepth(float depth); OcvDerate *defaultOcvDerate() const; void setDefaultOcvDerate(OcvDerate *derate); OcvDerate *findOcvDerate(const char *derate_name); void addOcvDerate(OcvDerate *derate); void addSupplyVoltage(const char *suppy_name, float voltage); bool supplyExists(const char *suppy_name) const; void supplyVoltage(const char *supply_name, // Return value. float &voltage, bool &exists) const; // Make scaled cell. Call LibertyCell::addScaledCell after it is complete. LibertyCell *makeScaledCell(const char *name, const char *filename); static void makeCornerMap(LibertyLibrary *lib, int ap_index, Network *network, Report *report); static void makeCornerMap(LibertyCell *link_cell, LibertyCell *map_cell, int ap_index, Report *report); static void makeCornerMap(LibertyCell *cell1, LibertyCell *cell2, bool link, int ap_index, Report *report); static void checkCorners(LibertyCell *cell, Corners *corners, Report *report); DriverWaveform *findDriverWaveform(const char *name); DriverWaveform *driverWaveformDefault() { return driver_waveform_default_; } void addDriverWaveform(DriverWaveform *driver_waveform); protected: float degradeWireSlew(const TableModel *model, float in_slew, float wire_delay) const; Units *units_; DelayModelType delay_model_type_; BusDclMap bus_dcls_; TableTemplateMap template_maps_[table_template_type_count]; float nominal_process_; float nominal_voltage_; float nominal_temperature_; ScaleFactors *scale_factors_; ScaleFactorsMap scale_factors_map_; TableModel *wire_slew_degradation_tbls_[RiseFall::index_count]; float default_input_pin_cap_; float default_output_pin_cap_; float default_bidirect_pin_cap_; RiseFallValues default_intrinsic_; RiseFallValues default_inout_pin_res_; RiseFallValues default_output_pin_res_; float default_fanout_load_; bool default_fanout_load_exists_; float default_max_cap_; bool default_max_cap_exists_; float default_max_fanout_; bool default_max_fanout_exists_; float default_max_slew_; bool default_max_slew_exists_; float input_threshold_[RiseFall::index_count]; float output_threshold_[RiseFall::index_count]; float slew_lower_threshold_[RiseFall::index_count]; float slew_upper_threshold_[RiseFall::index_count]; float slew_derate_from_library_; WireloadMap wireloads_; Wireload *default_wire_load_; WireloadMode default_wire_load_mode_; WireloadSelection *default_wire_load_selection_; WireloadSelectionMap wire_load_selections_; OperatingConditionsMap operating_conditions_; OperatingConditions *default_operating_conditions_; float ocv_arc_depth_; OcvDerate *default_ocv_derate_; OcvDerateMap ocv_derate_map_; SupplyVoltageMap supply_voltage_map_; LibertyCellSeq *buffers_; LibertyCellSeq *inverters_; DriverWaveformMap driver_waveform_map_; // Unnamed driver waveform. DriverWaveform *driver_waveform_default_; static constexpr float input_threshold_default_ = .5; static constexpr float output_threshold_default_ = .5; static constexpr float slew_lower_threshold_default_ = .2; static constexpr float slew_upper_threshold_default_ = .8; private: friend class LibertyCell; friend class LibertyCellIterator; }; class LibertyCellIterator : public Iterator { public: explicit LibertyCellIterator(const LibertyLibrary *library); bool hasNext(); LibertyCell *next(); private: ConcreteCellMap::ConstIterator iter_; }; //////////////////////////////////////////////////////////////// class LibertyCell : public ConcreteCell { public: LibertyCell(LibertyLibrary *library, const char *name, const char *filename); virtual ~LibertyCell(); LibertyLibrary *libertyLibrary() const { return liberty_library_; } LibertyLibrary *libertyLibrary() { return liberty_library_; } LibertyPort *findLibertyPort(const char *name) const; LibertyPortSeq findLibertyPortsMatching(PatternMatch *pattern) const; bool hasInternalPorts() const { return has_internal_ports_; } LibertyPgPort *findPgPort(const char *name) const; size_t pgPortCount() const { return pg_port_map_.size(); } ScaleFactors *scaleFactors() const { return scale_factors_; } void setScaleFactors(ScaleFactors *scale_factors); ModeDef *makeModeDef(const char *name); ModeDef *findModeDef(const char *name); float area() const { return area_; } void setArea(float area); bool dontUse() const { return dont_use_; } void setDontUse(bool dont_use); bool isMacro() const { return is_macro_; } void setIsMacro(bool is_macro); bool isMemory() const { return is_memory_; } void setIsMemory(bool is_memory); bool isPad() const { return is_pad_; } void setIsPad(bool is_pad); bool isClockCell() const { return is_clock_cell_; } void setIsClockCell(bool is_clock_cell); 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; bool isClockGateLatchNegedge() const; bool isClockGateOther() const; bool isClockGate() const; void setClockGateType(ClockGateType type); const TimingArcSetSeq &timingArcSets() const { return timing_arc_sets_; } // from or to may be nullptr to wildcard. const TimingArcSetSeq &timingArcSets(const LibertyPort *from, const LibertyPort *to) const; size_t timingArcSetCount() const; // Find a timing arc set equivalent to key. TimingArcSet *findTimingArcSet(TimingArcSet *key) const; TimingArcSet *findTimingArcSet(unsigned arc_set_index) const; bool hasTimingArcs(LibertyPort *port) const; const InternalPowerSeq &internalPowers() const { return internal_powers_; } const InternalPowerSeq &internalPowers(const LibertyPort *port); LeakagePowerSeq *leakagePowers() { return &leakage_powers_; } void leakagePower(// Return values. float &leakage, bool &exists) const; bool leakagePowerExists() const { return leakage_power_exists_; } // Register, Latch or Statetable. bool hasSequentials() const; const SequentialSeq &sequentials() const { return sequentials_; } // Find the sequential with the output connected to an (internal) port. Sequential *outputPortSequential(LibertyPort *port); const Statetable *statetable() const { return statetable_; } // Find bus declaration local to this cell. BusDcl *findBusDcl(const char *name) const; // True when TimingArcSetBuilder::makeRegLatchArcs infers register // timing arcs. bool hasInferedRegTimingArcs() const { return has_infered_reg_timing_arcs_; } TestCell *testCell() const { return test_cell_; } bool isLatchData(LibertyPort *port); void latchEnable(const TimingArcSet *arc_set, // Return values. const LibertyPort *&enable_port, const FuncExpr *&enable_func, const RiseFall *&enable_rf) const; const RiseFall *latchCheckEnableEdge(TimingArcSet *check_set); bool isDisabledConstraint() const { return is_disabled_constraint_; } LibertyCell *cornerCell(const Corner *corner, const MinMax *min_max); LibertyCell *cornerCell(const DcalcAnalysisPt *dcalc_ap); LibertyCell *cornerCell(int ap_index); // AOCV float ocvArcDepth() const; OcvDerate *ocvDerate() const; OcvDerate *findOcvDerate(const char *derate_name); // Build helpers. void makeSequential(int size, bool is_register, FuncExpr *clk, FuncExpr *data, FuncExpr *clear, FuncExpr *preset, LogicValue clr_preset_out, LogicValue clr_preset_out_inv, LibertyPort *output, LibertyPort *output_inv); void makeStatetable(LibertyPortSeq &input_ports, LibertyPortSeq &internal_ports, StatetableRows &table); void addBusDcl(BusDcl *bus_dcl); // Add scaled cell after it is complete. void addScaledCell(OperatingConditions *op_cond, LibertyCell *scaled_cell); unsigned addTimingArcSet(TimingArcSet *set); void addInternalPower(InternalPower *power); void addInternalPowerAttrs(InternalPowerAttrs *attrs); void addLeakagePower(LeakagePower *power); void setLeakagePower(float leakage); void setOcvArcDepth(float depth); void setOcvDerate(OcvDerate *derate); void addOcvDerate(OcvDerate *derate); void addPgPort(LibertyPgPort *pg_port); void setTestCell(TestCell *test); void setHasInferedRegTimingArcs(bool infered); void setIsDisabledConstraint(bool is_disabled); void setCornerCell(LibertyCell *corner_cell, int ap_index); // Call after cell is finished being constructed. void finish(bool infer_latches, Report *report, Debug *debug); bool isBuffer() const; bool isInverter() const; // Only valid when isBuffer() returns true. void bufferPorts(// Return values. LibertyPort *&input, LibertyPort *&output) const; // Check all liberty cells to make sure they exist // for all the defined corners. static void checkLibertyCorners(); void ensureVoltageWaveforms(const DcalcAnalysisPtSeq &dcalc_aps); const char *footprint() const; void setFootprint(const char *footprint); const char *userFunctionClass() const; void setUserFunctionClass(const char *user_function_class); protected: void addPort(ConcretePort *port); void setHasInternalPorts(bool has_internal); void setLibertyLibrary(LibertyLibrary *library); void makeLatchEnables(Report *report, Debug *debug); FuncExpr *findLatchEnableFunc(const LibertyPort *d, const LibertyPort *en, const RiseFall *en_rf) const; LatchEnable *makeLatchEnable(LibertyPort *d, LibertyPort *en, const RiseFall *en_rf, LibertyPort *q, TimingArcSet *d_to_q, TimingArcSet *en_to_q, TimingArcSet *setup_check, Debug *debug); TimingArcSet *findLatchSetup(const LibertyPort *d, const LibertyPort *en, const RiseFall *en_rf, const LibertyPort *q, const TimingArcSet *en_to_q, Report *report); bool condMatch(const TimingArcSet *arc_set1, const TimingArcSet *arc_set2); void findDefaultCondArcs(); void translatePresetClrCheckRoles(); void inferLatchRoles(Report *report, Debug *debug); void deleteInternalPowerAttrs(); void makeTimingArcMap(Report *report); void makeTimingArcPortMaps(); bool hasBufferFunc(const LibertyPort *input, const LibertyPort *output) const; bool hasInverterFunc(const LibertyPort *input, const LibertyPort *output) const; bool checkCornerCell(const Corner *corner, const MinMax *min_max) const; LibertyLibrary *liberty_library_; float area_; bool dont_use_; bool is_macro_; bool is_memory_; bool is_pad_; bool is_clock_cell_; bool is_level_shifter_; 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_; TimingArcSetMap timing_arc_set_map_; LibertyPortPairTimingArcMap port_timing_arc_set_map_; LibertyPortTimingArcMap timing_arc_set_from_map_; LibertyPortTimingArcMap timing_arc_set_to_map_; bool has_infered_reg_timing_arcs_; InternalPowerSeq internal_powers_; PortInternalPowerSeq port_internal_powers_; InternalPowerAttrsSeq internal_power_attrs_; LeakagePowerSeq leakage_powers_; SequentialSeq sequentials_; PortToSequentialMap port_to_seq_map_; Statetable *statetable_; BusDclMap bus_dcls_; ModeDefMap mode_defs_; ScaleFactors *scale_factors_; ScaledCellMap scaled_cells_; TestCell *test_cell_; // Latch D->Q to LatchEnable. LatchEnableMap latch_d_to_q_map_; // Latch EN->D setup to LatchEnable. LatchEnableMap latch_check_map_; LatchEnableSeq latch_enables_; // Ports that have latch D->Q timing arc sets from them. LibertyPortSet latch_data_ports_; float ocv_arc_depth_; OcvDerate *ocv_derate_; OcvDerateMap ocv_derate_map_; bool is_disabled_constraint_; Vector corner_cells_; float leakage_power_; bool leakage_power_exists_; LibertyPgPortMap pg_port_map_; bool has_internal_ports_; bool have_voltage_waveforms_; std::mutex waveform_lock_; const char *footprint_; const char *user_function_class_; private: friend class LibertyLibrary; friend class LibertyCellPortIterator; friend class LibertyCellPgPortIterator; friend class LibertyPort; friend class LibertyBuilder; }; class LibertyCellPortIterator : public Iterator { public: explicit LibertyCellPortIterator(const LibertyCell *cell); bool hasNext(); LibertyPort *next(); private: ConcretePortSeq::ConstIterator iter_; }; class LibertyCellPortBitIterator : public Iterator { public: explicit LibertyCellPortBitIterator(const LibertyCell *cell); virtual ~LibertyCellPortBitIterator(); bool hasNext(); LibertyPort *next(); private: ConcreteCellPortBitIterator *iter_; }; class LibertyCellPgPortIterator : public Iterator { public: LibertyCellPgPortIterator(const LibertyCell *cell); bool hasNext(); LibertyPgPort *next(); private: LibertyPgPortMap::Iterator iter_; }; //////////////////////////////////////////////////////////////// class LibertyPort : public ConcretePort { public: LibertyCell *libertyCell() const { return liberty_cell_; } LibertyLibrary *libertyLibrary() const { return liberty_cell_->libertyLibrary(); } LibertyPort *findLibertyMember(int index) const; LibertyPort *findLibertyBusBit(int index) const; BusDcl *busDcl() const { return bus_dcl_; } void setDirection(PortDirection *dir); ScanSignalType scanSignalType() const { return scan_signal_type_; } void setScanSignalType(ScanSignalType type); void fanoutLoad(// Return values. float &fanout_load, bool &exists) const; void setFanoutLoad(float fanout_load); float capacitance() const; float capacitance(const MinMax *min_max) const; float capacitance(const RiseFall *rf, const MinMax *min_max) const; void capacitance(const RiseFall *rf, const MinMax *min_max, // Return values. float &cap, bool &exists) const; // Capacitance at op_cond derated by library/cell scale factors // using pvt. float capacitance(const RiseFall *rf, const MinMax *min_max, const OperatingConditions *op_cond, const Pvt *pvt) const; bool capacitanceIsOneValue() const; void setCapacitance(float cap); void setCapacitance(const RiseFall *rf, const MinMax *min_max, float cap); // Max of rise/fall. float driveResistance() const; float driveResistance(const RiseFall *rf, const MinMax *min_max) const; // Zero load delay. ArcDelay intrinsicDelay(const StaState *sta) const; ArcDelay intrinsicDelay(const RiseFall *rf, const MinMax *min_max, const StaState *sta) const; FuncExpr *function() const { return function_; } void setFunction(FuncExpr *func); FuncExpr *&functionRef() { return function_; } // Tristate enable function. FuncExpr *tristateEnable() const { return tristate_enable_; } void setTristateEnable(FuncExpr *enable); FuncExpr *&tristateEnableRef() { return tristate_enable_; } void slewLimit(const MinMax *min_max, // Return values. float &limit, bool &exists) const; void setSlewLimit(float slew, const MinMax *min_max); void capacitanceLimit(const MinMax *min_max, // Return values. float &limit, bool &exists) const; void setCapacitanceLimit(float cap, const MinMax *min_max); void fanoutLimit(const MinMax *min_max, // Return values. float &limit, bool &exists) const; void setFanoutLimit(float fanout, const MinMax *min_max); void minPeriod(const OperatingConditions *op_cond, const Pvt *pvt, float &min_period, bool &exists) const; // Unscaled value. void minPeriod(float &min_period, bool &exists) const; void setMinPeriod(float min_period); // This corresponds to the min_pulse_width_high/low port attribute. // high = rise, low = fall void minPulseWidth(const RiseFall *hi_low, float &min_width, bool &exists) const; void setMinPulseWidth(const RiseFall *hi_low, float min_width); bool isClock() const; void setIsClock(bool is_clk); bool isClockGateClock() const { return is_clk_gate_clk_; } void setIsClockGateClock(bool is_clk_gate_clk); bool isClockGateEnable() const { return is_clk_gate_enable_; } void setIsClockGateEnable(bool is_clk_gate_enable); bool isClockGateOut() const { return is_clk_gate_out_; } void setIsClockGateOut(bool is_clk_gate_out); bool isPllFeedback() const { return is_pll_feedback_; } void setIsPllFeedback(bool is_pll_feedback); bool isolationCellData() const { return isolation_cell_data_; } void setIsolationCellData(bool isolation_cell_data); bool isolationCellEnable() const { return isolation_cell_enable_; } void setIsolationCellEnable(bool isolation_cell_enable); bool levelShifterData() const { return level_shifter_data_; } void setLevelShifterData(bool level_shifter_data); bool isSwitch() const { return is_switch_; } void setIsSwitch(bool is_switch); // Has register/latch rise/fall edges from pin. bool isRegClk() const { return is_reg_clk_; } void setIsRegClk(bool is_clk); // Is the clock for timing checks. bool isCheckClk() const { return is_check_clk_; } void setIsCheckClk(bool is_clk); bool isPad() const { return is_pad_; } void setIsPad(bool is_pad); RiseFall *pulseClkTrigger() const { return pulse_clk_trigger_; } // Rise for high, fall for low. RiseFall *pulseClkSense() const { return pulse_clk_sense_; } void setPulseClk(RiseFall *rfigger, RiseFall *sense); bool isDisabledConstraint() const { return is_disabled_constraint_; } void setIsDisabledConstraint(bool is_disabled); LibertyPort *cornerPort(const Corner *corner, const MinMax *min_max); const LibertyPort *cornerPort(const Corner *corner, const MinMax *min_max) const; LibertyPort *cornerPort(const DcalcAnalysisPt *dcalc_ap); const LibertyPort *cornerPort(const DcalcAnalysisPt *dcalc_ap) const; LibertyPort *cornerPort(int ap_index); const LibertyPort *cornerPort(int ap_index) const; void setCornerPort(LibertyPort *corner_port, int ap_index); const char *relatedGroundPin() const { return related_ground_pin_; } void setRelatedGroundPin(const char *related_ground_pin); const char *relatedPowerPin() const { return related_power_pin_; } void setRelatedPowerPin(const char *related_power_pin); const ReceiverModel *receiverModel() const { return receiver_model_.get(); } void setReceiverModel(ReceiverModelPtr receiver_model); DriverWaveform *driverWaveform(const RiseFall *rf) const; void setDriverWaveform(DriverWaveform *driver_waveform, const RiseFall *rf); float clkTreeDelay(float in_slew, const RiseFall *from_rf, const RiseFall *to_rf, const MinMax *min_max) const; float clkTreeDelay(float in_slew, const RiseFall *from_rf, const MinMax *min_max) const; void setClkTreeDelay(const TableModel *model, const RiseFall *from_rf, const RiseFall *to_rf, const MinMax *min_max); // deprecated 2024-06-22 RiseFallMinMax clkTreeDelays() const __attribute__ ((deprecated)); // deprecated 2024-02-27 RiseFallMinMax clockTreePathDelays() const __attribute__ ((deprecated)); static bool equiv(const LibertyPort *port1, const LibertyPort *port2); static bool less(const LibertyPort *port1, const LibertyPort *port2); protected: // Constructor is internal to LibertyBuilder. LibertyPort(LibertyCell *cell, const char *name, bool is_bus, BusDcl *bus_dcl, int from_index, int to_index, bool is_bundle, ConcretePortSeq *members); virtual ~LibertyPort(); void setMinPort(LibertyPort *min); void addScaledPort(OperatingConditions *op_cond, LibertyPort *scaled_port); RiseFallMinMax clkTreeDelays1() const; LibertyCell *liberty_cell_; BusDcl *bus_dcl_; FuncExpr *function_; ScanSignalType scan_signal_type_; FuncExpr *tristate_enable_; ScaledPortMap *scaled_ports_; RiseFallMinMax capacitance_; MinMaxFloatValues slew_limit_; // inputs and outputs MinMaxFloatValues cap_limit_; // outputs float fanout_load_; // inputs bool fanout_load_exists_; MinMaxFloatValues fanout_limit_; // outputs float min_period_; float min_pulse_width_[RiseFall::index_count]; RiseFall *pulse_clk_trigger_; RiseFall *pulse_clk_sense_; const char *related_ground_pin_; const char *related_power_pin_; Vector corner_ports_; ReceiverModelPtr receiver_model_; DriverWaveform *driver_waveform_[RiseFall::index_count]; // Redundant with clock_tree_path_delay timing arcs but faster to access. const TableModel *clk_tree_delay_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count]; unsigned int min_pulse_width_exists_:RiseFall::index_count; bool min_period_exists_:1; bool is_clk_:1; bool is_reg_clk_:1; bool is_check_clk_:1; bool is_clk_gate_clk_:1; bool is_clk_gate_enable_:1; bool is_clk_gate_out_:1; bool is_pll_feedback_:1; bool isolation_cell_data_:1; bool isolation_cell_enable_:1; bool level_shifter_data_:1; bool is_switch_:1; bool is_disabled_constraint_:1; bool is_pad_:1; private: friend class LibertyLibrary; friend class LibertyCell; friend class LibertyBuilder; friend class LibertyReader; }; LibertyPortSeq sortByName(const LibertyPortSet *set); class LibertyPortMemberIterator : public Iterator { public: explicit LibertyPortMemberIterator(const LibertyPort *port); virtual ~LibertyPortMemberIterator(); virtual bool hasNext(); virtual LibertyPort *next(); private: ConcretePortMemberIterator *iter_; }; // Process, voltage temperature. class Pvt { public: Pvt(float process, float voltage, float temperature); virtual ~Pvt() {} float process() const { return process_; } void setProcess(float process); float voltage() const { return voltage_; } void setVoltage(float voltage); float temperature() const { return temperature_; } void setTemperature(float temp); protected: float process_; float voltage_; float temperature_; }; class OperatingConditions : public Pvt { public: explicit OperatingConditions(const char *name); OperatingConditions(const char *name, float process, float voltage, float temperature, WireloadTree wire_load_tree); virtual ~OperatingConditions(); const char *name() const { return name_; } WireloadTree wireloadTree() const { return wire_load_tree_; } void setWireloadTree(WireloadTree tree); protected: const char *name_; WireloadTree wire_load_tree_; }; class ScaleFactors { public: explicit ScaleFactors(const char *name); ~ScaleFactors(); const char *name() const { return name_; } float scale(ScaleFactorType type, ScaleFactorPvt pvt, RiseFall *rf); float scale(ScaleFactorType type, ScaleFactorPvt pvt, int rf_index); float scale(ScaleFactorType type, ScaleFactorPvt pvt); void setScale(ScaleFactorType type, ScaleFactorPvt pvt, RiseFall *rf, float scale); void setScale(ScaleFactorType type, ScaleFactorPvt pvt, float scale); void print(); protected: const char *name_; float scales_[scale_factor_type_count][scale_factor_pvt_count][RiseFall::index_count]; }; class BusDcl { public: BusDcl(const char *name, int from, int to); ~BusDcl(); const char *name() const { return name_; } int from() const { return from_; } int to() const { return to_; } protected: const char *name_; int from_; int to_; }; // Cell mode_definition group. class ModeDef { public: ~ModeDef(); const char *name() const { return name_; } ModeValueDef *defineValue(const char *value, FuncExpr *cond, const char *sdf_cond); ModeValueDef *findValueDef(const char *value); ModeValueMap *values() { return &values_; } protected: // Private to LibertyCell::makeModeDef. explicit ModeDef(const char *name); const char *name_; ModeValueMap values_; private: friend class LibertyCell; }; // Mode definition mode_value group. class ModeValueDef { public: ~ModeValueDef(); const char *value() const { return value_; } FuncExpr *cond() const { return cond_; } FuncExpr *&condRef() { return cond_; } const char *sdfCond() const { return sdf_cond_; } void setSdfCond(const char *sdf_cond); protected: // Private to ModeDef::defineValue. ModeValueDef(const char *value, FuncExpr *cond, const char *sdf_cond); const char *value_; FuncExpr *cond_; const char *sdf_cond_; private: friend class ModeDef; }; class TableTemplate { public: explicit TableTemplate(const char *name); TableTemplate(const char *name, TableAxisPtr axis1, TableAxisPtr axis2, TableAxisPtr axis3); ~TableTemplate(); const char *name() const { return name_; } void setName(const char *name); const TableAxis *axis1() const { return axis1_.get(); } TableAxisPtr axis1ptr() const { return axis1_; } void setAxis1(TableAxisPtr axis); const TableAxis *axis2() const { return axis2_.get(); } TableAxisPtr axis2ptr() const { return axis2_; } void setAxis2(TableAxisPtr axis); const TableAxis *axis3() const { return axis3_.get(); } TableAxisPtr axis3ptr() const { return axis3_; } void setAxis3(TableAxisPtr axis); protected: const char *name_; TableAxisPtr axis1_; TableAxisPtr axis2_; TableAxisPtr axis3_; }; class TestCell : public LibertyCell { public: TestCell(LibertyLibrary *library, const char *name, const char *filename); protected: }; class OcvDerate { public: OcvDerate(const char *name); ~OcvDerate(); const char *name() const { return name_; } const Table *derateTable(const RiseFall *rf, const EarlyLate *early_late, PathType path_type); void setDerateTable(const RiseFall *rf, const EarlyLate *early_late, PathType path_type, TablePtr derate); private: const char *name_; // [rf_type][derate_type][path_type] TablePtr derate_[RiseFall::index_count][EarlyLate::index_count][path_type_count]; }; // Power/ground port. class LibertyPgPort { public: enum PgType { unknown, primary_power, primary_ground, backup_power, backup_ground, internal_power, internal_ground, nwell, pwell, deepnwell, deeppwell}; LibertyPgPort(const char *name, LibertyCell *cell); ~LibertyPgPort(); const char *name() const { return name_; } LibertyCell *cell() const { return cell_; } PgType pgType() const { return pg_type_; } void setPgType(PgType type); const char *voltageName() const { return voltage_name_; } void setVoltageName(const char *voltage_name); static bool equiv(const LibertyPgPort *port1, const LibertyPgPort *port2); private: const char *name_; PgType pg_type_; const char *voltage_name_; LibertyCell *cell_; }; string portLibertyToSta(const char *port_name); const char * scanSignalTypeName(ScanSignalType scan_type); } // namespace