This commit is contained in:
James Cherry 2019-04-01 09:05:07 -07:00
parent ed3ad4fb30
commit fcfec7ae54
16 changed files with 172 additions and 124 deletions

View File

@ -16,7 +16,7 @@
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_CXX_STANDARD 11)

View File

@ -16,6 +16,7 @@
#include "Machine.hh"
#include "StringUtil.hh"
#include "Corner.hh"
#include "DcalcAnalysisPt.hh"
namespace sta {
@ -23,19 +24,13 @@ namespace sta {
DcalcAnalysisPt::DcalcAnalysisPt(Corner *corner,
DcalcAPIndex index,
const OperatingConditions *op_cond,
const MinMax *cnst_min_max,
const MinMax *delay_min_max,
const MinMax *slew_min_max,
const MinMax *check_clk_slew_min_max,
const ParasiticAnalysisPt *parasitic_ap) :
const MinMax *min_max,
const MinMax *check_clk_slew_min_max) :
corner_(corner),
index_(index),
op_cond_(op_cond),
cnst_min_max_(cnst_min_max),
delay_min_max_(delay_min_max),
slew_min_max_(slew_min_max),
check_clk_slew_min_max_(check_clk_slew_min_max),
parasitic_ap_(parasitic_ap)
min_max_(min_max),
check_clk_slew_min_max_(check_clk_slew_min_max)
{
}
@ -45,11 +40,10 @@ DcalcAnalysisPt::setOperatingConditions(const OperatingConditions *op_cond)
op_cond_ = op_cond;
}
void
DcalcAnalysisPt::
setParasiticAnalysisPt(const ParasiticAnalysisPt *parasitic_ap)
ParasiticAnalysisPt *
DcalcAnalysisPt::parasiticAnalysisPt() const
{
parasitic_ap_ = parasitic_ap;
return corner_->findParasiticAnalysisPt(min_max_);
}
void

View File

@ -39,11 +39,8 @@ public:
DcalcAnalysisPt(Corner *corner,
DcalcAPIndex index,
const OperatingConditions *op_cond,
const MinMax *cnst_min_max,
const MinMax *delay_min_max,
const MinMax *slew_min_max,
const MinMax *check_clk_slew_min_max,
const ParasiticAnalysisPt *parasitic_ap);
const MinMax *min_max,
const MinMax *check_clk_slew_min_max);
Corner *corner() const { return corner_; }
// Which of the delay_count results this analysis point corresponds to.
DcalcAPIndex index() const { return index_; }
@ -54,16 +51,15 @@ public:
// Slew min/max of timing check clock.
const MinMax *checkClkSlewMinMax() const { return check_clk_slew_min_max_; }
// 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_)
const OperatingConditions *operatingConditions() const { return op_cond_; }
void setOperatingConditions(const OperatingConditions *op_cond);
// 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.
const MinMax *slewMinMax() const { return slew_min_max_; }
const ParasiticAnalysisPt *parasiticAnalysisPt()const{return parasitic_ap_;}
void setParasiticAnalysisPt(const ParasiticAnalysisPt *parasitic_ap);
const MinMax *slewMinMax() const { return min_max_; }
ParasiticAnalysisPt *parasiticAnalysisPt() const;
void setCheckClkSlewIndex(DcalcAPIndex index);
int libertyIndex() const;
@ -74,11 +70,8 @@ private:
DcalcAPIndex index_;
DcalcAPIndex check_clk_slew_index_;
const OperatingConditions *op_cond_;
const MinMax *cnst_min_max_;
const MinMax *delay_min_max_;
const MinMax *slew_min_max_;
const MinMax *min_max_;
const MinMax *check_clk_slew_min_max_;
const ParasiticAnalysisPt *parasitic_ap_;
};
} // namespace

View File

@ -848,7 +848,8 @@ LibertyCell::LibertyCell(LibertyLibrary *library,
ocv_arc_depth_(0.0),
ocv_derate_(nullptr),
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)
{
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

View File

@ -429,7 +429,10 @@ public:
bool hasTimingArcs(LibertyPort *port) const;
InternalPowerSeq *internalPowers() { return &internal_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;
void makeSequential(int size,
bool is_register,
@ -537,6 +540,7 @@ protected:
bool is_disabled_constraint_;
Vector<LibertyCell*> corner_cells_;
float leakage_power_;
bool leakage_power_exists_;
LibertyPgPortMap pg_port_map_;
private:

View File

@ -193,9 +193,17 @@ EstimateParasitics::estimatePiElmoreBalanced(const Pin *drvr_pin,
}
delete load_iter;
c1 = static_cast<float>(y2 * y2 / y3);
c2 = static_cast<float>(y1 - y2 * y2 / y3);
rpi = static_cast<float>(-y3 * y3 / (y2 * y2 * y2));
if (y3 == 0) {
// No loads.
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_cap = static_cast<float>(cap_fanout);
elmore_use_load_cap = true;

View File

@ -253,7 +253,8 @@ LibertyPortPairNameLess::operator()(const LibertyPortPair *pair1,
}
void
sortLibertyPortPairSet(LibertyPortPairSet *sets, LibertyPortPairSeq &pairs)
sortLibertyPortPairSet(LibertyPortPairSet *sets,
LibertyPortPairSeq &pairs)
{
LibertyPortPairSet::Iterator pair_iter(sets);
while (pair_iter.hasNext())

View File

@ -105,7 +105,8 @@ sortDisabledInstancePortsMap(DisabledInstancePortsMap *inst_map,
Network *network,
DisabledInstancePortsSeq &disables);
void
sortLibertyPortPairSet(LibertyPortPairSet *sets, LibertyPortPairSeq &pairs);
sortLibertyPortPairSet(LibertyPortPairSet *sets,
LibertyPortPairSeq &pairs);
} // namespace
#endif

View File

@ -24,24 +24,23 @@
namespace sta {
Corners::Corners(StaState *sta) :
StaState(sta),
default_corner_(nullptr)
StaState(sta)
{
}
Corners::~Corners()
{
clear();
parasitic_analysis_pts_.deleteContentsClear();
}
void
Corners::clear()
{
corners_.deleteContentsClear();
corner_map_.clear();
dcalc_analysis_pts_.deleteContentsClear();
path_analysis_pts_.deleteContentsClear();
default_corner_ = nullptr;
parasitic_analysis_pts_.deleteContentsClear();
}
int
@ -59,13 +58,13 @@ Corners::multiCorner() const
Corner *
Corners::findCorner(const char *corner_name)
{
return corners_.findKey(corner_name);
return corner_map_.findKey(corner_name);
}
Corner *
Corners::defaultCorner()
Corners::findCorner(int corner_index)
{
return default_corner_;
return corners_[corner_index];
}
void
@ -96,10 +95,9 @@ Corners::makeCorners(StringSet *corner_names)
while (name_iter.hasNext()) {
const char *name = name_iter.next();
Corner *corner = new Corner(name, index);
corners_.push_back(corner);
// Use the copied name in the map.
corners_[corner->name()] = corner;
if (default_corner_ == nullptr)
default_corner_ = corner;
corner_map_[corner->name()] = corner;
index++;
}
updateCornerParasiticAnalysisPts();
@ -142,11 +140,11 @@ Corners::makeParasiticAnalysisPtsMinMax()
void
Corners::updateCornerParasiticAnalysisPts()
{
CornerMap::Iterator corner_iter(corners_);
CornerSeq::Iterator corner_iter(corners_);
while (corner_iter.hasNext()) {
Corner *corner = corner_iter.next();
corner->setParasiticAnalysisPtcount(parasitic_analysis_pts_.size());
ParasiticAnalysisPtIterator ap_iter(this);
ParasiticAnalysisPtSeq::Iterator ap_iter(parasitic_analysis_pts_);
while (ap_iter.hasNext()) {
ParasiticAnalysisPt *ap = ap_iter.next();
corner->addParasiticAP(ap);
@ -160,7 +158,7 @@ Corners::makeAnalysisPts()
dcalc_analysis_pts_.deleteContentsClear();
path_analysis_pts_.deleteContentsClear();
CornerMap::Iterator corner_iter(corners_);
CornerSeq::Iterator corner_iter(corners_);
while (corner_iter.hasNext()) {
Corner *corner = corner_iter.next();
makeDcalcAnalysisPts(corner);
@ -200,13 +198,10 @@ Corners::makeDcalcAnalysisPt(Corner *corner,
const MinMax *check_clk_slew_min_max)
{
OperatingConditions *op_cond = sdc_->operatingConditions(min_max);
ParasiticAnalysisPt *parasitic_ap = corner->findParasiticAnalysisPt(min_max);
DcalcAnalysisPt *dcalc_ap = new DcalcAnalysisPt(corner,
dcalc_analysis_pts_.size(),
op_cond, min_max,
min_max, min_max,
check_clk_slew_min_max,
parasitic_ap);
check_clk_slew_min_max);
dcalc_analysis_pts_.push_back(dcalc_ap);
corner->addDcalcAP(dcalc_ap);
return dcalc_ap;

View File

@ -34,6 +34,7 @@ class Corner;
class Corners;
class LibertyLibrary;
typedef Vector<Corner*> CornerSeq;
typedef Map<const char *, Corner*, CharPtrLess> CornerMap;
typedef Vector<ParasiticAnalysisPt*> ParasiticAnalysisPtSeq;
typedef Vector<DcalcAnalysisPt*> DcalcAnalysisPtSeq;
@ -49,7 +50,7 @@ public:
int count() const;
bool multiCorner() const;
Corner *findCorner(const char *corner);
Corner *defaultCorner();
Corner *findCorner(int corner_index);
void makeCorners(StringSet *corner_names);
void analysisTypeChanged();
void operatingConditionsChanged();
@ -80,11 +81,11 @@ protected:
bool swap_clk_min_max,
DcalcAnalysisPt *dcalc_ap_min,
DcalcAnalysisPt *dcalc_ap_max);
CornerMap &corners() { return corners_; }
CornerSeq &corners() { return corners_; }
private:
CornerMap corners_;
Corner *default_corner_;
CornerMap corner_map_;
CornerSeq corners_;
ParasiticAnalysisPtSeq parasitic_analysis_pts_;
DcalcAnalysisPtSeq dcalc_analysis_pts_;
PathAnalysisPtSeq path_analysis_pts_;
@ -137,7 +138,7 @@ public:
virtual Corner *next();
protected:
CornerMap::ConstIterator iter_;
CornerSeq::ConstIterator iter_;
private:
DISALLOW_COPY_AND_ASSIGN(CornerIterator);

View File

@ -252,29 +252,59 @@ Power::loadCap(const Pin *to_pin,
}
void
Power::findLeakagePower(const Instance *inst,
Power::findLeakagePower(const Instance *,
LibertyCell *cell,
// Return values.
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);
while (pwr_iter.hasNext()) {
LeakagePower *leak = pwr_iter.next();
FuncExpr *when = leak->when();
if (when) {
LogicValue when_value = sim_->evalExpr(when, inst);
switch (when_value) {
case LogicValue::zero:
case LogicValue::one:
leakage = max(leakage, leak->power());
break;
case LogicValue::unknown:
default:
break;
FuncExprPortIterator port_iter(when);
float duty = 1.0;
while (port_iter.hasNext()) {
auto port = port_iter.next();
if (port->direction()->isAnyInput())
duty *= .5;
}
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);
}
@ -292,6 +322,15 @@ Power::findSwitchingPower(LibertyCell *cell,
result.setSwitching(switching);
}
float
Power::activity(const Pin *pin)
{
float activity1;
bool is_clk;
activity(pin, activity1, is_clk);
return activity1;
}
void
Power::activity(const Pin *pin,
// Return values.

View File

@ -78,6 +78,7 @@ protected:
// Return values.
float &activity,
bool &is_clk);
float activity(const Pin *pin);
float voltage(LibertyCell *cell,
const LibertyPort *port,
const DcalcAnalysisPt *dcalc_ap);

View File

@ -301,9 +301,8 @@ Sta::makeComponents()
updateComponentsState();
makeObservers();
// This must follow updateComponentsState.
corners_->makeParasiticAnalysisPtsSingle();
makeDefaultCorners();
setThreadCount(defaultThreadCount());
}
@ -667,8 +666,7 @@ Sta::setMinLibrary(const char *min_filename,
{
LibertyLibrary *max_lib = network_->findLibertyFilename(max_filename);
if (max_lib) {
LibertyLibrary *min_lib = readLibertyFile(min_filename,
corners_->defaultCorner(),
LibertyLibrary *min_lib = readLibertyFile(min_filename, cmd_corner_,
MinMaxAll::min(), false,
report_, debug_, network_);
return min_lib != nullptr;
@ -2339,12 +2337,6 @@ Sta::setClkThruTristateEnabled(bool enable)
////////////////////////////////////////////////////////////////
Corner *
Sta::defaultCorner()
{
return corners_->defaultCorner();
}
Corner *
Sta::findCorner(const char *corner_name)
{
@ -2357,24 +2349,33 @@ Sta::multiCorner()
return corners_->multiCorner();
}
// Init one corner named "default".
void
Sta::makeCorners()
{
corners_ = new Corners(this);
StringSet corner_names;
corner_names.insert("default");
makeCorners(&corner_names);
}
void
Sta::makeCorners(StringSet *corner_names)
{
corners_->makeCorners(corner_names);
cmd_corner_ = corners_->findCorner(0);
}
Corner *
Sta::cmdCorner() const
{
return cmd_corner_;
}
void
Sta::makeDefaultCorners()
Sta::setCmdCorner(Corner *corner)
{
StringSet corner_names;
corner_names.insert("default");
corners_->makeCorners(&corner_names);
cmd_corner_ = corner;
}
void
@ -3344,7 +3345,7 @@ Sta::setPortExtWireCap(Port *port,
const MinMaxAll *min_max,
float cap)
{
Corner *corner = corners_->defaultCorner();
Corner *corner = cmd_corner_;
TransRiseFallIterator tr_iter(tr);
while (tr_iter.hasNext()) {
TransRiseFall *tr1 = tr_iter.next();
@ -3489,7 +3490,7 @@ Sta::readSpef(const char *filename,
bool save,
bool quiet)
{
Corner *corner = corners_->defaultCorner();
Corner *corner = cmd_corner_;
const MinMax *cnst_min_max;
ParasiticAnalysisPt *ap;
if (min_max == MinMaxAll::all()) {
@ -3510,27 +3511,9 @@ Sta::readSpef(const char *filename,
reduce_to, delete_after_reduce,
op_cond, corner, cnst_min_max, save, quiet,
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();
search_->arrivalsInvalid();
return success;
}
void
@ -3542,7 +3525,7 @@ Sta::findPiElmore(Pin *drvr_pin,
float &c1,
bool &exists) const
{
Corner *corner = corners_->defaultCorner();
Corner *corner = cmd_corner_;
const ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(min_max);
if (parasitics_->hasPiElmore(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 c1)
{
Corner *corner = corners_->defaultCorner();
Corner *corner = cmd_corner_;
MinMaxIterator mm_iter(min_max);
while (mm_iter.hasNext()) {
MinMax *mm = mm_iter.next();
@ -3579,7 +3562,7 @@ Sta::findElmore(Pin *drvr_pin,
float &elmore,
bool &exists) const
{
Corner *corner = corners_->defaultCorner();
Corner *corner = cmd_corner_;
const ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(min_max);
if (parasitics_->hasPiElmore(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,
float elmore)
{
Corner *corner = corners_->defaultCorner();
Corner *corner = cmd_corner_;
MinMaxIterator mm_iter(min_max);
while (mm_iter.hasNext()) {
MinMax *mm = mm_iter.next();

View File

@ -1133,7 +1133,8 @@ public:
Tcl_Interp *tclInterp();
// Ensure that the timing graph has been built.
Graph *ensureGraph();
Corner *defaultCorner();
Corner *cmdCorner() const;
void setCmdCorner(Corner *corner);
Corner *findCorner(const char *corner_name);
bool multiCorner();
void makeCorners(StringSet *corner_names);
@ -1292,17 +1293,16 @@ protected:
void findRegisterPreamble();
bool crossesHierarchy(Edge *edge) const;
void deleteLeafInstanceBefore(Instance *inst);
void makeDefaultCorners();
void readLibertyAfter(LibertyLibrary *liberty,
Corner *corner,
const MinMax *min_max);
void parasiticsChangedAfter();
void powerPreamble();
void disableFanoutCrprPruning(Vertex *vertex,
int &fanou);
CmdNamespace cmd_namespace_;
Instance *current_instance_;
Corner *cmd_corner_;
CheckTiming *check_timing_;
CheckSlewLimits *check_slew_limits_;
CheckMinPulseWidths *check_min_pulse_widths_;

View File

@ -1255,7 +1255,7 @@ proc parse_corner { keys_var } {
} elseif { [multi_corner] } {
sta_error "-corner keyword required with multi-corner analysis."
} else {
return [default_corner]
return [cmd_corner]
}
}
@ -1289,7 +1289,7 @@ proc parse_corner_or_default { keys_var } {
return $corner
}
} else {
return [default_corner]
return [cmd_corner]
}
}

View File

@ -1988,6 +1988,13 @@ private:
~OperatingConditions();
};
class Corner
{
private:
Corner();
~Corner();
};
////////////////////////////////////////////////////////////////
//
// C++ functions visible as TCL functions.
@ -2735,10 +2742,24 @@ leaf_instance_iterator()
////////////////////////////////////////////////////////////////
Corner *
default_corner()
void
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 *
@ -5169,14 +5190,6 @@ arrivals_invalid()
sta->arrivalsInvalid();
}
void
define_corners_cmd(StringSet *corner_names)
{
Sta *sta = Sta::sta();
sta->makeCorners(corner_names);
delete corner_names;
}
%} // inline
////////////////////////////////////////////////////////////////
@ -6133,6 +6146,10 @@ finish()
}
%extend Corner {
const char *name() { return self->name(); }
}
// Local Variables:
// mode:c++
// End: