2018-09-28 17:54:21 +02:00
|
|
|
// OpenSTA, Static Timing Analyzer
|
2020-03-07 03:50:37 +01:00
|
|
|
// Copyright (c) 2020, 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
|
|
|
|
|
// 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/>.
|
|
|
|
|
|
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 "DisallowCopyAssign.hh"
|
|
|
|
|
#include "MinMax.hh"
|
|
|
|
|
#include "RiseFallMinMax.hh"
|
|
|
|
|
#include "ConcreteLibrary.hh"
|
|
|
|
|
#include "RiseFallValues.hh"
|
|
|
|
|
#include "MinMaxValues.hh"
|
|
|
|
|
#include "Transition.hh"
|
|
|
|
|
#include "LibertyClass.hh"
|
2018-09-28 17:54:21 +02:00
|
|
|
|
|
|
|
|
namespace sta {
|
|
|
|
|
|
2018-12-05 23:18:41 +01:00
|
|
|
class LibertyCellIterator;
|
2018-09-28 17:54:21 +02:00
|
|
|
class LibertyCellPortIterator;
|
|
|
|
|
class LibertyCellPortBitIterator;
|
|
|
|
|
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;
|
2018-09-28 17:54:21 +02:00
|
|
|
|
|
|
|
|
typedef Set<Library*> LibrarySet;
|
|
|
|
|
typedef Map<const char*, TableTemplate*, CharPtrLess> TableTemplateMap;
|
|
|
|
|
typedef Map<const char*, BusDcl *, CharPtrLess> BusDclMap;
|
|
|
|
|
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, count, unknown };
|
|
|
|
|
|
|
|
|
|
enum class TableTemplateType { delay, power, output_current, ocv, count };
|
2019-03-04 02:50:56 +01:00
|
|
|
|
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);
|
2019-07-01 07:30:53 +02:00
|
|
|
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;
|
2019-03-04 02:50:56 +01:00
|
|
|
void addTableTemplate(TableTemplate *tbl_template,
|
|
|
|
|
TableTemplateType type);
|
|
|
|
|
TableTemplate *findTableTemplate(const char *name,
|
|
|
|
|
TableTemplateType type);
|
2018-09-28 17:54:21 +02:00
|
|
|
float nominalProcess() { 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 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,
|
2018-09-28 17:54:21 +02: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);
|
2020-06-09 05:11:15 +02:00
|
|
|
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.
|
|
|
|
|
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_;
|
2019-03-13 01:25:53 +01:00
|
|
|
TableTemplateMap template_maps_[int(TableTemplateType::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_;
|
2020-06-09 05:11:15 +02:00
|
|
|
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
|
|
|
|
|
|
|
|
// Set if any library has rise/fall capacitances.
|
|
|
|
|
static bool found_rise_fall_caps_;
|
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:
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(LibertyLibrary);
|
|
|
|
|
|
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:
|
2018-12-05 23:18:41 +01:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(LibertyCellIterator);
|
2018-09-28 17:54:21 +02:00
|
|
|
|
|
|
|
|
ConcreteCellMap::ConstIterator iter_;
|
|
|
|
|
};
|
|
|
|
|
|
2018-12-05 23:18:41 +01:00
|
|
|
class TableTemplateIterator : public TableTemplateMap::ConstIterator
|
|
|
|
|
{
|
|
|
|
|
public:
|
2019-03-04 02:50:56 +01:00
|
|
|
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);
|
2019-07-01 07:30:53 +02:00
|
|
|
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_; }
|
2018-12-24 22:07:10 +01:00
|
|
|
LibertyPgPort *findPgPort(const char *name);
|
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);
|
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);
|
2019-06-24 04:52:29 +02:00
|
|
|
// 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;
|
2019-05-26 02:08:53 +02:00
|
|
|
|
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_; }
|
2019-05-26 02:08:53 +02:00
|
|
|
|
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);
|
2019-05-26 02:08:53 +02:00
|
|
|
|
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 *latchCheckEnableTrans(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);
|
|
|
|
|
|
2019-05-26 02:08:53 +02:00
|
|
|
// 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);
|
2019-06-28 22:38:56 +02:00
|
|
|
unsigned addTimingArcSet(TimingArcSet *set);
|
2019-05-26 02:08:53 +02:00
|
|
|
void addTimingArcAttrs(TimingArcAttrs *attrs);
|
2019-06-28 22:38:56 +02:00
|
|
|
void addInternalPower(InternalPower *power);
|
2019-05-26 02:08:53 +02:00
|
|
|
void addInternalPowerAttrs(InternalPowerAttrs *attrs);
|
2019-06-28 22:38:56 +02:00
|
|
|
void addLeakagePower(LeakagePower *power);
|
2019-05-26 02:08:53 +02:00
|
|
|
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);
|
2019-05-26 02:08:53 +02:00
|
|
|
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.
|
2019-06-28 22:38:56 +02:00
|
|
|
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:
|
2019-06-28 22:38:56 +02:00
|
|
|
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();
|
2019-06-28 22:38:56 +02:00
|
|
|
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_;
|
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:
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(LibertyCell);
|
|
|
|
|
|
|
|
|
|
friend class LibertyLibrary;
|
|
|
|
|
friend class LibertyCellPortIterator;
|
|
|
|
|
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:
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(LibertyCellPortIterator);
|
|
|
|
|
|
|
|
|
|
ConcretePortSeq::ConstIterator iter_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class LibertyCellPortBitIterator : public Iterator<LibertyPort*>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
explicit LibertyCellPortBitIterator(const LibertyCell *cell);
|
2019-07-01 07:30:53 +02:00
|
|
|
virtual ~LibertyCellPortBitIterator();
|
2018-09-28 17:54:21 +02:00
|
|
|
bool hasNext();
|
|
|
|
|
LibertyPort *next();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(LibertyCellPortBitIterator);
|
|
|
|
|
|
|
|
|
|
ConcreteCellPortBitIterator *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);
|
2019-06-24 04:52:29 +02:00
|
|
|
// 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_; }
|
2020-05-13 02:57:04 +02:00
|
|
|
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;
|
2020-06-09 05:11:15 +02:00
|
|
|
void fanoutLoad(// Return values.
|
|
|
|
|
float &fanout_load,
|
|
|
|
|
bool &exists) const;
|
|
|
|
|
void setFanoutLoad(float fanout_load);
|
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;
|
2019-04-11 05:36:48 +02:00
|
|
|
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);
|
2019-11-11 23:30:19 +01:00
|
|
|
float driveResistance(const RiseFall *rf,
|
2019-06-24 04:52:29 +02:00
|
|
|
const MinMax *min_max) const;
|
|
|
|
|
// Max of rise/fall.
|
|
|
|
|
float driveResistance() 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);
|
|
|
|
|
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,
|
|
|
|
|
int from_index,
|
|
|
|
|
int to_index,
|
|
|
|
|
bool is_bundle,
|
|
|
|
|
ConcretePortSeq *members);
|
2019-07-01 07:30:53 +02:00
|
|
|
virtual ~LibertyPort();
|
2019-06-28 22:38:56 +02:00
|
|
|
void setDirection(PortDirection *dir);
|
2018-09-28 17:54:21 +02:00
|
|
|
void setMinPort(LibertyPort *min);
|
|
|
|
|
void addScaledPort(OperatingConditions *op_cond,
|
|
|
|
|
LibertyPort *scaled_port);
|
|
|
|
|
|
|
|
|
|
LibertyCell *liberty_cell_;
|
|
|
|
|
FuncExpr *function_;
|
|
|
|
|
FuncExpr *tristate_enable_;
|
|
|
|
|
ScaledPortMap *scaled_ports_;
|
|
|
|
|
RiseFallMinMax capacitance_;
|
|
|
|
|
MinMaxFloatValues slew_limit_; // inputs and outputs
|
|
|
|
|
MinMaxFloatValues cap_limit_; // outputs
|
2020-06-09 05:11:15 +02:00
|
|
|
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:
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(LibertyPort);
|
|
|
|
|
|
|
|
|
|
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);
|
2019-07-01 07:30:53 +02:00
|
|
|
virtual ~LibertyPortMemberIterator();
|
2018-09-28 17:54:21 +02:00
|
|
|
virtual bool hasNext();
|
|
|
|
|
virtual LibertyPort *next();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(LibertyPortMemberIterator);
|
|
|
|
|
|
|
|
|
|
ConcretePortMemberIterator *iter_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Process, voltage temperature.
|
|
|
|
|
class Pvt
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
Pvt(float process,
|
|
|
|
|
float voltage,
|
|
|
|
|
float temperature);
|
2019-07-01 07:30:53 +02:00
|
|
|
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_;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(Pvt);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class OperatingConditions : public Pvt
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
explicit OperatingConditions(const char *name);
|
|
|
|
|
OperatingConditions(const char *name,
|
|
|
|
|
float process,
|
|
|
|
|
float voltage,
|
|
|
|
|
float temperature,
|
|
|
|
|
WireloadTree wire_load_tree);
|
2019-07-01 07:30:53 +02:00
|
|
|
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_;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(OperatingConditions);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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_;
|
2019-11-11 23:30:19 +01:00
|
|
|
float scales_[scale_factor_type_count][int(ScaleFactorPvt::count)][RiseFall::index_count];
|
2018-09-28 17:54:21 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(ScaleFactors);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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_;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(BusDcl);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 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:
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(ModeDef);
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(ModeValueDef);
|
|
|
|
|
|
|
|
|
|
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_;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(TableTemplate);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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_;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(TestCell);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
const char *name() { 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);
|
|
|
|
|
|
|
|
|
|
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
|