From 9e27f27060365b19f76c9fe3f67da1b8184dcab0 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 15 May 2021 16:55:10 -0700 Subject: [PATCH] corner parasitics APs --- include/sta/Corner.hh | 10 ++--- include/sta/Sta.hh | 16 +++++-- parasitics/Parasitics.i | 5 ++- parasitics/Parasitics.tcl | 6 ++- search/Corner.cc | 95 ++++++++++++++++++++++----------------- search/Sta.cc | 51 ++++++++++++++------- 6 files changed, 111 insertions(+), 72 deletions(-) diff --git a/include/sta/Corner.hh b/include/sta/Corner.hh index 1e8765e3..9f717a86 100644 --- a/include/sta/Corner.hh +++ b/include/sta/Corner.hh @@ -55,12 +55,9 @@ public: void analysisTypeChanged(); void operatingConditionsChanged(); - // Make one parasitic analysis point shared by all corners. - void makeParasiticAnalysisPtsSingle(); - // Make min/max parasitic analysis points shared by all corners. - void makeParasiticAnalysisPtsMinMax(); - // Make one parasitic analysis point for each corner. - void makeCornerParasiticAnalysisPts(); + // Make one parasitic analysis points. + void makeParasiticAnalysisPts(bool per_corner, + bool per_min_max); int parasiticAnalysisPtCount() const; ParasiticAnalysisPtSeq ¶siticAnalysisPts(); @@ -80,7 +77,6 @@ public: protected: void makeAnalysisPts(); - void updateCornerParasiticAnalysisPts(); void makeDcalcAnalysisPts(Corner *corner); DcalcAnalysisPt *makeDcalcAnalysisPt(Corner *corner, const MinMax *min_max, diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 21d5da4c..02daccfe 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -1052,17 +1052,24 @@ public: // Caller owns iterator and iterator->container(). 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. // 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 // networks (dspf) are reduced and deleted after reading each net // with reduce_to and delete_after_reduce. // Return true if successful. bool readSpef(const char *filename, Instance *instance, - const MinMaxAll *min_max, + const Corner *corner, + const MinMaxAll *min_max, bool increment, bool pin_cap_included, bool keep_coupling_caps, @@ -1343,6 +1350,7 @@ protected: void sdcChangedGraph(); void ensureGraphSdcAnnotated(); CornerSeq makeCornerSeq(Corner *corner) const; + void makeParasiticAnalysisPts(); CmdNamespace cmd_namespace_; Instance *current_instance_; @@ -1362,6 +1370,8 @@ protected: bool update_genclks_; EquivCells *equiv_cells_; bool graph_sdc_annotated_; + bool parasitics_per_corner_; + bool parasitics_per_min_max_; // Singleton sta used by tcl command interpreter. static Sta *sta_; diff --git a/parasitics/Parasitics.i b/parasitics/Parasitics.i index 342e83c1..34dd307b 100644 --- a/parasitics/Parasitics.i +++ b/parasitics/Parasitics.i @@ -36,7 +36,8 @@ using sta::TmpFloatSeq; bool read_spef_cmd(const char *filename, Instance *instance, - MinMaxAll *min_max, + const Corner *corner, + const MinMaxAll *min_max, bool increment, bool pin_cap_included, bool keep_coupling_caps, @@ -46,7 +47,7 @@ read_spef_cmd(const char *filename, bool quiet) { cmdLinkedNetwork(); - return Sta::sta()->readSpef(filename, instance, min_max, + return Sta::sta()->readSpef(filename, instance, corner, min_max, increment, pin_cap_included, keep_coupling_caps, coupling_cap_factor, reduce_to, delete_after_reduce, quiet); diff --git a/parasitics/Parasitics.tcl b/parasitics/Parasitics.tcl index 8a9b52a1..f66f2706 100644 --- a/parasitics/Parasitics.tcl +++ b/parasitics/Parasitics.tcl @@ -17,7 +17,8 @@ namespace eval sta { define_cmd_args "read_spef" \ - {[-min]\ + {[-corner corner]\ + [-min]\ [-max]\ [-path path]\ [-increment]\ @@ -46,6 +47,7 @@ proc_redirect read_spef { 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 increment [info exists flags(-increment)] set coupling_reduction_factor 1.0 @@ -67,7 +69,7 @@ proc_redirect read_spef { set quiet [info exists flags(-quiet)] set save [info exists flags(-save)] 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 \ $reduce_to $delete_after_reduce $quiet] } diff --git a/search/Corner.cc b/search/Corner.cc index 81f6d1f5..30480f27 100644 --- a/search/Corner.cc +++ b/search/Corner.cc @@ -114,32 +114,58 @@ Corners::copy(Corners *corners) } makeAnalysisPts(); - parasitic_analysis_pts_.deleteContentsClear(); for (ParasiticAnalysisPt *orig_ap : corners->parasitic_analysis_pts_) { ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(orig_ap->name(), orig_ap->index(), orig_ap->minMax()); parasitic_analysis_pts_.push_back(ap); } - updateCornerParasiticAnalysisPts(); -} -void -Corners::makeParasiticAnalysisPtsSingle() -{ - if (parasitic_analysis_pts_.size() != 1) { - parasitic_analysis_pts_.deleteContentsClear(); - ParasiticAnalysisPt *ap = new ParasiticAnalysisPt("min_max", 0, - MinMax::max()); - parasitic_analysis_pts_.push_back(ap); - updateCornerParasiticAnalysisPts(); + int i = 0; + for (Corner *orig : corners->corners_) { + Corner *corner = corners_[i]; + for (ParasiticAnalysisPt *ap : orig->parasitic_analysis_pts_) + corner->addParasiticAP(parasitic_analysis_pts_[ap->index()]); + i++; } } 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); for (MinMax *min_max : MinMax::range()) { int mm_index = min_max->index(); @@ -148,35 +174,20 @@ Corners::makeParasiticAnalysisPtsMinMax() min_max); 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_) { - ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(corner->name(), - ap_index, - min_max); - parasitic_analysis_pts_[ap_index] = ap; + corner->setParasiticAnalysisPtcount(2); + for (ParasiticAnalysisPt *ap : parasitic_analysis_pts_) + corner->addParasiticAP(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); - ap_index++; } } } diff --git a/search/Sta.cc b/search/Sta.cc index 751f19ef..7068ab41 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -270,7 +270,10 @@ Sta::Sta() : link_make_black_boxes_(true), update_genclks_(false), 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(); // This must follow updateComponentsState. - corners_->makeParasiticAnalysisPtsSingle(); + makeParasiticAnalysisPts(); setThreadCount(defaultThreadCount()); } @@ -2404,7 +2407,7 @@ Sta::makeCorners(StringSet *corner_names) { parasitics_->deleteParasitics(); corners_->makeCorners(corner_names); - corners_->makeParasiticAnalysisPtsSingle(); + makeParasiticAnalysisPts(); cmd_corner_ = corners_->findCorner(0); } @@ -3653,6 +3656,7 @@ Sta::setResistance(Net *net, bool Sta::readSpef(const char *filename, Instance *instance, + const Corner *corner, const MinMaxAll *min_max, bool increment, bool pin_cap_included, @@ -3662,19 +3666,14 @@ Sta::readSpef(const char *filename, bool delete_after_reduce, bool quiet) { - Corner *corner = cmd_corner_; - const MinMax *cnst_min_max; - ParasiticAnalysisPt *ap; - if (min_max == MinMaxAll::all()) { - corners_->makeParasiticAnalysisPtsSingle(); - ap = corner->findParasiticAnalysisPt(MinMax::max()); - cnst_min_max = MinMax::max(); - } - else { - corners_->makeParasiticAnalysisPtsMinMax(); - cnst_min_max = min_max->asMinMax(); - ap = corner->findParasiticAnalysisPt(cnst_min_max); - } + setParasiticAnalysisPts(corner != nullptr, + min_max != MinMaxAll::all()); + if (corner == nullptr) + corner = cmd_corner_; + const MinMax *cnst_min_max = (min_max == MinMaxAll::all()) + ? cnst_min_max = MinMax::max() + : cnst_min_max = min_max->asMinMax(); + ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(cnst_min_max); const OperatingConditions *op_cond = sdc_->operatingConditions(cnst_min_max); bool success = readSpefFile(filename, instance, ap, increment, @@ -3688,6 +3687,26 @@ Sta::readSpef(const char *filename, 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 Sta::findPiElmore(Pin *drvr_pin, const RiseFall *rf,