2.0.13
This commit is contained in:
parent
ed3ad4fb30
commit
fcfec7ae54
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
cmake_minimum_required (VERSION 3.9)
|
cmake_minimum_required (VERSION 3.9)
|
||||||
|
|
||||||
project(STA VERSION 2.0.12)
|
project(STA VERSION 2.0.13)
|
||||||
|
|
||||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include "Machine.hh"
|
#include "Machine.hh"
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
|
#include "Corner.hh"
|
||||||
#include "DcalcAnalysisPt.hh"
|
#include "DcalcAnalysisPt.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
@ -23,19 +24,13 @@ namespace sta {
|
||||||
DcalcAnalysisPt::DcalcAnalysisPt(Corner *corner,
|
DcalcAnalysisPt::DcalcAnalysisPt(Corner *corner,
|
||||||
DcalcAPIndex index,
|
DcalcAPIndex index,
|
||||||
const OperatingConditions *op_cond,
|
const OperatingConditions *op_cond,
|
||||||
const MinMax *cnst_min_max,
|
const MinMax *min_max,
|
||||||
const MinMax *delay_min_max,
|
const MinMax *check_clk_slew_min_max) :
|
||||||
const MinMax *slew_min_max,
|
|
||||||
const MinMax *check_clk_slew_min_max,
|
|
||||||
const ParasiticAnalysisPt *parasitic_ap) :
|
|
||||||
corner_(corner),
|
corner_(corner),
|
||||||
index_(index),
|
index_(index),
|
||||||
op_cond_(op_cond),
|
op_cond_(op_cond),
|
||||||
cnst_min_max_(cnst_min_max),
|
min_max_(min_max),
|
||||||
delay_min_max_(delay_min_max),
|
check_clk_slew_min_max_(check_clk_slew_min_max)
|
||||||
slew_min_max_(slew_min_max),
|
|
||||||
check_clk_slew_min_max_(check_clk_slew_min_max),
|
|
||||||
parasitic_ap_(parasitic_ap)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,11 +40,10 @@ DcalcAnalysisPt::setOperatingConditions(const OperatingConditions *op_cond)
|
||||||
op_cond_ = op_cond;
|
op_cond_ = op_cond;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
ParasiticAnalysisPt *
|
||||||
DcalcAnalysisPt::
|
DcalcAnalysisPt::parasiticAnalysisPt() const
|
||||||
setParasiticAnalysisPt(const ParasiticAnalysisPt *parasitic_ap)
|
|
||||||
{
|
{
|
||||||
parasitic_ap_ = parasitic_ap;
|
return corner_->findParasiticAnalysisPt(min_max_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,8 @@ public:
|
||||||
DcalcAnalysisPt(Corner *corner,
|
DcalcAnalysisPt(Corner *corner,
|
||||||
DcalcAPIndex index,
|
DcalcAPIndex index,
|
||||||
const OperatingConditions *op_cond,
|
const OperatingConditions *op_cond,
|
||||||
const MinMax *cnst_min_max,
|
const MinMax *min_max,
|
||||||
const MinMax *delay_min_max,
|
const MinMax *check_clk_slew_min_max);
|
||||||
const MinMax *slew_min_max,
|
|
||||||
const MinMax *check_clk_slew_min_max,
|
|
||||||
const ParasiticAnalysisPt *parasitic_ap);
|
|
||||||
Corner *corner() const { return corner_; }
|
Corner *corner() const { return corner_; }
|
||||||
// Which of the delay_count results this analysis point corresponds to.
|
// Which of the delay_count results this analysis point corresponds to.
|
||||||
DcalcAPIndex index() const { return index_; }
|
DcalcAPIndex index() const { return index_; }
|
||||||
|
|
@ -54,16 +51,15 @@ public:
|
||||||
// Slew min/max of timing check clock.
|
// Slew min/max of timing check clock.
|
||||||
const MinMax *checkClkSlewMinMax() const { return check_clk_slew_min_max_; }
|
const MinMax *checkClkSlewMinMax() const { return check_clk_slew_min_max_; }
|
||||||
// Constraint min/max values to use.
|
// Constraint min/max values to use.
|
||||||
const MinMax *constraintMinMax() const { return cnst_min_max_; }
|
const MinMax *constraintMinMax() const { return min_max_; }
|
||||||
// Constraints::operatingCondition(cnst_min_max_)
|
// Constraints::operatingCondition(cnst_min_max_)
|
||||||
const OperatingConditions *operatingConditions() const { return op_cond_; }
|
const OperatingConditions *operatingConditions() const { return op_cond_; }
|
||||||
void setOperatingConditions(const OperatingConditions *op_cond);
|
void setOperatingConditions(const OperatingConditions *op_cond);
|
||||||
// Delay merging min/max operator (for wires).
|
// Delay merging min/max operator (for wires).
|
||||||
const MinMax *delayMinMax() const { return delay_min_max_; }
|
const MinMax *delayMinMax() const { return min_max_; }
|
||||||
// Merge min/max slews across timing arcs.
|
// Merge min/max slews across timing arcs.
|
||||||
const MinMax *slewMinMax() const { return slew_min_max_; }
|
const MinMax *slewMinMax() const { return min_max_; }
|
||||||
const ParasiticAnalysisPt *parasiticAnalysisPt()const{return parasitic_ap_;}
|
ParasiticAnalysisPt *parasiticAnalysisPt() const;
|
||||||
void setParasiticAnalysisPt(const ParasiticAnalysisPt *parasitic_ap);
|
|
||||||
void setCheckClkSlewIndex(DcalcAPIndex index);
|
void setCheckClkSlewIndex(DcalcAPIndex index);
|
||||||
int libertyIndex() const;
|
int libertyIndex() const;
|
||||||
|
|
||||||
|
|
@ -74,11 +70,8 @@ private:
|
||||||
DcalcAPIndex index_;
|
DcalcAPIndex index_;
|
||||||
DcalcAPIndex check_clk_slew_index_;
|
DcalcAPIndex check_clk_slew_index_;
|
||||||
const OperatingConditions *op_cond_;
|
const OperatingConditions *op_cond_;
|
||||||
const MinMax *cnst_min_max_;
|
const MinMax *min_max_;
|
||||||
const MinMax *delay_min_max_;
|
|
||||||
const MinMax *slew_min_max_;
|
|
||||||
const MinMax *check_clk_slew_min_max_;
|
const MinMax *check_clk_slew_min_max_;
|
||||||
const ParasiticAnalysisPt *parasitic_ap_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -848,7 +848,8 @@ LibertyCell::LibertyCell(LibertyLibrary *library,
|
||||||
ocv_arc_depth_(0.0),
|
ocv_arc_depth_(0.0),
|
||||||
ocv_derate_(nullptr),
|
ocv_derate_(nullptr),
|
||||||
is_disabled_constraint_(false),
|
is_disabled_constraint_(false),
|
||||||
leakage_power_(0.0)
|
leakage_power_(0.0),
|
||||||
|
leakage_power_exists_(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1081,6 +1082,16 @@ void
|
||||||
LibertyCell::setLeakagePower(float leakage)
|
LibertyCell::setLeakagePower(float leakage)
|
||||||
{
|
{
|
||||||
leakage_power_ = leakage;
|
leakage_power_ = leakage;
|
||||||
|
leakage_power_exists_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LibertyCell::leakagePower(// Return values.
|
||||||
|
float &leakage,
|
||||||
|
bool &exists) const
|
||||||
|
{
|
||||||
|
leakage = leakage_power_;
|
||||||
|
exists = leakage_power_exists_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -429,7 +429,10 @@ public:
|
||||||
bool hasTimingArcs(LibertyPort *port) const;
|
bool hasTimingArcs(LibertyPort *port) const;
|
||||||
InternalPowerSeq *internalPowers() { return &internal_powers_; }
|
InternalPowerSeq *internalPowers() { return &internal_powers_; }
|
||||||
LeakagePowerSeq *leakagePowers() { return &leakage_powers_; }
|
LeakagePowerSeq *leakagePowers() { return &leakage_powers_; }
|
||||||
float leakagePower() const { return leakage_power_; }
|
void leakagePower(// Return values.
|
||||||
|
float &leakage,
|
||||||
|
bool &exists) const;
|
||||||
|
bool leakagePowerEx() const { return leakage_power_exists_; }
|
||||||
bool hasSequentials() const;
|
bool hasSequentials() const;
|
||||||
void makeSequential(int size,
|
void makeSequential(int size,
|
||||||
bool is_register,
|
bool is_register,
|
||||||
|
|
@ -537,6 +540,7 @@ protected:
|
||||||
bool is_disabled_constraint_;
|
bool is_disabled_constraint_;
|
||||||
Vector<LibertyCell*> corner_cells_;
|
Vector<LibertyCell*> corner_cells_;
|
||||||
float leakage_power_;
|
float leakage_power_;
|
||||||
|
bool leakage_power_exists_;
|
||||||
LibertyPgPortMap pg_port_map_;
|
LibertyPgPortMap pg_port_map_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -193,9 +193,17 @@ EstimateParasitics::estimatePiElmoreBalanced(const Pin *drvr_pin,
|
||||||
}
|
}
|
||||||
delete load_iter;
|
delete load_iter;
|
||||||
|
|
||||||
c1 = static_cast<float>(y2 * y2 / y3);
|
if (y3 == 0) {
|
||||||
c2 = static_cast<float>(y1 - y2 * y2 / y3);
|
// No loads.
|
||||||
rpi = static_cast<float>(-y3 * y3 / (y2 * y2 * y2));
|
c1 = 0.0;
|
||||||
|
c2 = 0.0;
|
||||||
|
rpi = 0.0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c1 = static_cast<float>(y2 * y2 / y3);
|
||||||
|
c2 = static_cast<float>(y1 - y2 * y2 / y3);
|
||||||
|
rpi = static_cast<float>(-y3 * y3 / (y2 * y2 * y2));
|
||||||
|
}
|
||||||
elmore_res = static_cast<float>(res_fanout);
|
elmore_res = static_cast<float>(res_fanout);
|
||||||
elmore_cap = static_cast<float>(cap_fanout);
|
elmore_cap = static_cast<float>(cap_fanout);
|
||||||
elmore_use_load_cap = true;
|
elmore_use_load_cap = true;
|
||||||
|
|
|
||||||
|
|
@ -253,7 +253,8 @@ LibertyPortPairNameLess::operator()(const LibertyPortPair *pair1,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sortLibertyPortPairSet(LibertyPortPairSet *sets, LibertyPortPairSeq &pairs)
|
sortLibertyPortPairSet(LibertyPortPairSet *sets,
|
||||||
|
LibertyPortPairSeq &pairs)
|
||||||
{
|
{
|
||||||
LibertyPortPairSet::Iterator pair_iter(sets);
|
LibertyPortPairSet::Iterator pair_iter(sets);
|
||||||
while (pair_iter.hasNext())
|
while (pair_iter.hasNext())
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,8 @@ sortDisabledInstancePortsMap(DisabledInstancePortsMap *inst_map,
|
||||||
Network *network,
|
Network *network,
|
||||||
DisabledInstancePortsSeq &disables);
|
DisabledInstancePortsSeq &disables);
|
||||||
void
|
void
|
||||||
sortLibertyPortPairSet(LibertyPortPairSet *sets, LibertyPortPairSeq &pairs);
|
sortLibertyPortPairSet(LibertyPortPairSet *sets,
|
||||||
|
LibertyPortPairSeq &pairs);
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -24,24 +24,23 @@
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
Corners::Corners(StaState *sta) :
|
Corners::Corners(StaState *sta) :
|
||||||
StaState(sta),
|
StaState(sta)
|
||||||
default_corner_(nullptr)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Corners::~Corners()
|
Corners::~Corners()
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
parasitic_analysis_pts_.deleteContentsClear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Corners::clear()
|
Corners::clear()
|
||||||
{
|
{
|
||||||
corners_.deleteContentsClear();
|
corners_.deleteContentsClear();
|
||||||
|
corner_map_.clear();
|
||||||
dcalc_analysis_pts_.deleteContentsClear();
|
dcalc_analysis_pts_.deleteContentsClear();
|
||||||
path_analysis_pts_.deleteContentsClear();
|
path_analysis_pts_.deleteContentsClear();
|
||||||
default_corner_ = nullptr;
|
parasitic_analysis_pts_.deleteContentsClear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -59,13 +58,13 @@ Corners::multiCorner() const
|
||||||
Corner *
|
Corner *
|
||||||
Corners::findCorner(const char *corner_name)
|
Corners::findCorner(const char *corner_name)
|
||||||
{
|
{
|
||||||
return corners_.findKey(corner_name);
|
return corner_map_.findKey(corner_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Corner *
|
Corner *
|
||||||
Corners::defaultCorner()
|
Corners::findCorner(int corner_index)
|
||||||
{
|
{
|
||||||
return default_corner_;
|
return corners_[corner_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -96,10 +95,9 @@ Corners::makeCorners(StringSet *corner_names)
|
||||||
while (name_iter.hasNext()) {
|
while (name_iter.hasNext()) {
|
||||||
const char *name = name_iter.next();
|
const char *name = name_iter.next();
|
||||||
Corner *corner = new Corner(name, index);
|
Corner *corner = new Corner(name, index);
|
||||||
|
corners_.push_back(corner);
|
||||||
// Use the copied name in the map.
|
// Use the copied name in the map.
|
||||||
corners_[corner->name()] = corner;
|
corner_map_[corner->name()] = corner;
|
||||||
if (default_corner_ == nullptr)
|
|
||||||
default_corner_ = corner;
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
updateCornerParasiticAnalysisPts();
|
updateCornerParasiticAnalysisPts();
|
||||||
|
|
@ -142,11 +140,11 @@ Corners::makeParasiticAnalysisPtsMinMax()
|
||||||
void
|
void
|
||||||
Corners::updateCornerParasiticAnalysisPts()
|
Corners::updateCornerParasiticAnalysisPts()
|
||||||
{
|
{
|
||||||
CornerMap::Iterator corner_iter(corners_);
|
CornerSeq::Iterator corner_iter(corners_);
|
||||||
while (corner_iter.hasNext()) {
|
while (corner_iter.hasNext()) {
|
||||||
Corner *corner = corner_iter.next();
|
Corner *corner = corner_iter.next();
|
||||||
corner->setParasiticAnalysisPtcount(parasitic_analysis_pts_.size());
|
corner->setParasiticAnalysisPtcount(parasitic_analysis_pts_.size());
|
||||||
ParasiticAnalysisPtIterator ap_iter(this);
|
ParasiticAnalysisPtSeq::Iterator ap_iter(parasitic_analysis_pts_);
|
||||||
while (ap_iter.hasNext()) {
|
while (ap_iter.hasNext()) {
|
||||||
ParasiticAnalysisPt *ap = ap_iter.next();
|
ParasiticAnalysisPt *ap = ap_iter.next();
|
||||||
corner->addParasiticAP(ap);
|
corner->addParasiticAP(ap);
|
||||||
|
|
@ -160,7 +158,7 @@ Corners::makeAnalysisPts()
|
||||||
dcalc_analysis_pts_.deleteContentsClear();
|
dcalc_analysis_pts_.deleteContentsClear();
|
||||||
path_analysis_pts_.deleteContentsClear();
|
path_analysis_pts_.deleteContentsClear();
|
||||||
|
|
||||||
CornerMap::Iterator corner_iter(corners_);
|
CornerSeq::Iterator corner_iter(corners_);
|
||||||
while (corner_iter.hasNext()) {
|
while (corner_iter.hasNext()) {
|
||||||
Corner *corner = corner_iter.next();
|
Corner *corner = corner_iter.next();
|
||||||
makeDcalcAnalysisPts(corner);
|
makeDcalcAnalysisPts(corner);
|
||||||
|
|
@ -200,13 +198,10 @@ Corners::makeDcalcAnalysisPt(Corner *corner,
|
||||||
const MinMax *check_clk_slew_min_max)
|
const MinMax *check_clk_slew_min_max)
|
||||||
{
|
{
|
||||||
OperatingConditions *op_cond = sdc_->operatingConditions(min_max);
|
OperatingConditions *op_cond = sdc_->operatingConditions(min_max);
|
||||||
ParasiticAnalysisPt *parasitic_ap = corner->findParasiticAnalysisPt(min_max);
|
|
||||||
DcalcAnalysisPt *dcalc_ap = new DcalcAnalysisPt(corner,
|
DcalcAnalysisPt *dcalc_ap = new DcalcAnalysisPt(corner,
|
||||||
dcalc_analysis_pts_.size(),
|
dcalc_analysis_pts_.size(),
|
||||||
op_cond, min_max,
|
op_cond, min_max,
|
||||||
min_max, min_max,
|
check_clk_slew_min_max);
|
||||||
check_clk_slew_min_max,
|
|
||||||
parasitic_ap);
|
|
||||||
dcalc_analysis_pts_.push_back(dcalc_ap);
|
dcalc_analysis_pts_.push_back(dcalc_ap);
|
||||||
corner->addDcalcAP(dcalc_ap);
|
corner->addDcalcAP(dcalc_ap);
|
||||||
return dcalc_ap;
|
return dcalc_ap;
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ class Corner;
|
||||||
class Corners;
|
class Corners;
|
||||||
class LibertyLibrary;
|
class LibertyLibrary;
|
||||||
|
|
||||||
|
typedef Vector<Corner*> CornerSeq;
|
||||||
typedef Map<const char *, Corner*, CharPtrLess> CornerMap;
|
typedef Map<const char *, Corner*, CharPtrLess> CornerMap;
|
||||||
typedef Vector<ParasiticAnalysisPt*> ParasiticAnalysisPtSeq;
|
typedef Vector<ParasiticAnalysisPt*> ParasiticAnalysisPtSeq;
|
||||||
typedef Vector<DcalcAnalysisPt*> DcalcAnalysisPtSeq;
|
typedef Vector<DcalcAnalysisPt*> DcalcAnalysisPtSeq;
|
||||||
|
|
@ -49,7 +50,7 @@ public:
|
||||||
int count() const;
|
int count() const;
|
||||||
bool multiCorner() const;
|
bool multiCorner() const;
|
||||||
Corner *findCorner(const char *corner);
|
Corner *findCorner(const char *corner);
|
||||||
Corner *defaultCorner();
|
Corner *findCorner(int corner_index);
|
||||||
void makeCorners(StringSet *corner_names);
|
void makeCorners(StringSet *corner_names);
|
||||||
void analysisTypeChanged();
|
void analysisTypeChanged();
|
||||||
void operatingConditionsChanged();
|
void operatingConditionsChanged();
|
||||||
|
|
@ -80,11 +81,11 @@ protected:
|
||||||
bool swap_clk_min_max,
|
bool swap_clk_min_max,
|
||||||
DcalcAnalysisPt *dcalc_ap_min,
|
DcalcAnalysisPt *dcalc_ap_min,
|
||||||
DcalcAnalysisPt *dcalc_ap_max);
|
DcalcAnalysisPt *dcalc_ap_max);
|
||||||
CornerMap &corners() { return corners_; }
|
CornerSeq &corners() { return corners_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CornerMap corners_;
|
CornerMap corner_map_;
|
||||||
Corner *default_corner_;
|
CornerSeq corners_;
|
||||||
ParasiticAnalysisPtSeq parasitic_analysis_pts_;
|
ParasiticAnalysisPtSeq parasitic_analysis_pts_;
|
||||||
DcalcAnalysisPtSeq dcalc_analysis_pts_;
|
DcalcAnalysisPtSeq dcalc_analysis_pts_;
|
||||||
PathAnalysisPtSeq path_analysis_pts_;
|
PathAnalysisPtSeq path_analysis_pts_;
|
||||||
|
|
@ -137,7 +138,7 @@ public:
|
||||||
virtual Corner *next();
|
virtual Corner *next();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CornerMap::ConstIterator iter_;
|
CornerSeq::ConstIterator iter_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_COPY_AND_ASSIGN(CornerIterator);
|
DISALLOW_COPY_AND_ASSIGN(CornerIterator);
|
||||||
|
|
|
||||||
|
|
@ -252,29 +252,59 @@ Power::loadCap(const Pin *to_pin,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Power::findLeakagePower(const Instance *inst,
|
Power::findLeakagePower(const Instance *,
|
||||||
LibertyCell *cell,
|
LibertyCell *cell,
|
||||||
// Return values.
|
// Return values.
|
||||||
PowerResult &result)
|
PowerResult &result)
|
||||||
{
|
{
|
||||||
float leakage = cell->leakagePower();
|
float cond_leakage = 0.0;
|
||||||
|
bool found_cond = false;
|
||||||
|
float default_leakage = 0.0;
|
||||||
|
bool found_default = false;
|
||||||
LibertyCellLeakagePowerIterator pwr_iter(cell);
|
LibertyCellLeakagePowerIterator pwr_iter(cell);
|
||||||
while (pwr_iter.hasNext()) {
|
while (pwr_iter.hasNext()) {
|
||||||
LeakagePower *leak = pwr_iter.next();
|
LeakagePower *leak = pwr_iter.next();
|
||||||
FuncExpr *when = leak->when();
|
FuncExpr *when = leak->when();
|
||||||
if (when) {
|
if (when) {
|
||||||
LogicValue when_value = sim_->evalExpr(when, inst);
|
FuncExprPortIterator port_iter(when);
|
||||||
switch (when_value) {
|
float duty = 1.0;
|
||||||
case LogicValue::zero:
|
while (port_iter.hasNext()) {
|
||||||
case LogicValue::one:
|
auto port = port_iter.next();
|
||||||
leakage = max(leakage, leak->power());
|
if (port->direction()->isAnyInput())
|
||||||
break;
|
duty *= .5;
|
||||||
case LogicValue::unknown:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
debugPrint4(debug_, "power", 2, "leakage %s %s %.3e * %.2f\n",
|
||||||
|
cell->name(),
|
||||||
|
when->asString(),
|
||||||
|
leak->power(),
|
||||||
|
duty);
|
||||||
|
cond_leakage += leak->power() * duty;
|
||||||
|
found_cond = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
debugPrint2(debug_, "power", 2, "leakage default %s %.3e\n",
|
||||||
|
cell->name(),
|
||||||
|
leak->power());
|
||||||
|
default_leakage += leak->power();
|
||||||
|
found_default = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
float leakage = 0.0;
|
||||||
|
float leak;
|
||||||
|
bool exists;
|
||||||
|
cell->leakagePower(leak, exists);
|
||||||
|
if (exists) {
|
||||||
|
// Prefer cell_leakage_power until propagated activities exist.
|
||||||
|
debugPrint2(debug_, "power", 2, "leakage %s cell %.3e\n",
|
||||||
|
cell->name(),
|
||||||
|
leak);
|
||||||
|
leakage = leak;
|
||||||
|
}
|
||||||
|
// Ignore default leakages unless there are no conditional leakage groups.
|
||||||
|
else if (found_cond)
|
||||||
|
leakage = cond_leakage;
|
||||||
|
else if (found_default)
|
||||||
|
leakage = default_leakage;
|
||||||
result.setLeakage(leakage);
|
result.setLeakage(leakage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -292,6 +322,15 @@ Power::findSwitchingPower(LibertyCell *cell,
|
||||||
result.setSwitching(switching);
|
result.setSwitching(switching);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
Power::activity(const Pin *pin)
|
||||||
|
{
|
||||||
|
float activity1;
|
||||||
|
bool is_clk;
|
||||||
|
activity(pin, activity1, is_clk);
|
||||||
|
return activity1;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Power::activity(const Pin *pin,
|
Power::activity(const Pin *pin,
|
||||||
// Return values.
|
// Return values.
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,7 @@ protected:
|
||||||
// Return values.
|
// Return values.
|
||||||
float &activity,
|
float &activity,
|
||||||
bool &is_clk);
|
bool &is_clk);
|
||||||
|
float activity(const Pin *pin);
|
||||||
float voltage(LibertyCell *cell,
|
float voltage(LibertyCell *cell,
|
||||||
const LibertyPort *port,
|
const LibertyPort *port,
|
||||||
const DcalcAnalysisPt *dcalc_ap);
|
const DcalcAnalysisPt *dcalc_ap);
|
||||||
|
|
|
||||||
|
|
@ -301,9 +301,8 @@ Sta::makeComponents()
|
||||||
updateComponentsState();
|
updateComponentsState();
|
||||||
|
|
||||||
makeObservers();
|
makeObservers();
|
||||||
|
// This must follow updateComponentsState.
|
||||||
corners_->makeParasiticAnalysisPtsSingle();
|
corners_->makeParasiticAnalysisPtsSingle();
|
||||||
makeDefaultCorners();
|
|
||||||
setThreadCount(defaultThreadCount());
|
setThreadCount(defaultThreadCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -667,8 +666,7 @@ Sta::setMinLibrary(const char *min_filename,
|
||||||
{
|
{
|
||||||
LibertyLibrary *max_lib = network_->findLibertyFilename(max_filename);
|
LibertyLibrary *max_lib = network_->findLibertyFilename(max_filename);
|
||||||
if (max_lib) {
|
if (max_lib) {
|
||||||
LibertyLibrary *min_lib = readLibertyFile(min_filename,
|
LibertyLibrary *min_lib = readLibertyFile(min_filename, cmd_corner_,
|
||||||
corners_->defaultCorner(),
|
|
||||||
MinMaxAll::min(), false,
|
MinMaxAll::min(), false,
|
||||||
report_, debug_, network_);
|
report_, debug_, network_);
|
||||||
return min_lib != nullptr;
|
return min_lib != nullptr;
|
||||||
|
|
@ -2339,12 +2337,6 @@ Sta::setClkThruTristateEnabled(bool enable)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Corner *
|
|
||||||
Sta::defaultCorner()
|
|
||||||
{
|
|
||||||
return corners_->defaultCorner();
|
|
||||||
}
|
|
||||||
|
|
||||||
Corner *
|
Corner *
|
||||||
Sta::findCorner(const char *corner_name)
|
Sta::findCorner(const char *corner_name)
|
||||||
{
|
{
|
||||||
|
|
@ -2357,24 +2349,33 @@ Sta::multiCorner()
|
||||||
return corners_->multiCorner();
|
return corners_->multiCorner();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init one corner named "default".
|
||||||
void
|
void
|
||||||
Sta::makeCorners()
|
Sta::makeCorners()
|
||||||
{
|
{
|
||||||
corners_ = new Corners(this);
|
corners_ = new Corners(this);
|
||||||
|
StringSet corner_names;
|
||||||
|
corner_names.insert("default");
|
||||||
|
makeCorners(&corner_names);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Sta::makeCorners(StringSet *corner_names)
|
Sta::makeCorners(StringSet *corner_names)
|
||||||
{
|
{
|
||||||
corners_->makeCorners(corner_names);
|
corners_->makeCorners(corner_names);
|
||||||
|
cmd_corner_ = corners_->findCorner(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Corner *
|
||||||
|
Sta::cmdCorner() const
|
||||||
|
{
|
||||||
|
return cmd_corner_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Sta::makeDefaultCorners()
|
Sta::setCmdCorner(Corner *corner)
|
||||||
{
|
{
|
||||||
StringSet corner_names;
|
cmd_corner_ = corner;
|
||||||
corner_names.insert("default");
|
|
||||||
corners_->makeCorners(&corner_names);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -3344,7 +3345,7 @@ Sta::setPortExtWireCap(Port *port,
|
||||||
const MinMaxAll *min_max,
|
const MinMaxAll *min_max,
|
||||||
float cap)
|
float cap)
|
||||||
{
|
{
|
||||||
Corner *corner = corners_->defaultCorner();
|
Corner *corner = cmd_corner_;
|
||||||
TransRiseFallIterator tr_iter(tr);
|
TransRiseFallIterator tr_iter(tr);
|
||||||
while (tr_iter.hasNext()) {
|
while (tr_iter.hasNext()) {
|
||||||
TransRiseFall *tr1 = tr_iter.next();
|
TransRiseFall *tr1 = tr_iter.next();
|
||||||
|
|
@ -3489,7 +3490,7 @@ Sta::readSpef(const char *filename,
|
||||||
bool save,
|
bool save,
|
||||||
bool quiet)
|
bool quiet)
|
||||||
{
|
{
|
||||||
Corner *corner = corners_->defaultCorner();
|
Corner *corner = cmd_corner_;
|
||||||
const MinMax *cnst_min_max;
|
const MinMax *cnst_min_max;
|
||||||
ParasiticAnalysisPt *ap;
|
ParasiticAnalysisPt *ap;
|
||||||
if (min_max == MinMaxAll::all()) {
|
if (min_max == MinMaxAll::all()) {
|
||||||
|
|
@ -3510,27 +3511,9 @@ Sta::readSpef(const char *filename,
|
||||||
reduce_to, delete_after_reduce,
|
reduce_to, delete_after_reduce,
|
||||||
op_cond, corner, cnst_min_max, save, quiet,
|
op_cond, corner, cnst_min_max, save, quiet,
|
||||||
report_, network_, parasitics_);
|
report_, network_, parasitics_);
|
||||||
parasiticsChangedAfter();
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Sta::parasiticsChangedAfter()
|
|
||||||
{
|
|
||||||
// Update the delay calculation analysis points to use the parasitics.
|
|
||||||
CornerIterator corner_iter(sta_);
|
|
||||||
while (corner_iter.hasNext()) {
|
|
||||||
Corner *corner = corner_iter.next();
|
|
||||||
MinMaxIterator mm_iter;
|
|
||||||
while (mm_iter.hasNext()) {
|
|
||||||
MinMax *min_max = mm_iter.next();
|
|
||||||
ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(min_max);
|
|
||||||
DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
|
|
||||||
dcalc_ap->setParasiticAnalysisPt(ap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
graph_delay_calc_->delaysInvalid();
|
graph_delay_calc_->delaysInvalid();
|
||||||
search_->arrivalsInvalid();
|
search_->arrivalsInvalid();
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -3542,7 +3525,7 @@ Sta::findPiElmore(Pin *drvr_pin,
|
||||||
float &c1,
|
float &c1,
|
||||||
bool &exists) const
|
bool &exists) const
|
||||||
{
|
{
|
||||||
Corner *corner = corners_->defaultCorner();
|
Corner *corner = cmd_corner_;
|
||||||
const ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(min_max);
|
const ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(min_max);
|
||||||
if (parasitics_->hasPiElmore(drvr_pin, tr, ap)) {
|
if (parasitics_->hasPiElmore(drvr_pin, tr, ap)) {
|
||||||
Parasitic *pi_elmore = parasitics_->findPiElmore(drvr_pin, tr, ap);
|
Parasitic *pi_elmore = parasitics_->findPiElmore(drvr_pin, tr, ap);
|
||||||
|
|
@ -3561,7 +3544,7 @@ Sta::makePiElmore(Pin *drvr_pin,
|
||||||
float rpi,
|
float rpi,
|
||||||
float c1)
|
float c1)
|
||||||
{
|
{
|
||||||
Corner *corner = corners_->defaultCorner();
|
Corner *corner = cmd_corner_;
|
||||||
MinMaxIterator mm_iter(min_max);
|
MinMaxIterator mm_iter(min_max);
|
||||||
while (mm_iter.hasNext()) {
|
while (mm_iter.hasNext()) {
|
||||||
MinMax *mm = mm_iter.next();
|
MinMax *mm = mm_iter.next();
|
||||||
|
|
@ -3579,7 +3562,7 @@ Sta::findElmore(Pin *drvr_pin,
|
||||||
float &elmore,
|
float &elmore,
|
||||||
bool &exists) const
|
bool &exists) const
|
||||||
{
|
{
|
||||||
Corner *corner = corners_->defaultCorner();
|
Corner *corner = cmd_corner_;
|
||||||
const ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(min_max);
|
const ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(min_max);
|
||||||
if (parasitics_->hasPiElmore(drvr_pin, tr, ap)) {
|
if (parasitics_->hasPiElmore(drvr_pin, tr, ap)) {
|
||||||
Parasitic *pi_elmore = parasitics_->findPiElmore(drvr_pin, tr, ap);
|
Parasitic *pi_elmore = parasitics_->findPiElmore(drvr_pin, tr, ap);
|
||||||
|
|
@ -3597,7 +3580,7 @@ Sta::setElmore(Pin *drvr_pin,
|
||||||
const MinMaxAll *min_max,
|
const MinMaxAll *min_max,
|
||||||
float elmore)
|
float elmore)
|
||||||
{
|
{
|
||||||
Corner *corner = corners_->defaultCorner();
|
Corner *corner = cmd_corner_;
|
||||||
MinMaxIterator mm_iter(min_max);
|
MinMaxIterator mm_iter(min_max);
|
||||||
while (mm_iter.hasNext()) {
|
while (mm_iter.hasNext()) {
|
||||||
MinMax *mm = mm_iter.next();
|
MinMax *mm = mm_iter.next();
|
||||||
|
|
|
||||||
|
|
@ -1133,7 +1133,8 @@ public:
|
||||||
Tcl_Interp *tclInterp();
|
Tcl_Interp *tclInterp();
|
||||||
// Ensure that the timing graph has been built.
|
// Ensure that the timing graph has been built.
|
||||||
Graph *ensureGraph();
|
Graph *ensureGraph();
|
||||||
Corner *defaultCorner();
|
Corner *cmdCorner() const;
|
||||||
|
void setCmdCorner(Corner *corner);
|
||||||
Corner *findCorner(const char *corner_name);
|
Corner *findCorner(const char *corner_name);
|
||||||
bool multiCorner();
|
bool multiCorner();
|
||||||
void makeCorners(StringSet *corner_names);
|
void makeCorners(StringSet *corner_names);
|
||||||
|
|
@ -1292,17 +1293,16 @@ protected:
|
||||||
void findRegisterPreamble();
|
void findRegisterPreamble();
|
||||||
bool crossesHierarchy(Edge *edge) const;
|
bool crossesHierarchy(Edge *edge) const;
|
||||||
void deleteLeafInstanceBefore(Instance *inst);
|
void deleteLeafInstanceBefore(Instance *inst);
|
||||||
void makeDefaultCorners();
|
|
||||||
void readLibertyAfter(LibertyLibrary *liberty,
|
void readLibertyAfter(LibertyLibrary *liberty,
|
||||||
Corner *corner,
|
Corner *corner,
|
||||||
const MinMax *min_max);
|
const MinMax *min_max);
|
||||||
void parasiticsChangedAfter();
|
|
||||||
void powerPreamble();
|
void powerPreamble();
|
||||||
void disableFanoutCrprPruning(Vertex *vertex,
|
void disableFanoutCrprPruning(Vertex *vertex,
|
||||||
int &fanou);
|
int &fanou);
|
||||||
|
|
||||||
CmdNamespace cmd_namespace_;
|
CmdNamespace cmd_namespace_;
|
||||||
Instance *current_instance_;
|
Instance *current_instance_;
|
||||||
|
Corner *cmd_corner_;
|
||||||
CheckTiming *check_timing_;
|
CheckTiming *check_timing_;
|
||||||
CheckSlewLimits *check_slew_limits_;
|
CheckSlewLimits *check_slew_limits_;
|
||||||
CheckMinPulseWidths *check_min_pulse_widths_;
|
CheckMinPulseWidths *check_min_pulse_widths_;
|
||||||
|
|
|
||||||
|
|
@ -1255,7 +1255,7 @@ proc parse_corner { keys_var } {
|
||||||
} elseif { [multi_corner] } {
|
} elseif { [multi_corner] } {
|
||||||
sta_error "-corner keyword required with multi-corner analysis."
|
sta_error "-corner keyword required with multi-corner analysis."
|
||||||
} else {
|
} else {
|
||||||
return [default_corner]
|
return [cmd_corner]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1289,7 +1289,7 @@ proc parse_corner_or_default { keys_var } {
|
||||||
return $corner
|
return $corner
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return [default_corner]
|
return [cmd_corner]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
39
tcl/StaTcl.i
39
tcl/StaTcl.i
|
|
@ -1988,6 +1988,13 @@ private:
|
||||||
~OperatingConditions();
|
~OperatingConditions();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Corner
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Corner();
|
||||||
|
~Corner();
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// C++ functions visible as TCL functions.
|
// C++ functions visible as TCL functions.
|
||||||
|
|
@ -2735,10 +2742,24 @@ leaf_instance_iterator()
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Corner *
|
void
|
||||||
default_corner()
|
define_corners_cmd(StringSet *corner_names)
|
||||||
{
|
{
|
||||||
return Sta::sta()->defaultCorner();
|
Sta *sta = Sta::sta();
|
||||||
|
sta->makeCorners(corner_names);
|
||||||
|
delete corner_names;
|
||||||
|
}
|
||||||
|
|
||||||
|
Corner *
|
||||||
|
cmd_corner()
|
||||||
|
{
|
||||||
|
return Sta::sta()->cmdCorner();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_cmd_corner(Corner *corner)
|
||||||
|
{
|
||||||
|
Sta::sta()->setCmdCorner(corner);
|
||||||
}
|
}
|
||||||
|
|
||||||
Corner *
|
Corner *
|
||||||
|
|
@ -5169,14 +5190,6 @@ arrivals_invalid()
|
||||||
sta->arrivalsInvalid();
|
sta->arrivalsInvalid();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
define_corners_cmd(StringSet *corner_names)
|
|
||||||
{
|
|
||||||
Sta *sta = Sta::sta();
|
|
||||||
sta->makeCorners(corner_names);
|
|
||||||
delete corner_names;
|
|
||||||
}
|
|
||||||
|
|
||||||
%} // inline
|
%} // inline
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -6133,6 +6146,10 @@ finish()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%extend Corner {
|
||||||
|
const char *name() { return self->name(); }
|
||||||
|
}
|
||||||
|
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
// mode:c++
|
// mode:c++
|
||||||
// End:
|
// End:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue