OpenSTA/include/sta/Liberty.hh

1071 lines
34 KiB
C++
Raw Normal View History

2018-09-28 17:54:21 +02:00
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2022, Parallax Software, Inc.
2018-09-28 17:54:21 +02:00
//
// 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
2018-09-28 17:54:21 +02:00
// 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 <https://www.gnu.org/licenses/>.
2018-09-28 17:54:21 +02:00
2020-02-16 01:13:16 +01:00
#pragma once
2018-09-28 17:54:21 +02:00
2020-04-05 23:53:44 +02:00
#include "MinMax.hh"
#include "RiseFallMinMax.hh"
#include "ConcreteLibrary.hh"
#include "RiseFallValues.hh"
#include "MinMaxValues.hh"
#include "Transition.hh"
2020-12-20 16:31:33 +01:00
#include "Delay.hh"
2020-04-05 23:53:44 +02:00
#include "LibertyClass.hh"
2018-09-28 17:54:21 +02:00
namespace sta {
class WriteTimingModel;
2018-12-05 23:18:41 +01:00
class LibertyCellIterator;
2018-09-28 17:54:21 +02:00
class LibertyCellPortIterator;
class LibertyCellPortBitIterator;
2021-01-29 00:30:58 +01:00
class LibertyCellPgPortIterator;
2018-09-28 17:54:21 +02:00
class LibertyPortMemberIterator;
class ModeValueDef;
class TestCell;
class PatternMatch;
class LatchEnable;
class Report;
class Debug;
class LibertyBuilder;
class LibertyReader;
class OcvDerate;
2018-12-05 23:18:41 +01:00
class TimingArcAttrs;
class InternalPowerAttrs;
2018-12-24 22:07:10 +01:00
class LibertyPgPort;
2020-12-20 16:31:33 +01:00
class StaState;
2018-09-28 17:54:21 +02:00
typedef Set<Library*> LibrarySet;
typedef Map<const char*, TableTemplate*, CharPtrLess> TableTemplateMap;
typedef Vector<TableTemplate*> TableTemplateSeq;
2018-09-28 17:54:21 +02:00
typedef Map<const char*, BusDcl *, CharPtrLess> BusDclMap;
typedef Vector<BusDcl *> BusDclSeq;
2018-09-28 17:54:21 +02:00
typedef Map<const char*, ScaleFactors*, CharPtrLess> ScaleFactorsMap;
typedef Map<const char*, Wireload*, CharPtrLess> WireloadMap;
typedef Map<const char*, WireloadSelection*, CharPtrLess> WireloadSelectionMap;
typedef Map<const char*, OperatingConditions*,
CharPtrLess> OperatingConditionsMap;
typedef Map<LibertyPort*, Sequential*> PortToSequentialMap;
typedef Vector<TimingArcSet*> TimingArcSetSeq;
typedef Set<TimingArcSet*, TimingArcSetLess> TimingArcSetMap;
2019-03-21 18:48:50 +01:00
typedef Map<LibertyPortPair, TimingArcSetSeq*,
2018-12-05 23:18:41 +01:00
LibertyPortPairLess> LibertyPortPairTimingArcMap;
2018-09-28 17:54:21 +02:00
typedef Vector<InternalPower*> InternalPowerSeq;
2020-04-07 03:27:40 +02:00
typedef Map<const LibertyPort *, InternalPowerSeq> PortInternalPowerSeq;
2018-09-28 17:54:21 +02:00
typedef Vector<LeakagePower*> LeakagePowerSeq;
2018-12-05 23:18:41 +01:00
typedef Map<const LibertyPort*, TimingArcSetSeq*> LibertyPortTimingArcMap;
2018-09-28 17:54:21 +02:00
typedef Map<const OperatingConditions*, LibertyCell*> ScaledCellMap;
typedef Map<const OperatingConditions*, LibertyPort*> ScaledPortMap;
typedef Map<const char *, ModeDef*, CharPtrLess> ModeDefMap;
typedef Map<const char *, ModeValueDef*, CharPtrLess> ModeValueMap;
typedef Map<TimingArcSet*, LatchEnable*> LatchEnableMap;
typedef Map<const char *, OcvDerate*, CharPtrLess> OcvDerateMap;
2018-12-05 23:18:41 +01:00
typedef Vector<TimingArcAttrs*> TimingArcAttrsSeq;
typedef Vector<InternalPowerAttrs*> InternalPowerAttrsSeq;
2018-12-21 07:41:54 +01:00
typedef Map<const char *, float, CharPtrLess> SupplyVoltageMap;
2018-12-24 22:07:10 +01:00
typedef Map<const char *, LibertyPgPort*, CharPtrLess> LibertyPgPortMap;
2018-09-28 17:54:21 +02:00
2019-03-13 01:25:53 +01:00
enum class ClockGateType { none, latch_posedge, latch_negedge, other };
enum class DelayModelType { cmos_linear, cmos_pwl, cmos2, table, polynomial, dcm };
enum class ScaleFactorPvt { process, volt, temp, unknown };
constexpr int scale_factor_pvt_count = int(ScaleFactorPvt::unknown) + 1;
2019-03-13 01:25:53 +01:00
enum class TableTemplateType { delay, power, output_current, ocv };
constexpr int table_template_type_count = int(TableTemplateType::ocv) + 1;
2018-09-28 17:54:21 +02:00
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();
2018-09-28 17:54:21 +02:00
LibertyCell *findLibertyCell(const char *name) const;
void findLibertyCellsMatching(PatternMatch *pattern,
LibertyCellSeq *cells);
2019-05-28 07:46:24 +02:00
// Liberty cells that are buffers.
LibertyCellSeq *buffers();
2018-09-28 17:54:21 +02:00
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_; }
2018-09-28 17:54:21 +02:00
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 tr_index,
const LibertyCell *cell,
const Pvt *pvt) const;
void setWireSlewDegradationTable(TableModel *model,
2019-11-11 23:30:19 +01:00
RiseFall *rf);
TableModel *wireSlewDegradationTable(const RiseFall *rf) const;
2018-09-28 17:54:21 +02:00
float degradeWireSlew(const LibertyCell *cell,
2019-11-11 23:30:19 +01:00
const RiseFall *rf,
2018-09-28 17:54:21 +02:00
const Pvt *pvt,
float in_slew,
float wire_delay) const;
// Check for supported axis variables.
// Return true if axes are supported.
static bool checkSlewDegradationAxes(Table *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);
2019-11-11 23:30:19 +01:00
void defaultIntrinsic(const RiseFall *rf,
2020-12-20 16:31:33 +01:00
// Return values.
float &intrisic,
bool &exists) const;
2019-11-11 23:30:19 +01:00
void setDefaultIntrinsic(const RiseFall *rf,
2018-09-28 17:54:21 +02:00
float value);
// Uses defaultOutputPinRes or defaultBidirectPinRes based on dir.
2019-11-11 23:30:19 +01:00
void defaultPinResistance(const RiseFall *rf,
2018-09-28 17:54:21 +02:00
const PortDirection *dir,
// Return values.
float &res,
bool &exists) const;
2019-11-11 23:30:19 +01:00
void defaultBidirectPinRes(const RiseFall *rf,
2018-09-28 17:54:21 +02:00
// Return values.
float &res,
bool &exists) const;
2019-11-11 23:30:19 +01:00
void setDefaultBidirectPinRes(const RiseFall *rf,
2018-09-28 17:54:21 +02:00
float value);
2019-11-11 23:30:19 +01:00
void defaultOutputPinRes(const RiseFall *rf,
2018-09-28 17:54:21 +02:00
// Return values.
float &res,
bool &exists) const;
2019-11-11 23:30:19 +01:00
void setDefaultOutputPinRes(const RiseFall *rf,
2018-09-28 17:54:21 +02:00
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;
2018-09-28 17:54:21 +02:00
void setDefaultFanoutLoad(float load);
// Logic thresholds.
2019-11-11 23:30:19 +01:00
float inputThreshold(const RiseFall *rf) const;
void setInputThreshold(const RiseFall *rf,
2018-09-28 17:54:21 +02:00
float th);
2019-11-11 23:30:19 +01:00
float outputThreshold(const RiseFall *rf) const;
void setOutputThreshold(const RiseFall *rf,
2018-09-28 17:54:21 +02:00
float th);
// Slew thresholds (measured).
2019-11-11 23:30:19 +01:00
float slewLowerThreshold(const RiseFall *rf) const;
void setSlewLowerThreshold(const RiseFall *rf,
2018-09-28 17:54:21 +02:00
float th);
2019-11-11 23:30:19 +01:00
float slewUpperThreshold(const RiseFall *rf) const;
void setSlewUpperThreshold(const RiseFall *rf,
2018-09-28 17:54:21 +02:00
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.
2020-11-07 22:28:47 +01:00
// slew(measured) = slew_derate_from_library * slew(table)
// measured is from slew_lower_threshold to slew_upper_threshold
2018-09-28 17:54:21 +02:00
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);
2018-12-21 07:41:54 +01:00
void addSupplyVoltage(const char *suppy_name,
float voltage);
2019-01-04 01:14:15 +01:00
bool supplyExists(const char *suppy_name) const;
2019-03-13 01:25:53 +01:00
void supplyVoltage(const char *supply_name,
// Return value.
float &voltage,
bool &exists) const;
2018-09-28 17:54:21 +02:00
// Make scaled cell. Call LibertyCell::addScaledCell after it is complete.
LibertyCell *makeScaledCell(const char *name,
const char *filename);
2019-05-28 07:46:24 +02:00
2018-09-28 17:54:21 +02:00
static void
makeCornerMap(LibertyLibrary *lib,
int ap_index,
2019-03-20 05:30:19 +01:00
Network *network,
Report *report);
2018-09-28 17:54:21 +02:00
static void
makeCornerMap(LibertyCell *link_cell,
LibertyCell *map_cell,
2019-03-20 05:30:19 +01:00
int ap_index,
Report *report);
static void
makeCornerMap(LibertyCell *cell1,
LibertyCell *cell2,
bool link,
int ap_index,
Report *report);
2018-09-28 17:54:21 +02:00
protected:
float degradeWireSlew(const LibertyCell *cell,
const Pvt *pvt,
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];
2018-09-28 17:54:21 +02:00
float nominal_process_;
float nominal_voltage_;
float nominal_temperature_;
ScaleFactors *scale_factors_;
ScaleFactorsMap scale_factors_map_;
2019-11-11 23:30:19 +01:00
TableModel *wire_slew_degradation_tbls_[RiseFall::index_count];
2018-09-28 17:54:21 +02:00
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_;
2018-09-28 17:54:21 +02:00
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_;
2019-11-11 23:30:19 +01:00
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];
2018-09-28 17:54:21 +02:00
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_;
2018-12-21 07:41:54 +01:00
SupplyVoltageMap supply_voltage_map_;
2019-05-28 07:46:24 +02:00
LibertyCellSeq *buffers_;
2018-09-28 17:54:21 +02:00
2019-03-13 01:25:53 +01:00
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;
2018-09-28 17:54:21 +02:00
private:
2019-05-28 07:46:24 +02:00
friend class LibertyCell;
2018-12-05 23:18:41 +01:00
friend class LibertyCellIterator;
friend class TableTemplateIterator;
friend class OperatingConditionsIterator;
2018-09-28 17:54:21 +02:00
};
2018-12-05 23:18:41 +01:00
class LibertyCellIterator : public Iterator<LibertyCell*>
2018-09-28 17:54:21 +02:00
{
public:
2018-12-05 23:18:41 +01:00
explicit LibertyCellIterator(const LibertyLibrary *library);
2018-09-28 17:54:21 +02:00
bool hasNext();
LibertyCell *next();
private:
ConcreteCellMap::ConstIterator iter_;
};
2018-12-05 23:18:41 +01:00
class TableTemplateIterator : public TableTemplateMap::ConstIterator
{
public:
TableTemplateIterator(const LibertyLibrary *library,
TableTemplateType type) :
2019-03-13 01:25:53 +01:00
TableTemplateMap::ConstIterator(library->template_maps_[int(type)]) {}
2018-12-05 23:18:41 +01:00
};
class OperatingConditionsIterator : public OperatingConditionsMap::ConstIterator
{
public:
OperatingConditionsIterator(const LibertyLibrary *library) :
OperatingConditionsMap::ConstIterator(library->operating_conditions_) {}
};
////////////////////////////////////////////////////////////////
2018-09-28 17:54:21 +02:00
class LibertyCell : public ConcreteCell
{
public:
LibertyCell(LibertyLibrary *library,
const char *name,
const char *filename);
virtual ~LibertyCell();
2019-01-17 00:37:31 +01:00
LibertyLibrary *libertyLibrary() const { return liberty_library_; }
2018-09-28 17:54:21 +02:00
LibertyLibrary *libertyLibrary() { return liberty_library_; }
LibertyPort *findLibertyPort(const char *name) const;
void findLibertyPortsMatching(PatternMatch *pattern,
LibertyPortSeq *ports) const;
bool hasInternalPorts() const { return has_internal_ports_; }
2021-01-29 00:30:58 +01:00
LibertyPgPort *findPgPort(const char *name) const;
size_t pgPortCount() const { return pg_port_map_.size(); }
2018-09-28 17:54:21 +02:00
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);
2018-11-26 18:15:52 +01:00
bool isMacro() const { return is_macro_; }
void setIsMacro(bool is_macro);
2020-06-10 05:02:59 +02:00
bool isMemory() const { return is_memory_; }
void setIsMemory(bool is_memory);
2018-11-26 18:15:52 +01:00
bool isPad() const { return is_pad_; }
void setIsPad(bool is_pad);
2021-01-23 04:32:47 +01:00
bool isLevelShifter() const { return is_level_shifter_; }
void setIsLevelShifter(bool is_level_shifter);
2018-09-28 17:54:21 +02:00
bool interfaceTiming() const { return interface_timing_; }
void setInterfaceTiming(bool value);
bool isClockGateLatchPosedge() const;
bool isClockGateLatchNegedge() const;
bool isClockGateOther() const;
bool isClockGate() const;
2019-03-13 01:25:53 +01:00
void setClockGateType(ClockGateType type);
// from or to may be nullptr to wildcard.
2018-12-05 23:18:41 +01:00
TimingArcSetSeq *timingArcSets(const LibertyPort *from,
const LibertyPort *to) const;
2018-09-28 17:54:21 +02:00
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;
2020-04-07 03:27:40 +02:00
InternalPowerSeq *internalPowers();
InternalPowerSeq *internalPowers(const LibertyPort *port);
2019-03-21 18:48:50 +01:00
LeakagePowerSeq *leakagePowers() { return &leakage_powers_; }
2019-04-01 18:05:07 +02:00
void leakagePower(// Return values.
float &leakage,
bool &exists) const;
2020-04-07 03:27:40 +02:00
bool leakagePowerExists() const { return leakage_power_exists_; }
2018-09-28 17:54:21 +02:00
bool hasSequentials() const;
// Find the sequential with the output connected to an (internal) port.
Sequential *outputPortSequential(LibertyPort *port);
2018-09-28 17:54:21 +02:00
// 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(TimingArcSet *arc_set,
// Return values.
LibertyPort *&enable_port,
FuncExpr *&enable_func,
2019-11-11 23:30:19 +01:00
RiseFall *&enable_rf) const;
RiseFall *latchCheckEnableEdge(TimingArcSet *check_set);
2018-09-28 17:54:21 +02:00
bool isDisabledConstraint() const { return is_disabled_constraint_; }
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 addBusDcl(BusDcl *bus_dcl);
// Add scaled cell after it is complete.
void addScaledCell(OperatingConditions *op_cond,
LibertyCell *scaled_cell);
unsigned addTimingArcSet(TimingArcSet *set);
void addTimingArcAttrs(TimingArcAttrs *attrs);
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);
2018-12-24 22:07:10 +01:00
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);
2019-05-26 05:02:33 +02:00
bool isBuffer() const;
2020-07-09 17:42:52 +02:00
bool isInverter() const;
2019-05-28 07:46:24 +02:00
// Only valid when isBuffer() returns true.
void bufferPorts(// Return values.
LibertyPort *&input,
2019-11-05 18:14:35 +01:00
LibertyPort *&output) const;
2018-12-24 22:07:10 +01:00
2018-09-28 17:54:21 +02:00
protected:
void addPort(ConcretePort *port);
2018-09-28 17:54:21 +02:00
void setHasInternalPorts(bool has_internal);
void setLibertyLibrary(LibertyLibrary *library);
2018-12-05 23:18:41 +01:00
void deleteTimingArcAttrs();
2018-09-28 17:54:21 +02:00
void makeLatchEnables(Report *report,
Debug *debug);
FuncExpr *findLatchEnableFunc(LibertyPort *data,
LibertyPort *enable) const;
LatchEnable *makeLatchEnable(LibertyPort *d,
LibertyPort *en,
LibertyPort *q,
TimingArcSet *d_to_q,
TimingArcSet *en_to_q,
TimingArcSet *setup_check,
Debug *debug);
void findDefaultCondArcs();
void translatePresetClrCheckRoles();
void inferLatchRoles(Debug *debug);
2018-12-05 23:18:41 +01:00
void deleteInternalPowerAttrs();
2019-03-20 05:30:19 +01:00
void makeTimingArcMap(Report *report);
void makeTimingArcPortMaps();
2019-05-26 05:02:33 +02:00
bool hasBufferFunc(const LibertyPort *input,
const LibertyPort *output) const;
2020-07-09 17:42:52 +02:00
bool hasInverterFunc(const LibertyPort *input,
const LibertyPort *output) const;
2018-09-28 17:54:21 +02:00
LibertyLibrary *liberty_library_;
float area_;
bool dont_use_;
2018-11-26 18:15:52 +01:00
bool is_macro_;
2020-06-10 05:02:59 +02:00
bool is_memory_;
2018-11-26 18:15:52 +01:00
bool is_pad_;
2021-01-23 04:32:47 +01:00
bool is_level_shifter_;
2018-09-28 17:54:21 +02:00
bool has_internal_ports_;
bool interface_timing_;
ClockGateType clock_gate_type_;
2019-03-21 18:48:50 +01:00
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_;
2018-12-05 23:18:41 +01:00
TimingArcAttrsSeq timing_arc_attrs_;
2018-09-28 17:54:21 +02:00
bool has_infered_reg_timing_arcs_;
2019-03-21 18:48:50 +01:00
InternalPowerSeq internal_powers_;
2020-04-07 03:27:40 +02:00
PortInternalPowerSeq port_internal_powers_;
2018-12-05 23:18:41 +01:00
InternalPowerAttrsSeq internal_power_attrs_;
2019-03-21 18:48:50 +01:00
LeakagePowerSeq leakage_powers_;
SequentialSeq sequentials_;
PortToSequentialMap port_to_seq_map_;
2018-09-28 17:54:21 +02:00
BusDclMap bus_dcls_;
2019-03-21 18:48:50 +01:00
ModeDefMap mode_defs_;
2018-09-28 17:54:21 +02:00
ScaleFactors *scale_factors_;
2019-03-21 18:48:50 +01:00
ScaledCellMap scaled_cells_;
2018-09-28 17:54:21 +02:00
TestCell *test_cell_;
// Latch D->Q to LatchEnable.
LatchEnableMap latch_d_to_q_map_;
// Latch EN->D setup to LatchEnable.
LatchEnableMap latch_check_map_;
// 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<LibertyCell*> corner_cells_;
2018-11-26 18:15:52 +01:00
float leakage_power_;
2019-04-01 18:05:07 +02:00
bool leakage_power_exists_;
2018-12-24 22:07:10 +01:00
LibertyPgPortMap pg_port_map_;
2018-09-28 17:54:21 +02:00
private:
friend class LibertyLibrary;
friend class LibertyCellPortIterator;
2021-01-29 00:30:58 +01:00
friend class LibertyCellPgPortIterator;
2018-09-28 17:54:21 +02:00
friend class LibertyPort;
friend class LibertyBuilder;
2018-12-05 23:18:41 +01:00
friend class LibertyCellTimingArcSetIterator;
friend class LibertyCellSequentialIterator;
2018-09-28 17:54:21 +02:00
};
class LibertyCellPortIterator : public Iterator<LibertyPort*>
{
public:
explicit LibertyCellPortIterator(const LibertyCell *cell);
bool hasNext();
LibertyPort *next();
private:
ConcretePortSeq::ConstIterator iter_;
};
class LibertyCellPortBitIterator : public Iterator<LibertyPort*>
{
public:
explicit LibertyCellPortBitIterator(const LibertyCell *cell);
virtual ~LibertyCellPortBitIterator();
2018-09-28 17:54:21 +02:00
bool hasNext();
LibertyPort *next();
private:
ConcreteCellPortBitIterator *iter_;
};
2021-01-29 00:30:58 +01:00
class LibertyCellPgPortIterator : public Iterator<LibertyPgPort*>
{
public:
LibertyCellPgPortIterator(const LibertyCell *cell);
bool hasNext();
LibertyPgPort *next();
private:
LibertyPgPortMap::Iterator iter_;
};
2019-03-21 18:48:50 +01:00
class LibertyCellTimingArcSetIterator : public TimingArcSetSeq::ConstIterator
2018-12-05 23:18:41 +01:00
{
public:
LibertyCellTimingArcSetIterator(const LibertyCell *cell);
// from or to may be nullptr to wildcard.
2018-12-05 23:18:41 +01:00
LibertyCellTimingArcSetIterator(const LibertyCell *cell,
const LibertyPort *from,
const LibertyPort *to);
};
class LibertyCellSequentialIterator : public SequentialSeq::ConstIterator
{
public:
LibertyCellSequentialIterator(const LibertyCell *cell) :
SequentialSeq::ConstIterator(cell->sequentials_) {}
};
////////////////////////////////////////////////////////////////
2018-09-28 17:54:21 +02:00
class LibertyPort : public ConcretePort
{
public:
LibertyCell *libertyCell() const { return liberty_cell_; }
LibertyLibrary *libertyLibrary() const { return liberty_cell_->libertyLibrary(); }
2018-09-28 17:54:21 +02:00
LibertyPort *findLibertyMember(int index) const;
LibertyPort *findLibertyBusBit(int index) const;
BusDcl *busDcl() const { return bus_dcl_; }
void setDirection(PortDirection *dir);
void fanoutLoad(// Return values.
float &fanout_load,
bool &exists) const;
void setFanoutLoad(float fanout_load);
2020-07-10 01:10:21 +02:00
float capacitance() const;
float capacitance(const MinMax *min_max) const;
2019-11-11 23:30:19 +01:00
float capacitance(const RiseFall *rf,
2018-09-28 17:54:21 +02:00
const MinMax *min_max) const;
2019-11-11 23:30:19 +01:00
void capacitance(const RiseFall *rf,
2018-09-28 17:54:21 +02:00
const MinMax *min_max,
// Return values.
float &cap,
bool &exists) const;
// Capacitance at op_cond derated by library/cell scale factors
// using pvt.
2019-11-11 23:30:19 +01:00
float capacitance(const RiseFall *rf,
2018-09-28 17:54:21 +02:00
const MinMax *min_max,
const OperatingConditions *op_cond,
const Pvt *pvt) const;
bool capacitanceIsOneValue() const;
2018-09-28 17:54:21 +02:00
void setCapacitance(float cap);
2019-11-11 23:30:19 +01:00
void setCapacitance(const RiseFall *rf,
2018-09-28 17:54:21 +02:00
const MinMax *min_max,
float cap);
// Max of rise/fall.
float driveResistance() const;
2020-10-25 22:59:54 +01:00
float driveResistance(const RiseFall *rf,
const MinMax *min_max) const;
// Zero load delay.
2020-12-20 16:31:33 +01:00
ArcDelay intrinsicDelay(const StaState *sta) const;
ArcDelay intrinsicDelay(const RiseFall *rf,
const MinMax *min_max,
const StaState *sta) const;
2018-09-28 17:54:21 +02:00
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);
// high = rise, low = fall
2019-11-11 23:30:19 +01:00
void minPulseWidth(const RiseFall *hi_low,
2018-09-28 17:54:21 +02:00
const OperatingConditions *op_cond,
const Pvt *pvt,
float &min_width,
bool &exists) const;
// Unscaled value.
2019-11-11 23:30:19 +01:00
void minPulseWidth(const RiseFall *hi_low,
2018-09-28 17:54:21 +02:00
float &min_width,
bool &exists) const;
2019-11-11 23:30:19 +01:00
void setMinPulseWidth(RiseFall *hi_low,
2018-09-28 17:54:21 +02:00
float min_width);
bool isClock() const;
void setIsClock(bool is_clk);
bool isClockGateClockPin() const { return is_clk_gate_clk_pin_; }
void setIsClockGateClockPin(bool is_clk_gate_clk);
bool isClockGateEnablePin() const { return is_clk_gate_enable_pin_; }
void setIsClockGateEnablePin(bool is_clk_gate_enable);
bool isClockGateOutPin() const { return is_clk_gate_out_pin_; }
void setIsClockGateOutPin(bool is_clk_gate_out);
bool isPllFeedbackPin() const { return is_pll_feedback_pin_; }
void setIsPllFeedbackPin(bool is_pll_feedback_pin);
// 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);
2019-11-11 23:30:19 +01:00
RiseFall *pulseClkTrigger() const { return pulse_clk_trigger_; }
2018-09-28 17:54:21 +02:00
// Rise for high, fall for low.
2019-11-11 23:30:19 +01:00
RiseFall *pulseClkSense() const { return pulse_clk_sense_; }
void setPulseClk(RiseFall *rfigger,
RiseFall *sense);
2018-09-28 17:54:21 +02:00
bool isDisabledConstraint() const { return is_disabled_constraint_; }
void setIsDisabledConstraint(bool is_disabled);
LibertyPort *cornerPort(int ap_index);
2020-11-11 19:31:47 +01:00
const LibertyPort *cornerPort(int ap_index) const;
2018-09-28 17:54:21 +02:00
void setCornerPort(LibertyPort *corner_port,
int ap_index);
2018-12-24 22:07:10 +01:00
const char *relatedGroundPin() const { return related_ground_pin_; }
void setRelatedGroundPin(const char *related_ground_pin);
2018-11-26 18:15:52 +01:00
const char *relatedPowerPin() const { return related_power_pin_; }
void setRelatedPowerPin(const char *related_power_pin);
2018-09-28 17:54:21 +02:00
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,
2018-09-28 17:54:21 +02:00
int to_index,
bool is_bundle,
ConcretePortSeq *members);
virtual ~LibertyPort();
2018-09-28 17:54:21 +02:00
void setMinPort(LibertyPort *min);
void addScaledPort(OperatingConditions *op_cond,
LibertyPort *scaled_port);
LibertyCell *liberty_cell_;
BusDcl *bus_dcl_;
2018-09-28 17:54:21 +02:00
FuncExpr *function_;
FuncExpr *tristate_enable_;
ScaledPortMap *scaled_ports_;
RiseFallMinMax capacitance_;
MinMaxFloatValues slew_limit_; // inputs and outputs
2018-09-28 17:54:21 +02:00
MinMaxFloatValues cap_limit_; // outputs
float fanout_load_; // inputs
bool fanout_load_exists_;
2018-09-28 17:54:21 +02:00
MinMaxFloatValues fanout_limit_; // outputs
float min_period_;
2019-11-11 23:30:19 +01:00
float min_pulse_width_[RiseFall::index_count];
RiseFall *pulse_clk_trigger_;
RiseFall *pulse_clk_sense_;
2018-12-24 22:07:10 +01:00
const char *related_ground_pin_;
2018-11-26 18:15:52 +01:00
const char *related_power_pin_;
2018-09-28 17:54:21 +02:00
Vector<LibertyPort*> corner_ports_;
2019-11-11 23:30:19 +01:00
unsigned int min_pulse_width_exists_:RiseFall::index_count;
2018-09-28 17:54:21 +02:00
bool min_period_exists_:1;
bool is_clk_:1;
bool is_reg_clk_:1;
bool is_check_clk_:1;
bool is_clk_gate_clk_pin_:1;
bool is_clk_gate_enable_pin_:1;
bool is_clk_gate_out_pin_:1;
bool is_pll_feedback_pin_:1;
bool is_disabled_constraint_:1;
private:
friend class LibertyLibrary;
friend class LibertyCell;
friend class LibertyBuilder;
friend class LibertyReader;
};
void
sortLibertyPortSet(LibertyPortSet *set,
LibertyPortSeq &ports);
class LibertyPortMemberIterator : public Iterator<LibertyPort*>
{
public:
explicit LibertyPortMemberIterator(const LibertyPort *port);
virtual ~LibertyPortMemberIterator();
2018-09-28 17:54:21 +02:00
virtual bool hasNext();
virtual LibertyPort *next();
private:
ConcretePortMemberIterator *iter_;
};
// Process, voltage temperature.
class Pvt
{
public:
Pvt(float process,
float voltage,
float temperature);
virtual ~Pvt() {}
2018-09-28 17:54:21 +02:00
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();
2018-09-28 17:54:21 +02:00
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,
2019-11-11 23:30:19 +01:00
RiseFall *rf);
2018-09-28 17:54:21 +02:00
float scale(ScaleFactorType type,
ScaleFactorPvt pvt,
int tr_index);
float scale(ScaleFactorType type,
ScaleFactorPvt pvt);
void setScale(ScaleFactorType type,
ScaleFactorPvt pvt,
2019-11-11 23:30:19 +01:00
RiseFall *rf,
2018-09-28 17:54:21 +02:00
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];
2018-09-28 17:54:21 +02:00
};
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,
TableAxis *axis1,
TableAxis *axis2,
TableAxis *axis3);
~TableTemplate();
const char *name() const { return name_; }
void setName(const char *name);
TableAxis *axis1() const { return axis1_; }
void setAxis1(TableAxis *axis);
TableAxis *axis2() const { return axis2_; }
void setAxis2(TableAxis *axis);
TableAxis *axis3() const { return axis3_; }
void setAxis3(TableAxis *axis);
protected:
const char *name_;
TableAxis *axis1_;
TableAxis *axis2_;
TableAxis *axis3_;
};
class TestCell
{
public:
TestCell();
TestCell(LibertyPort *data_in,
LibertyPort *scan_in,
LibertyPort *scan_enable,
LibertyPort *scan_out,
LibertyPort *scan_out_inv);
LibertyPort *dataIn() const { return data_in_; }
void setDataIn(LibertyPort *port);
LibertyPort *scanIn() const { return scan_in_; }
void setScanIn(LibertyPort *port);
LibertyPort *scanEnable() const { return scan_enable_; }
void setScanEnable(LibertyPort *port);
LibertyPort *scanOut() const { return scan_out_; }
void setScanOut(LibertyPort *port);
LibertyPort *scanOutInv() const { return scan_out_inv_; }
void setScanOutInv(LibertyPort *port);
protected:
LibertyPort *data_in_;
LibertyPort *scan_in_;
LibertyPort *scan_enable_;
LibertyPort *scan_out_;
LibertyPort *scan_out_inv_;
};
class OcvDerate
{
public:
OcvDerate(const char *name);
~OcvDerate();
const char *name() const { return name_; }
2019-11-11 23:30:19 +01:00
Table *derateTable(const RiseFall *rf,
2018-09-28 17:54:21 +02:00
const EarlyLate *early_late,
PathType path_type);
2019-11-11 23:30:19 +01:00
void setDerateTable(const RiseFall *rf,
2018-09-28 17:54:21 +02:00
const EarlyLate *early_late,
PathType path_type,
Table *derate);
private:
const char *name_;
// [rf_type][derate_type][path_type]
2019-11-11 23:30:19 +01:00
Table *derate_[RiseFall::index_count][EarlyLate::index_count][path_type_count];
2018-09-28 17:54:21 +02:00
};
2018-12-24 22:07:10 +01:00
// Power/ground port.
class LibertyPgPort
{
public:
2018-12-26 20:03:31 +01:00
enum PgType { unknown,
primary_power, primary_ground,
backup_power, backup_ground,
internal_power, internal_ground,
nwell, pwell,
deepnwell, deeppwell};
2019-01-01 21:25:25 +01:00
LibertyPgPort(const char *name,
LibertyCell *cell);
2018-12-24 22:07:10 +01:00
~LibertyPgPort();
2021-01-29 00:30:58 +01:00
const char *name() const { return name_; }
2019-01-01 21:25:25 +01:00
LibertyCell *cell() const { return cell_; }
2018-12-24 22:07:10 +01:00
PgType pgType() const { return pg_type_; }
void setPgType(PgType type);
const char *voltageName() const { return voltage_name_; }
void setVoltageName(const char *voltage_name);
2021-01-29 00:30:58 +01:00
static bool equiv(const LibertyPgPort *port1,
const LibertyPgPort *port2);
2018-12-24 22:07:10 +01:00
private:
const char *name_;
PgType pg_type_;
const char *voltage_name_;
2019-01-01 21:25:25 +01:00
LibertyCell *cell_;
2018-12-24 22:07:10 +01:00
};
2018-09-28 17:54:21 +02:00
} // namespace