corner parasitics APs

This commit is contained in:
James Cherry 2021-05-15 16:55:10 -07:00
parent 8cf84facee
commit 9e27f27060
6 changed files with 111 additions and 72 deletions

View File

@ -55,12 +55,9 @@ public:
void analysisTypeChanged(); void analysisTypeChanged();
void operatingConditionsChanged(); void operatingConditionsChanged();
// Make one parasitic analysis point shared by all corners. // Make one parasitic analysis points.
void makeParasiticAnalysisPtsSingle(); void makeParasiticAnalysisPts(bool per_corner,
// Make min/max parasitic analysis points shared by all corners. bool per_min_max);
void makeParasiticAnalysisPtsMinMax();
// Make one parasitic analysis point for each corner.
void makeCornerParasiticAnalysisPts();
int parasiticAnalysisPtCount() const; int parasiticAnalysisPtCount() const;
ParasiticAnalysisPtSeq &parasiticAnalysisPts(); ParasiticAnalysisPtSeq &parasiticAnalysisPts();
@ -80,7 +77,6 @@ public:
protected: protected:
void makeAnalysisPts(); void makeAnalysisPts();
void updateCornerParasiticAnalysisPts();
void makeDcalcAnalysisPts(Corner *corner); void makeDcalcAnalysisPts(Corner *corner);
DcalcAnalysisPt *makeDcalcAnalysisPt(Corner *corner, DcalcAnalysisPt *makeDcalcAnalysisPt(Corner *corner,
const MinMax *min_max, const MinMax *min_max,

View File

@ -1052,17 +1052,24 @@ public:
// Caller owns iterator and iterator->container(). // Caller owns iterator and iterator->container().
SlowDrvrIterator *slowDrvrIterator(); SlowDrvrIterator *slowDrvrIterator();
// Make parasitic analysis points.
// per_corner per_min_max ap_count
// false false 1
// false true 2
// true false corners
// true true corners*2
void setParasiticAnalysisPts(bool per_corner,
bool per_min_max);
// Annotate hierarchical "instance" with parasitics. // Annotate hierarchical "instance" with parasitics.
// The parasitic analysis point is ap_name. // The parasitic analysis point is ap_name.
// The parasitics are used by delay calculation analysis points
// specfied by min_max.
// The parasitic memory footprint is much smaller if parasitic // The parasitic memory footprint is much smaller if parasitic
// networks (dspf) are reduced and deleted after reading each net // networks (dspf) are reduced and deleted after reading each net
// with reduce_to and delete_after_reduce. // with reduce_to and delete_after_reduce.
// Return true if successful. // Return true if successful.
bool readSpef(const char *filename, bool readSpef(const char *filename,
Instance *instance, Instance *instance,
const MinMaxAll *min_max, const Corner *corner,
const MinMaxAll *min_max,
bool increment, bool increment,
bool pin_cap_included, bool pin_cap_included,
bool keep_coupling_caps, bool keep_coupling_caps,
@ -1343,6 +1350,7 @@ protected:
void sdcChangedGraph(); void sdcChangedGraph();
void ensureGraphSdcAnnotated(); void ensureGraphSdcAnnotated();
CornerSeq makeCornerSeq(Corner *corner) const; CornerSeq makeCornerSeq(Corner *corner) const;
void makeParasiticAnalysisPts();
CmdNamespace cmd_namespace_; CmdNamespace cmd_namespace_;
Instance *current_instance_; Instance *current_instance_;
@ -1362,6 +1370,8 @@ protected:
bool update_genclks_; bool update_genclks_;
EquivCells *equiv_cells_; EquivCells *equiv_cells_;
bool graph_sdc_annotated_; bool graph_sdc_annotated_;
bool parasitics_per_corner_;
bool parasitics_per_min_max_;
// Singleton sta used by tcl command interpreter. // Singleton sta used by tcl command interpreter.
static Sta *sta_; static Sta *sta_;

View File

@ -36,7 +36,8 @@ using sta::TmpFloatSeq;
bool bool
read_spef_cmd(const char *filename, read_spef_cmd(const char *filename,
Instance *instance, Instance *instance,
MinMaxAll *min_max, const Corner *corner,
const MinMaxAll *min_max,
bool increment, bool increment,
bool pin_cap_included, bool pin_cap_included,
bool keep_coupling_caps, bool keep_coupling_caps,
@ -46,7 +47,7 @@ read_spef_cmd(const char *filename,
bool quiet) bool quiet)
{ {
cmdLinkedNetwork(); cmdLinkedNetwork();
return Sta::sta()->readSpef(filename, instance, min_max, return Sta::sta()->readSpef(filename, instance, corner, min_max,
increment, pin_cap_included, increment, pin_cap_included,
keep_coupling_caps, coupling_cap_factor, keep_coupling_caps, coupling_cap_factor,
reduce_to, delete_after_reduce, quiet); reduce_to, delete_after_reduce, quiet);

View File

@ -17,7 +17,8 @@
namespace eval sta { namespace eval sta {
define_cmd_args "read_spef" \ define_cmd_args "read_spef" \
{[-min]\ {[-corner corner]\
[-min]\
[-max]\ [-max]\
[-path path]\ [-path path]\
[-increment]\ [-increment]\
@ -46,6 +47,7 @@ proc_redirect read_spef {
sta_error 433 "path instance '$path' not found." sta_error 433 "path instance '$path' not found."
} }
} }
set corner [parse_corner_or_all keys]
set min_max [parse_min_max_all_flags flags] set min_max [parse_min_max_all_flags flags]
set increment [info exists flags(-increment)] set increment [info exists flags(-increment)]
set coupling_reduction_factor 1.0 set coupling_reduction_factor 1.0
@ -67,7 +69,7 @@ proc_redirect read_spef {
set quiet [info exists flags(-quiet)] set quiet [info exists flags(-quiet)]
set save [info exists flags(-save)] set save [info exists flags(-save)]
set filename [file nativename [lindex $args 0]] set filename [file nativename [lindex $args 0]]
return [read_spef_cmd $filename $instance $min_max $increment \ return [read_spef_cmd $filename $instance $corner $min_max $increment \
$pin_cap_included $keep_coupling_caps $coupling_reduction_factor \ $pin_cap_included $keep_coupling_caps $coupling_reduction_factor \
$reduce_to $delete_after_reduce $quiet] $reduce_to $delete_after_reduce $quiet]
} }

View File

@ -114,32 +114,58 @@ Corners::copy(Corners *corners)
} }
makeAnalysisPts(); makeAnalysisPts();
parasitic_analysis_pts_.deleteContentsClear();
for (ParasiticAnalysisPt *orig_ap : corners->parasitic_analysis_pts_) { for (ParasiticAnalysisPt *orig_ap : corners->parasitic_analysis_pts_) {
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(orig_ap->name(), orig_ap->index(), ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(orig_ap->name(), orig_ap->index(),
orig_ap->minMax()); orig_ap->minMax());
parasitic_analysis_pts_.push_back(ap); parasitic_analysis_pts_.push_back(ap);
} }
updateCornerParasiticAnalysisPts();
}
void int i = 0;
Corners::makeParasiticAnalysisPtsSingle() for (Corner *orig : corners->corners_) {
{ Corner *corner = corners_[i];
if (parasitic_analysis_pts_.size() != 1) { for (ParasiticAnalysisPt *ap : orig->parasitic_analysis_pts_)
parasitic_analysis_pts_.deleteContentsClear(); corner->addParasiticAP(parasitic_analysis_pts_[ap->index()]);
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt("min_max", 0, i++;
MinMax::max());
parasitic_analysis_pts_.push_back(ap);
updateCornerParasiticAnalysisPts();
} }
} }
void void
Corners::makeParasiticAnalysisPtsMinMax() Corners::makeParasiticAnalysisPts(bool per_corner,
bool per_min_max)
{ {
if (parasitic_analysis_pts_.size() != 2) { parasitic_analysis_pts_.deleteContentsClear();
parasitic_analysis_pts_.deleteContentsClear(); if (per_corner && per_min_max) {
// each corner has min/max parasitics
parasitic_analysis_pts_.resize(corners_.size() * MinMax::index_count);
for (Corner *corner : corners_) {
corner->setParasiticAnalysisPtcount(1);
for (MinMax *min_max : MinMax::range()) {
int mm_index = min_max->index();
int ap_index = corner->index() * MinMax::index_count + mm_index;
string ap_name = corner->name();
ap_name += "_";
ap_name += min_max->asString();
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(ap_name.c_str(),
ap_index,
min_max);
parasitic_analysis_pts_.push_back(ap);
corner->addParasiticAP(ap);
}
}
}
else if (per_corner && !per_min_max) {
// each corner has parasitics
parasitic_analysis_pts_.resize(corners_.size());
for (Corner *corner : corners_) {
corner->setParasiticAnalysisPtcount(1);
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt("min_max", 0,
MinMax::max());
parasitic_analysis_pts_.push_back(ap);
corner->addParasiticAP(ap);
}
}
else if (!per_corner && per_min_max) {
// min/max parasitics shared by all corners
parasitic_analysis_pts_.resize(MinMax::index_count); parasitic_analysis_pts_.resize(MinMax::index_count);
for (MinMax *min_max : MinMax::range()) { for (MinMax *min_max : MinMax::range()) {
int mm_index = min_max->index(); int mm_index = min_max->index();
@ -148,35 +174,20 @@ Corners::makeParasiticAnalysisPtsMinMax()
min_max); min_max);
parasitic_analysis_pts_[mm_index] = ap; parasitic_analysis_pts_[mm_index] = ap;
} }
updateCornerParasiticAnalysisPts();
}
}
void
Corners::updateCornerParasiticAnalysisPts()
{
for (Corner *corner : corners_) {
corner->setParasiticAnalysisPtcount(parasitic_analysis_pts_.size());
for (ParasiticAnalysisPt *ap : parasitic_analysis_pts_)
corner->addParasiticAP(ap);
}
}
void
Corners::makeCornerParasiticAnalysisPts()
{
if (parasitic_analysis_pts_.size() != corners_.size()) {
parasitic_analysis_pts_.deleteContentsClear();
parasitic_analysis_pts_.resize(corners_.size());
MinMax *min_max = MinMax::max();
int ap_index = 0;
for (Corner *corner : corners_) { for (Corner *corner : corners_) {
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(corner->name(), corner->setParasiticAnalysisPtcount(2);
ap_index, for (ParasiticAnalysisPt *ap : parasitic_analysis_pts_)
min_max); corner->addParasiticAP(ap);
parasitic_analysis_pts_[ap_index] = ap; }
}
else if (!per_corner && !per_min_max) {
// single parasitics shared by all corners
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt("min_max", 0,
MinMax::max());
parasitic_analysis_pts_.push_back(ap);
for (Corner *corner : corners_) {
corner->setParasiticAnalysisPtcount(1);
corner->addParasiticAP(ap); corner->addParasiticAP(ap);
ap_index++;
} }
} }
} }

View File

@ -270,7 +270,10 @@ Sta::Sta() :
link_make_black_boxes_(true), link_make_black_boxes_(true),
update_genclks_(false), update_genclks_(false),
equiv_cells_(nullptr), equiv_cells_(nullptr),
graph_sdc_annotated_(false) graph_sdc_annotated_(false),
// Default to same parasitics for each corner min/max.
parasitics_per_corner_(false),
parasitics_per_min_max_(false)
{ {
} }
@ -299,7 +302,7 @@ Sta::makeComponents()
makeObservers(); makeObservers();
// This must follow updateComponentsState. // This must follow updateComponentsState.
corners_->makeParasiticAnalysisPtsSingle(); makeParasiticAnalysisPts();
setThreadCount(defaultThreadCount()); setThreadCount(defaultThreadCount());
} }
@ -2404,7 +2407,7 @@ Sta::makeCorners(StringSet *corner_names)
{ {
parasitics_->deleteParasitics(); parasitics_->deleteParasitics();
corners_->makeCorners(corner_names); corners_->makeCorners(corner_names);
corners_->makeParasiticAnalysisPtsSingle(); makeParasiticAnalysisPts();
cmd_corner_ = corners_->findCorner(0); cmd_corner_ = corners_->findCorner(0);
} }
@ -3653,6 +3656,7 @@ Sta::setResistance(Net *net,
bool bool
Sta::readSpef(const char *filename, Sta::readSpef(const char *filename,
Instance *instance, Instance *instance,
const Corner *corner,
const MinMaxAll *min_max, const MinMaxAll *min_max,
bool increment, bool increment,
bool pin_cap_included, bool pin_cap_included,
@ -3662,19 +3666,14 @@ Sta::readSpef(const char *filename,
bool delete_after_reduce, bool delete_after_reduce,
bool quiet) bool quiet)
{ {
Corner *corner = cmd_corner_; setParasiticAnalysisPts(corner != nullptr,
const MinMax *cnst_min_max; min_max != MinMaxAll::all());
ParasiticAnalysisPt *ap; if (corner == nullptr)
if (min_max == MinMaxAll::all()) { corner = cmd_corner_;
corners_->makeParasiticAnalysisPtsSingle(); const MinMax *cnst_min_max = (min_max == MinMaxAll::all())
ap = corner->findParasiticAnalysisPt(MinMax::max()); ? cnst_min_max = MinMax::max()
cnst_min_max = MinMax::max(); : cnst_min_max = min_max->asMinMax();
} ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(cnst_min_max);
else {
corners_->makeParasiticAnalysisPtsMinMax();
cnst_min_max = min_max->asMinMax();
ap = corner->findParasiticAnalysisPt(cnst_min_max);
}
const OperatingConditions *op_cond = const OperatingConditions *op_cond =
sdc_->operatingConditions(cnst_min_max); sdc_->operatingConditions(cnst_min_max);
bool success = readSpefFile(filename, instance, ap, increment, bool success = readSpefFile(filename, instance, ap, increment,
@ -3688,6 +3687,26 @@ Sta::readSpef(const char *filename,
return success; return success;
} }
void
Sta::setParasiticAnalysisPts(bool per_corner,
bool per_min_max)
{
if (per_corner != parasitics_per_corner_
|| per_min_max != parasitics_per_min_max_) {
deleteParasitics();
parasitics_per_corner_ = per_corner;
parasitics_per_min_max_ = per_min_max;
makeParasiticAnalysisPts();
}
}
void
Sta::makeParasiticAnalysisPts()
{
corners_->makeParasiticAnalysisPts(parasitics_per_corner_,
parasitics_per_min_max_);
}
void void
Sta::findPiElmore(Pin *drvr_pin, Sta::findPiElmore(Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,