diff --git a/Brewfile b/Brewfile new file mode 100644 index 00000000..b4f025b6 --- /dev/null +++ b/Brewfile @@ -0,0 +1,9 @@ +brew "bison" +brew "cmake" +brew "eigen" +brew "flex" +brew "swig" +brew "tcl-tk@8" + +tap "mht208/formal" +brew "mht208/formal/cudd" diff --git a/CMakeLists.txt b/CMakeLists.txt index 530b3b0e..6a06e180 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.14) cmake_policy(SET CMP0086 NEW) endif() -project(STA VERSION 2.6.0 +project(STA VERSION 2.6.2 LANGUAGES CXX ) @@ -184,15 +184,11 @@ set(STA_SOURCE search/MakeTimingModel.cc search/Path.cc search/PathAnalysisPt.cc + search/Path.cc search/PathEnd.cc search/PathEnum.cc - search/PathEnumed.cc search/PathExpanded.cc search/PathGroup.cc - search/PathPrev.cc - search/PathRef.cc - search/PathVertex.cc - search/PathVertexPtr.cc search/Property.cc search/ReportPath.cc search/Search.cc diff --git a/README.md b/README.md index 97b08cc8..3b2c1754 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ OpenSTA is open source, meaning the sources are published and can be compiled locally. Derivative works are supported as long as they adhere to the GPL license requirements. However, OpenSTA is not supported by a public community of developers as many other open -source projects are. The copyright and develpment are exclusive to +source projects are. The copyright and development are exclusive to Parallax Software. Removing copyright and license notices from OpenSTA sources (or any @@ -86,7 +86,7 @@ OpenSTA is built with CMake. ### Prerequisites -The build dependency versions are show below. Other versions may +The build dependency versions are shown below. Other versions may work, but these are the versions used for development. ``` @@ -207,10 +207,13 @@ docker run -i -v $HOME:/data OpenSTA ## Build on Macos/Darwin -THe XCode versions of Tcl, Flex and Bison cannot be used to build OpenSTA. -Use Homebrew to install them. +The XCode versions of Tcl, Flex and Bison cannot be used to build OpenSTA. +Use Homebrew to install them. The following command installs the tools +required to build OpenSTA in the Brewfile. - brew install cmake swig flex bison tcl-tk zlib +``` +brew bundle install +``` Set these variables before using cmake to cirumvent the Xcode versions. @@ -255,12 +258,12 @@ case directory. Contributors must sign the Contributor License Agreement (doc/CLA.txt) when submitting pull requests. -All contributors should read doc/CodingGuidelines.txt for nodes on +All contributors should read doc/CodingGuidelines.txt for notes on making code that adheres to the existing naming and formatting style. Contributions that claim 4% performance improvements in OpenROAD flow scripts will largely be ignored. Small performance improvements -simply do not justify the time requied to audit and verify the changes. +simply do not justify the time required to audit and verify the changes. Contributions that add dependencies on external libraries like boost, abseil and Intel TBB will not be accepted. diff --git a/app/StaMain.cc b/app/StaMain.cc index 8587a2db..6a111a35 100644 --- a/app/StaMain.cc +++ b/app/StaMain.cc @@ -98,10 +98,10 @@ sourceTclFile(const char *filename, Tcl_Interp *interp) { string cmd; - stringPrint(cmd, "source %s%s%s", - echo ? "-echo " : "", - verbose ? "-verbose " : "", - filename); + stringPrint(cmd, "sta::include_file %s %s %s", + filename, + echo ? "1" : "0", + verbose ? "1" : "0"); int code = Tcl_Eval(interp, cmd.c_str()); const char *result = Tcl_GetStringResult(interp); if (result[0] != '\0') diff --git a/dcalc/CcsCeffDelayCalc.cc b/dcalc/CcsCeffDelayCalc.cc index 3fb99fa2..2149efca 100644 --- a/dcalc/CcsCeffDelayCalc.cc +++ b/dcalc/CcsCeffDelayCalc.cc @@ -119,7 +119,7 @@ CcsCeffDelayCalc::gateDelay(const Pin *drvr_pin, ref_time_ = output_waveforms_->referenceTime(in_slew_); debugPrint(debug_, "ccs_dcalc", 1, "%s %s", drvr_cell->name(), - drvr_rf_->asString()); + drvr_rf_->to_string().c_str()); ArcDelay gate_delay; Slew drvr_slew; gateDelaySlew(drvr_library, drvr_rf_, gate_delay, drvr_slew); diff --git a/dcalc/DelayCalcBase.cc b/dcalc/DelayCalcBase.cc index fcf3986d..b4484664 100644 --- a/dcalc/DelayCalcBase.cc +++ b/dcalc/DelayCalcBase.cc @@ -55,7 +55,7 @@ DelayCalcBase::reduceParasitic(const Parasitic *parasitic_network, while (pin_iter->hasNext()) { const Pin *pin = pin_iter->next(); if (network_->isDriver(pin)) { - for (RiseFall *rf : RiseFall::range()) { + for (const RiseFall *rf : RiseFall::range()) { for (const MinMax *min_max : min_max->range()) { if (corner == nullptr) { for (const Corner *corner1 : *corners_) { diff --git a/dcalc/DmpCeff.cc b/dcalc/DmpCeff.cc index 10030c4f..a47348d7 100644 --- a/dcalc/DmpCeff.cc +++ b/dcalc/DmpCeff.cc @@ -1600,17 +1600,18 @@ DmpCeffDelayCalc::reportGateDelay(const Pin *drvr_pin, const DcalcAnalysisPt *dcalc_ap, int digits) { - gateDelay(drvr_pin, arc, in_slew, load_cap, parasitic, load_pin_index_map, dcalc_ap); + ArcDcalcResult dcalc_result = gateDelay(drvr_pin, arc, in_slew, load_cap, + parasitic, load_pin_index_map, dcalc_ap); GateTableModel *model = arc->gateTableModel(dcalc_ap); float c_eff = 0.0; string result; + const LibertyCell *drvr_cell = arc->to()->libertyCell(); + const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary(); + const Units *units = drvr_library->units(); + const Unit *cap_unit = units->capacitanceUnit(); + const Unit *res_unit = units->resistanceUnit(); if (parasitic && dmp_alg_) { c_eff = dmp_alg_->ceff(); - const LibertyCell *drvr_cell = arc->to()->libertyCell(); - const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary(); - const Units *units = drvr_library->units(); - const Unit *cap_unit = units->capacitanceUnit(); - const Unit *res_unit = units->resistanceUnit(); float c2, rpi, c1; parasitics_->piModel(parasitic, c2, rpi, c1); result += "Pi model C2="; @@ -1626,9 +1627,13 @@ DmpCeffDelayCalc::reportGateDelay(const Pin *drvr_pin, else c_eff = load_cap; if (model) { + const Unit *time_unit = units->timeUnit(); float in_slew1 = delayAsFloat(in_slew); result += model->reportGateDelay(pinPvt(drvr_pin, dcalc_ap), in_slew1, c_eff, pocv_enabled_, digits); + result += "Driver waveform slew = "; + result += time_unit->asString(dcalc_result.drvrSlew(), digits); + result += '\n'; } return result; } diff --git a/dcalc/GraphDelayCalc.cc b/dcalc/GraphDelayCalc.cc index cdf1a997..da42e090 100644 --- a/dcalc/GraphDelayCalc.cc +++ b/dcalc/GraphDelayCalc.cc @@ -171,7 +171,7 @@ void GraphDelayCalc::delayInvalid(Vertex *vertex) { debugPrint(debug_, "delay_calc", 2, "delay invalid %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); if (graph_ && incremental_) { invalid_delays_->insert(vertex); // Invalidate driver that triggers dcalc for multi-driver nets. @@ -315,7 +315,7 @@ GraphDelayCalc::seedDrvrSlew(Vertex *drvr_vertex, { const Pin *drvr_pin = drvr_vertex->pin(); debugPrint(debug_, "delay_calc", 2, "seed driver slew %s", - drvr_vertex->name(sdc_network_)); + drvr_vertex->to_string(this).c_str()); InputDrive *drive = 0; if (network_->isTopLevelPort(drvr_pin)) { Port *port = network_->port(drvr_pin); @@ -426,7 +426,7 @@ GraphDelayCalc::seedLoadSlew(Vertex *vertex) { const Pin *pin = vertex->pin(); debugPrint(debug_, "delay_calc", 2, "seed load slew %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); ClockSet *clks = sdc_->findLeafPinClocks(pin); initSlew(vertex); for (const RiseFall *rf : RiseFall::range()) { @@ -501,7 +501,7 @@ GraphDelayCalc::findInputDriverDelay(const LibertyCell *drvr_cell, { debugPrint(debug_, "delay_calc", 2, " driver cell %s %s", drvr_cell->name(), - rf->asString()); + rf->to_string().c_str()); for (TimingArcSet *arc_set : drvr_cell->timingArcSets(from_port, to_port)) { for (TimingArc *arc : arc_set->arcs()) { if (arc->toEdge()->asRiseFall() == rf) { @@ -525,10 +525,10 @@ GraphDelayCalc::findInputArcDelay(const Pin *drvr_pin, { debugPrint(debug_, "delay_calc", 3, " %s %s -> %s %s (%s)", arc->from()->name(), - arc->fromEdge()->asString(), + arc->fromEdge()->to_string().c_str(), arc->to()->name(), - arc->toEdge()->asString(), - arc->role()->asString()); + arc->toEdge()->to_string().c_str(), + arc->role()->to_string().c_str()); const RiseFall *drvr_rf = arc->toEdge()->asRiseFall(); if (drvr_rf) { DcalcAPIndex ap_index = dcalc_ap->index(); @@ -577,7 +577,7 @@ GraphDelayCalc::findVertexDelay(Vertex *vertex, { const Pin *pin = vertex->pin(); debugPrint(debug_, "delay_calc", 2, "find delays %s (%s)", - vertex->name(sdc_network_), + vertex->to_string(this).c_str(), network_->cellName(network_->instance(pin))); if (vertex->isRoot()) { seedRootSlew(vertex, arc_delay_calc); @@ -1091,12 +1091,12 @@ GraphDelayCalc::annotateDelaySlew(Edge *edge, debugPrint(debug_, "delay_calc", 3, " %s %s -> %s %s (%s) corner:%s/%s", arc->from()->name(), - arc->fromEdge()->asString(), + arc->fromEdge()->to_string().c_str(), arc->to()->name(), - arc->toEdge()->asString(), - arc->role()->asString(), + arc->toEdge()->to_string().c_str(), + arc->role()->to_string().c_str(), dcalc_ap->corner()->name(), - dcalc_ap->delayMinMax()->asString()); + dcalc_ap->delayMinMax()->to_string().c_str()); debugPrint(debug_, "delay_calc", 3, " gate delay = %s slew = %s", delayAsString(gate_delay, this), @@ -1149,7 +1149,7 @@ GraphDelayCalc::annotateLoadDelays(Vertex *drvr_vertex, Slew load_slew = dcalc_result.loadSlew(load_idx); debugPrint(debug_, "delay_calc", 3, " %s load delay = %s slew = %s", - load_vertex->name(sdc_network_), + load_vertex->to_string(this).c_str(), delayAsString(wire_delay, this), delayAsString(load_slew, this)); bool load_changed = false; @@ -1465,8 +1465,8 @@ GraphDelayCalc::findCheckEdgeDelays(Edge *edge, network_->portName(to_pin)); bool delay_changed = false; for (TimingArc *arc : arc_set->arcs()) { - RiseFall *from_rf = arc->fromEdge()->asRiseFall(); - RiseFall *to_rf = arc->toEdge()->asRiseFall(); + const RiseFall *from_rf = arc->fromEdge()->asRiseFall(); + const RiseFall *to_rf = arc->toEdge()->asRiseFall(); if (from_rf && to_rf) { const LibertyPort *related_out_port = arc_set->relatedOut(); const Pin *related_out_pin = 0; @@ -1482,12 +1482,12 @@ GraphDelayCalc::findCheckEdgeDelays(Edge *edge, debugPrint(debug_, "delay_calc", 3, " %s %s -> %s %s (%s) corner:%s/%s", arc_set->from()->name(), - arc->fromEdge()->asString(), + arc->fromEdge()->to_string().c_str(), arc_set->to()->name(), - arc->toEdge()->asString(), - arc_set->role()->asString(), + arc->toEdge()->to_string().c_str(), + arc_set->role()->to_string().c_str(), dcalc_ap->corner()->name(), - dcalc_ap->delayMinMax()->asString()); + dcalc_ap->delayMinMax()->to_string().c_str()); debugPrint(debug_, "delay_calc", 3, " from_slew = %s to_slew = %s", delayAsString(from_slew, this), @@ -1538,13 +1538,13 @@ GraphDelayCalc::reportDelayCalc(const Edge *edge, Vertex *from_vertex = edge->from(graph_); Vertex *to_vertex = edge->to(graph_); Pin *to_pin = to_vertex->pin(); - TimingRole *role = arc->role(); + const TimingRole *role = arc->role(); const Instance *inst = network_->instance(to_pin); const TimingArcSet *arc_set = edge->timingArcSet(); string result; DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max); - RiseFall *from_rf = arc->fromEdge()->asRiseFall(); - RiseFall *to_rf = arc->toEdge()->asRiseFall(); + const RiseFall *from_rf = arc->fromEdge()->asRiseFall(); + const RiseFall *to_rf = arc->toEdge()->asRiseFall(); if (from_rf && to_rf) { const LibertyPort *related_out_port = arc_set->relatedOut(); const Pin *related_out_pin = 0; diff --git a/dcalc/PrimaDelayCalc.cc b/dcalc/PrimaDelayCalc.cc index c8226076..7aeb442f 100644 --- a/dcalc/PrimaDelayCalc.cc +++ b/dcalc/PrimaDelayCalc.cc @@ -228,7 +228,7 @@ PrimaDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args, output_waveforms_[drvr_idx] = output_waveforms; debugPrint(debug_, "ccs_dcalc", 1, "%s %s", dcalc_arg.drvrCell()->name(), - drvr_rf_->asString()); + drvr_rf_->to_string().c_str()); LibertyCell *drvr_cell = dcalc_arg.drvrCell(); const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary(); bool vdd_exists; @@ -741,7 +741,7 @@ PrimaDelayCalc::dcalcResults() debugPrint(debug_, "ccs_dcalc", 2, "load %s %s delay %s slew %s", network_->pathName(load_pin), - drvr_rf_->asString(), + drvr_rf_->to_string().c_str(), delayAsString(wire_delay, this), delayAsString(load_slew, this)); diff --git a/doc/ApiChanges.txt b/doc/ApiChanges.txt index 9dd06296..7f4863b8 100644 --- a/doc/ApiChanges.txt +++ b/doc/ApiChanges.txt @@ -24,6 +24,45 @@ This file summarizes STA API changes for each release. +Release 2.6.2 2024/03/30 +------------------------ + +The following functions have been renamed to to_string and return std::string +instead of "const char*" + + Vertex::name + FuncExpr::asString + TimingRole::name + MinMax::asString + MinMaxAll::asString + RiseFall::asString + RiseFallBoth::asString + Transition::asString + Tag::asString + timingSenseString + +The following classes now return const objects. + + MinMax + MinMaxAll + RiseFall + RiseFallBoth + Transition + TimingRole + +Release 2.6.1 2025/03/?? +------------------------- + +The following classes have been replaced by the class Path. + PathEnumed + PathPrev + PathRef + PathVertex + PathVertexPtr + PathVertexRep + +The PathExpanded::prevArc function has been removed. Use Path::prevArc instead. + Release 2.4.0 2023/01/19 ------------------------- diff --git a/doc/ChangeLog.txt b/doc/ChangeLog.txt index 41a1c6a3..29d7c8be 100644 --- a/doc/ChangeLog.txt +++ b/doc/ChangeLog.txt @@ -3,6 +3,19 @@ OpenSTA Timing Analyzer Release Notes This file summarizes user visible changes for each release. +Realase 2.6.1 2025/03/30 +------------------------- + +The Tcl "source" command is no longer redefined to support "-echo" and +"-verbose" arguments and redirecton. Use the "include" command instead. + + include [-echo] [-verbose] filename [> filename] [>> filename] + -echo echos commands as they are read + -verbose prints command results as they are evaluated + +Unlike the Tcl source command, "include" expands filenames with tilda '~' +and respects sta_continue_on_error. + Release 2.6.0 2024/07/22 ------------------------- diff --git a/doc/OpenSTA.odt b/doc/OpenSTA.odt index ed627906..6e57b780 100644 Binary files a/doc/OpenSTA.odt and b/doc/OpenSTA.odt differ diff --git a/doc/OpenSTA.pdf b/doc/OpenSTA.pdf index 6c9590d8..2293d8f8 100644 Binary files a/doc/OpenSTA.pdf and b/doc/OpenSTA.pdf differ diff --git a/graph/Graph.cc b/graph/Graph.cc index c0961f05..b0f45b22 100644 --- a/graph/Graph.cc +++ b/graph/Graph.cc @@ -206,7 +206,7 @@ Graph::makePortInstanceEdges(const Instance *inst, // Vertices can be missing from the graph if the pins // are power or ground. if (from_vertex) { - TimingRole *role = arc_set->role(); + const TimingRole *role = arc_set->role(); bool is_check = role->isTimingCheckBetween(); if (to_bidirect_drvr_vertex && !is_check) makeEdge(from_vertex, to_bidirect_drvr_vertex, arc_set); @@ -571,75 +571,25 @@ Graph::gateEdgeArc(const Pin *in_pin, //////////////////////////////////////////////////////////////// -Arrival * -Graph::makeArrivals(Vertex *vertex, - uint32_t count) +Path * +Graph::makePaths(Vertex *vertex, + uint32_t count) { - Arrival *arrivals = new Arrival[count]; - vertex->setArrivals(arrivals); - return arrivals; + Path *paths = new Path[count]; + vertex->setPaths(paths); + return paths; } -Arrival * -Graph::arrivals(const Vertex *vertex) const +Path * +Graph::paths(const Vertex *vertex) const { - return vertex->arrivals(); -} - -void -Graph::deleteArrivals(Vertex *vertex) -{ - vertex->setArrivals(nullptr); -} - -Required * -Graph::requireds(const Vertex *vertex) const -{ - return vertex->requireds(); -} - -Required * -Graph::makeRequireds(Vertex *vertex, - uint32_t count) -{ - Required *requireds = new Arrival[count]; - vertex->setRequireds(requireds); - return requireds; -} - -void -Graph::deleteRequireds(Vertex *vertex) -{ - vertex->setRequireds(nullptr); -} - -PathPrev * -Graph::prevPaths(const Vertex *vertex) const -{ - return vertex->prevPaths(); -} - -PathPrev * -Graph::makePrevPaths(Vertex *vertex, - uint32_t count) -{ - PathPrev *prev_paths = new PathPrev[count]; - vertex->setPrevPaths(prev_paths); - return prev_paths; -} - -void -Graph::deletePrevPaths(Vertex *vertex) -{ - vertex->setPrevPaths(nullptr); + return vertex->paths(); } void Graph::deletePaths(Vertex *vertex) { - deleteArrivals(vertex); - deleteRequireds(vertex); - deletePrevPaths(vertex); + vertex->setPaths(nullptr); vertex->tag_group_index_ = tag_group_index_max; vertex->crpr_path_pruning_disabled_ = false; } @@ -1007,9 +957,7 @@ Vertex::init(Pin *pin, in_edges_ = edge_id_null; out_edges_ = edge_id_null; slews_ = nullptr; - arrivals_ = nullptr; - requireds_ = nullptr; - prev_paths_ = nullptr; + paths_ = nullptr; tag_group_index_ = tag_group_index_max; slew_annotated_ = false; sim_value_ = unsigned(LogicValue::unknown); @@ -1035,12 +983,8 @@ Vertex::clear() { delete [] slews_; slews_ = nullptr; - delete [] arrivals_; - arrivals_ = nullptr; - delete [] requireds_; - requireds_ = nullptr; - delete [] prev_paths_; - prev_paths_ = nullptr; + delete [] paths_; + paths_ = nullptr; } void @@ -1049,19 +993,27 @@ Vertex::setObjectIdx(ObjectIdx idx) object_idx_ = idx; } -const char * -Vertex::name(const Network *network) const +string +Vertex::to_string(const StaState *sta) const { + const Network *network = sta->network(); if (network->direction(pin_)->isBidirect()) { - const char *pin_name = network->pathName(pin_); - return stringPrintTmp("%s %s", - pin_name, - is_bidirect_drvr_ ? "driver" : "load"); + string str = network->pathName(pin_); + str += ' '; + str += is_bidirect_drvr_ ? "driver" : "load"; + return str; } else return network->pathName(pin_); } +const char * +Vertex::name(const Network *network) const +{ + string name = to_string(network); + return makeTmpString(name); +} + bool Vertex::isDriver(const Network *network) const { @@ -1153,24 +1105,10 @@ Vertex::setTagGroupIndex(TagGroupIndex tag_index) } void -Vertex::setArrivals(Arrival *arrivals) +Vertex::setPaths(Path *paths) { - delete [] arrivals_; - arrivals_ = arrivals; -} - -void -Vertex::setRequireds(Required *requireds) -{ - delete [] requireds_; - requireds_ = requireds; -} - -void -Vertex::setPrevPaths(PathPrev *prev_paths) -{ - delete [] prev_paths_; - prev_paths_ = prev_paths; + delete [] paths_; + paths_ = paths; } LogicValue @@ -1315,6 +1253,16 @@ Edge::setObjectIdx(ObjectIdx idx) object_idx_ = idx; } +string +Edge::to_string(const StaState *sta) const +{ + const Graph *graph = sta->graph(); + string str = from(graph)->to_string(sta); + str += " -> "; + str += to(graph)->to_string(sta); + return str; +} + void Edge::setTimingArcSet(TimingArcSet *set) { @@ -1380,7 +1328,7 @@ Edge::setDelayAnnotationIsIncremental(bool is_incr) delay_annotation_is_incremental_ = is_incr; } -TimingRole * +const TimingRole * Edge::role() const { return arc_set_->role(); @@ -1414,7 +1362,7 @@ Edge::setSimTimingSense(TimingSense sense) bool Edge::isDisabledConstraint() const { - TimingRole *role = arc_set_->role(); + const TimingRole *role = arc_set_->role(); bool is_wire = role->isWire(); return is_disabled_constraint_ || arc_set_->isDisabledConstraint() diff --git a/graph/Graph.i b/graph/Graph.i index 0db3793e..0c2f57b2 100644 --- a/graph/Graph.i +++ b/graph/Graph.i @@ -316,8 +316,8 @@ Vertex *from() { return self->from(Sta::sta()->graph()); } Vertex *to() { return self->to(Sta::sta()->graph()); } Pin *from_pin() { return self->from(Sta::sta()->graph())->pin(); } Pin *to_pin() { return self->to(Sta::sta()->graph())->pin(); } -TimingRole *role() { return self->role(); } -const char *sense() { return timingSenseString(self->sense()); } +const TimingRole *role() { return self->role(); } +const char *sense() { return to_string(self->sense()); } TimingArcSeq & timing_arcs() { return self->timingArcSet()->arcs(); } bool is_disabled_loop() { return Sta::sta()->isDisabledLoop(self); } @@ -334,7 +334,7 @@ bool is_disabled_bidirect_net_path() bool is_disabled_preset_clear() { return Sta::sta()->isDisabledPresetClr(self); } const char * -sim_timing_sense(){return timingSenseString(Sta::sta()->simTimingSense(self));} +sim_timing_sense(){return to_string(Sta::sta()->simTimingSense(self));} FloatSeq arc_delays(TimingArc *arc) @@ -376,14 +376,14 @@ arc_delay(TimingArc *arc, return delayAsFloat(Sta::sta()->arcDelay(self, arc, dcalc_ap)); } -const char * +string cond() { FuncExpr *cond = self->timingArcSet()->cond(); if (cond) - return cond->asString(); + return cond->to_string(); else - return nullptr; + return ""; } const char * @@ -414,7 +414,9 @@ latch_d_to_q_en() const RiseFall *enable_rf; lib_cell->latchEnable(d_q_set, enable_port, enable_func, enable_rf); if (enable_port) - return stringPrintTmp("%s %s", enable_port->name(), enable_rf->asString()); + return stringPrintTmp("%s %s", + enable_port->name(), + enable_rf->to_string().c_str()); } return ""; } diff --git a/include/sta/Bfs.hh b/include/sta/Bfs.hh index 4056303a..bf198cf5 100644 --- a/include/sta/Bfs.hh +++ b/include/sta/Bfs.hh @@ -75,7 +75,7 @@ public: // Notify iterator that vertex will be deleted. void deleteVertexBefore(Vertex *vertex); void remove(Vertex *vertex); - void reportEntries(const Network *network); + void reportEntries(); virtual bool hasNext(); bool hasNext(Level to_level); diff --git a/include/sta/Clock.hh b/include/sta/Clock.hh index e2b70a31..d372aab2 100644 --- a/include/sta/Clock.hh +++ b/include/sta/Clock.hh @@ -203,7 +203,7 @@ class ClockEdge public: Clock *clock() const { return clock_; } ~ClockEdge(); - RiseFall *transition() const { return rf_; } + const RiseFall *transition() const { return rf_; } float time() const { return time_; } const char *name() const { return name_; } int index() const { return index_; } @@ -213,11 +213,12 @@ public: friend class Clock; // builder private: - ClockEdge(Clock *clock, RiseFall *rf); + ClockEdge(Clock *clock, + const RiseFall *rf); void setTime(float time); Clock *clock_; - RiseFall *rf_; + const RiseFall *rf_; const char *name_; float time_; int index_; @@ -262,7 +263,7 @@ public: void removeUncertainty(const RiseFallBoth *src_rf, const RiseFallBoth *tgt_rf, const SetupHoldAll *setup_hold); - const RiseFallMinMax *uncertainties(RiseFall *src_rf) const; + const RiseFallMinMax *uncertainties(const RiseFall *src_rf) const; bool empty() const; private: diff --git a/include/sta/ConcreteLibrary.hh b/include/sta/ConcreteLibrary.hh index 98a62075..26128899 100644 --- a/include/sta/ConcreteLibrary.hh +++ b/include/sta/ConcreteLibrary.hh @@ -45,10 +45,10 @@ class PatternMatch; class LibertyCell; class LibertyPort; -typedef Map ConcreteCellMap; +typedef Map ConcreteCellMap; typedef std::map AttributeMap; typedef Vector ConcretePortSeq; -typedef Map ConcretePortMap; +typedef Map ConcretePortMap; typedef ConcreteCellMap::ConstIterator ConcreteLibraryCellIterator; typedef ConcretePortSeq::ConstIterator ConcreteCellPortIterator; typedef ConcretePortSeq::ConstIterator ConcretePortMemberIterator; @@ -60,11 +60,11 @@ public: const char *filename, bool is_liberty); virtual ~ConcreteLibrary(); - const char *name() const { return name_; } + const char *name() const { return name_.c_str(); } void setName(const char *name); ObjectId id() const { return id_; } bool isLiberty() const { return is_liberty_; } - const char *filename() const { return filename_; } + const char *filename() const { return filename_.c_str(); } void addCell(ConcreteCell *cell); ConcreteCell *makeCell(const char *name, bool is_leaf, @@ -82,9 +82,9 @@ protected: void renameCell(ConcreteCell *cell, const char *cell_name); - const char *name_; + string name_; ObjectId id_; - const char *filename_; + string filename_; bool is_liberty_; char bus_brkt_left_; char bus_brkt_right_; @@ -99,9 +99,9 @@ class ConcreteCell public: // Use ConcreteLibrary::deleteCell. virtual ~ConcreteCell(); - const char *name() const { return name_; } + const char *name() const { return name_.c_str(); } ObjectId id() const { return id_; } - const char *filename() const { return filename_; } + const char *filename() const { return filename_.c_str(); } ConcreteLibrary *library() const { return library_; } LibertyCell *libertyCell() const { return liberty_cell_; } void setLibertyCell(LibertyCell *cell); @@ -156,10 +156,10 @@ protected: const char *name, int index); - const char *name_; + string name_; ObjectId id_; // Filename is optional. - const char *filename_; + string filename_; ConcreteLibrary *library_; LibertyCell *liberty_cell_; // External application cell. @@ -181,7 +181,7 @@ class ConcretePort { public: virtual ~ConcretePort(); - const char *name() const { return name_; } + const char *name() const { return name_.c_str(); } ObjectId id() const { return id_; } const char *busName() const; Cell *cell() const; @@ -236,7 +236,7 @@ protected: ConcretePortSeq *member_ports, ConcreteCell *cell); - const char *name_; + string name_; ObjectId id_; ConcreteCell *cell_; PortDirection *direction_; diff --git a/include/sta/Corner.hh b/include/sta/Corner.hh index 015b77bc..99f58bbc 100644 --- a/include/sta/Corner.hh +++ b/include/sta/Corner.hh @@ -51,7 +51,7 @@ class Corners : public StaState { public: explicit Corners(StaState *sta); - virtual ~Corners(); + ~Corners(); void clear(); int count() const; void copy(Corners *corners); @@ -106,8 +106,7 @@ class Corner public: Corner(const char *name, int index); - ~Corner(); - const char *name() const { return name_; } + const char *name() const { return name_.c_str(); } int index() const { return index_; } ParasiticAnalysisPt *findParasiticAnalysisPt(const MinMax *min_max) const; int parasiticAnalysisPtcount(); @@ -127,7 +126,7 @@ protected: void addPathAP(PathAnalysisPt *path_ap); private: - const char *name_; + string name_; int index_; ParasiticAnalysisPtSeq parasitic_analysis_pts_; DcalcAnalysisPtSeq dcalc_analysis_pts_; diff --git a/include/sta/CycleAccting.hh b/include/sta/CycleAccting.hh index 2bd06ff3..3cc5a045 100644 --- a/include/sta/CycleAccting.hh +++ b/include/sta/CycleAccting.hh @@ -95,7 +95,7 @@ private: int tgt_cycle, float delay, float req); - void setAccting(TimingRole *role, + void setAccting(const TimingRole *role, int src_cycle, int tgt_cycle, float delay, diff --git a/include/sta/DataCheck.hh b/include/sta/DataCheck.hh index 589d5365..3e55f4a8 100644 --- a/include/sta/DataCheck.hh +++ b/include/sta/DataCheck.hh @@ -56,7 +56,7 @@ public: const RiseFallBoth *to_rf, const SetupHoldAll *setup_hold); bool empty() const; - void marginIsOneValue(SetupHold *setup_hold, + void marginIsOneValue(const SetupHold *setup_hold, // Return values. float &value, bool &one_value) const; diff --git a/include/sta/FuncExpr.hh b/include/sta/FuncExpr.hh index 73a3aeb8..5ccf2be1 100644 --- a/include/sta/FuncExpr.hh +++ b/include/sta/FuncExpr.hh @@ -24,12 +24,16 @@ #pragma once +#include + #include "Set.hh" #include "NetworkClass.hh" #include "LibertyClass.hh" namespace sta { +using std::string; + class FuncExpr { public: @@ -75,7 +79,7 @@ public: TimingSense portTimingSense(const LibertyPort *port) const; // Return true if expression has port as an input. bool hasPort(const LibertyPort *port) const; - const char *asString() const; + string to_string() const; // Sub expression for a bus function (bit_offset is 0 to bus->size()-1). FuncExpr *bitSubExpr(int bit_offset); // Check to make sure the function and port size are compatible. @@ -84,9 +88,9 @@ public: bool checkSize(LibertyPort *port); private: - const char *asString(bool with_parens) const; - const char *asStringSubexpr(bool with_parens, - char op) const; + string to_string(bool with_parens) const; + string to_string(bool with_parens, + char op) const; Operator op_; FuncExpr *left_; diff --git a/include/sta/Graph.hh b/include/sta/Graph.hh index 4aa2313a..daff9bb6 100644 --- a/include/sta/Graph.hh +++ b/include/sta/Graph.hh @@ -36,7 +36,7 @@ #include "Delay.hh" #include "GraphClass.hh" #include "VertexId.hh" -#include "PathPrev.hh" +#include "Path.hh" #include "StaState.hh" namespace sta { @@ -96,19 +96,9 @@ public: void deleteVertex(Vertex *vertex); bool hasFaninOne(Vertex *vertex) const; VertexId vertexCount() { return vertices_->size(); } - Arrival *makeArrivals(Vertex *vertex, - uint32_t count); - Arrival *arrivals(const Vertex *vertex) const; - void deleteArrivals(Vertex *vertex); - Required *makeRequireds(Vertex *vertex, - uint32_t count); - Required *requireds(const Vertex *vertex) const; - void deleteRequireds(Vertex *vertex); - PathPrev *makePrevPaths(Vertex *vertex, - uint32_t count); - PathPrev *prevPaths(const Vertex *vertex) const; - void deletePrevPaths(Vertex *vertex); - // Private to Search::deletePaths(Vertex). + Path *makePaths(Vertex *vertex, + uint32_t count); + Path *paths(const Vertex *vertex) const; void deletePaths(Vertex *vertex); // Reported slew are the same as those in the liberty tables. @@ -257,6 +247,8 @@ public: ~Vertex(); Pin *pin() const { return pin_; } // Pin path with load/driver suffix for bidirects. + string to_string(const StaState *sta) const; + // compatibility const char *name(const Network *network) const; bool isBidirectDriver() const { return is_bidirect_drvr_; } bool isDriver(const Network *network) const; @@ -269,10 +261,8 @@ public: void setColor(LevelColor color); Slew *slews() { return slews_; } const Slew *slews() const { return slews_; } - Arrival *arrivals() const { return arrivals_; } - Arrival *requireds() const { return requireds_; } - PathPrev *prevPaths() const { return prev_paths_; } - void setPrevPaths(PathPrev *prev_paths); + Path *paths() const { return paths_; } + void setPaths(Path *paths); TagGroupIndex tagGroupIndex() const; void setTagGroupIndex(TagGroupIndex tag_index); // Slew is annotated by sdc set_annotated_transition cmd. @@ -311,7 +301,6 @@ public: bool isRegClk() const { return is_reg_clk_; } bool crprPathPruningDisabled() const { return crpr_path_pruning_disabled_;} void setCrprPathPruningDisabled(bool disabled); - bool hasRequireds() const { return requireds_ != nullptr; } // ObjectTable interface. ObjectIdx objectIdx() const { return object_idx_; } @@ -324,8 +313,6 @@ protected: bool is_bidirect_drvr, bool is_reg_clk); void clear(); - void setArrivals(Arrival *arrivals); - void setRequireds(Required *requireds); void setSlews(Slew *slews); Pin *pin_; @@ -335,9 +322,7 @@ protected: // Delay calc Slew *slews_; // Search - Arrival *arrivals_; - Arrival *requireds_; - PathPrev *prev_paths_; + Path *paths_; // These fields are written by multiple threads, so they // cannot share the same word as the following bit fields. @@ -381,11 +366,12 @@ class Edge public: Edge(); ~Edge(); + string to_string(const StaState *sta) const; Vertex *to(const Graph *graph) const { return graph->vertex(to_); } VertexId to() const { return to_; } Vertex *from(const Graph *graph) const { return graph->vertex(from_); } VertexId from() const { return from_; } - TimingRole *role() const; + const TimingRole *role() const; bool isWire() const; TimingSense sense() const; TimingArcSet *timingArcSet() const { return arc_set_; } diff --git a/include/sta/InternalPower.hh b/include/sta/InternalPower.hh index c4411ad6..6c9e8756 100644 --- a/include/sta/InternalPower.hh +++ b/include/sta/InternalPower.hh @@ -40,9 +40,9 @@ public: void deleteContents(); FuncExpr *when() const { return when_; } FuncExpr *&whenRef() { return when_; } - void setModel(RiseFall *rf, + void setModel(const RiseFall *rf, InternalPowerModel *model); - InternalPowerModel *model(RiseFall *rf) const; + InternalPowerModel *model(const RiseFall *rf) const; const char *relatedPgPin() const { return related_pg_pin_; } void setRelatedPgPin(const char *related_pg_pin); @@ -65,7 +65,7 @@ public: LibertyPort *relatedPort() const { return related_port_; } FuncExpr *when() const { return when_; } const char *relatedPgPin() const { return related_pg_pin_; } - float power(RiseFall *rf, + float power(const RiseFall *rf, const Pvt *pvt, float in_slew, float load_cap); diff --git a/include/sta/Liberty.hh b/include/sta/Liberty.hh index 1ac7921f..23e881d9 100644 --- a/include/sta/Liberty.hh +++ b/include/sta/Liberty.hh @@ -88,9 +88,9 @@ typedef Map LatchEnableMap; typedef Vector LatchEnableSeq; typedef Map OcvDerateMap; typedef Vector InternalPowerAttrsSeq; -typedef Map SupplyVoltageMap; -typedef Map LibertyPgPortMap; -typedef Map DriverWaveformMap; +typedef Map SupplyVoltageMap; +typedef Map LibertyPgPortMap; +typedef Map DriverWaveformMap; typedef Vector DcalcAnalysisPtSeq; enum class ClockGateType { none, latch_posedge, latch_negedge, other }; @@ -135,7 +135,7 @@ scaleFactorTypeLowHighSuffix(ScaleFactorType type); // Timing sense as a string. const char * -timingSenseString(TimingSense sense); +to_string(TimingSense sense); // Opposite timing sense. TimingSense @@ -188,7 +188,7 @@ public: const Pvt *pvt) const; void setWireSlewDegradationTable(TableModel *model, - RiseFall *rf); + const RiseFall *rf); TableModel *wireSlewDegradationTable(const RiseFall *rf) const; float degradeWireSlew(const RiseFall *rf, float in_slew, @@ -647,8 +647,8 @@ protected: bool has_internal_ports_; std::atomic have_voltage_waveforms_; std::mutex waveform_lock_; - const char *footprint_; - const char *user_function_class_; + string footprint_; + string user_function_class_; private: friend class LibertyLibrary; @@ -809,11 +809,11 @@ public: void setIsCheckClk(bool is_clk); bool isPad() const { return is_pad_; } void setIsPad(bool is_pad); - RiseFall *pulseClkTrigger() const { return pulse_clk_trigger_; } + const RiseFall *pulseClkTrigger() const { return pulse_clk_trigger_; } // Rise for high, fall for low. - RiseFall *pulseClkSense() const { return pulse_clk_sense_; } - void setPulseClk(RiseFall *rfigger, - RiseFall *sense); + const RiseFall *pulseClkSense() const { return pulse_clk_sense_; } + void setPulseClk(const RiseFall *rfigger, + const RiseFall *sense); bool isDisabledConstraint() const { return is_disabled_constraint_; } void setIsDisabledConstraint(bool is_disabled); LibertyPort *cornerPort(const Corner *corner, @@ -826,9 +826,9 @@ public: const LibertyPort *cornerPort(int ap_index) const; void setCornerPort(LibertyPort *corner_port, int ap_index); - const char *relatedGroundPin() const { return related_ground_pin_; } + const char *relatedGroundPin() const; void setRelatedGroundPin(const char *related_ground_pin); - const char *relatedPowerPin() const { return related_power_pin_; } + const char *relatedPowerPin() const; void setRelatedPowerPin(const char *related_power_pin); const ReceiverModel *receiverModel() const { return receiver_model_.get(); } void setReceiverModel(ReceiverModelPtr receiver_model); @@ -886,10 +886,10 @@ protected: MinMaxFloatValues fanout_limit_; // outputs float min_period_; float min_pulse_width_[RiseFall::index_count]; - RiseFall *pulse_clk_trigger_; - RiseFall *pulse_clk_sense_; - const char *related_ground_pin_; - const char *related_power_pin_; + const RiseFall *pulse_clk_trigger_; + const RiseFall *pulse_clk_sense_; + string related_ground_pin_; + string related_power_pin_; Vector corner_ports_; ReceiverModelPtr receiver_model_; DriverWaveform *driver_waveform_[RiseFall::index_count]; @@ -958,19 +958,18 @@ protected: class OperatingConditions : public Pvt { public: - explicit OperatingConditions(const char *name); + OperatingConditions(const char *name); OperatingConditions(const char *name, float process, float voltage, float temperature, WireloadTree wire_load_tree); - virtual ~OperatingConditions(); - const char *name() const { return name_; } + const char *name() const { return name_.c_str(); } WireloadTree wireloadTree() const { return wire_load_tree_; } void setWireloadTree(WireloadTree tree); protected: - const char *name_; + string name_; WireloadTree wire_load_tree_; }; @@ -978,11 +977,10 @@ class ScaleFactors { public: explicit ScaleFactors(const char *name); - ~ScaleFactors(); - const char *name() const { return name_; } + const char *name() const { return name_.c_str(); } float scale(ScaleFactorType type, ScaleFactorPvt pvt, - RiseFall *rf); + const RiseFall *rf); float scale(ScaleFactorType type, ScaleFactorPvt pvt, int rf_index); @@ -990,7 +988,7 @@ public: ScaleFactorPvt pvt); void setScale(ScaleFactorType type, ScaleFactorPvt pvt, - RiseFall *rf, + const RiseFall *rf, float scale); void setScale(ScaleFactorType type, ScaleFactorPvt pvt, @@ -998,7 +996,7 @@ public: void print(); protected: - const char *name_; + string name_; float scales_[scale_factor_type_count][scale_factor_pvt_count][RiseFall::index_count]; }; @@ -1008,13 +1006,12 @@ public: BusDcl(const char *name, int from, int to); - ~BusDcl(); - const char *name() const { return name_; } + const char *name() const { return name_.c_str(); } int from() const { return from_; } int to() const { return to_; } protected: - const char *name_; + string name_; int from_; int to_; }; @@ -1024,7 +1021,7 @@ class ModeDef { public: ~ModeDef(); - const char *name() const { return name_; } + const char *name() const { return name_.c_str(); } ModeValueDef *defineValue(const char *value, FuncExpr *cond, const char *sdf_cond); @@ -1033,9 +1030,9 @@ public: protected: // Private to LibertyCell::makeModeDef. - explicit ModeDef(const char *name); + ModeDef(const char *name); - const char *name_; + string name_; ModeValueMap values_; private: @@ -1047,10 +1044,10 @@ class ModeValueDef { public: ~ModeValueDef(); - const char *value() const { return value_; } + const char *value() const { return value_.c_str(); } FuncExpr *cond() const { return cond_; } FuncExpr *&condRef() { return cond_; } - const char *sdfCond() const { return sdf_cond_; } + const char *sdfCond() const { return sdf_cond_.c_str(); } void setSdfCond(const char *sdf_cond); protected: @@ -1059,9 +1056,9 @@ protected: FuncExpr *cond, const char *sdf_cond); - const char *value_; + string value_; FuncExpr *cond_; - const char *sdf_cond_; + string sdf_cond_; private: friend class ModeDef; @@ -1070,13 +1067,12 @@ private: class TableTemplate { public: - explicit TableTemplate(const char *name); + TableTemplate(const char *name); TableTemplate(const char *name, TableAxisPtr axis1, TableAxisPtr axis2, TableAxisPtr axis3); - ~TableTemplate(); - const char *name() const { return name_; } + const char *name() const { return name_.c_str(); } void setName(const char *name); const TableAxis *axis1() const { return axis1_.get(); } TableAxisPtr axis1ptr() const { return axis1_; } @@ -1089,7 +1085,7 @@ public: void setAxis3(TableAxisPtr axis); protected: - const char *name_; + string name_; TableAxisPtr axis1_; TableAxisPtr axis2_; TableAxisPtr axis3_; @@ -1137,20 +1133,19 @@ public: deepnwell, deeppwell}; LibertyPgPort(const char *name, LibertyCell *cell); - ~LibertyPgPort(); - const char *name() const { return name_; } + const char *name() const { return name_.c_str(); } LibertyCell *cell() const { return cell_; } PgType pgType() const { return pg_type_; } void setPgType(PgType type); - const char *voltageName() const { return voltage_name_; } + const char *voltageName() const { return voltage_name_.c_str(); } void setVoltageName(const char *voltage_name); static bool equiv(const LibertyPgPort *port1, const LibertyPgPort *port2); private: - const char *name_; + string name_; PgType pg_type_; - const char *voltage_name_; + string voltage_name_; LibertyCell *cell_; }; diff --git a/include/sta/MinMax.hh b/include/sta/MinMax.hh index 4ff72999..6555852b 100644 --- a/include/sta/MinMax.hh +++ b/include/sta/MinMax.hh @@ -26,10 +26,14 @@ #include #include +#include + #include "Iterator.hh" namespace sta { +using std::string; + class MinMax; class MinMaxAll; @@ -46,15 +50,15 @@ public: static void init(); static void destroy(); // Singleton accessors. - static MinMax *min() { return &min_; } - static MinMax *max() { return &max_; } - static EarlyLate *early() { return &min_; } - static EarlyLate *late() { return &max_; } + static const MinMax *min() { return &min_; } + static const MinMax *max() { return &max_; } + static const EarlyLate *early() { return &min_; } + static const EarlyLate *late() { return &max_; } static int minIndex() { return min_.index_; } static int earlyIndex() { return min_.index_; } static int maxIndex() { return max_.index_; } static int lateIndex() { return max_.index_; } - const char *asString() const { return name_; } + const string &to_string() const { return name_; } int index() const { return index_; } float initValue() const { return init_value_; } int initValueInt() const { return init_value_int_; } @@ -64,17 +68,17 @@ public: // min/max(value1, value2) float minMax(float value1, float value2) const; - MinMaxAll *asMinMaxAll() const; - MinMax *opposite() const; + const MinMaxAll *asMinMaxAll() const; + const MinMax *opposite() const; // for range support. // for (auto min_max : MinMax::range()) {} - static const std::array &range() { return range_; } + static const std::array &range() { return range_; } // for (auto mm_index : MinMax::rangeIndex()) {} static const std::array &rangeIndex() { return range_index_; } // Find MinMax from name. - static MinMax *find(const char *min_max); + static const MinMax *find(const char *min_max); // Find MinMax from index. - static MinMax *find(int index); + static const MinMax *find(int index); static const int index_max = 1; static const int index_count = 2; static const int index_bit_count = 1; @@ -87,16 +91,16 @@ private: bool (*compare)(float value1, float value2)); - const char *name_; + const string name_; int index_; float init_value_; int init_value_int_; bool (*compare_)(float value1, float value2); - static MinMax min_; - static MinMax max_; - static const std::array range_; + static const MinMax min_; + static const MinMax max_; + static const std::array range_; static const std::array range_index_; }; @@ -105,36 +109,36 @@ class MinMaxAll { public: // Singleton accessors. - static MinMaxAll *min() { return &min_; } - static MinMaxAll *early() { return &min_; } - static MinMaxAll *max() { return &max_; } - static MinMaxAll *late() { return &max_; } - static MinMaxAll *all() { return &all_; } - const char *asString() const { return name_; } + static const MinMaxAll *min() { return &min_; } + static const MinMaxAll *early() { return &min_; } + static const MinMaxAll *max() { return &max_; } + static const MinMaxAll *late() { return &max_; } + static const MinMaxAll *all() { return &all_; } + const string &to_string() const { return name_; } int index() const { return index_; } - MinMax *asMinMax() const; + const MinMax *asMinMax() const; bool matches(const MinMax *min_max) const; bool matches(const MinMaxAll *min_max) const; - static MinMaxAll *find(const char *min_max); + static const MinMaxAll *find(const char *min_max); // for (const auto min_max : min_max->range()) {} - const std::vector &range() const { return range_; } + const std::vector &range() const { return range_; } // for (const auto mm_index : min_max->rangeIndex()) {} const std::vector &rangeIndex() const { return range_index_; } private: MinMaxAll(const char *name, int index, - std::vector range, + std::vector range, std::vector range_index); - const char *name_; + const string name_; int index_; - const std::vector range_; + const std::vector range_; const std::vector range_index_; - static MinMaxAll min_; - static MinMaxAll max_; - static MinMaxAll all_; + static const MinMaxAll min_; + static const MinMaxAll max_; + static const MinMaxAll all_; }; } // namespace diff --git a/include/sta/Path.hh b/include/sta/Path.hh index 1be09c28..762ea987 100644 --- a/include/sta/Path.hh +++ b/include/sta/Path.hh @@ -37,57 +37,96 @@ namespace sta { class DcalcAnalysisPt; -// Abstract base class for Path API. class Path { public: - Path() {} - virtual ~Path() {} - virtual const char *name(const StaState *sta) const; - virtual bool isNull() const = 0; - virtual Path *path() { return isNull() ? nullptr : this; } - virtual const Path *path() const { return isNull() ? nullptr : this; } - virtual void setRef(PathRef *ref) const = 0; - virtual void setRef(PathRef &ref) const { setRef(&ref); } - virtual Vertex *vertex(const StaState *sta) const = 0; - virtual VertexId vertexId(const StaState *sta) const = 0; - virtual Pin *pin(const StaState *sta) const; - virtual Tag *tag(const StaState *sta) const = 0; - virtual TagIndex tagIndex(const StaState *sta) const; - virtual ClkInfo *clkInfo(const StaState *sta) const; - virtual const ClockEdge *clkEdge(const StaState *sta) const; - virtual const Clock *clock(const StaState *sta) const; - virtual bool isClock(const StaState *sta) const; - virtual const RiseFall *transition(const StaState *sta) const = 0; - virtual int rfIndex(const StaState *sta) const; - virtual const MinMax *minMax(const StaState *sta) const; - virtual PathAnalysisPt *pathAnalysisPt(const StaState *sta) const = 0; - virtual PathAPIndex pathAnalysisPtIndex(const StaState *sta) const; - virtual DcalcAnalysisPt *dcalcAnalysisPt(const StaState *sta) const; - virtual Arrival arrival(const StaState *sta) const = 0; - virtual void setArrival(Arrival arrival, - const StaState *sta) = 0; - virtual void initArrival(const StaState *sta); - virtual bool arrivalIsInitValue(const StaState *sta) const; - virtual const Required &required(const StaState *sta) const = 0; - virtual void setRequired(const Required &required, - const StaState *sta) = 0; - virtual void initRequired(const StaState *sta); - virtual bool requiredIsInitValue(const StaState *sta) const; - virtual Slack slack(const StaState *sta) const; - virtual Slew slew(const StaState *sta) const; + Path(); + Path(Path *path); + Path(Vertex *vertex, + Tag *tag, + const StaState *sta); + Path(Vertex *vertex, + Tag *tag, + Arrival arrival, + Path *prev_path, + Edge *prev_edge, + TimingArc *prev_arc, + const StaState *sta); + Path(Vertex *vertex, + Tag *tag, + Arrival arrival, + Path *prev_path, + Edge *prev_edge, + TimingArc *prev_arc, + bool is_enum, + const StaState *sta); + ~Path(); + string to_string(const StaState *sta) const; + bool isNull() const; + // prev_path null + void init(Vertex *vertex, + Arrival arrival, + const StaState *sta); + void init(Vertex *vertex, + Tag *tag, + Arrival arrival, + Path *prev_path, + Edge *prev_edge, + TimingArc *prev_arc, + const StaState *sta); + void init(Vertex *vertex, + Tag *tag, + const StaState *sta); + void init(Vertex *vertex, + Tag *tag, + Arrival arrival, + const StaState *sta); + + Vertex *vertex(const StaState *sta) const; + VertexId vertexId(const StaState *sta) const; + Pin *pin(const StaState *sta) const; + Tag *tag(const StaState *sta) const; + TagIndex tagIndex(const StaState *sta) const; + void setTag(Tag *tag); + size_t pathIndex(const StaState *sta) const; + ClkInfo *clkInfo(const StaState *sta) const; + const ClockEdge *clkEdge(const StaState *sta) const; + const Clock *clock(const StaState *sta) const; + bool isClock(const StaState *sta) const; + const RiseFall *transition(const StaState *sta) const; + int rfIndex(const StaState *sta) const; + const MinMax *minMax(const StaState *sta) const; + PathAnalysisPt *pathAnalysisPt(const StaState *sta) const; + PathAPIndex pathAnalysisPtIndex(const StaState *sta) const; + DcalcAnalysisPt *dcalcAnalysisPt(const StaState *sta) const; + Arrival &arrival() { return arrival_; } + const Arrival &arrival() const { return arrival_; } + void setArrival(Arrival arrival); + Required &required() { return required_; } + const Required &required() const {return required_; } + void setRequired(const Required &required); + Slack slack(const StaState *sta) const; + Slew slew(const StaState *sta) const; // This takes the same time as prevPath and prevArc combined. - virtual void prevPath(const StaState *sta, - // Return values. - PathRef &prev_path, - TimingArc *&prev_arc) const = 0; - virtual void prevPath(const StaState *sta, - // Return values. - PathRef &prev_path) const; - virtual TimingArc *prevArc(const StaState *sta) const; - // Find the previous edge given the previous arc found above. - Edge *prevEdge(const TimingArc *prev_arc, - const StaState *sta) const; + Path *prevPath() const; + void setPrevPath(Path *prev_path); + void clearPrevPath(const StaState *sta); + TimingArc *prevArc(const StaState *sta) const; + Edge *prevEdge(const StaState *sta) const; + Vertex *prevVertex(const StaState *sta) const; + void setPrevEdgeArc(Edge *prev_edge, + TimingArc *prev_arc, + const StaState *sta); + bool isEnum() const { return is_enum_; } + void setIsEnum(bool is_enum); + void checkPrevPath(const StaState *sta) const; + void checkPrevPaths(const StaState *sta) const; + + static Path *vertexPath(const Path &path, + const StaState *sta); + static Path *vertexPath(const Vertex *vertex, + Tag *tag, + const StaState *sta); static bool less(const Path *path1, const Path *path2, @@ -118,6 +157,18 @@ public: static bool lessAll(const Path *path1, const Path *path2, const StaState *sta); + +protected: + Path *prev_path_; + Arrival arrival_; + Required required_; + union { + VertexId vertex_id_; + EdgeId prev_edge_id_; + }; + TagIndex tag_index_:tag_index_bit_count; + bool is_enum_:1; + unsigned prev_arc_idx_:2; }; // Compare all path attributes (vertex, transition, tag, analysis point). @@ -132,4 +183,47 @@ protected: const StaState *sta_; }; +// Iterator for paths on a vertex. +class VertexPathIterator : public Iterator +{ +public: + // Iterate over all vertex paths. + VertexPathIterator(Vertex *vertex, + const StaState *sta); + // Iterate over vertex paths with the same transition and + // analysis pt but different tags. + VertexPathIterator(Vertex *vertex, + const RiseFall *rf, + const PathAnalysisPt *path_ap, + const StaState *sta); + // Iterate over vertex paths with the same transition and + // analysis pt min/max but different tags. + VertexPathIterator(Vertex *vertex, + const RiseFall *rf, + const MinMax *min_max, + const StaState *sta); + VertexPathIterator(Vertex *vertex, + const RiseFall *rf, + const PathAnalysisPt *path_ap, + const MinMax *min_max, + const StaState *sta); + virtual ~VertexPathIterator(); + virtual bool hasNext(); + virtual Path *next(); + +private: + void findNext(); + + const Search *search_; + //bool filtered_; + const RiseFall *rf_; + const PathAnalysisPt *path_ap_; + const MinMax *min_max_; + Path *paths_; + size_t path_count_; + //size_t path_index_; + Path *next_; + PathIndexMap::Iterator path_iter_; +}; + } // namespace diff --git a/include/sta/PathAnalysisPt.hh b/include/sta/PathAnalysisPt.hh index bd829b61..49fd4490 100644 --- a/include/sta/PathAnalysisPt.hh +++ b/include/sta/PathAnalysisPt.hh @@ -24,6 +24,8 @@ #pragma once +#include + #include "Iterator.hh" #include "MinMax.hh" #include "SdcClass.hh" @@ -35,6 +37,8 @@ class MinMax; class DcalcAnalysisPt; class Corner; +using std::string; + class PathAnalysisPt { public: @@ -42,6 +46,7 @@ public: PathAPIndex index, const MinMax *path_min_max, DcalcAnalysisPt *dcalc_ap); + string to_string() const; Corner *corner() const { return corner_; } PathAPIndex index() const { return index_; } const MinMax *pathMinMax() const { return path_min_max_; } diff --git a/include/sta/PathEnd.hh b/include/sta/PathEnd.hh index 5491aa21..46351593 100644 --- a/include/sta/PathEnd.hh +++ b/include/sta/PathEnd.hh @@ -30,7 +30,7 @@ #include "GraphClass.hh" #include "SdcClass.hh" #include "SearchClass.hh" -#include "PathRef.hh" +#include "Path.hh" #include "StaState.hh" namespace sta { @@ -73,10 +73,9 @@ public: virtual PathEnd *copy() = 0; virtual ~PathEnd(); void deletePath(); - Path *path() { return &path_; } - const Path *path() const { return &path_; } - PathRef &pathRef() { return path_; } - virtual void setPath(const Path *path); + Path *path() { return path_; } + const Path *path() const { return path_; } + virtual void setPath(Path *path); Vertex *vertex(const StaState *sta) const; const MinMax *minMax(const StaState *sta) const; // Synonym for minMax(). @@ -118,8 +117,8 @@ public: virtual float sourceClkOffset(const StaState *sta) const = 0; virtual Delay sourceClkLatency(const StaState *sta) const; virtual Delay sourceClkInsertionDelay(const StaState *sta) const; - virtual PathVertex *targetClkPath(); - virtual const PathVertex *targetClkPath() const; + virtual Path *targetClkPath(); + virtual const Path *targetClkPath() const; virtual const Clock *targetClk(const StaState *sta) const; virtual const ClockEdge *targetClkEdge(const StaState *sta) const; const RiseFall *targetClkEndTrans(const StaState *sta) const; @@ -138,7 +137,7 @@ public: // Target clock uncertainty + inter-clk uncertainty. virtual float targetClkUncertainty(const StaState *sta) const; virtual float targetClkMcpAdjustment(const StaState *sta) const; - virtual TimingRole *checkRole(const StaState *sta) const; + virtual const TimingRole *checkRole(const StaState *sta) const; const TimingRole *checkGenericRole(const StaState *sta) const; virtual bool pathDelayMarginIsExternal() const; virtual PathDelay *pathDelay() const; @@ -149,7 +148,7 @@ public: virtual MultiCyclePath *multiCyclePath() const; virtual TimingArc *checkArc() const { return nullptr; } // PathEndDataCheck data clock path. - virtual const PathVertex *dataClkPath() const { return nullptr; } + virtual const Path *dataClkPath() const { return nullptr; } virtual int setupDefaultCycles() const { return 1; } virtual Delay clkSkew(const StaState *sta); virtual bool ignoreClkLatency(const StaState * /* sta */) const { return false; } @@ -173,11 +172,11 @@ public: // Helper common to multiple PathEnd classes and used // externally. // Target clock insertion delay + latency. - static Delay checkTgtClkDelay(const PathVertex *tgt_clk_path, + static Delay checkTgtClkDelay(const Path *tgt_clk_path, const ClockEdge *tgt_clk_edge, const TimingRole *check_role, const StaState *sta); - static void checkTgtClkDelay(const PathVertex *tgt_clk_path, + static void checkTgtClkDelay(const Path *tgt_clk_path, const ClockEdge *tgt_clk_edge, const TimingRole *check_role, const StaState *sta, @@ -186,11 +185,11 @@ public: Delay &latency); static float checkClkUncertainty(const ClockEdge *src_clk_edge, const ClockEdge *tgt_clk_edge, - const PathVertex *tgt_clk_path, + const Path *tgt_clk_path, const TimingRole *check_role, const StaState *sta); // Non inter-clock uncertainty. - static float checkTgtClkUncertainty(const PathVertex *tgt_clk_path, + static float checkTgtClkUncertainty(const Path *tgt_clk_path, const ClockEdge *tgt_clk_edge, const TimingRole *check_role, const StaState *sta); @@ -211,14 +210,14 @@ protected: static float outputDelayMargin(OutputDelay *output_delay, const Path *path, const StaState *sta); - static float pathDelaySrcClkOffset(const PathRef &path, + static float pathDelaySrcClkOffset(const Path *path, PathDelay *path_delay, Arrival src_clk_arrival, const StaState *sta); - static bool ignoreClkLatency(const PathRef &path, + static bool ignoreClkLatency(const Path *path, PathDelay *path_delay, const StaState *sta); - PathRef path_; + Path *path_; }; class PathEndUnconstrained : public PathEnd @@ -247,8 +246,8 @@ public: virtual Delay sourceClkInsertionDelay(const StaState *sta) const; virtual const Clock *targetClk(const StaState *sta) const; virtual const ClockEdge *targetClkEdge(const StaState *sta) const; - virtual PathVertex *targetClkPath(); - virtual const PathVertex *targetClkPath() const; + virtual Path *targetClkPath(); + virtual const Path *targetClkPath() const; virtual float targetClkTime(const StaState *sta) const; virtual float targetClkOffset(const StaState *sta) const; virtual Arrival targetClkArrival(const StaState *sta) const; @@ -263,13 +262,13 @@ public: virtual Slack slackNoCrpr(const StaState *sta) const; virtual int exceptPathCmp(const PathEnd *path_end, const StaState *sta) const; - virtual void setPath(const Path *path); + virtual void setPath(Path *path); protected: PathEndClkConstrained(Path *path, - PathVertex *clk_path); + Path *clk_path); PathEndClkConstrained(Path *path, - PathVertex *clk_path, + Path *clk_path, Crpr crpr, bool crpr_valid); @@ -281,7 +280,7 @@ protected: virtual Arrival targetClkArrivalNoCrpr(const StaState *sta) const; virtual Required requiredTimeNoCrpr(const StaState *sta) const; - PathVertex clk_path_; + Path *clk_path_; mutable Crpr crpr_; mutable bool crpr_valid_; }; @@ -296,10 +295,10 @@ public: protected: PathEndClkConstrainedMcp(Path *path, - PathVertex *clk_path, + Path *clk_path, MultiCyclePath *mcp); PathEndClkConstrainedMcp(Path *path, - PathVertex *clk_path, + Path *clk_path, MultiCyclePath *mcp, Crpr crpr, bool crpr_valid); @@ -321,7 +320,7 @@ public: PathEndCheck(Path *path, TimingArc *check_arc, Edge *check_edge, - PathVertex *clk_path, + Path *clk_path, MultiCyclePath *mcp, const StaState *sta); virtual PathEnd *copy(); @@ -332,7 +331,7 @@ public: virtual bool isCheck() const { return true; } virtual ArcDelay margin(const StaState *sta) const; virtual float macroClkTreeDelay(const StaState *sta) const; - virtual TimingRole *checkRole(const StaState *sta) const; + virtual const TimingRole *checkRole(const StaState *sta) const; virtual TimingArc *checkArc() const { return check_arc_; } virtual int exceptPathCmp(const PathEnd *path_end, const StaState *sta) const; @@ -342,7 +341,7 @@ protected: PathEndCheck(Path *path, TimingArc *check_arc, Edge *check_edge, - PathVertex *clk_path, + Path *clk_path, MultiCyclePath *mcp, Crpr crpr, bool crpr_valid); @@ -360,7 +359,7 @@ public: PathEndLatchCheck(Path *path, TimingArc *check_arc, Edge *check_edge, - PathVertex *disable_path, + Path *disable_path, MultiCyclePath *mcp, PathDelay *path_delay, const StaState *sta); @@ -371,11 +370,11 @@ public: virtual bool isLatchCheck() const { return true; } virtual PathDelay *pathDelay() const { return path_delay_; } virtual PathEnd *copy(); - PathVertex *latchDisable(); - const PathVertex *latchDisable() const; + Path *latchDisable(); + const Path *latchDisable() const; virtual void reportShort(const ReportPath *report) const; virtual void reportFull(const ReportPath *report) const; - virtual TimingRole *checkRole(const StaState *sta) const; + virtual const TimingRole *checkRole(const StaState *sta) const; virtual Required requiredTime(const StaState *sta) const; virtual Arrival borrow(const StaState *sta) const; Arrival targetClkWidth(const StaState *sta) const; @@ -403,8 +402,8 @@ protected: PathEndLatchCheck(Path *path, TimingArc *check_arc, Edge *check_edge, - PathVertex *clk_path, - PathVertex *disable, + Path *clk_path, + Path *disable, MultiCyclePath *mcp, PathDelay *path_delay, Delay src_clk_arrival, @@ -412,7 +411,7 @@ protected: bool crpr_valid); private: - PathVertex disable_path_; + Path *disable_path_; PathDelay *path_delay_; // Source clk arrival for set_max_delay -ignore_clk_latency. Arrival src_clk_arrival_; @@ -426,7 +425,7 @@ class PathEndOutputDelay : public PathEndClkConstrainedMcp public: PathEndOutputDelay(OutputDelay *output_delay, Path *path, - PathVertex *clk_path, + Path *clk_path, MultiCyclePath *mcp, const StaState *sta); virtual PathEnd *copy(); @@ -436,7 +435,7 @@ public: virtual void reportFull(const ReportPath *report) const; virtual bool isOutputDelay() const { return true; } virtual ArcDelay margin(const StaState *sta) const; - virtual TimingRole *checkRole(const StaState *sta) const; + virtual const TimingRole *checkRole(const StaState *sta) const; virtual const ClockEdge *targetClkEdge(const StaState *sta) const; virtual Arrival targetClkArrivalNoCrpr(const StaState *sta) const; virtual Delay targetClkDelay(const StaState *sta) const; @@ -448,7 +447,7 @@ public: protected: PathEndOutputDelay(OutputDelay *output_delay, Path *path, - PathVertex *clk_path, + Path *clk_path, MultiCyclePath *mcp, Crpr crpr, bool crpr_valid); @@ -470,8 +469,8 @@ class PathEndGatedClock : public PathEndClkConstrainedMcp { public: PathEndGatedClock(Path *gating_ref, - PathVertex *clk_path, - TimingRole *check_role, + Path *clk_path, + const TimingRole *check_role, MultiCyclePath *mcp, ArcDelay margin, const StaState *sta); @@ -482,20 +481,20 @@ public: virtual void reportFull(const ReportPath *report) const; virtual bool isGatedClock() const { return true; } virtual ArcDelay margin(const StaState *) const { return margin_; } - virtual TimingRole *checkRole(const StaState *sta) const; + virtual const TimingRole *checkRole(const StaState *sta) const; virtual int exceptPathCmp(const PathEnd *path_end, const StaState *sta) const; protected: PathEndGatedClock(Path *gating_ref, - PathVertex *clk_path, - TimingRole *check_role, + Path *clk_path, + const TimingRole *check_role, MultiCyclePath *mcp, ArcDelay margin, Crpr crpr, bool crpr_valid); - TimingRole *check_role_; + const TimingRole *check_role_; ArcDelay margin_; }; @@ -504,7 +503,7 @@ class PathEndDataCheck : public PathEndClkConstrainedMcp public: PathEndDataCheck(DataCheck *check, Path *data_path, - PathVertex *data_clk_path, + Path *data_clk_path, MultiCyclePath *mcp, const StaState *sta); virtual PathEnd *copy(); @@ -514,30 +513,28 @@ public: virtual void reportFull(const ReportPath *report) const; virtual bool isDataCheck() const { return true; } virtual const ClockEdge *targetClkEdge(const StaState *sta) const; - virtual TimingRole *checkRole(const StaState *sta) const; + virtual const TimingRole *checkRole(const StaState *sta) const; virtual ArcDelay margin(const StaState *sta) const; virtual int exceptPathCmp(const PathEnd *path_end, const StaState *sta) const; - virtual const PathVertex *dataClkPath() const { return &data_clk_path_; } + virtual const Path *dataClkPath() const { return data_clk_path_; } protected: PathEndDataCheck(DataCheck *check, Path *data_path, - PathVertex *data_clk_path, - PathVertex *clk_path, + Path *data_clk_path, + Path *clk_path, MultiCyclePath *mcp, Crpr crpr, bool crpr_valid); - void clkPath(PathVertex *path, - const StaState *sta, - // Return value. - PathVertex &clk_path); + Path *clkPath(Path *path, + const StaState *sta); Arrival requiredTimeNoCrpr(const StaState *sta) const; // setup uses zero cycle default virtual int setupDefaultCycles() const { return 0; } private: - PathVertex data_clk_path_; + Path *data_clk_path_; DataCheck *check_; }; @@ -554,7 +551,7 @@ public: // Path delay to timing check. PathEndPathDelay(PathDelay *path_delay, Path *path, - PathVertex *clk_path, + Path *clk_path, TimingArc *check_arc, Edge *check_edge, const StaState *sta); @@ -569,7 +566,7 @@ public: virtual void reportShort(const ReportPath *report) const; virtual void reportFull(const ReportPath *report) const; virtual bool isPathDelay() const { return true; } - virtual TimingRole *checkRole(const StaState *sta) const; + virtual const TimingRole *checkRole(const StaState *sta) const; virtual bool pathDelayMarginIsExternal() const; virtual PathDelay *pathDelay() const { return path_delay_; } virtual ArcDelay margin(const StaState *sta) const; @@ -588,7 +585,7 @@ public: protected: PathEndPathDelay(PathDelay *path_delay, Path *path, - PathVertex *clk_path, + Path *clk_path, TimingArc *check_arc, Edge *check_edge, OutputDelay *output_delay, diff --git a/include/sta/PathExpanded.hh b/include/sta/PathExpanded.hh index 1abf7ae4..784409bf 100644 --- a/include/sta/PathExpanded.hh +++ b/include/sta/PathExpanded.hh @@ -27,7 +27,7 @@ #include "TimingArc.hh" #include "GraphClass.hh" #include "SearchClass.hh" -#include "PathRef.hh" +#include "Path.hh" #include "StaState.hh" namespace sta { @@ -48,33 +48,31 @@ public: size_t size() const { return paths_.size(); } // path(0) is the startpoint. // path(size()-1) is the endpoint. - const PathRef *path(size_t index) const; - TimingArc *prevArc(size_t index) const; + const Path *path(size_t index) const; // Returns the path start point. // Register/Latch Q pin // Input pin - const PathRef *startPath() const; - const PathRef *startPrevPath() const; - const PathRef *endPath() const; - TimingArc *startPrevArc() const; + const Path *startPath() const; + const Path *startPrevPath() const; + const Path *endPath() const; + const TimingArc *startPrevArc() const; size_t startIndex() const; - void clkPath(PathRef &clk_path) const; + const Path *clkPath() const; void latchPaths(// Return values. - const PathRef *&d_path, - const PathRef *&q_path, + const Path *&d_path, + const Path *&q_path, Edge *&d_q_edge) const; protected: - void expandGenclk(PathRef *clk_path); + void expandGenclk(const Path *clk_path); // Convert external index that starts at the path root // and increases to an index for paths_ (reversed). size_t pathsIndex(size_t index) const; - // The PathRefs in paths_ are in reverse order. + // The Paths in paths_ are in reverse order. // paths_[0] is the endpoint. // paths_[size-1] is the beginning of the path. - PathRefSeq paths_; - TimingArcSeq prev_arcs_; + ConstPathSeq paths_; // Index of the startpoint. size_t start_index_; const StaState *sta_; diff --git a/include/sta/PathGroup.hh b/include/sta/PathGroup.hh index f60bfea7..bb26b89e 100644 --- a/include/sta/PathGroup.hh +++ b/include/sta/PathGroup.hh @@ -74,12 +74,12 @@ public: PathGroupIterator *iterator(); // This does NOT delete the path ends. void clear(); - static int group_path_count_max; + static size_t group_path_count_max; protected: PathGroup(const char *name, - int group_path_count, - int endpoint_path_count, + size_t group_path_count, + size_t endpoint_path_count, bool unique_pins, float min_slack, float max_slack, @@ -91,8 +91,8 @@ protected: void sort(); const char *name_; - int group_path_count_; - int endpoint_path_count_; + size_t group_path_count_; + size_t endpoint_path_count_; bool unique_pins_; float slack_min_; float slack_max_; diff --git a/include/sta/PathPrev.hh b/include/sta/PathPrev.hh deleted file mode 100644 index 3643bef1..00000000 --- a/include/sta/PathPrev.hh +++ /dev/null @@ -1,75 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2025, Parallax Software, Inc. -// -// 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 . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#pragma once - -#include "SdcClass.hh" -#include "SearchClass.hh" - -namespace sta { - -// "Pointer" to a previous path on a vertex (PathVertex) thru an edge/arc. -class PathPrev -{ -public: - PathPrev(); - PathPrev(const PathVertex *path, - const Edge *prev_edge, - const TimingArc *prev_arc, - const StaState *sta); - void init(); - void init(const PathPrev *path); - void init(const PathPrev &path); - void init(const PathVertex *path, - const Edge *prev_edge, - const TimingArc *prev_arc, - const StaState *sta); - bool isNull() const; - const char *name(const StaState *sta) const; - Vertex *vertex(const StaState *sta) const; - VertexId vertexId(const StaState *sta) const; - Edge *prevEdge(const StaState *sta) const; - TimingArc *prevArc(const StaState *sta) const; - Tag *tag(const StaState *sta) const; - TagIndex tagIndex() const { return prev_tag_index_; } - Arrival arrival(const StaState *sta) const; - void prevPath(const StaState *sta, - // Return values. - PathRef &prev_path, - TimingArc *&prev_arc) const; - - static bool equal(const PathPrev *path1, - const PathPrev *path2); - static bool equal(const PathPrev &path1, - const PathPrev &path2); - static int cmp(const PathPrev &path1, - const PathPrev &path2); - -protected: - EdgeId prev_edge_id_; - TagIndex prev_tag_index_:tag_index_bit_count; - unsigned prev_arc_idx_:2; -}; - -} // namespace diff --git a/include/sta/PathRef.hh b/include/sta/PathRef.hh deleted file mode 100644 index 50288e28..00000000 --- a/include/sta/PathRef.hh +++ /dev/null @@ -1,94 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2025, Parallax Software, Inc. -// -// 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 . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#pragma once - -#include "Vector.hh" -#include "SearchClass.hh" -#include "Path.hh" -#include "PathVertex.hh" - -namespace sta { - -// Path reference to either a PathVertex or PathEnum. -// This "could" be made smaller by using a union for -// path_vertex_.vertex_ and path_enumed_ and a non-legal -// value for path_vertex_.arrival_index_ (because a nullptr tag -// in PathVertex is valid). -class PathRef : public Path -{ -public: - PathRef(); - PathRef(const Path *path); - PathRef(const PathRef &path); - PathRef(const PathRef *path); - PathRef(const PathVertex &path); - void init(); - void init(const PathRef &path); - void init(const PathRef *path); - void init(const PathVertex &path); - void init(const PathVertex *path); - void init(const PathPrev &path, - const StaState *sta); - void init(Vertex *vertex, - Tag *tag, - int arrival_index); - void init(PathEnumed *path); - virtual void setRef(PathRef *ref) const; - virtual bool isNull() const; - virtual Vertex *vertex(const StaState *sta) const; - virtual VertexId vertexId(const StaState *sta) const; - virtual Tag *tag(const StaState *sta) const; - virtual TagIndex tagIndex(const StaState *sta) const; - virtual const RiseFall *transition(const StaState *sta) const; - virtual int rfIndex(const StaState *sta) const; - virtual PathAnalysisPt *pathAnalysisPt(const StaState *sta) const; - virtual PathAPIndex pathAnalysisPtIndex(const StaState *sta) const; - void arrivalIndex(int &arrival_index, - bool &arrival_exists) const; - virtual Arrival arrival(const StaState *sta) const; - virtual void setArrival(Arrival arrival, - const StaState *sta); - virtual const Required &required(const StaState *sta) const; - virtual void setRequired(const Required &required, - const StaState *sta); - virtual void prevPath(const StaState *sta, - // Return values. - PathRef &prev_path, - TimingArc *&prev_arc) const; - void deleteRep(); - - using Path::setRef; - using Path::prevPath; - -protected: - PathVertex path_vertex_; - PathEnumed *path_enumed_; - -private: - friend class PathVertex; - friend class PathEnumed; -}; - -} // namespace diff --git a/include/sta/PathVertex.hh b/include/sta/PathVertex.hh deleted file mode 100644 index 9d21140f..00000000 --- a/include/sta/PathVertex.hh +++ /dev/null @@ -1,158 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2025, Parallax Software, Inc. -// -// 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 . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#pragma once - -#include "SearchClass.hh" -#include "Path.hh" - -namespace sta { - -class PathPrev; -class PathVertexPtr; - -// Implements Path API for a vertex. -class PathVertex : public Path -{ -public: - PathVertex(); - PathVertex(const PathVertex &path); - PathVertex(const PathVertex *path); - PathVertex(const PathPrev *path, - const StaState *sta); - PathVertex(const PathPrev &path, - const StaState *sta); - PathVertex(const PathVertexPtr &path, - const StaState *sta); - // If tag is not in the vertex tag group isNull() is true. - PathVertex(Vertex *vertex, - Tag *tag, - const StaState *sta); - PathVertex(Vertex *vertex, - Tag *tag, - int arrival_index); - void init(); - void init(const PathPrev *path, - const StaState *sta); - void init(const PathPrev &path, - const StaState *sta); - void init(const PathVertexPtr &path, - const StaState *sta); - void init(Vertex *vertex, - Tag *tag, - const StaState *sta); - void init(Vertex *vertex, - Tag *tag, - int arrival_index); - void operator=(const PathVertex &path); - virtual bool isNull() const; - virtual void setRef(PathRef *ref) const; - virtual Vertex *vertex(const StaState *) const { return vertex_; } - virtual VertexId vertexId(const StaState *sta) const; - virtual Tag *tag(const StaState *) const { return tag_; } - virtual TagIndex tagIndex(const StaState *sta) const; - virtual const RiseFall *transition(const StaState *) const; - virtual int rfIndex(const StaState *sta) const; - virtual PathAnalysisPt *pathAnalysisPt(const StaState *sta) const; - virtual PathAPIndex pathAnalysisPtIndex(const StaState *sta) const; - void arrivalIndex(int &arrival_index, - bool &arrival_exists) const; - void setArrivalIndex(int arrival_index); - virtual Arrival arrival(const StaState *sta) const; - virtual void setArrival(Arrival arrival, - const StaState *sta); - virtual const Required &required(const StaState *sta) const; - virtual void setRequired(const Required &required, - const StaState *sta); - virtual void prevPath(const StaState *sta, - // Return values. - PathRef &prev_path, - TimingArc *&prev_arc) const; - void prevPath(const StaState *sta, - // Return values. - PathVertex &prev_path) const; - void prevPath(const StaState *sta, - // Return values. - PathVertex &prev_path, - TimingArc *&prev_arc) const; - static bool equal(const PathVertex *path1, - const PathVertex *path2); - - using Path::setRef; - using Path::prevPath; - -protected: - Vertex *vertex_; - Tag *tag_; - int arrival_index_; - -private: - friend class PathRef; - friend class VertexPathIterator; - friend bool pathVertexEqual(const PathVertex *path1, - const PathVertex *path2); -}; - -// Iterator for vertex paths. -class VertexPathIterator : public Iterator -{ -public: - // Iterate over all vertex paths. - VertexPathIterator(Vertex *vertex, - const StaState *sta); - // Iterate over vertex paths with the same transition and - // analysis pt but different tags. - VertexPathIterator(Vertex *vertex, - const RiseFall *rf, - const PathAnalysisPt *path_ap, - const StaState *sta); - // Iterate over vertex paths with the same transition and - // analysis pt min/max but different tags. - VertexPathIterator(Vertex *vertex, - const RiseFall *rf, - const MinMax *min_max, - const StaState *sta); - VertexPathIterator(Vertex *vertex, - const RiseFall *rf, - const PathAnalysisPt *path_ap, - const MinMax *min_max, - const StaState *sta); - virtual ~VertexPathIterator(); - virtual bool hasNext(); - virtual PathVertex *next(); - -private: - void findNext(); - - const Search *search_; - Vertex *vertex_; - const RiseFall *rf_; - const PathAnalysisPt *path_ap_; - const MinMax *min_max_; - ArrivalMap::Iterator arrival_iter_; - PathVertex path_; - PathVertex next_; -}; - -} // namespace diff --git a/include/sta/PathVertexPtr.hh b/include/sta/PathVertexPtr.hh deleted file mode 100644 index 80c89649..00000000 --- a/include/sta/PathVertexPtr.hh +++ /dev/null @@ -1,63 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2025, Parallax Software, Inc. -// -// 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 . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#pragma once - -#include "SearchClass.hh" - -namespace sta { - -// "Pointer" to a vertex path because there is no real path object to point to. -class PathVertexPtr -{ -public: - PathVertexPtr(); - PathVertexPtr(const PathVertex *path, - const StaState *sta); - void init(); - void init(const PathVertexPtr *path); - void init(const PathVertexPtr &path); - void init(const PathVertex *path, - const StaState *sta); - bool isNull() const; - const char *name(const StaState *sta) const; - Vertex *vertex(const StaState *sta) const; - VertexId vertexId() const { return vertex_id_; } - Tag *tag(const StaState *sta) const; - TagIndex tagIndex() const { return tag_index_; } - Arrival arrival(const StaState *sta) const; - - static bool equal(const PathVertexPtr *path1, - const PathVertexPtr *path2); - static bool equal(const PathVertexPtr &path1, - const PathVertexPtr &path2); - static int cmp(const PathVertexPtr &path1, - const PathVertexPtr &path2); - -protected: - VertexId vertex_id_; - TagIndex tag_index_; -}; - -} // namespace diff --git a/include/sta/PathVertexRep.hh b/include/sta/PathVertexRep.hh deleted file mode 100644 index d6249426..00000000 --- a/include/sta/PathVertexRep.hh +++ /dev/null @@ -1,75 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2025, Parallax Software, Inc. -// -// 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 . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#pragma once - -#include "SdcClass.hh" -#include "SearchClass.hh" - -namespace sta { - -// "Pointer" to a previous path on a vertex (PathVertex) thru an edge/arc. -class PathVertexRep -{ -public: - PathVertexRep(); - PathVertexRep(const PathVertex *path, - const Edge *prev_edge, - const TimingArc *prev_arc, - const StaState *sta); - void init(); - void init(const PathVertexRep *path); - void init(const PathVertexRep &path); - void init(const PathVertex *path, - const Edge *prev_edge, - const TimingArc *prev_arc, - const StaState *sta); - bool isNull() const; - const char *name(const StaState *sta) const; - Vertex *vertex(const StaState *sta) const; - VertexId vertexId(const StaState *sta) const; - Edge *prevEdge(const StaState *sta) const; - TimingArc *prevArc(const StaState *sta) const; - Tag *tag(const StaState *sta) const; - TagIndex tagIndex() const { return prev_tag_index_; } - Arrival arrival(const StaState *sta) const; - void prevPath(const StaState *sta, - // Return values. - PathRef &prev_path, - TimingArc *&prev_arc) const; - - static bool equal(const PathVertexRep *path1, - const PathVertexRep *path2); - static bool equal(const PathVertexRep &path1, - const PathVertexRep &path2); - static int cmp(const PathVertexRep &path1, - const PathVertexRep &path2); - -protected: - EdgeId prev_edge_id_; - TagIndex prev_tag_index_:tag_index_bit_count; - unsigned prev_arc_idx_:2; -}; - -} // namespace diff --git a/include/sta/PortDelay.hh b/include/sta/PortDelay.hh index 1457654f..4220bf7c 100644 --- a/include/sta/PortDelay.hh +++ b/include/sta/PortDelay.hh @@ -48,7 +48,7 @@ public: void setNetworkLatencyIncluded(bool included); const Pin *refPin() const { return ref_pin_; } void setRefPin(const Pin *ref_pin); - RiseFall *refTransition() const; + const RiseFall *refTransition() const; protected: PortDelay(const Pin *pin, diff --git a/include/sta/Property.hh b/include/sta/Property.hh index c795ed80..3b175c72 100644 --- a/include/sta/Property.hh +++ b/include/sta/Property.hh @@ -55,7 +55,7 @@ public: type_library, type_cell, type_port, type_liberty_library, type_liberty_cell, type_liberty_port, type_instance, type_pin, type_pins, type_net, - type_clk, type_clks, type_path_refs, type_pwr_activity }; + type_clk, type_clks, type_paths, type_pwr_activity }; PropertyValue(); PropertyValue(const char *value); PropertyValue(string &value); @@ -77,7 +77,7 @@ public: PropertyValue(const Clock *value); PropertyValue(ClockSeq *value); PropertyValue(ClockSet *value); - PropertyValue(PathRefSeq *value); + PropertyValue(ConstPathSeq *value); PropertyValue(PwrActivity *value); // Copy constructor. PropertyValue(const PropertyValue &props); @@ -103,7 +103,7 @@ public: const Net *net() const { return net_; } const Clock *clock() const { return clk_; } ClockSeq *clocks() const { return clks_; } - PathRefSeq *pathRefs() const { return path_refs_; } + ConstPathSeq *paths() const { return paths_; } PwrActivity pwrActivity() const { return pwr_activity_; } // Copy assignment. @@ -129,7 +129,7 @@ private: const Net *net_; const Clock *clk_; ClockSeq *clks_; - PathRefSeq *path_refs_; + ConstPathSeq *paths_; PwrActivity pwr_activity_; }; const Unit *unit_; @@ -196,7 +196,7 @@ getProperty(PathEnd *end, Sta *sta); PropertyValue -getProperty(PathRef *end, +getProperty(Path *end, const char *property, Sta *sta); diff --git a/include/sta/Search.hh b/include/sta/Search.hh index d59e9fa5..8129ae4f 100644 --- a/include/sta/Search.hh +++ b/include/sta/Search.hh @@ -1,4 +1,4 @@ -// OpenSTA, Static Timing Analyzer +// opensta, Static Timing Analyzer // Copyright (c) 2025, Parallax Software, Inc. // // This program is free software: you can redistribute it and/or modify @@ -39,6 +39,7 @@ #include "SearchClass.hh" #include "SearchPred.hh" #include "VertexVisitor.hh" +#include "Path.hh" namespace sta { @@ -99,8 +100,8 @@ public: bool unconstrained, const Corner *corner, const MinMaxAll *min_max, - int group_path_count, - int endpoint_path_count, + size_t group_path_count, + size_t endpoint_path_count, bool unique_pins, float slack_min, float slack_max, @@ -126,6 +127,7 @@ public: void requiredInvalid(const Pin *pin); // Vertex will be deleted. void deleteVertexBefore(Vertex *vertex); + void deleteEdgeBefore(Edge *edge); // Find all arrival times (propatating thru latches). void findAllArrivals(); // Find all arrivals (without latch propagation). @@ -226,7 +228,7 @@ public: TagIndex tagCount() const; TagGroupIndex tagGroupCount() const; void reportTagGroups() const; - void reportArrivalCountHistogram() const; + void reportPathCountHistogram() const; virtual int clkInfoCount() const; virtual bool isEndpoint(Vertex *vertex) const; virtual bool isEndpoint(Vertex *vertex, @@ -252,22 +254,28 @@ public: const RiseFall *to_rf, const MinMax *min_max, const PathAnalysisPt *path_ap); - Tag *thruClkTag(PathVertex *from_path, + Tag *thruClkTag(Path *from_path, + Vertex *from_vertex, Tag *from_tag, bool to_propagates_clk, Edge *edge, const RiseFall *to_rf, + bool arc_delay_min_max_eq, const MinMax *min_max, const PathAnalysisPt *path_ap); - ClkInfo *thruClkInfo(PathVertex *from_path, + ClkInfo *thruClkInfo(Path *from_path, + Vertex *from_vertex, ClkInfo *from_clk_info, + bool from_is_clk, Edge *edge, Vertex *to_vertex, const Pin *to_pin, + bool to_is_clk, + bool arc_delay_min_max_eq, const MinMax *min_max, const PathAnalysisPt *path_ap); ClkInfo *clkInfoWithCrprClkPath(ClkInfo *from_clk_info, - PathVertex *from_path, + Path *from_path, const PathAnalysisPt *path_ap); void seedClkArrivals(const Pin *pin, Vertex *vertex, @@ -333,7 +341,7 @@ public: float latency, ClockUncertainties *uncertainties, const PathAnalysisPt *path_ap, - PathVertex *crpr_clk_path); + Path *crpr_clk_path); ClkInfo *findClkInfo(const ClockEdge *clk_edge, const Pin *clk_src, bool is_propagated, @@ -372,7 +380,33 @@ public: bool unconstrained, bool thru_latches); VertexSeq filteredEndpoints(); - bool alwaysSavePrevPaths() const { return always_save_prev_paths_; } + + Arrival *arrivals(const Vertex *vertex) const; + Arrival *makeArrivals(const Vertex *vertex, + uint32_t count); + void deleteArrivals(const Vertex *vertex); + Required *requireds(const Vertex *vertex) const; + bool hasRequireds(const Vertex *vertex) const; + Required *makeRequireds(const Vertex *vertex, + uint32_t count); + void deleteRequireds(const Vertex *vertex); + size_t arrivalCount() const; + size_t requiredCount() const; + Path *prevPaths(const Vertex *vertex) const; + Path *makePrevPaths(const Vertex *vertex, + uint32_t count); + void deletePrevPaths(Vertex *vertex); + bool crprPathPruningDisabled(const Vertex *vertex) const; + void setCrprPathPruningDisabled(const Vertex *vertex, + bool disabled); + bool bfsInQueue(const Vertex *vertex, + BfsIndex index) const; + void setBfsInQueue(const Vertex *vertex, + BfsIndex index, + bool value); + TagGroupIndex tagGroupIndex(const Vertex *vertex) const; + void setTagGroupIndex(const Vertex *vertex, + TagGroupIndex tag_index); protected: void init(StaState *sta); @@ -538,7 +572,8 @@ protected: void tnsNotifyBefore(Vertex *vertex); bool matchesFilterTo(Path *path, const ClockEdge *to_clk_edge) const; - PathRef pathClkPathArrival1(const Path *path) const; + const Path *pathClkPathArrival1(const Path *path) const; + void deletePathsState(const Vertex *vertex) const; void clocks(const Vertex *vertex, // Return value. ClockSet &clks) const; @@ -613,7 +648,6 @@ protected: std::mutex pending_latch_outputs_lock_; VertexSet *endpoints_; VertexSet *invalid_endpoints_; - bool always_save_prev_paths_; // Filter exception to tag arrivals for // report_timing -from pin|inst -through. // -to is always nullptr. @@ -676,7 +710,7 @@ protected: bool visitArc(const Pin *from_pin, Vertex *from_vertex, const RiseFall *from_rf, - PathVertex *from_path, + Path *from_path, Edge *edge, TimingArc *arc, const Pin *to_pin, @@ -688,7 +722,7 @@ protected: virtual bool visitFromPath(const Pin *from_pin, Vertex *from_vertex, const RiseFall *from_rf, - PathVertex *from_path, + Path *from_path, Edge *edge, TimingArc *arc, const Pin *to_pin, @@ -701,7 +735,7 @@ protected: Vertex *from_vertex, const RiseFall *from_rf, Tag *from_tag, - PathVertex *from_path, + Path *from_path, const Arrival &from_arrival, Edge *edge, TimingArc *arc, @@ -734,7 +768,7 @@ public: Vertex *from_vertex, const RiseFall *from_rf, Tag *from_tag, - PathVertex *from_path, + Path *from_path, const Arrival &from_arrival, Edge *edge, TimingArc *arc, @@ -775,14 +809,14 @@ public: RequiredCmp(); void requiredsInit(Vertex *vertex, const StaState *sta); - void requiredSet(int arrival_index, - Required required, + void requiredSet(size_t path_index, + Required &required, const MinMax *min_max, const StaState *sta); // Return true if the requireds changed. bool requiredsSave(Vertex *vertex, const StaState *sta); - Required required(int arrival_index); + Required required(size_t path_index); protected: ArrivalSeq requireds_; @@ -805,7 +839,7 @@ protected: Vertex *from_vertex, const RiseFall *from_rf, Tag *from_tag, - PathVertex *from_path, + Path *from_path, const Arrival &from_arrival, Edge *edge, TimingArc *arc, diff --git a/include/sta/SearchClass.hh b/include/sta/SearchClass.hh index ac558426..39c516f3 100644 --- a/include/sta/SearchClass.hh +++ b/include/sta/SearchClass.hh @@ -41,12 +41,6 @@ namespace sta { class Search; class Corner; class Path; -class PathRep; -class PathVertex; -class PathPrev; -class PathVertexPtr; -class PathRef; -class PathEnumed; class PathEnd; class PathGroup; class Tag; @@ -120,12 +114,12 @@ typedef Vector MaxSkewCheckSeq; typedef StringSet PathGroupNameSet; typedef Vector PathEndSeq; typedef Vector ArrivalSeq; -typedef Map VertexPathCountMap; -typedef UnorderedMap ArrivalMap; -typedef Vector PathVertexSeq; +typedef Map VertexPathCountMap; +typedef UnorderedMap PathIndexMap; typedef Vector SlackSeq; typedef Delay Crpr; -typedef Vector PathRefSeq; +typedef Vector PathSeq; +typedef vector ConstPathSeq; enum class ReportPathFormat { full, full_clock, diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 48df74b8..61b0b66e 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -1000,21 +1000,21 @@ public: VertexPathIterator *vertexPathIterator(Vertex *vertex, const RiseFall *rf, const MinMax *min_max); - PathRef vertexWorstArrivalPath(Vertex *vertex, - const RiseFall *rf, - const MinMax *min_max); - PathRef vertexWorstArrivalPath(Vertex *vertex, - const MinMax *min_max); - PathRef vertexWorstRequiredPath(Vertex *vertex, - const RiseFall *rf, - const MinMax *min_max); - PathRef vertexWorstRequiredPath(Vertex *vertex, - const MinMax *min_max); - PathRef vertexWorstSlackPath(Vertex *vertex, - const MinMax *min_max); - PathRef vertexWorstSlackPath(Vertex *vertex, + Path *vertexWorstArrivalPath(Vertex *vertex, const RiseFall *rf, const MinMax *min_max); + Path *vertexWorstArrivalPath(Vertex *vertex, + const MinMax *min_max); + Path *vertexWorstRequiredPath(Vertex *vertex, + const RiseFall *rf, + const MinMax *min_max); + Path *vertexWorstRequiredPath(Vertex *vertex, + const MinMax *min_max); + Path *vertexWorstSlackPath(Vertex *vertex, + const MinMax *min_max); + Path *vertexWorstSlackPath(Vertex *vertex, + const RiseFall *rf, + const MinMax *min_max); // Find the min clock period for rise/rise and fall/fall paths of a clock // using the slack. This does NOT correctly predict min period when there @@ -1112,10 +1112,9 @@ public: TagIndex tagCount() const; TagGroupIndex tagGroupCount() const; int clkInfoCount() const; - int arrivalCount() const; - int requiredCount() const; - int vertexArrivalCount(Vertex *vertex) const; - Vertex *maxArrivalCountVertex() const; + int pathCount() const; + int vertexPathCount(Vertex *vertex) const; + Vertex *maxPathCountVertex() const; LogicValue simLogicValue(const Pin *pin); // Propagate liberty constant functions and pins tied high/low through @@ -1314,7 +1313,7 @@ public: LibertyLibrarySeq *map_libs); LibertyCellSeq *equivCells(LibertyCell *cell); - void writePathSpice(PathRef *path, + void writePathSpice(Path *path, const char *spice_filename, const char *subckt_filename, const char *lib_subckt_filename, diff --git a/include/sta/StringUtil.hh b/include/sta/StringUtil.hh index 36f1de94..ddcdb606 100644 --- a/include/sta/StringUtil.hh +++ b/include/sta/StringUtil.hh @@ -190,6 +190,8 @@ stringPrintTmp(const char *fmt, char * makeTmpString(size_t length); +char * +makeTmpString(string &str); bool isTmpString(const char *str); diff --git a/include/sta/TableModel.hh b/include/sta/TableModel.hh index f18c163c..5834b44a 100644 --- a/include/sta/TableModel.hh +++ b/include/sta/TableModel.hh @@ -483,7 +483,7 @@ public: ~ReceiverModel(); void setCapacitanceModel(TableModel *table_model, size_t segment, - RiseFall *rf); + const RiseFall *rf); static bool checkAxes(TablePtr table); private: @@ -576,14 +576,13 @@ private: class DriverWaveform { public: - DriverWaveform(const char *name, + DriverWaveform(const string &name, TablePtr waveforms); - ~DriverWaveform(); - const char *name() const { return name_; } + const char *name() const { return name_.c_str(); } Table1 waveform(float slew); private: - const char *name_; + string name_; TablePtr waveforms_; }; diff --git a/include/sta/TimingArc.hh b/include/sta/TimingArc.hh index 992369cc..544f60f5 100644 --- a/include/sta/TimingArc.hh +++ b/include/sta/TimingArc.hh @@ -83,7 +83,7 @@ enum class TimingType { }; const char * -timingTypeString(TimingType type); +to_string(TimingType type); TimingType findTimingType(const char *string); bool @@ -146,7 +146,7 @@ public: LibertyPort *from, LibertyPort *to, LibertyPort *related_out, - TimingRole *role, + const TimingRole *role, TimingArcAttrsPtr attrs); virtual ~TimingArcSet(); LibertyCell *libertyCell() const; @@ -154,7 +154,7 @@ public: LibertyPort *to() const { return to_; } bool isWire() const; LibertyPort *relatedOut() const { return related_out_; } - TimingRole *role() const { return role_; }; + const TimingRole *role() const { return role_; }; TimingSense sense() const; // Rise/fall if the arc set is rising_edge or falling_edge. const RiseFall *isRisingFallingEdge() const; @@ -170,7 +170,7 @@ public: TimingArcIndex addTimingArc(TimingArc *arc); void deleteTimingArc(TimingArc *arc); TimingArc *findTimingArc(unsigned arc_index); - void setRole(TimingRole *role); + void setRole(const TimingRole *role); FuncExpr *cond() const { return attrs_->cond(); } // Cond default is the timing arcs with no condition when there are // other conditional timing arcs between the same pins. @@ -205,13 +205,13 @@ public: static int wireArcCount() { return 2; } protected: - TimingArcSet(TimingRole *role, + TimingArcSet(const TimingRole *role, TimingArcAttrsPtr attrs); LibertyPort *from_; LibertyPort *to_; LibertyPort *related_out_; - TimingRole *role_; + const TimingRole *role_; // TimingArcAttrs are shared by TimingArcSets in a bus with timing groups. TimingArcAttrsPtr attrs_; TimingArcSeq arcs_; @@ -232,15 +232,15 @@ class TimingArc { public: TimingArc(TimingArcSet *set, - Transition *from_rf, - Transition *to_rf, + const Transition *from_rf, + const Transition *to_rf, TimingModel *model); ~TimingArc(); LibertyPort *from() const { return set_->from(); } LibertyPort *to() const { return set_->to(); } - Transition *fromEdge() const { return from_rf_; } - Transition *toEdge() const { return to_rf_; } - TimingRole *role() const { return set_->role(); } + const Transition *fromEdge() const { return from_rf_; } + const Transition *toEdge() const { return to_rf_; } + const TimingRole *role() const { return set_->role(); } TimingArcSet *set() const { return set_; } TimingSense sense() const; // Index in TimingArcSet. @@ -266,8 +266,8 @@ protected: TimingModel *scaled_model); TimingArcSet *set_; - Transition *from_rf_; - Transition *to_rf_; + const Transition *from_rf_; + const Transition *to_rf_; unsigned index_; TimingModel *model_; ScaledTimingModelMap *scaled_models_; diff --git a/include/sta/TimingRole.hh b/include/sta/TimingRole.hh index d3a93015..bc6cf44b 100644 --- a/include/sta/TimingRole.hh +++ b/include/sta/TimingRole.hh @@ -24,52 +24,51 @@ #pragma once +#include + #include "MinMax.hh" -#include "Map.hh" #include "StringUtil.hh" namespace sta { class TimingRole; -typedef Map TimingRoleMap; +typedef std::map TimingRoleMap; class TimingRole { public: - static void init(); - static void destroy(); - static TimingRole *find(const char *name); + static const TimingRole *find(const char *name); // Singleton accessors. - static TimingRole *wire() { return wire_; } - static TimingRole *combinational() { return combinational_; } - static TimingRole *tristateEnable() { return tristate_enable_; } - static TimingRole *tristateDisable() { return tristate_disable_; } - static TimingRole *regClkToQ() { return reg_clk_q_; } - static TimingRole *regSetClr() { return reg_set_clr_; } - static TimingRole *latchEnToQ() { return latch_en_q_; } - static TimingRole *latchDtoQ() { return latch_d_q_; } - static TimingRole *setup() { return setup_; } - static TimingRole *hold() { return hold_; } - static TimingRole *recovery() { return recovery_; } - static TimingRole *removal() { return removal_; } - static TimingRole *width() { return width_; } - static TimingRole *period() { return period_; } - static TimingRole *skew() { return skew_; } - static TimingRole *nochange() { return nochange_; } - static TimingRole *outputSetup() { return output_setup_; } - static TimingRole *outputHold() { return output_hold_; } - static TimingRole *gatedClockSetup() { return gated_clk_setup_; } - static TimingRole *gatedClockHold() { return gated_clk_hold_; } - static TimingRole *latchSetup() { return latch_setup_; } - static TimingRole *latchHold() { return latch_hold_; } - static TimingRole *dataCheckSetup() { return data_check_setup_; } - static TimingRole *dataCheckHold() { return data_check_hold_; } - static TimingRole *nonSeqSetup() { return non_seq_setup_; } - static TimingRole *nonSeqHold() { return non_seq_hold_; } - static TimingRole *clockTreePathMin() { return clock_tree_path_min_; } - static TimingRole *clockTreePathMax() { return clock_tree_path_max_; } - const char *asString() const { return name_; } + static const TimingRole *wire() { return &wire_; } + static const TimingRole *combinational() { return &combinational_; } + static const TimingRole *tristateEnable() { return &tristate_enable_; } + static const TimingRole *tristateDisable() { return &tristate_disable_; } + static const TimingRole *regClkToQ() { return ®_clk_q_; } + static const TimingRole *regSetClr() { return ®_set_clr_; } + static const TimingRole *latchEnToQ() { return &latch_en_q_; } + static const TimingRole *latchDtoQ() { return &latch_d_q_; } + static const TimingRole *setup() { return &setup_; } + static const TimingRole *hold() { return &hold_; } + static const TimingRole *recovery() { return &recovery_; } + static const TimingRole *removal() { return &removal_; } + static const TimingRole *width() { return &width_; } + static const TimingRole *period() { return &period_; } + static const TimingRole *skew() { return &skew_; } + static const TimingRole *nochange() { return &nochange_; } + static const TimingRole *outputSetup() { return &output_setup_; } + static const TimingRole *outputHold() { return &output_hold_; } + static const TimingRole *gatedClockSetup() { return &gated_clk_setup_; } + static const TimingRole *gatedClockHold() { return &gated_clk_hold_; } + static const TimingRole *latchSetup() { return &latch_setup_; } + static const TimingRole *latchHold() { return &latch_hold_; } + static const TimingRole *dataCheckSetup() { return &data_check_setup_; } + static const TimingRole *dataCheckHold() { return &data_check_hold_; } + static const TimingRole *nonSeqSetup() { return &non_seq_setup_; } + static const TimingRole *nonSeqHold() { return &non_seq_hold_; } + static const TimingRole *clockTreePathMin() { return &clock_tree_path_min_; } + static const TimingRole *clockTreePathMax() { return &clock_tree_path_max_; } + const string &to_string() const { return name_; } int index() const { return index_; } bool isWire() const; bool isTimingCheck() const { return is_timing_check_; } @@ -82,12 +81,12 @@ public: const TimingRole *genericRole() const; const TimingRole *sdfRole() const; // Timing check data path min/max. - MinMax *pathMinMax() const { return path_min_max_; } + const MinMax *pathMinMax() const { return path_min_max_; } // Timing check target clock path insertion delay early/late. const EarlyLate *tgtClkEarlyLate() const; // Pseudo role to match sdf IOPATH. - static TimingRole *sdfIopath() { return sdf_iopath_; } + static const TimingRole *sdfIopath() { return &sdf_iopath_; } static bool less(const TimingRole *role1, const TimingRole *role2); static const int index_max = 26; @@ -97,48 +96,48 @@ private: bool is_sdf_iopath, bool is_timing_check, bool is_non_seq_check, - MinMax *path_min_max, + const MinMax *path_min_max, // generic_type = nullptr means type is the same as this. - TimingRole *generic_role, + const TimingRole *generic_role, int index); - const char *name_; + const string name_; bool is_timing_check_; bool is_sdf_iopath_; bool is_non_seq_check_; - TimingRole *generic_role_; + const TimingRole *generic_role_; unsigned index_; - MinMax *path_min_max_; + const MinMax *path_min_max_; - static TimingRole *wire_; - static TimingRole *combinational_; - static TimingRole *tristate_enable_; - static TimingRole *tristate_disable_; - static TimingRole *reg_clk_q_; - static TimingRole *reg_set_clr_; - static TimingRole *latch_en_q_; - static TimingRole *latch_d_q_; - static TimingRole *setup_; - static TimingRole *hold_; - static TimingRole *recovery_; - static TimingRole *removal_; - static TimingRole *width_; - static TimingRole *period_; - static TimingRole *skew_; - static TimingRole *nochange_; - static TimingRole *sdf_iopath_; - static TimingRole *output_setup_; - static TimingRole *output_hold_; - static TimingRole *gated_clk_setup_; - static TimingRole *gated_clk_hold_; - static TimingRole *latch_setup_; - static TimingRole *latch_hold_; - static TimingRole *data_check_setup_; - static TimingRole *data_check_hold_; - static TimingRole *non_seq_setup_; - static TimingRole *non_seq_hold_; - static TimingRole *clock_tree_path_min_; - static TimingRole *clock_tree_path_max_; + static const TimingRole wire_; + static const TimingRole combinational_; + static const TimingRole tristate_enable_; + static const TimingRole tristate_disable_; + static const TimingRole reg_clk_q_; + static const TimingRole reg_set_clr_; + static const TimingRole latch_en_q_; + static const TimingRole latch_d_q_; + static const TimingRole setup_; + static const TimingRole hold_; + static const TimingRole recovery_; + static const TimingRole removal_; + static const TimingRole width_; + static const TimingRole period_; + static const TimingRole skew_; + static const TimingRole nochange_; + static const TimingRole sdf_iopath_; + static const TimingRole output_setup_; + static const TimingRole output_hold_; + static const TimingRole gated_clk_setup_; + static const TimingRole gated_clk_hold_; + static const TimingRole latch_setup_; + static const TimingRole latch_hold_; + static const TimingRole data_check_setup_; + static const TimingRole data_check_hold_; + static const TimingRole non_seq_setup_; + static const TimingRole non_seq_hold_; + static const TimingRole clock_tree_path_min_; + static const TimingRole clock_tree_path_max_; static TimingRoleMap timing_roles_; friend class TimingRoleLess; diff --git a/include/sta/Transition.hh b/include/sta/Transition.hh index fca92270..87220d3d 100644 --- a/include/sta/Transition.hh +++ b/include/sta/Transition.hh @@ -37,34 +37,33 @@ class Transition; class RiseFall; class RiseFallBoth; -typedef Map TransitionMap; +typedef Map TransitionMap; // Rise/fall transition. class RiseFall { public: // Singleton accessors. - static RiseFall *rise() { return &rise_; } - static RiseFall *fall() { return &fall_; } + static const RiseFall *rise() { return &rise_; } + static const RiseFall *fall() { return &fall_; } static int riseIndex() { return rise_.sdf_triple_index_; } static int fallIndex() { return fall_.sdf_triple_index_; } - const char *asString() const { return short_name_; } - const char *name() const { return name_; } - const char *shortName() const { return short_name_; } - void setShortName(const char *short_name); + const string &to_string() const { return short_name_; } + const char *name() const { return name_.c_str(); } + const char *shortName() const { return short_name_.c_str(); } int index() const { return sdf_triple_index_; } - RiseFallBoth *asRiseFallBoth(); + const RiseFallBoth *asRiseFallBoth(); const RiseFallBoth *asRiseFallBoth() const; - Transition *asTransition() const; - // Find transition corresponding to tr_str. - static RiseFall *find(const char *tr_str); + const Transition *asTransition() const; + // Find transition corresponding to rf_str. + static const RiseFall *find(const char *rf_str); // Find transition from index. - static RiseFall *find(int index); - RiseFall *opposite() const; + static const RiseFall *find(int index); + const RiseFall *opposite() const; // for range support. // for (auto rf : RiseFall::range()) {} - static const std::array &range() { return range_; } + static const std::array &range() { return range_; } // for (auto rf_index : RiseFall::rangeIndex()) {} static const std::array &rangeIndex() { return range_index_; } static const int index_count = 2; @@ -73,17 +72,16 @@ public: protected: RiseFall(const char *name, - const char *short_name, - int sdf_triple_index); - ~RiseFall(); + const char *short_name, + int sdf_triple_index); - const char *name_; - const char *short_name_; + const string name_; + const string short_name_; const int sdf_triple_index_; - static RiseFall rise_; - static RiseFall fall_; - static const std::array range_; + static const RiseFall rise_; + static const RiseFall fall_; + static const std::array range_; static const std::array range_index_; }; @@ -92,21 +90,20 @@ class RiseFallBoth { public: // Singleton accessors. - static RiseFallBoth *rise() { return &rise_; } - static RiseFallBoth *fall() { return &fall_; } - static RiseFallBoth *riseFall() { return &rise_fall_; } - const char *asString() const { return short_name_; } - const char *name() const { return name_; } - const char *shortName() const { return short_name_; } - void setShortName(const char *short_name); + static const RiseFallBoth *rise() { return &rise_; } + static const RiseFallBoth *fall() { return &fall_; } + static const RiseFallBoth *riseFall() { return &rise_fall_; } + const string &to_string() const { return short_name_; } + const char *name() const { return name_.c_str(); } + const char *shortName() const { return short_name_.c_str(); } int index() const { return sdf_triple_index_; } bool matches(const RiseFall *rf) const; bool matches(const Transition *tr) const; - RiseFall *asRiseFall() const { return as_rise_fall_; } + const RiseFall *asRiseFall() const { return as_rise_fall_; } // Find transition corresponding to string. - static RiseFallBoth *find(const char *tr_str); + static const RiseFallBoth *find(const char *tr_str); // for (const auto rf : rf->range()) {} - const std::vector &range() const { return range_; } + const std::vector &range() const { return range_; } // for (const auto rf_index : rf->rangeIndex()) {} const std::vector &rangeIndex() const { return range_index_; } @@ -116,23 +113,22 @@ public: protected: RiseFallBoth(const char *name, - const char *short_name, - int sdf_triple_index, - RiseFall *as_rise_fall, - std::vector range, - std::vector range_index); - ~RiseFallBoth(); + const char *short_name, + int sdf_triple_index, + const RiseFall *as_rise_fall, + std::vector range, + std::vector range_index); - const char *name_; - const char *short_name_; + const string name_; + const string short_name_; const int sdf_triple_index_; - RiseFall *as_rise_fall_; - const std::vector range_; + const RiseFall *as_rise_fall_; + const std::vector range_; const std::vector range_index_; - static RiseFallBoth rise_; - static RiseFallBoth fall_; - static RiseFallBoth rise_fall_; + static const RiseFallBoth rise_; + static const RiseFallBoth fall_; + static const RiseFallBoth rise_fall_; }; // General SDF transition. @@ -140,58 +136,56 @@ class Transition { public: // Singleton accessors. - static Transition *rise() { return &rise_; } - static Transition *fall() { return &fall_; } - static Transition *tr0Z() { return &tr_0Z_; } - static Transition *trZ1() { return &tr_Z1_; } - static Transition *tr1Z() { return &tr_1Z_; } - static Transition *trZ0() { return &tr_Z0_; } - static Transition *tr0X() { return &tr_0X_; } - static Transition *trX1() { return &tr_X1_; } - static Transition *tr1X() { return &tr_1X_; } - static Transition *trX0() { return &tr_X0_; } - static Transition *trXZ() { return &tr_XZ_; } - static Transition *trZX() { return &tr_ZX_; } - void setName(const char *name); + static const Transition *rise() { return &rise_; } + static const Transition *fall() { return &fall_; } + static const Transition *tr0Z() { return &tr_0Z_; } + static const Transition *trZ1() { return &tr_Z1_; } + static const Transition *tr1Z() { return &tr_1Z_; } + static const Transition *trZ0() { return &tr_Z0_; } + static const Transition *tr0X() { return &tr_0X_; } + static const Transition *trX1() { return &tr_X1_; } + static const Transition *tr1X() { return &tr_1X_; } + static const Transition *trX0() { return &tr_X0_; } + static const Transition *trXZ() { return &tr_XZ_; } + static const Transition *trZX() { return &tr_ZX_; } // Matches rise and fall. - static Transition *riseFall() { return &rise_fall_; } - const char *asString() const { return name_; } + static const Transition *riseFall() { return &rise_fall_; } + const string &to_string() const { return name_; } // As initial/final value pair. - const char *asInitFinalString() const { return init_final_; } + const char *asInitFinalString() const { return init_final_.c_str(); } int sdfTripleIndex() const { return sdf_triple_index_; } int index() const { return sdf_triple_index_; } - RiseFall *asRiseFall() const { return as_rise_fall_; } + const RiseFall *asRiseFall() const { return as_rise_fall_; } const RiseFallBoth *asRiseFallBoth() const; bool matches(const Transition *tr) const; // Find transition corresponding to string. - static Transition *find(const char *tr_str); + static const Transition *find(const char *tr_str); static int maxIndex() { return max_index_; } private: Transition(const char *name, const char *init_final, - RiseFall *as_rise_fall, + const RiseFall *as_rise_fall, int sdf_triple_index); - ~Transition(); - const char *name_; - const char *init_final_; - RiseFall *as_rise_fall_; + const string name_; + const string init_final_; + const RiseFall *as_rise_fall_; const int sdf_triple_index_; - static Transition rise_; - static Transition fall_; - static Transition tr_0Z_; - static Transition tr_Z1_; - static Transition tr_1Z_; - static Transition tr_Z0_; - static Transition tr_0X_; - static Transition tr_X1_; - static Transition tr_1X_; - static Transition tr_X0_; - static Transition tr_XZ_; - static Transition tr_ZX_; - static Transition rise_fall_; + static const Transition rise_; + static const Transition fall_; + static const Transition tr_0Z_; + static const Transition tr_Z1_; + static const Transition tr_1Z_; + static const Transition tr_Z0_; + static const Transition tr_0X_; + static const Transition tr_X1_; + static const Transition tr_1X_; + static const Transition tr_X0_; + static const Transition tr_XZ_; + static const Transition tr_ZX_; + static const Transition rise_fall_; static const int index_count = 13; static const int index_max = (index_count - 1); static const int index_bit_count = 4; diff --git a/include/sta/VisitPathEnds.hh b/include/sta/VisitPathEnds.hh index c91b117d..f6114b3f 100644 --- a/include/sta/VisitPathEnds.hh +++ b/include/sta/VisitPathEnds.hh @@ -85,7 +85,7 @@ protected: Path *path, const RiseFall *end_rf, const ClockEdge *tgt_clk_edge, - PathVertex *ref_path, + Path *ref_path, const MinMax *min_max, PathEndVisitor *visitor, bool &is_constrained); @@ -118,7 +118,7 @@ protected: const PathAnalysisPt *clk_ap, const Pin *from_pin, Vertex *from_vertex, - RiseFall *from_rf, + const RiseFall *from_rf, bool filtered, PathEndVisitor *visitor, bool &is_constrained); diff --git a/liberty/FuncExpr.cc b/liberty/FuncExpr.cc index 55dd8821..be095ac7 100644 --- a/liberty/FuncExpr.cc +++ b/liberty/FuncExpr.cc @@ -193,34 +193,29 @@ FuncExpr::portTimingSense(const LibertyPort *port) const return TimingSense::unknown; } -const char * -FuncExpr::asString() const +string +FuncExpr::to_string() const { - return asString(false); + return to_string(false); } -const char * -FuncExpr::asString(bool with_parens) const +string +FuncExpr::to_string(bool with_parens) const { switch (op_) { case op_port: return port_->name(); case op_not: { - const char *left = left_->asString(true); - size_t left_length = strlen(left); - size_t length = left_length + 2; - char *result = makeTmpString(length); - char *ptr = result; - *ptr++ = '!'; - strcpy(ptr, left); + string result = "!"; + result += left_->to_string(true); return result; } case op_or: - return asStringSubexpr(with_parens, '+'); + return to_string(with_parens, '+'); case op_and: - return asStringSubexpr(with_parens, '*'); + return to_string(with_parens, '*'); case op_xor: - return asStringSubexpr(with_parens, '^'); + return to_string(with_parens, '^'); case op_one: return "1"; case op_zero: @@ -230,25 +225,19 @@ FuncExpr::asString(bool with_parens) const } } -const char * -FuncExpr::asStringSubexpr(bool with_parens, - char op) const +string +FuncExpr::to_string(bool with_parens, + char op) const { - const char *left = left_->asString(true); - const char *right = right_->asString(true); - size_t length = strlen(left) + 1 + strlen(right) + 1; + string right = right_->to_string(true); + string result; if (with_parens) - length += 2; - char *result = makeTmpString(length); - char *r = result; + result += '('; + result += left_->to_string(true); + result += op; + result += right_->to_string(true); if (with_parens) - *r++= '('; - stringAppend(r, left); - *r++ = op; - stringAppend(r, right); - if (with_parens) - *r++ = ')'; - *r = '\0'; + result += ')'; return result; } diff --git a/liberty/InternalPower.cc b/liberty/InternalPower.cc index 5c6c29f9..feaa44b2 100644 --- a/liberty/InternalPower.cc +++ b/liberty/InternalPower.cc @@ -56,13 +56,13 @@ InternalPowerAttrs::deleteContents() } InternalPowerModel * -InternalPowerAttrs::model(RiseFall *rf) const +InternalPowerAttrs::model(const RiseFall *rf) const { return models_[rf->index()]; } void -InternalPowerAttrs::setModel(RiseFall *rf, +InternalPowerAttrs::setModel(const RiseFall *rf, InternalPowerModel *model) { models_[rf->index()] = model; @@ -86,9 +86,9 @@ InternalPower::InternalPower(LibertyCell *cell, when_(attrs->when()), related_pg_pin_(attrs->relatedPgPin()) { - for (auto tr : RiseFall::range()) { - int tr_index = tr->index(); - models_[tr_index] = attrs->model(tr); + for (auto rf : RiseFall::range()) { + int rf_index = rf->index(); + models_[rf_index] = attrs->model(rf); } cell->addInternalPower(this); } @@ -105,7 +105,7 @@ InternalPower::libertyCell() const } float -InternalPower::power(RiseFall *rf, +InternalPower::power(const RiseFall *rf, const Pvt *pvt, float in_slew, float load_cap) diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index e4893739..f9f7dd59 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -130,8 +130,6 @@ LibertyLibrary::~LibertyLibrary() delete units_; ocv_derate_map_.deleteContents(); - for (auto [supply_name, volt] : supply_voltage_map_) - stringDelete(supply_name); delete buffers_; delete inverters_; driver_waveform_map_.deleteContents(); @@ -325,7 +323,7 @@ LibertyLibrary::scaleFactor(ScaleFactorType type, void LibertyLibrary::setWireSlewDegradationTable(TableModel *model, - RiseFall *rf) + const RiseFall *rf) { int rf_index = rf->index(); if (wire_slew_degradation_tbls_[rf_index]) @@ -799,7 +797,7 @@ LibertyLibrary::makeCornerMap(LibertyCell *cell1, cell1->name(), arc_set1->from() ? arc_set1->from()->name() : "", arc_set1->to()->name(), - arc_set1->role()->asString(), + arc_set1->role()->to_string().c_str(), cell2->library()->name(), cell2->name()); } @@ -817,7 +815,7 @@ LibertyLibrary::checkCorners(LibertyCell *cell, cell->libertyLibrary()->name(), cell->name(), corner->name(), - min_max->asString()); + min_max->to_string().c_str()); } } } @@ -864,7 +862,7 @@ void LibertyLibrary::addSupplyVoltage(const char *supply_name, float voltage) { - supply_voltage_map_[stringCopy(supply_name)] = voltage; + supply_voltage_map_[supply_name] = voltage; } void @@ -948,9 +946,7 @@ LibertyCell::LibertyCell(LibertyLibrary *library, leakage_power_(0.0), leakage_power_exists_(false), has_internal_ports_(false), - have_voltage_waveforms_(false), - footprint_(nullptr), - user_function_class_(nullptr) + have_voltage_waveforms_(false) { liberty_cell_ = this; } @@ -978,9 +974,6 @@ LibertyCell::~LibertyCell() ocv_derate_map_.deleteContents(); pg_port_map_.deleteContents(); - - stringDelete(footprint_); - stringDelete(user_function_class_); } LibertyPort * @@ -1248,7 +1241,7 @@ LibertyCell::addTimingArcSet(TimingArcSet *arc_set) timing_arc_sets_.push_back(arc_set); LibertyPort *from = arc_set->from(); - TimingRole *role = arc_set->role(); + const TimingRole *role = arc_set->role(); if (role == TimingRole::regClkToQ() || role == TimingRole::latchEnToQ()) from->setIsRegClk(true); @@ -1772,7 +1765,7 @@ LibertyCell::makeLatchEnables(Report *report, && en_rf != RiseFall::rise()) report->warn(1114, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function positive sense.", library_->name(), - name_, + name(), en->name(), q->name(), en_rf == RiseFall::rise()?"rising":"falling"); @@ -1780,7 +1773,7 @@ LibertyCell::makeLatchEnables(Report *report, && en_rf != RiseFall::fall()) report->warn(1115, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function negative sense.", library_->name(), - name_, + name(), en->name(), q->name(), en_rf == RiseFall::rise()?"rising":"falling"); @@ -1831,7 +1824,7 @@ LibertyCell::findLatchSetup(const LibertyPort *d, if (from_rf == en_rf) { report->warn(1113, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with %s -> %s setup_%s check.", library_->name(), - name_, + name(), en->name(), q->name(), en_rf == RiseFall::rise() ? "rising" : "falling", @@ -1913,7 +1906,7 @@ LibertyCell::inferLatchRoles(Report *report, LibertyPort *q = en_to_q->to(); for (TimingArcSet *d_to_q : timingArcSets(nullptr, q)) { // Look for combinational d->q arcs. - TimingRole *d_to_q_role = d_to_q->role(); + const TimingRole *d_to_q_role = d_to_q->role(); if (((d_to_q_role == TimingRole::combinational() && d_to_q->arcCount() == 2 && (d_to_q->sense() == TimingSense::positive_unate @@ -2002,28 +1995,35 @@ LibertyCell::ensureVoltageWaveforms(const DcalcAnalysisPtSeq &dcalc_aps) } } +const char * +LibertyCell::footprint() const +{ + if (footprint_.empty()) + return nullptr; + else + return footprint_.c_str(); +} + + void LibertyCell::setFootprint(const char *footprint) { - footprint_ = stringCopy(footprint); + footprint_ = footprint; } -const char* -LibertyCell::footprint() const +const char * +LibertyCell::userFunctionClass() const { - return footprint_; + if (user_function_class_.empty()) + return nullptr; + else + return user_function_class_.c_str(); } void LibertyCell::setUserFunctionClass(const char *user_function_class) { - user_function_class_ = stringCopy(user_function_class); -} - -const char* -LibertyCell::userFunctionClass() const -{ - return user_function_class_; + user_function_class_ = user_function_class; } //////////////////////////////////////////////////////////////// @@ -2091,8 +2091,6 @@ LibertyPort::LibertyPort(LibertyCell *cell, min_period_(0.0), pulse_clk_trigger_(nullptr), pulse_clk_sense_(nullptr), - related_ground_pin_(nullptr), - related_power_pin_(nullptr), receiver_model_(nullptr), driver_waveform_{nullptr, nullptr}, min_pulse_width_exists_(false), @@ -2129,8 +2127,6 @@ LibertyPort::~LibertyPort() if (tristate_enable_) tristate_enable_->deleteSubexprs(); delete scaled_ports_; - stringDelete(related_ground_pin_); - stringDelete(related_power_pin_); } void @@ -2597,8 +2593,8 @@ LibertyPort::setIsSwitch(bool is_switch) } void -LibertyPort::setPulseClk(RiseFall *trigger, - RiseFall *sense) +LibertyPort::setPulseClk(const RiseFall *trigger, + const RiseFall *sense) { pulse_clk_trigger_ = trigger; pulse_clk_sense_ = sense; @@ -2673,16 +2669,34 @@ LibertyPort::setCornerPort(LibertyPort *corner_port, corner_ports_[ap_index] = corner_port; } +const char * +LibertyPort::relatedGroundPin() const +{ + if (related_ground_pin_.empty()) + return nullptr; + else + return related_ground_pin_.c_str(); +} + void LibertyPort::setRelatedGroundPin(const char *related_ground_pin) { - related_ground_pin_ = stringCopy(related_ground_pin); + related_ground_pin_ = related_ground_pin; +} + +const char * +LibertyPort::relatedPowerPin() const +{ + if (related_power_pin_.empty()) + return nullptr; + else + return related_power_pin_.c_str(); } void LibertyPort::setRelatedPowerPin(const char *related_power_pin) { - related_power_pin_ = stringCopy(related_power_pin); + related_power_pin_ = related_power_pin; } void @@ -2846,28 +2860,22 @@ LibertyPortMemberIterator::next() BusDcl::BusDcl(const char *name, int from, int to) : - name_(stringCopy(name)), + name_(name), from_(from), to_(to) { } -BusDcl::~BusDcl() -{ - stringDelete(name_); -} - //////////////////////////////////////////////////////////////// ModeDef::ModeDef(const char *name) : - name_(stringCopy(name)) + name_(name) { } ModeDef::~ModeDef() { values_.deleteContents(); - stringDelete(name_); } ModeValueDef * @@ -2891,31 +2899,28 @@ ModeDef::findValueDef(const char *value) ModeValueDef::ModeValueDef(const char *value, FuncExpr *cond, const char *sdf_cond) : - value_(stringCopy(value)), + value_(value), cond_(cond), - sdf_cond_(stringCopy(sdf_cond)) + sdf_cond_(sdf_cond ? sdf_cond : "") { } ModeValueDef::~ModeValueDef() { - stringDelete(value_); if (cond_) cond_->deleteSubexprs(); - if (sdf_cond_) - stringDelete(sdf_cond_); } void ModeValueDef::setSdfCond(const char *sdf_cond) { - sdf_cond_ = stringCopy(sdf_cond); + sdf_cond_ = sdf_cond; } //////////////////////////////////////////////////////////////// TableTemplate::TableTemplate(const char *name) : - name_(stringCopy(name)), + name_(name), axis1_(nullptr), axis2_(nullptr), axis3_(nullptr) @@ -2926,23 +2931,17 @@ TableTemplate::TableTemplate(const char *name, TableAxisPtr axis1, TableAxisPtr axis2, TableAxisPtr axis3) : - name_(stringCopy(name)), + name_(name), axis1_(axis1), axis2_(axis2), axis3_(axis3) { } -TableTemplate::~TableTemplate() -{ - stringDelete(name_); -} - void TableTemplate::setName(const char *name) { - stringDelete(name_); - name_ = stringCopy(name); + name_ = name; } void @@ -2994,7 +2993,7 @@ Pvt::setTemperature(float temp) OperatingConditions::OperatingConditions(const char *name) : Pvt(0.0, 0.0, 0.0), - name_(stringCopy(name)), + name_(name), // Default wireload tree. wire_load_tree_(WireloadTree::balanced) { @@ -3006,16 +3005,11 @@ OperatingConditions::OperatingConditions(const char *name, float temperature, WireloadTree wire_load_tree) : Pvt(process, voltage, temperature), - name_(stringCopy(name)), + name_(name), wire_load_tree_(wire_load_tree) { } -OperatingConditions::~OperatingConditions() -{ - stringDelete(name_); -} - void OperatingConditions::setWireloadTree(WireloadTree tree) { @@ -3101,7 +3095,7 @@ scaleFactorPvtName(ScaleFactorPvt pvt) //////////////////////////////////////////////////////////////// ScaleFactors::ScaleFactors(const char *name) : - name_(stringCopy(name)) + name_(name) { for (int type = 0; type < scale_factor_type_count; type++) { for (int pvt = 0; pvt < scale_factor_pvt_count; pvt++) { @@ -3112,15 +3106,10 @@ ScaleFactors::ScaleFactors(const char *name) : } } -ScaleFactors::~ScaleFactors() -{ - stringDelete(name_); -} - void ScaleFactors::setScale(ScaleFactorType type, ScaleFactorPvt pvt, - RiseFall *rf, + const RiseFall *rf, float scale) { scales_[int(type)][int(pvt)][rf->index()] = scale; @@ -3137,7 +3126,7 @@ ScaleFactors::setScale(ScaleFactorType type, float ScaleFactors::scale(ScaleFactorType type, ScaleFactorPvt pvt, - RiseFall *rf) + const RiseFall *rf) { return scales_[int(type)][int(pvt)][rf->index()]; } @@ -3232,19 +3221,12 @@ OcvDerate::setDerateTable(const RiseFall *rf, LibertyPgPort::LibertyPgPort(const char *name, LibertyCell *cell) : - name_(stringCopy(name)), + name_(name), pg_type_(unknown), - voltage_name_(nullptr), cell_(cell) { } -LibertyPgPort::~LibertyPgPort() -{ - stringDelete(name_); - stringDelete(voltage_name_); -} - void LibertyPgPort::setPgType(PgType type) { @@ -3254,14 +3236,14 @@ LibertyPgPort::setPgType(PgType type) void LibertyPgPort::setVoltageName(const char *voltage_name) { - voltage_name_ = stringCopy(voltage_name); + voltage_name_ = voltage_name; } bool LibertyPgPort::equiv(const LibertyPgPort *port1, const LibertyPgPort *port2) { - return stringEq(port1->name_, port2->name_) + return port1->name_ == port2->name_ && port1->pg_type_ == port2->pg_type_; } @@ -3281,7 +3263,7 @@ LibertyCellPgPortIterator::hasNext() LibertyPgPort * LibertyCellPgPortIterator::next() { - const char *name; + string name; LibertyPgPort *port; iter_.next(name, port); return port; diff --git a/liberty/Liberty.i b/liberty/Liberty.i index 43ba05e2..afa00e87 100644 --- a/liberty/Liberty.i +++ b/liberty/Liberty.i @@ -206,7 +206,7 @@ find_liberty_cell(const char *name) } bool -timing_role_is_check(TimingRole *role) +timing_role_is_check(const TimingRole *role) { return role->isTimingCheck(); } @@ -313,24 +313,24 @@ bool is_bus() { return self->isBus(); } LibertyPortMemberIterator * member_iterator() { return new LibertyPortMemberIterator(self); } -const char * +string function() { FuncExpr *func = self->function(); if (func) - return func->asString(); + return func->to_string(); else - return nullptr; + return ""; } -const char * +string tristate_enable() { FuncExpr *enable = self->tristateEnable(); if (enable) - return enable->asString(); + return enable->to_string(); else - return nullptr; + return ""; } float @@ -358,7 +358,7 @@ scan_signal_type() %extend TimingArcSet { LibertyPort *from() { return self->from(); } LibertyPort *to() { return self->to(); } -TimingRole *role() { return self->role(); } +const TimingRole *role() { return self->role(); } const char *sdf_cond() { return self->sdfCond(); } const char * @@ -381,11 +381,11 @@ timing_arcs() { return self->arcs(); } %extend TimingArc { LibertyPort *from() { return self->from(); } LibertyPort *to() { return self->to(); } -Transition *from_edge() { return self->fromEdge(); } +const Transition *from_edge() { return self->fromEdge(); } const char *from_edge_name() { return self->fromEdge()->asRiseFall()->name(); } -Transition *to_edge() { return self->toEdge(); } +const Transition *to_edge() { return self->toEdge(); } const char *to_edge_name() { return self->toEdge()->asRiseFall()->name(); } -TimingRole *role() { return self->role(); } +const TimingRole *role() { return self->role(); } float time_voltage(float in_slew, diff --git a/liberty/LibertyBuilder.cc b/liberty/LibertyBuilder.cc index 1bbca275..9370f13d 100644 --- a/liberty/LibertyBuilder.cc +++ b/liberty/LibertyBuilder.cc @@ -59,8 +59,7 @@ LibertyPort * LibertyBuilder::makePort(LibertyCell *cell, const char *port_name) { - string sta_name = portLibertyToSta(port_name); - LibertyPort *port = new LibertyPort(cell, sta_name.c_str(), false, nullptr, + LibertyPort *port = new LibertyPort(cell, port_name, false, nullptr, -1, -1, false, nullptr); cell->addPort(port); return port; @@ -73,12 +72,11 @@ LibertyBuilder::makeBusPort(LibertyCell *cell, int to_index, BusDcl *bus_dcl) { - string sta_name = portLibertyToSta(bus_name); - LibertyPort *port = new LibertyPort(cell, sta_name.c_str(), true, bus_dcl, + LibertyPort *port = new LibertyPort(cell, bus_name, true, bus_dcl, from_index, to_index, false, new ConcretePortSeq); cell->addPort(port); - makeBusPortBits(cell->library(), cell, port, sta_name.c_str(), from_index, to_index); + makeBusPortBits(cell->library(), cell, port, bus_name, from_index, to_index); return port; } @@ -329,7 +327,7 @@ LibertyBuilder::makeCombinationalArcs(LibertyCell *cell, } TimingModel *model; - RiseFall *to_rf; + const RiseFall *to_rf; switch (sense) { case TimingSense::positive_unate: if (to_rise) { @@ -393,18 +391,20 @@ LibertyBuilder::makeLatchDtoQArcs(LibertyCell *cell, TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port, TimingRole::latchDtoQ(), attrs); TimingModel *model; - RiseFall *to_rf = RiseFall::rise(); + const RiseFall *to_rf = RiseFall::rise(); model = attrs->model(to_rf); if (model) { - RiseFall *from_rf = (sense == TimingSense::negative_unate) ? - to_rf->opposite() : to_rf; + const RiseFall *from_rf = (sense == TimingSense::negative_unate) + ? to_rf->opposite() + : to_rf; makeTimingArc(arc_set, from_rf, to_rf, model); } to_rf = RiseFall::fall(); model = attrs->model(to_rf); if (model) { - RiseFall *from_rf = (sense == TimingSense::negative_unate) ? - to_rf->opposite() : to_rf; + const RiseFall *from_rf = (sense == TimingSense::negative_unate) + ? to_rf->opposite() + : to_rf; makeTimingArc(arc_set, from_rf, to_rf, model); } return arc_set; @@ -414,7 +414,7 @@ TimingArcSet * LibertyBuilder::makeRegLatchArcs(LibertyCell *cell, LibertyPort *from_port, LibertyPort *to_port, - RiseFall *from_rf, + const RiseFall *from_rf, TimingArcAttrsPtr attrs) { FuncExpr *to_func = to_port->function(); @@ -424,7 +424,7 @@ LibertyBuilder::makeRegLatchArcs(LibertyCell *cell, Sequential *seq = cell->outputPortSequential(func_port); if (seq) { if (seq->clock() && seq->clock()->hasPort(from_port)) { - TimingRole *role = seq->isRegister() ? + const TimingRole *role = seq->isRegister() ? TimingRole::regClkToQ() : TimingRole::latchEnToQ(); return makeFromTransitionArcs(cell, from_port, to_port, nullptr, from_rf, role, attrs); @@ -451,8 +451,8 @@ LibertyBuilder::makeFromTransitionArcs(LibertyCell *cell, LibertyPort *from_port, LibertyPort *to_port, LibertyPort *related_out, - RiseFall *from_rf, - TimingRole *role, + const RiseFall *from_rf, + const TimingRole *role, TimingArcAttrsPtr attrs) { TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port, @@ -469,7 +469,7 @@ TimingArcSet * LibertyBuilder::makePresetClrArcs(LibertyCell *cell, LibertyPort *from_port, LibertyPort *to_port, - RiseFall *to_rf, + const RiseFall *to_rf, TimingArcAttrsPtr attrs) { TimingArcSet *arc_set = nullptr; @@ -477,7 +477,7 @@ LibertyBuilder::makePresetClrArcs(LibertyCell *cell, if (model) { arc_set = makeTimingArcSet(cell, from_port, to_port, TimingRole::regSetClr(), attrs); - RiseFall *opp_rf = to_rf->opposite(); + const RiseFall *opp_rf = to_rf->opposite(); switch (attrs->timingSense()) { case TimingSense::positive_unate: makeTimingArc(arc_set, to_rf, to_rf, model); @@ -515,7 +515,7 @@ LibertyBuilder::makeTristateEnableArcs(LibertyCell *cell, if (sense == TimingSense::unknown && tristate_enable) sense = tristate_enable->portTimingSense(from_port); TimingModel *model; - RiseFall *to_rf; + const RiseFall *to_rf; switch (sense) { case TimingSense::positive_unate: if (to_rise) { @@ -586,7 +586,7 @@ LibertyBuilder::makeTristateDisableArcs(LibertyCell *cell, if (sense == TimingSense::unknown && tristate_enable) sense = timingSenseOpposite(tristate_enable->portTimingSense(from_port)); TimingModel *model; - RiseFall *to_rf; + const RiseFall *to_rf; switch (sense) { case TimingSense::positive_unate: if (to_rise) { @@ -644,7 +644,7 @@ LibertyBuilder::makeTristateDisableArcs(LibertyCell *cell, TimingArcSet * LibertyBuilder::makeClockTreePathArcs(LibertyCell *cell, LibertyPort *to_port, - TimingRole *role, + const TimingRole *role, const MinMax *min_max, TimingArcAttrsPtr attrs) { @@ -653,7 +653,7 @@ LibertyBuilder::makeClockTreePathArcs(LibertyCell *cell, TimingModel *model = attrs->model(to_rf); if (model) { const GateTableModel *gate_model = dynamic_cast(model); - RiseFall *opp_rf = to_rf->opposite(); + const RiseFall *opp_rf = to_rf->opposite(); switch (attrs->timingSense()) { case TimingSense::positive_unate: makeTimingArc(arc_set, to_rf, to_rf, model); @@ -683,7 +683,7 @@ LibertyBuilder::makeMinPulseWidthArcs(LibertyCell *cell, LibertyPort *from_port, LibertyPort *to_port, LibertyPort *related_out, - TimingRole *role, + const TimingRole *role, TimingArcAttrsPtr attrs) { if (from_port == nullptr) @@ -704,7 +704,7 @@ TimingArcSet * LibertyBuilder::makeTimingArcSet(LibertyCell *cell, LibertyPort *from, LibertyPort *to, - TimingRole *role, + const TimingRole *role, TimingArcAttrsPtr attrs) { return new TimingArcSet(cell, from, to, nullptr, role, attrs); @@ -715,7 +715,7 @@ LibertyBuilder::makeTimingArcSet(LibertyCell *cell, LibertyPort *from, LibertyPort *to, LibertyPort *related_out, - TimingRole *role, + const TimingRole *role, TimingArcAttrsPtr attrs) { return new TimingArcSet(cell, from, to, related_out, role, attrs); @@ -723,8 +723,8 @@ LibertyBuilder::makeTimingArcSet(LibertyCell *cell, TimingArc * LibertyBuilder::makeTimingArc(TimingArcSet *set, - RiseFall *from_rf, - RiseFall *to_rf, + const RiseFall *from_rf, + const RiseFall *to_rf, TimingModel *model) { return new TimingArc(set, from_rf->asTransition(), @@ -733,8 +733,8 @@ LibertyBuilder::makeTimingArc(TimingArcSet *set, TimingArc * LibertyBuilder::makeTimingArc(TimingArcSet *set, - Transition *from_rf, - Transition *to_rf, + const Transition *from_rf, + const Transition *to_rf, TimingModel *model) { return new TimingArc(set, from_rf, to_rf, model); diff --git a/liberty/LibertyBuilder.hh b/liberty/LibertyBuilder.hh index 47c6d6e9..9ce87931 100644 --- a/liberty/LibertyBuilder.hh +++ b/liberty/LibertyBuilder.hh @@ -78,8 +78,8 @@ public: LibertyPort *from_port, LibertyPort *to_port, LibertyPort *related_out, - RiseFall *from_rf, - TimingRole *role, + const RiseFall *from_rf, + const TimingRole *role, TimingArcAttrsPtr attrs); TimingArcSet *makeCombinationalArcs(LibertyCell *cell, LibertyPort *from_port, @@ -89,14 +89,14 @@ public: TimingArcAttrsPtr attrs); TimingArcSet *makeClockTreePathArcs(LibertyCell *cell, LibertyPort *to_port, - TimingRole *role, + const TimingRole *role, const MinMax *min_max, TimingArcAttrsPtr attrs); TimingArcSet *makeMinPulseWidthArcs(LibertyCell *cell, LibertyPort *from_port, LibertyPort *to_port, LibertyPort *related_out, - TimingRole *role, + const TimingRole *role, TimingArcAttrsPtr attrs); protected: @@ -122,21 +122,21 @@ protected: virtual TimingArcSet *makeTimingArcSet(LibertyCell *cell, LibertyPort *from, LibertyPort *to, - TimingRole *role, + const TimingRole *role, TimingArcAttrsPtr attrs); virtual TimingArcSet *makeTimingArcSet(LibertyCell *cell, LibertyPort *from, LibertyPort *to, LibertyPort *related_out, - TimingRole *role, + const TimingRole *role, TimingArcAttrsPtr attrs); virtual TimingArc *makeTimingArc(TimingArcSet *set, - Transition *from_rf, - Transition *to_rf, + const Transition *from_rf, + const Transition *to_rf, TimingModel *model); TimingArc *makeTimingArc(TimingArcSet *set, - RiseFall *from_rf, - RiseFall *to_rf, + const RiseFall *from_rf, + const RiseFall *to_rf, TimingModel *model); TimingArcSet *makeLatchDtoQArcs(LibertyCell *cell, LibertyPort *from_port, @@ -146,12 +146,12 @@ protected: TimingArcSet *makeRegLatchArcs(LibertyCell *cell, LibertyPort *from_port, LibertyPort *to_port, - RiseFall *from_rf, + const RiseFall *from_rf, TimingArcAttrsPtr attrs); TimingArcSet *makePresetClrArcs(LibertyCell *cell, LibertyPort *from_port, LibertyPort *to_port, - RiseFall *to_rf, + const RiseFall *to_rf, TimingArcAttrsPtr attrs); TimingArcSet *makeTristateEnableArcs(LibertyCell *cell, LibertyPort *from_port, diff --git a/liberty/LibertyParser.cc b/liberty/LibertyParser.cc index 6cf896cd..9bd82954 100644 --- a/liberty/LibertyParser.cc +++ b/liberty/LibertyParser.cc @@ -78,7 +78,7 @@ LibertyParser::makeDefine(LibertyAttrValueSeq *values, const char *value_type_name = (*values)[2]->stringValue(); LibertyAttrType value_type = attrValueType(value_type_name); LibertyGroupType group_type = groupType(group_type_name); - define = new LibertyDefine(stringCopy(define_name), group_type, + define = new LibertyDefine(define_name, group_type, value_type, line); LibertyGroup *group = this->group(); group->addDefine(define); @@ -128,6 +128,7 @@ LibertyParser::groupBegin(const char *type, int line) { LibertyGroup *group = new LibertyGroup(type, params, line); + stringDelete(type); group_visitor_->begin(group); group_stack_.push_back(group); } @@ -168,6 +169,7 @@ LibertyParser::makeSimpleAttr(const char *name, int line) { LibertyAttr *attr = new LibertySimpleAttr(name, value, line); + stringDelete(name); group_visitor_->visitAttr(attr); LibertyGroup *group = this->group(); if (group && group_visitor_->save(attr)) { @@ -198,6 +200,7 @@ LibertyParser::makeComplexAttr(const char *name, } else { LibertyAttr *attr = new LibertyComplexAttr(name, values, line); + stringDelete(name); group_visitor_->visitAttr(attr); if (group_visitor_->save(attr)) { LibertyGroup *group = this->group(); @@ -210,11 +213,12 @@ LibertyParser::makeComplexAttr(const char *name, } LibertyStmt * -LibertyParser::makeVariable(char *var, +LibertyParser::makeVariable(const char *var, float value, int line) { LibertyVariable *variable = new LibertyVariable(var, value, line); + stringDelete(var); group_visitor_->visitVariable(variable); if (group_visitor_->save(variable)) return variable; @@ -227,7 +231,9 @@ LibertyParser::makeVariable(char *var, LibertyAttrValue * LibertyParser::makeStringAttrValue(char *value) { - return new LibertyStringAttrValue(value); + LibertyAttrValue *attr = new LibertyStringAttrValue(value); + stringDelete(value); + return attr; } LibertyAttrValue * @@ -290,7 +296,6 @@ LibertyGroup::addAttribute(LibertyAttr *attr) LibertyGroup::~LibertyGroup() { - stringDelete(type_); if (params_) { params_->deleteContents(); delete params_; @@ -370,11 +375,6 @@ LibertyAttr::LibertyAttr(const char *name, { } -LibertyAttr::~LibertyAttr() -{ - stringDelete(name_); -} - LibertySimpleAttr::LibertySimpleAttr(const char *name, LibertyAttrValue *value, int line) : @@ -426,11 +426,6 @@ LibertyStringAttrValue::LibertyStringAttrValue(const char *value) : { } -LibertyStringAttrValue::~LibertyStringAttrValue() -{ - stringDelete(value_); -} - float LibertyStringAttrValue::floatValue() { @@ -441,7 +436,7 @@ LibertyStringAttrValue::floatValue() const char * LibertyStringAttrValue::stringValue() { - return value_; + return value_.c_str(); } LibertyFloatAttrValue::LibertyFloatAttrValue(float value) : @@ -475,11 +470,6 @@ LibertyDefine::LibertyDefine(const char *name, { } -LibertyDefine::~LibertyDefine() -{ - stringDelete(name_); -} - //////////////////////////////////////////////////////////////// LibertyVariable::LibertyVariable(const char *var, @@ -491,11 +481,6 @@ LibertyVariable::LibertyVariable(const char *var, { } -LibertyVariable::~LibertyVariable() -{ - stringDelete(var_); -} - //////////////////////////////////////////////////////////////// LibertyScanner::LibertyScanner(std::istream *stream, diff --git a/liberty/LibertyParser.hh b/liberty/LibertyParser.hh index 4006f37a..17d31700 100644 --- a/liberty/LibertyParser.hh +++ b/liberty/LibertyParser.hh @@ -48,11 +48,11 @@ class LibertyScanner; typedef Vector LibertyStmtSeq; typedef Vector LibertyGroupSeq; typedef Vector LibertyAttrSeq; -typedef Map LibertyAttrMap; -typedef Map LibertyDefineMap; +typedef Map LibertyAttrMap; +typedef Map LibertyDefineMap; typedef Vector LibertyAttrValueSeq; -typedef Map LibertyVariableMap; -typedef MapLibertyGroupVisitorMap; +typedef Map LibertyVariableMap; +typedef MapLibertyGroupVisitorMap; typedef LibertyAttrValueSeq::Iterator LibertyAttrValueIterator; typedef Vector LibertyGroupSeq; @@ -88,7 +88,7 @@ public: int line); LibertyAttrValue *makeStringAttrValue(char *value); LibertyAttrValue *makeFloatAttrValue(float value); - LibertyStmt *makeVariable(char *var, + LibertyStmt *makeVariable(const char *var, float value, int line); @@ -103,7 +103,7 @@ private: class LibertyStmt { public: - explicit LibertyStmt(int line); + LibertyStmt(int line); virtual ~LibertyStmt() {} int line() const { return line_; } virtual bool isGroup() const { return false; } @@ -126,7 +126,7 @@ public: int line); virtual ~LibertyGroup(); virtual bool isGroup() const { return true; } - const char *type() const { return type_; } + const char *type() const { return type_.c_str(); } // First param as a string. const char *firstName(); // Second param as a string. @@ -143,7 +143,7 @@ public: protected: void parseNames(LibertyAttrValueSeq *values); - const char *type_; + string type_; LibertyAttrValueSeq *params_; LibertyAttrSeq *attrs_; LibertyAttrMap *attr_map_; @@ -154,13 +154,13 @@ protected: class LibertySubgroupIterator : public LibertyGroupSeq::Iterator { public: - explicit LibertySubgroupIterator(LibertyGroup *group); + LibertySubgroupIterator(LibertyGroup *group); }; class LibertyAttrIterator : public LibertyAttrSeq::Iterator { public: - explicit LibertyAttrIterator(LibertyGroup *group); + LibertyAttrIterator(LibertyGroup *group); }; // Abstract base class for attributes. @@ -169,8 +169,7 @@ class LibertyAttr : public LibertyStmt public: LibertyAttr(const char *name, int line); - virtual ~LibertyAttr(); - const char *name() const { return name_; } + const char *name() const { return name_.c_str(); } virtual bool isAttribute() const { return true; } virtual bool isSimple() const = 0; virtual bool isComplex() const = 0; @@ -178,7 +177,7 @@ public: virtual LibertyAttrValue *firstValue() = 0; protected: - const char *name_; + string name_; }; // Abstract base class for simple attributes. @@ -232,21 +231,22 @@ public: class LibertyStringAttrValue : public LibertyAttrValue { public: - explicit LibertyStringAttrValue(const char *value); - virtual ~LibertyStringAttrValue(); + LibertyStringAttrValue(const char *value); + virtual ~LibertyStringAttrValue() {} virtual bool isFloat() { return false; } virtual bool isString() { return true; } virtual float floatValue(); virtual const char *stringValue(); private: - const char *value_; + string value_; }; class LibertyFloatAttrValue : public LibertyAttrValue { public: - explicit LibertyFloatAttrValue(float value); + LibertyFloatAttrValue(float value); + virtual ~LibertyFloatAttrValue() {} virtual bool isString() { return false; } virtual bool isFloat() { return true; } virtual float floatValue(); @@ -266,14 +266,13 @@ public: LibertyGroupType group_type, LibertyAttrType value_type, int line); - virtual ~LibertyDefine(); virtual bool isDefine() const { return true; } - const char *name() const { return name_; } + const char *name() const { return name_.c_str(); } LibertyGroupType groupType() const { return group_type_; } LibertyAttrType valueType() const { return value_type_; } private: - const char *name_; + string name_; LibertyGroupType group_type_; LibertyAttrType value_type_; }; @@ -288,15 +287,12 @@ public: LibertyVariable(const char *var, float value, int line); - // var_ is NOT deleted by ~LibertyVariable because the group - // variable map ref's it. - virtual ~LibertyVariable(); virtual bool isVariable() const { return true; } - const char *variable() const { return var_; } + const char *variable() const { return var_.c_str(); } float value() const { return value_; } private: - const char *var_; + string var_; float value_; }; diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index cfcc1fb2..0ff9257d 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -141,25 +141,7 @@ LibertyReader::init(const char *filename, LibertyReader::~LibertyReader() { - if (var_map_) { - LibertyVariableMap::Iterator iter(var_map_); - while (iter.hasNext()) { - const char *var; - float value; - iter.next(var, value); - stringDelete(var); - } - delete var_map_; - } - - // Scaling factor attribute names are allocated, so delete them. - LibraryAttrMap::Iterator attr_iter(attr_visitor_map_); - while (attr_iter.hasNext()) { - const char *attr_name; - LibraryAttrVisitor visitor; - attr_iter.next(attr_name, visitor); - stringDelete(attr_name); - } + delete var_map_; } LibertyLibrary * @@ -183,7 +165,7 @@ void LibertyReader::defineAttrVisitor(const char *attr_name, LibraryAttrVisitor visitor) { - attr_visitor_map_[stringCopy(attr_name)] = visitor; + attr_visitor_map_[attr_name] = visitor; } void @@ -1125,7 +1107,7 @@ LibertyReader::visitDefaultIntrinsicFall(LibertyAttr *attr) void LibertyReader::visitDefaultIntrinsic(LibertyAttr *attr, - RiseFall *rf) + const RiseFall *rf) { if (library_) { float value; @@ -1150,7 +1132,7 @@ LibertyReader::visitDefaultInoutPinFallRes(LibertyAttr *attr) void LibertyReader::visitDefaultInoutPinRes(LibertyAttr *attr, - RiseFall *rf) + const RiseFall *rf) { if (library_) { float value; @@ -1175,7 +1157,7 @@ LibertyReader::visitDefaultOutputPinFallRes(LibertyAttr *attr) void LibertyReader::visitDefaultOutputPinRes(LibertyAttr *attr, - RiseFall *rf) + const RiseFall *rf) { if (library_) { float value; @@ -1267,7 +1249,7 @@ LibertyReader::visitInputThresholdPctRise(LibertyAttr *attr) void LibertyReader::visitInputThresholdPct(LibertyAttr *attr, - RiseFall *rf) + const RiseFall *rf) { if (library_) { float value; @@ -1293,7 +1275,7 @@ LibertyReader::visitOutputThresholdPctRise(LibertyAttr *attr) void LibertyReader::visitOutputThresholdPct(LibertyAttr *attr, - RiseFall *rf) + const RiseFall *rf) { if (library_) { float value; @@ -1319,7 +1301,7 @@ LibertyReader::visitSlewLowerThresholdPctRise(LibertyAttr *attr) void LibertyReader::visitSlewLowerThresholdPct(LibertyAttr *attr, - RiseFall *rf) + const RiseFall *rf) { if (library_) { float value; @@ -1345,7 +1327,7 @@ LibertyReader::visitSlewUpperThresholdPctRise(LibertyAttr *attr) void LibertyReader::visitSlewUpperThresholdPct(LibertyAttr *attr, - RiseFall *rf) + const RiseFall *rf) { if (library_) { float value; @@ -1616,7 +1598,7 @@ LibertyReader::visitScaleFactorSuffix(LibertyAttr *attr) if (scale_factors_) { ScaleFactorPvt pvt = ScaleFactorPvt::unknown; ScaleFactorType type = ScaleFactorType::unknown; - RiseFall *rf = nullptr; + const RiseFall *rf = nullptr; // Parse the attribute name. TokenParser parser(attr->name(), "_"); if (parser.hasNext()) @@ -1654,7 +1636,7 @@ LibertyReader::visitScaleFactorPrefix(LibertyAttr *attr) if (scale_factors_) { ScaleFactorPvt pvt = ScaleFactorPvt::unknown; ScaleFactorType type = ScaleFactorType::unknown; - RiseFall *rf = nullptr; + const RiseFall *rf = nullptr; // Parse the attribute name. TokenParser parser(attr->name(), "_"); if (parser.hasNext()) @@ -1692,7 +1674,7 @@ LibertyReader::visitScaleFactorHiLow(LibertyAttr *attr) if (scale_factors_) { ScaleFactorPvt pvt = ScaleFactorPvt::unknown; ScaleFactorType type = ScaleFactorType::unknown; - RiseFall *rf = nullptr; + const RiseFall *rf = nullptr; const char *pvt_name = nullptr; const char *type_name = nullptr; const char *tr_name = nullptr; @@ -2217,7 +2199,7 @@ LibertyReader::makeStatetable() for (const string &internal : statetable_->internalPorts()) { LibertyPort *port = cell_->findLibertyPort(internal.c_str()); if (port == nullptr) - port = builder_.makePort(cell_, internal.c_str()); + port = makePort(cell_, internal.c_str()); internal_ports.push_back(port); } cell_->makeStatetable(input_ports, internal_ports, statetable_->table()); @@ -2630,7 +2612,7 @@ LibertyReader::beginReceiverCapacitance2Fall(LibertyGroup *group) void LibertyReader::beginReceiverCapacitance(LibertyGroup *group, int index, - RiseFall *rf) + const RiseFall *rf) { if (timing_ || ports_) { beginTableModel(group, TableTemplateType::delay, rf, 1.0, @@ -2676,7 +2658,7 @@ LibertyReader::beginOutputCurrentFall(LibertyGroup *group) } void -LibertyReader::beginOutputCurrent(RiseFall *rf, +LibertyReader::beginOutputCurrent(const RiseFall *rf, LibertyGroup *group) { if (timing_) { @@ -2802,13 +2784,13 @@ void LibertyReader::beginNormalizedDriverWaveform(LibertyGroup *group) { beginTable(group, TableTemplateType::delay, time_scale_); - driver_waveform_name_ = nullptr; + driver_waveform_name_.clear(); } void LibertyReader::visitDriverWaveformName(LibertyAttr *attr) { - driver_waveform_name_ = stringCopy(getAttrString(attr)); + driver_waveform_name_ = getAttrString(attr); } void @@ -3183,7 +3165,7 @@ LibertyReader::beginPin(LibertyGroup *group) debugPrint(debug_, "liberty", 1, " port %s", name); LibertyPort *port = findPort(name); if (port == nullptr) - port = builder_.makePort(cell_, name); + port = makePort(cell_, name); ports_->push_back(port); } else @@ -3197,7 +3179,7 @@ LibertyReader::beginPin(LibertyGroup *group) if (param->isString()) { const char *name = param->stringValue(); debugPrint(debug_, "liberty", 1, " port %s", name); - LibertyPort *port = builder_.makePort(cell_, name); + LibertyPort *port = makePort(cell_, name); ports_->push_back(port); } else @@ -3216,6 +3198,25 @@ LibertyReader::beginPin(LibertyGroup *group) } } +LibertyPort * +LibertyReader::makePort(LibertyCell *cell, + const char *port_name) +{ + string sta_name = portLibertyToSta(port_name); + return builder_.makePort(cell, sta_name.c_str()); +} + +LibertyPort * +LibertyReader::makeBusPort(LibertyCell *cell, + const char *bus_name, + int from_index, + int to_index, + BusDcl *bus_dcl) +{ + string sta_name = portLibertyToSta(bus_name); + return builder_.makeBusPort(cell, bus_name, from_index, to_index, bus_dcl); +} + void LibertyReader::endPin(LibertyGroup *) { @@ -3328,8 +3329,8 @@ LibertyReader::visitBusType(LibertyAttr *attr) if (bus_dcl) { for (const char *name : bus_names_) { debugPrint(debug_, "liberty", 1, " bus %s", name); - LibertyPort *port = builder_.makeBusPort(cell_, name, bus_dcl->from(), - bus_dcl->to(), bus_dcl); + LibertyPort *port = makeBusPort(cell_, name, bus_dcl->from(), + bus_dcl->to(), bus_dcl); ports_->push_back(port); } } @@ -3374,7 +3375,7 @@ LibertyReader::visitMembers(LibertyAttr *attr) const char *port_name = value->stringValue(); LibertyPort *port = findPort(port_name); if (port == nullptr) - port = builder_.makePort(cell_, port_name); + port = makePort(cell_, port_name); members->push_back(port); } else @@ -3648,7 +3649,7 @@ LibertyReader::visitMinFanout(LibertyAttr *attr) void LibertyReader::visitFanout(LibertyAttr *attr, - MinMax *min_max) + const MinMax *min_max) { if (ports_) { float fanout; @@ -3675,7 +3676,8 @@ LibertyReader::visitMinTransition(LibertyAttr *attr) } void -LibertyReader::visitMinMaxTransition(LibertyAttr *attr, MinMax *min_max) +LibertyReader::visitMinMaxTransition(LibertyAttr *attr, + const MinMax *min_max) { if (cell_) { float value; @@ -3706,7 +3708,7 @@ LibertyReader::visitMinCapacitance(LibertyAttr *attr) void LibertyReader::visitMinMaxCapacitance(LibertyAttr *attr, - MinMax *min_max) + const MinMax *min_max) { if (cell_) { float value; @@ -3770,8 +3772,8 @@ LibertyReader::visitPulseClock(LibertyAttr *attr) if (cell_) { const char *pulse_clk = getAttrString(attr); if (pulse_clk) { - RiseFall *trigger = nullptr; - RiseFall *sense = nullptr; + const RiseFall *trigger = nullptr; + const RiseFall *sense = nullptr; if (stringEq(pulse_clk, "rise_triggered_high_pulse")) { trigger = RiseFall::rise(); sense = RiseFall::rise(); @@ -3980,16 +3982,16 @@ LibertyReader::beginSequential(LibertyGroup *group, LibertyPort *out_port_inv = nullptr; if (out_name) { if (has_size) - out_port = builder_.makeBusPort(cell_, out_name, size - 1, 0, nullptr); + out_port = makeBusPort(cell_, out_name, size - 1, 0, nullptr); else - out_port = builder_.makePort(cell_, out_name); + out_port = makePort(cell_, out_name); out_port->setDirection(PortDirection::internal()); } if (out_inv_name) { if (has_size) - out_port_inv = builder_.makeBusPort(cell_, out_inv_name, size - 1, 0, nullptr); + out_port_inv = makeBusPort(cell_, out_inv_name, size - 1, 0, nullptr); else - out_port_inv = builder_.makePort(cell_, out_inv_name); + out_port_inv = makePort(cell_, out_inv_name); out_port_inv->setDirection(PortDirection::internal()); } sequential_ = new SequentialGroup(is_register, is_bank, @@ -4435,7 +4437,7 @@ LibertyReader::visitIntrinsicFall(LibertyAttr *attr) void LibertyReader::visitIntrinsic(LibertyAttr *attr, - RiseFall *rf) + const RiseFall *rf) { if (timing_) { float value; @@ -4460,7 +4462,7 @@ LibertyReader::visitFallResistance(LibertyAttr *attr) void LibertyReader::visitRiseFallResistance(LibertyAttr *attr, - RiseFall *rf) + const RiseFall *rf) { if (timing_) { float value; @@ -4593,7 +4595,7 @@ LibertyReader::endRiseFallTransitionDegredation(LibertyGroup *group) void LibertyReader::beginTimingTableModel(LibertyGroup *group, - RiseFall *rf, + const RiseFall *rf, ScaleFactorType scale_factor_type) { if (timing_) @@ -4606,7 +4608,7 @@ LibertyReader::beginTimingTableModel(LibertyGroup *group, void LibertyReader::beginTableModel(LibertyGroup *group, TableTemplateType type, - RiseFall *rf, + const RiseFall *rf, float scale, ScaleFactorType scale_factor_type) { @@ -4807,7 +4809,7 @@ LibertyReader::beginLut(LibertyGroup *group) while (parser.hasNext()) { char *name = parser.next(); if (name[0] != '\0') { - LibertyPort *port = builder_.makePort(cell_, name); + LibertyPort *port = makePort(cell_, name); port->setDirection(PortDirection::internal()); } } @@ -5186,7 +5188,7 @@ LibertyReader::parseFunc(const char *func, return parseFuncExpr(func, cell_, error_msg.c_str(), report_); } -EarlyLateAll * +const EarlyLateAll * LibertyReader::getAttrEarlyLate(LibertyAttr *attr) { const char *value = getAttrString(attr); @@ -5210,7 +5212,7 @@ LibertyReader::visitVariable(LibertyVariable *var) if (var_map_ == nullptr) var_map_ = new LibertyVariableMap; const char *var_name = var->variable(); - const char *key; + string key; float value; bool exists; var_map_->findKey(var_name, key, value, exists); @@ -5219,7 +5221,7 @@ LibertyReader::visitVariable(LibertyVariable *var) (*var_map_)[key] = var->value(); } else - (*var_map_)[stringCopy(var_name)] = var->value(); + (*var_map_)[var_name] = var->value(); } void @@ -5918,7 +5920,7 @@ TimingGroup::setRelatedOutputPortName(const char *name) } void -TimingGroup::setIntrinsic(RiseFall *rf, +TimingGroup::setIntrinsic(const RiseFall *rf, float value) { int rf_index = rf->index(); @@ -5927,7 +5929,7 @@ TimingGroup::setIntrinsic(RiseFall *rf, } void -TimingGroup::intrinsic(RiseFall *rf, +TimingGroup::intrinsic(const RiseFall *rf, // Return values. float &value, bool &exists) @@ -5938,7 +5940,7 @@ TimingGroup::intrinsic(RiseFall *rf, } void -TimingGroup::setResistance(RiseFall *rf, +TimingGroup::setResistance(const RiseFall *rf, float value) { int rf_index = rf->index(); @@ -5947,7 +5949,7 @@ TimingGroup::setResistance(RiseFall *rf, } void -TimingGroup::resistance(RiseFall *rf, +TimingGroup::resistance(const RiseFall *rf, // Return values. float &value, bool &exists) @@ -5958,63 +5960,63 @@ TimingGroup::resistance(RiseFall *rf, } TableModel * -TimingGroup::cell(RiseFall *rf) +TimingGroup::cell(const RiseFall *rf) { return cell_[rf->index()]; } void -TimingGroup::setCell(RiseFall *rf, +TimingGroup::setCell(const RiseFall *rf, TableModel *model) { cell_[rf->index()] = model; } TableModel * -TimingGroup::constraint(RiseFall *rf) +TimingGroup::constraint(const RiseFall *rf) { return constraint_[rf->index()]; } void -TimingGroup::setConstraint(RiseFall *rf, +TimingGroup::setConstraint(const RiseFall *rf, TableModel *model) { constraint_[rf->index()] = model; } TableModel * -TimingGroup::transition(RiseFall *rf) +TimingGroup::transition(const RiseFall *rf) { return transition_[rf->index()]; } void -TimingGroup::setTransition(RiseFall *rf, +TimingGroup::setTransition(const RiseFall *rf, TableModel *model) { transition_[rf->index()] = model; } void -TimingGroup::setDelaySigma(RiseFall *rf, - EarlyLate *early_late, +TimingGroup::setDelaySigma(const RiseFall *rf, + const EarlyLate *early_late, TableModel *model) { delay_sigma_[rf->index()][early_late->index()] = model; } void -TimingGroup::setSlewSigma(RiseFall *rf, - EarlyLate *early_late, +TimingGroup::setSlewSigma(const RiseFall *rf, + const EarlyLate *early_late, TableModel *model) { slew_sigma_[rf->index()][early_late->index()] = model; } void -TimingGroup::setConstraintSigma(RiseFall *rf, - EarlyLate *early_late, +TimingGroup::setConstraintSigma(const RiseFall *rf, + const EarlyLate *early_late, TableModel *model) { constraint_sigma_[rf->index()][early_late->index()] = model; @@ -6027,13 +6029,13 @@ TimingGroup::setReceiverModel(ReceiverModelPtr receiver_model) } OutputWaveforms * -TimingGroup::outputWaveforms(RiseFall *rf) +TimingGroup::outputWaveforms(const RiseFall *rf) { return output_waveforms_[rf->index()]; } void -TimingGroup::setOutputWaveforms(RiseFall *rf, +TimingGroup::setOutputWaveforms(const RiseFall *rf, OutputWaveforms *output_waveforms) { output_waveforms_[rf->index()] = output_waveforms; diff --git a/liberty/LibertyReaderPvt.hh b/liberty/LibertyReaderPvt.hh index 64837d66..b546758f 100644 --- a/liberty/LibertyReaderPvt.hh +++ b/liberty/LibertyReaderPvt.hh @@ -64,8 +64,8 @@ using std::vector; typedef void (LibertyReader::*LibraryAttrVisitor)(LibertyAttr *attr); typedef void (LibertyReader::*LibraryGroupVisitor)(LibertyGroup *group); -typedef Map LibraryAttrMap; -typedef Map LibraryGroupMap; +typedef Map LibraryAttrMap; +typedef Map LibraryGroupMap; typedef Vector PortGroupSeq; typedef Vector SequentialGroupSeq; typedef Vector LibertyFuncSeq; @@ -122,15 +122,15 @@ public: virtual void visitDefaultIntrinsicRise(LibertyAttr *attr); virtual void visitDefaultIntrinsicFall(LibertyAttr *attr); virtual void visitDefaultIntrinsic(LibertyAttr *attr, - RiseFall *rf); + const RiseFall *rf); virtual void visitDefaultInoutPinRiseRes(LibertyAttr *attr); virtual void visitDefaultInoutPinFallRes(LibertyAttr *attr); virtual void visitDefaultInoutPinRes(LibertyAttr *attr, - RiseFall *rf); + const RiseFall *rf); virtual void visitDefaultOutputPinRiseRes(LibertyAttr *attr); virtual void visitDefaultOutputPinFallRes(LibertyAttr *attr); virtual void visitDefaultOutputPinRes(LibertyAttr *attr, - RiseFall *rf); + const RiseFall *rf); virtual void visitDefaultFanoutLoad(LibertyAttr *attr); virtual void visitDefaultWireLoad(LibertyAttr *attr); virtual void visitDefaultWireLoadMode(LibertyAttr *attr); @@ -139,19 +139,19 @@ public: virtual void visitInputThresholdPctFall(LibertyAttr *attr); virtual void visitInputThresholdPctRise(LibertyAttr *attr); virtual void visitInputThresholdPct(LibertyAttr *attr, - RiseFall *rf); + const RiseFall *rf); virtual void visitOutputThresholdPctFall(LibertyAttr *attr); virtual void visitOutputThresholdPctRise(LibertyAttr *attr); virtual void visitOutputThresholdPct(LibertyAttr *attr, - RiseFall *rf); + const RiseFall *rf); virtual void visitSlewLowerThresholdPctFall(LibertyAttr *attr); virtual void visitSlewLowerThresholdPctRise(LibertyAttr *attr); virtual void visitSlewLowerThresholdPct(LibertyAttr *attr, - RiseFall *rf); + const RiseFall *rf); virtual void visitSlewUpperThresholdPctFall(LibertyAttr *attr); virtual void visitSlewUpperThresholdPctRise(LibertyAttr *attr); virtual void visitSlewUpperThresholdPct(LibertyAttr *attr, - RiseFall *rf); + const RiseFall *rf); virtual void visitSlewDerateFromLibrary(LibertyAttr *attr); virtual void beginTechnology(LibertyGroup *group); @@ -247,15 +247,15 @@ public: virtual void visitMaxFanout(LibertyAttr *attr); virtual void visitMinFanout(LibertyAttr *attr); virtual void visitFanout(LibertyAttr *attr, - MinMax *min_max); + const MinMax *min_max); virtual void visitMaxTransition(LibertyAttr *attr); virtual void visitMinTransition(LibertyAttr *attr); virtual void visitMinMaxTransition(LibertyAttr *attr, - MinMax *min_max); + const MinMax *min_max); virtual void visitMaxCapacitance(LibertyAttr *attr); virtual void visitMinCapacitance(LibertyAttr *attr); virtual void visitMinMaxCapacitance(LibertyAttr *attr, - MinMax *min_max); + const MinMax *min_max); virtual void visitMinPeriod(LibertyAttr *attr); virtual void visitMinPulseWidthLow(LibertyAttr *attr); virtual void visitMinPulseWidthHigh(LibertyAttr *attr); @@ -267,7 +267,7 @@ public: virtual void visitClockGateOutPin(LibertyAttr *attr); void visitIsPllFeedbackPin(LibertyAttr *attr); virtual void visitSignalType(LibertyAttr *attr); - EarlyLateAll *getAttrEarlyLate(LibertyAttr *attr); + const EarlyLateAll *getAttrEarlyLate(LibertyAttr *attr); virtual void visitClock(LibertyAttr *attr); virtual void visitIsolationCellDataPin(LibertyAttr *attr); virtual void visitIsolationCellEnablePin(LibertyAttr *attr); @@ -350,11 +350,11 @@ public: virtual void visitIntrinsicRise(LibertyAttr *attr); virtual void visitIntrinsicFall(LibertyAttr *attr); virtual void visitIntrinsic(LibertyAttr *attr, - RiseFall *rf); + const RiseFall *rf); virtual void visitRiseResistance(LibertyAttr *attr); virtual void visitFallResistance(LibertyAttr *attr); virtual void visitRiseFallResistance(LibertyAttr *attr, - RiseFall *rf); + const RiseFall *rf); virtual void visitValue(LibertyAttr *attr); virtual void visitValues(LibertyAttr *attr); virtual void beginCellRise(LibertyGroup *group); @@ -373,12 +373,12 @@ public: virtual void beginTableModel(LibertyGroup *group, TableTemplateType type, - RiseFall *rf, + const RiseFall *rf, float scale, ScaleFactorType scale_factor_type); virtual void endTableModel(); virtual void beginTimingTableModel(LibertyGroup *group, - RiseFall *rf, + const RiseFall *rf, ScaleFactorType scale_factor_type); virtual void beginTable(LibertyGroup *group, TableTemplateType type, @@ -469,14 +469,14 @@ public: virtual void beginReceiverCapacitance2Fall(LibertyGroup *group); void beginReceiverCapacitance(LibertyGroup *group, int index, - RiseFall *rf); + const RiseFall *rf); void endReceiverCapacitance(LibertyGroup *group, int index, - RiseFall *rf); + const RiseFall *rf); // ccs void beginOutputCurrentRise(LibertyGroup *group); void beginOutputCurrentFall(LibertyGroup *group); - void beginOutputCurrent(RiseFall *rf, + void beginOutputCurrent(const RiseFall *rf, LibertyGroup *group); void endOutputCurrentRiseFall(LibertyGroup *group); void beginVector(LibertyGroup *group); @@ -500,6 +500,14 @@ public: const char *port_name); protected: + LibertyPort *makePort(LibertyCell *cell, + const char *port_name); + LibertyPort *makeBusPort(LibertyCell *cell, + const char *bus_name, + int from_index, + int to_index, + BusDcl *bus_dcl); + TimingModel *makeScalarCheckModel(float value, ScaleFactorType scale_factor_type, const RiseFall *rf); @@ -639,12 +647,12 @@ protected: InternalPowerGroup *internal_power_; LeakagePowerGroup *leakage_power_; LeakagePowerGroupSeq leakage_powers_; - RiseFall *rf_; + const RiseFall *rf_; int index_; OcvDerate *ocv_derate_; - RiseFallBoth *rf_type_; - EarlyLateAll *derate_type_; - EarlyLateAll *sigma_type_; + const RiseFallBoth *rf_type_; + const EarlyLateAll *derate_type_; + const EarlyLateAll *sigma_type_; PathType path_type_; LibertyPgPort *pg_port_; ScaleFactorType scale_factor_type_; @@ -668,7 +676,7 @@ protected: OutputWaveforms *output_waveforms_; float reference_time_; bool reference_time_exists_; - const char *driver_waveform_name_; + string driver_waveform_name_; TestCell *test_cell_; // Saved state while parsing test_cell. @@ -827,41 +835,41 @@ public: TimingArcAttrsPtr attrs() { return attrs_; } const char *relatedOutputPortName()const {return related_output_port_name_;} void setRelatedOutputPortName(const char *name); - void intrinsic(RiseFall *rf, + void intrinsic(const RiseFall *rf, // Return values. float &value, bool &exists); - void setIntrinsic(RiseFall *rf, + void setIntrinsic(const RiseFall *rf, float value); - void resistance(RiseFall *rf, + void resistance(const RiseFall *rf, // Return values. float &value, bool &exists); - void setResistance(RiseFall *rf, + void setResistance(const RiseFall *rf, float value); - TableModel *cell(RiseFall *rf); - void setCell(RiseFall *rf, + TableModel *cell(const RiseFall *rf); + void setCell(const RiseFall *rf, TableModel *model); - TableModel *constraint(RiseFall *rf); - void setConstraint(RiseFall *rf, + TableModel *constraint(const RiseFall *rf); + void setConstraint(const RiseFall *rf, TableModel *model); - TableModel *transition(RiseFall *rf); - void setTransition(RiseFall *rf, + TableModel *transition(const RiseFall *rf); + void setTransition(const RiseFall *rf, TableModel *model); void makeTimingModels(LibertyCell *cell, LibertyReader *visitor); - void setDelaySigma(RiseFall *rf, - EarlyLate *early_late, + void setDelaySigma(const RiseFall *rf, + const EarlyLate *early_late, TableModel *model); - void setSlewSigma(RiseFall *rf, - EarlyLate *early_late, + void setSlewSigma(const RiseFall *rf, + const EarlyLate *early_late, TableModel *model); - void setConstraintSigma(RiseFall *rf, - EarlyLate *early_late, + void setConstraintSigma(const RiseFall *rf, + const EarlyLate *early_late, TableModel *model); void setReceiverModel(ReceiverModelPtr receiver_model); - OutputWaveforms *outputWaveforms(RiseFall *rf); - void setOutputWaveforms(RiseFall *rf, + OutputWaveforms *outputWaveforms(const RiseFall *rf); + void setOutputWaveforms(const RiseFall *rf, OutputWaveforms *output_current); protected: diff --git a/liberty/LibertyWriter.cc b/liberty/LibertyWriter.cc index 684c314c..4d7cb6c2 100644 --- a/liberty/LibertyWriter.cc +++ b/liberty/LibertyWriter.cc @@ -358,16 +358,18 @@ LibertyWriter::writePortAttrs(const LibertyPort *port) // cannot ref internal ports until sequentials are written && !(func->port() && func->port()->direction()->isInternal())) - fprintf(stream_, " function : \"%s\";\n", func->asString()); + fprintf(stream_, " function : \"%s\";\n", func->to_string().c_str()); auto tristate_enable = port->tristateEnable(); if (tristate_enable) { if (tristate_enable->op() == FuncExpr::op_not) { FuncExpr *three_state = tristate_enable->left(); - fprintf(stream_, " three_state : \"%s\";\n", three_state->asString()); + fprintf(stream_, " three_state : \"%s\";\n", + three_state->to_string().c_str()); } else { FuncExpr three_state(FuncExpr::op_not, tristate_enable, nullptr, nullptr); - fprintf(stream_, " three_state : \"%s\";\n", three_state.asString()); + fprintf(stream_, " three_state : \"%s\";\n", + three_state.to_string().c_str()); } } if (port->isClock()) @@ -417,12 +419,12 @@ LibertyWriter::writeTimingArcSet(const TimingArcSet *arc_set) if (sense != TimingSense::unknown && sense != TimingSense::non_unate) fprintf(stream_, " timing_sense : %s;\n", - timingSenseString(sense)); + to_string(sense)); const char *timing_type = timingTypeString(arc_set); if (timing_type) fprintf(stream_, " timing_type : %s;\n", timing_type); - for (RiseFall *rf : RiseFall::range()) { + for (const RiseFall *rf : RiseFall::range()) { TimingArc *arc = arc_set->arcTo(rf); if (arc) writeTimingModels(arc, rf); @@ -634,7 +636,7 @@ LibertyWriter::timingTypeString(const TimingArcSet *arc_set) library_->name(), arc_set->to()->libertyCell()->name(), arc_set->to()->name(), - role->asString()); + role->to_string().c_str()); return nullptr; } } diff --git a/liberty/TableModel.cc b/liberty/TableModel.cc index 09dc8222..7d847a79 100644 --- a/liberty/TableModel.cc +++ b/liberty/TableModel.cc @@ -375,7 +375,7 @@ ReceiverModel::~ReceiverModel() void ReceiverModel::setCapacitanceModel(TableModel *table_model, size_t segment, - RiseFall *rf) + const RiseFall *rf) { if ((segment + 1) * RiseFall::index_count > capacitance_models_.size()) capacitance_models_.resize((segment + 1) * RiseFall::index_count); @@ -2062,18 +2062,13 @@ OutputWaveforms::finalResistance() //////////////////////////////////////////////////////////////// -DriverWaveform::DriverWaveform(const char *name, +DriverWaveform::DriverWaveform(const string &name, TablePtr waveforms) : name_(name), waveforms_(waveforms) { } -DriverWaveform::~DriverWaveform() -{ - stringDelete(name_); -} - Table1 DriverWaveform::waveform(float slew) { diff --git a/liberty/TimingArc.cc b/liberty/TimingArc.cc index e1b1497d..1e7fd408 100644 --- a/liberty/TimingArc.cc +++ b/liberty/TimingArc.cc @@ -188,7 +188,7 @@ TimingArcSet::TimingArcSet(LibertyCell *cell, LibertyPort *from, LibertyPort *to, LibertyPort *related_out, - TimingRole *role, + const TimingRole *role, TimingArcAttrsPtr attrs) : from_(from), to_(to), @@ -204,7 +204,7 @@ TimingArcSet::TimingArcSet(LibertyCell *cell, { } -TimingArcSet::TimingArcSet(TimingRole *role, +TimingArcSet::TimingArcSet(const TimingRole *role, TimingArcAttrsPtr attrs) : from_(nullptr), to_(nullptr), @@ -292,7 +292,7 @@ TimingArcSet::findTimingArc(unsigned arc_index) } void -TimingArcSet::setRole(TimingRole *role) +TimingArcSet::setRole(const TimingRole *role) { role_ = role; } @@ -422,8 +422,8 @@ timingArcSetLess(const TimingArcSet *set1, LibertyPort *to1 = set1->to(); LibertyPort *to2 = set2->to(); if (LibertyPort::equiv(to1, to2)) { - TimingRole *role1 = set1->role(); - TimingRole *role2 = set2->role(); + const TimingRole *role1 = set1->role(); + const TimingRole *role2 = set2->role(); if (role1 == role2) { const FuncExpr *cond1 = set1->cond(); const FuncExpr *cond2 = set2->cond(); @@ -536,8 +536,8 @@ TimingArcSet::destroy() //////////////////////////////////////////////////////////////// TimingArc::TimingArc(TimingArcSet *set, - Transition *from_rf, - Transition *to_rf, + const Transition *from_rf, + const Transition *to_rf, TimingModel *model) : set_(set), from_rf_(from_rf), @@ -664,7 +664,7 @@ static EnumNameMap timing_sense_name_map = }; const char * -timingSenseString(TimingSense sense) +to_string(TimingSense sense) { return timing_sense_name_map.find(sense); } diff --git a/liberty/TimingRole.cc b/liberty/TimingRole.cc index 6d699fdb..819ba929 100644 --- a/liberty/TimingRole.cc +++ b/liberty/TimingRole.cc @@ -26,178 +26,75 @@ namespace sta { -TimingRole *TimingRole::wire_; -TimingRole *TimingRole::combinational_; -TimingRole *TimingRole::tristate_enable_; -TimingRole *TimingRole::tristate_disable_; -TimingRole *TimingRole::reg_clk_q_; -TimingRole *TimingRole::reg_set_clr_; -TimingRole *TimingRole::latch_en_q_; -TimingRole *TimingRole::latch_d_q_; -TimingRole *TimingRole::sdf_iopath_; -TimingRole *TimingRole::setup_; -TimingRole *TimingRole::hold_; -TimingRole *TimingRole::recovery_; -TimingRole *TimingRole::removal_; -TimingRole *TimingRole::width_; -TimingRole *TimingRole::period_; -TimingRole *TimingRole::skew_; -TimingRole *TimingRole::nochange_; -TimingRole *TimingRole::output_setup_; -TimingRole *TimingRole::output_hold_; -TimingRole *TimingRole::gated_clk_setup_; -TimingRole *TimingRole::gated_clk_hold_; -TimingRole *TimingRole::latch_setup_; -TimingRole *TimingRole::latch_hold_; -TimingRole *TimingRole::data_check_setup_; -TimingRole *TimingRole::data_check_hold_; -TimingRole *TimingRole::non_seq_setup_; -TimingRole *TimingRole::non_seq_hold_; -TimingRole *TimingRole::clock_tree_path_min_; -TimingRole *TimingRole::clock_tree_path_max_; - TimingRoleMap TimingRole::timing_roles_; - -void -TimingRole::init() -{ - wire_ = new TimingRole("wire", false, false, false, nullptr, nullptr, 0); - combinational_ = new TimingRole("combinational", true, false, false, - nullptr, nullptr, 1); - tristate_enable_ = new TimingRole("tristate enable", - true, false, false, - nullptr, nullptr, 2); - tristate_disable_ = new TimingRole("tristate disable", - true, false, false, - nullptr, nullptr, 3); - reg_clk_q_ = new TimingRole("Reg Clk to Q", true, false, false, - nullptr, nullptr, 4); - reg_set_clr_ = new TimingRole("Reg Set/Clr", true, false, false, - nullptr, nullptr, 5); - latch_en_q_ = new TimingRole("Latch En to Q", true, false, false, - nullptr, TimingRole::regClkToQ(), 6); - latch_d_q_ = new TimingRole("Latch D to Q", true, false, false, - nullptr, nullptr, 7); - - sdf_iopath_ = new TimingRole("sdf IOPATH", true, false, false, - nullptr, nullptr, 8); - - setup_ = new TimingRole("setup", false, true, false, - MinMax::max(), nullptr, 9); - hold_ = new TimingRole("hold", false, true, false, - MinMax::min(), nullptr, 10); - recovery_ = new TimingRole("recovery", false, true, false, - MinMax::max(), TimingRole::setup(), 11); - removal_ = new TimingRole("removal", false, true, false, - MinMax::min(), TimingRole::hold(), 12); - width_ = new TimingRole("width", false, true, false, - nullptr, nullptr, 13); - period_ = new TimingRole("period", false, true, false, - nullptr, nullptr, 14); - skew_ = new TimingRole("skew", false, true, false, - nullptr, nullptr, 15); - nochange_ = new TimingRole("nochange", true, false, false, - nullptr, nullptr, 16); - - output_setup_ = new TimingRole("output setup", false, true, false, - MinMax::max(), TimingRole::setup(), 17); - output_hold_ = new TimingRole("output hold", false, true, false, - MinMax::min(), TimingRole::hold(), 18); - gated_clk_setup_ = new TimingRole("clock gating setup", - false, true, false, - MinMax::max(), TimingRole::setup(),19); - gated_clk_hold_ = new TimingRole("clock gating hold", false, true, false, - MinMax::min(), TimingRole::hold(),20); - latch_setup_ = new TimingRole("latch setup", false, true, false, - MinMax::max(), TimingRole::setup(),21); - latch_hold_ = new TimingRole("latch hold", false, true, false, - MinMax::min(), TimingRole::hold(),22); - data_check_setup_ = new TimingRole("data check setup", - false, true, false, - MinMax::max(),TimingRole::setup(),23); - data_check_hold_ = new TimingRole("data check hold", false, true, false, - MinMax::min(), TimingRole::hold(), 24); - non_seq_setup_ = new TimingRole("non-sequential setup", false, true, true, - MinMax::max(), TimingRole::setup(), 25); - non_seq_hold_ = new TimingRole("non-sequential hold", false, true, true, - MinMax::min(), TimingRole::hold(), 26); - clock_tree_path_min_ = new TimingRole("min clock tree path", false, false, false, - MinMax::min(), nullptr, 27); - clock_tree_path_max_ = new TimingRole("max clock tree path", false, false, false, - MinMax::max(), nullptr, 28); -} - -void -TimingRole::destroy() -{ - delete wire_; - wire_ = nullptr; - delete combinational_; - combinational_ = nullptr; - delete tristate_enable_; - tristate_enable_ = nullptr; - delete tristate_disable_; - tristate_disable_ = nullptr; - delete reg_clk_q_; - reg_clk_q_ = nullptr; - delete reg_set_clr_; - reg_set_clr_ = nullptr; - delete latch_en_q_; - latch_en_q_ = nullptr; - delete latch_d_q_; - latch_d_q_ = nullptr; - delete sdf_iopath_; - sdf_iopath_ = nullptr; - delete setup_; - setup_ = nullptr; - delete hold_; - hold_ = nullptr; - delete recovery_; - recovery_ = nullptr; - delete removal_; - removal_ = nullptr; - delete width_; - width_ = nullptr; - delete period_; - period_ = nullptr; - delete skew_; - skew_ = nullptr; - delete nochange_; - nochange_ = nullptr; - delete output_setup_; - output_setup_ = nullptr; - delete output_hold_; - output_hold_ = nullptr; - delete gated_clk_setup_; - gated_clk_setup_ = nullptr; - delete gated_clk_hold_; - gated_clk_hold_ = nullptr; - delete latch_setup_; - latch_setup_ = nullptr; - delete latch_hold_; - latch_hold_ = nullptr; - delete data_check_setup_; - data_check_setup_ = nullptr; - delete data_check_hold_; - data_check_hold_ = nullptr; - delete non_seq_setup_; - non_seq_setup_ = nullptr; - delete non_seq_hold_; - non_seq_hold_ = nullptr; - delete clock_tree_path_min_; - clock_tree_path_min_ = nullptr; - delete clock_tree_path_max_; - clock_tree_path_max_ = nullptr; - - timing_roles_.clear(); -} +const TimingRole TimingRole::wire_("wire", false, false, false, nullptr, nullptr, 0); +const TimingRole TimingRole::combinational_("combinational", true, false, false, + nullptr, nullptr, 1); +const TimingRole TimingRole::tristate_enable_("tristate enable", + true, false, false, + nullptr, nullptr, 2); +const TimingRole TimingRole::tristate_disable_("tristate disable", + true, false, false, + nullptr, nullptr, 3); +const TimingRole TimingRole::reg_clk_q_("Reg Clk to Q", true, false, false, + nullptr, nullptr, 4); +const TimingRole TimingRole::reg_set_clr_("Reg Set/Clr", true, false, false, + nullptr, nullptr, 5); +const TimingRole TimingRole::latch_en_q_("Latch En to Q", true, false, false, + nullptr, TimingRole::regClkToQ(), 6); +const TimingRole TimingRole::latch_d_q_("Latch D to Q", true, false, false, + nullptr, nullptr, 7); +const TimingRole TimingRole::sdf_iopath_("sdf IOPATH", true, false, false, + nullptr, nullptr, 8); +const TimingRole TimingRole::setup_("setup", false, true, false, + MinMax::max(), nullptr, 9); +const TimingRole TimingRole::hold_("hold", false, true, false, + MinMax::min(), nullptr, 10); +const TimingRole TimingRole::recovery_("recovery", false, true, false, + MinMax::max(), TimingRole::setup(), 11); +const TimingRole TimingRole::removal_("removal", false, true, false, + MinMax::min(), TimingRole::hold(), 12); +const TimingRole TimingRole::width_("width", false, true, false, + nullptr, nullptr, 13); +const TimingRole TimingRole::period_("period", false, true, false, + nullptr, nullptr, 14); +const TimingRole TimingRole::skew_("skew", false, true, false, + nullptr, nullptr, 15); +const TimingRole TimingRole::nochange_("nochange", true, false, false, + nullptr, nullptr, 16); +const TimingRole TimingRole::output_setup_("output setup", false, true, false, + MinMax::max(), TimingRole::setup(), 17); +const TimingRole TimingRole::output_hold_("output hold", false, true, false, + MinMax::min(), TimingRole::hold(), 18); +const TimingRole TimingRole::gated_clk_setup_("clock gating setup", + false, true, false, + MinMax::max(), TimingRole::setup(),19); +const TimingRole TimingRole::gated_clk_hold_("clock gating hold", false, true, false, + MinMax::min(), TimingRole::hold(),20); +const TimingRole TimingRole::latch_setup_("latch setup", false, true, false, + MinMax::max(), TimingRole::setup(),21); +const TimingRole TimingRole::latch_hold_("latch hold", false, true, false, + MinMax::min(), TimingRole::hold(),22); +const TimingRole TimingRole::data_check_setup_("data check setup", + false, true, false, + MinMax::max(),TimingRole::setup(),23); +const TimingRole TimingRole::data_check_hold_("data check hold", false, true, false, + MinMax::min(), TimingRole::hold(), 24); +const TimingRole TimingRole::non_seq_setup_("non-sequential setup", false, true, true, + MinMax::max(), TimingRole::setup(), 25); +const TimingRole TimingRole::non_seq_hold_("non-sequential hold", false, true, true, + MinMax::min(), TimingRole::hold(), 26); +const TimingRole TimingRole::clock_tree_path_min_("min clock tree path", false, false, + false, MinMax::min(), nullptr, 27); +const TimingRole TimingRole::clock_tree_path_max_("max clock tree path", false, false, + false, MinMax::max(), nullptr, 28); TimingRole::TimingRole(const char *name, bool is_sdf_iopath, bool is_timing_check, bool is_non_seq_check, - MinMax *path_min_max, - TimingRole *generic_role, + const MinMax *path_min_max, + const TimingRole *generic_role, int index) : name_(name), is_timing_check_(is_timing_check), @@ -210,7 +107,7 @@ TimingRole::TimingRole(const char *name, timing_roles_[name] = this; } -TimingRole * +const TimingRole * TimingRole::find(const char *name) { return timing_roles_[name]; @@ -220,7 +117,7 @@ const TimingRole * TimingRole::sdfRole() const { if (is_sdf_iopath_) - return sdf_iopath_; + return &sdf_iopath_; else return this; } @@ -243,35 +140,35 @@ TimingRole::tgtClkEarlyLate() const bool TimingRole::isWire() const { - return this == wire_; + return this == &wire_; } bool TimingRole::isAsyncTimingCheck() const { - return this == recovery_ - || this == removal_; + return this == &recovery_ + || this == &removal_; } bool TimingRole::isDataCheck() const { - return this == data_check_setup_ - || this == data_check_hold_; + return this == &data_check_setup_ + || this == &data_check_hold_; } bool TimingRole::isLatchDtoQ() const { - return this == latch_d_q_; + return this == &latch_d_q_; } bool TimingRole::isTimingCheckBetween() const { return is_timing_check_ - && this != width_ - && this != period_; + && this != &width_ + && this != &period_; } bool diff --git a/network/ConcreteLibrary.cc b/network/ConcreteLibrary.cc index 7c6ebb6a..fb52df22 100644 --- a/network/ConcreteLibrary.cc +++ b/network/ConcreteLibrary.cc @@ -45,9 +45,9 @@ static constexpr char escape_ = '\\'; ConcreteLibrary::ConcreteLibrary(const char *name, const char *filename, bool is_liberty) : - name_(stringCopy(name)), + name_(name), id_(ConcreteNetwork::nextObjectId()), - filename_(stringCopy(filename)), + filename_(filename ? filename : ""), is_liberty_(is_liberty), bus_brkt_left_('['), bus_brkt_right_(']') @@ -56,8 +56,6 @@ ConcreteLibrary::ConcreteLibrary(const char *name, ConcreteLibrary::~ConcreteLibrary() { - stringDelete(name_); - stringDelete(filename_); cell_map_.deleteContents(); } @@ -131,9 +129,9 @@ ConcreteCell::ConcreteCell(const char *name, const char *filename, bool is_leaf, ConcreteLibrary *library) : - name_(stringCopy(name)), + name_(name), id_(ConcreteNetwork::nextObjectId()), - filename_(stringCopy(filename)), + filename_(filename ? filename : ""), library_(library), liberty_cell_(nullptr), ext_cell_(nullptr), @@ -144,19 +142,14 @@ ConcreteCell::ConcreteCell(const char *name, ConcreteCell::~ConcreteCell() { - stringDelete(name_); - if (filename_) - stringDelete(filename_); ports_.deleteContents(); } void ConcreteCell::setName(const char *name) { - const char *name_cpy = stringCopy(name); - library_->renameCell(this, name_cpy); - stringDelete(name_); - name_ = name_cpy; + library_->renameCell(this, name); + name_ = name; } void @@ -422,7 +415,7 @@ ConcretePort::ConcretePort(const char *name, bool is_bundle, ConcretePortSeq *member_ports, ConcreteCell *cell) : - name_(stringCopy(name)), + name_(name), id_(ConcreteNetwork::nextObjectId()), cell_(cell), direction_(PortDirection::unknown()), @@ -444,7 +437,6 @@ ConcretePort::~ConcretePort() if (is_bus_) member_ports_->deleteContents(); delete member_ports_; - stringDelete(name_); } Cell * @@ -471,14 +463,14 @@ ConcretePort::busName() const if (is_bus_) { ConcreteLibrary *lib = cell_->library(); return stringPrintTmp("%s%c%d:%d%c", - name_, + name(), lib->busBrktLeft(), from_index_, to_index_, lib->busBrktRight()); } else - return name_; + return name(); } ConcretePort * diff --git a/parasitics/ReduceParasitics.cc b/parasitics/ReduceParasitics.cc index d1ac79fb..7f2f4ef1 100644 --- a/parasitics/ReduceParasitics.cc +++ b/parasitics/ReduceParasitics.cc @@ -312,8 +312,8 @@ reduceToPiElmore(const Parasitic *parasitic_network, if (drvr_node) { debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s %s %s", sta->network()->pathName(drvr_pin), - rf->asString(), - min_max->asString()); + rf->to_string().c_str(), + min_max->to_string().c_str()); ReduceToPiElmore reducer(sta); return reducer.makePiElmore(parasitic_network, drvr_pin, drvr_node, coupling_cap_factor, rf, corner, diff --git a/power/Power.cc b/power/Power.cc index cd564c3f..a0981adb 100644 --- a/power/Power.cc +++ b/power/Power.cc @@ -50,7 +50,7 @@ #include "DcalcAnalysisPt.hh" #include "GraphDelayCalc.hh" #include "Corner.hh" -#include "PathVertex.hh" +#include "Path.hh" #include "search/Levelize.hh" #include "search/Sim.hh" #include "Search.hh" @@ -364,7 +364,7 @@ ActivitySrchPred::ActivitySrchPred(const StaState *sta) : bool ActivitySrchPred::searchThru(Edge *edge) { - TimingRole *role = edge->role(); + const TimingRole *role = edge->role(); return SearchPredNonLatch2::searchThru(edge) && role != TimingRole::regClkToQ(); } @@ -421,7 +421,7 @@ PropActivityVisitor::visit(Vertex *vertex) Pin *pin = vertex->pin(); Instance *inst = network_->instance(pin); debugPrint(debug_, "power_activity", 3, "visit %s", - vertex->name(network_)); + vertex->to_string(this).c_str()); bool changed = false; if (power_->hasUserActivity(pin)) { PwrActivity &activity = power_->userActivity(pin); @@ -709,7 +709,7 @@ Power::seedActivities(BfsFwdIterator &bfs) if (!sdc_->isLeafPinClock(pin) && !network_->direction(pin)->isInternal()) { debugPrint(debug_, "power_activity", 3, "seed %s", - vertex->name(network_)); + vertex->to_string(this).c_str()); if (hasUserActivity(pin)) setActivity(pin, userActivity(pin)); else @@ -743,7 +743,7 @@ Power::seedRegOutputActivities(const Instance *inst, && (func->port() == seq->output() || func->port() == seq->outputInv())) { debugPrint(debug_, "power_reg", 1, "enqueue reg output %s", - vertex->name(network_)); + vertex->to_string(this).c_str()); bfs.enqueue(vertex); } } @@ -870,7 +870,7 @@ Power::findInputInternalPower(const Pin *pin, const char *related_pg_pin = pwr->relatedPgPin(); float energy = 0.0; int rf_count = 0; - for (RiseFall *rf : RiseFall::range()) { + for (const RiseFall *rf : RiseFall::range()) { float slew = getSlew(vertex, rf, corner); if (!delayInf(slew)) { float table_energy = pwr->power(rf, pvt, slew, load_cap); @@ -900,7 +900,7 @@ Power::findInputInternalPower(const Pin *pin, float port_internal = energy * duty * activity.density(); debugPrint(debug_, "power", 2, " %3s %6s %.2f %.2f %9.2e %9.2e %s", port->name(), - when ? when->asString() : "", + when ? when->to_string().c_str() : "", activity.density() * 1e-9, duty, energy, @@ -1031,9 +1031,9 @@ Power::findOutputInternalPower(const LibertyPort *to_port, } float energy = 0.0; int rf_count = 0; - for (RiseFall *to_rf : RiseFall::range()) { + for (const RiseFall *to_rf : RiseFall::range()) { // Use unateness to find from_rf. - RiseFall *from_rf = positive_unate ? to_rf : to_rf->opposite(); + const RiseFall *from_rf = positive_unate ? to_rf : to_rf->opposite(); float slew = from_vertex ? getSlew(from_vertex, from_rf, corner) : 0.0; @@ -1058,7 +1058,7 @@ Power::findOutputInternalPower(const LibertyPort *to_port, debugPrint(debug_, "power", 2, "%3s -> %-3s %6s %.3f %.3f %.3f %9.2e %9.2e %s", from_corner_port ? from_corner_port->name() : "-" , to_port->name(), - when ? when->asString() : "", + when ? when->to_string().c_str() : "", to_activity.density() * 1e-9, duty, weight, @@ -1189,7 +1189,7 @@ Power::findLeakagePower(const Instance *inst, float cond_duty = cond_activity.duty(); debugPrint(debug_, "power", 2, "leakage %s %s %.3e * %.2f", cell->name(), - when->asString(), + when->to_string().c_str(), leak->power(), cond_duty); cond_leakage += leak->power() * cond_duty; @@ -1339,7 +1339,7 @@ Power::findClk(const Pin *to_pin) if (to_vertex) { VertexPathIterator path_iter(to_vertex, this); while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); + Path *path = path_iter.next(); const Clock *path_clk = path->clock(this); if (path_clk && (clk == nullptr diff --git a/sdc/Clock.cc b/sdc/Clock.cc index 6ca85055..8e7aadd1 100644 --- a/sdc/Clock.cc +++ b/sdc/Clock.cc @@ -535,10 +535,10 @@ Clock::isDivideByOneCombinational() const //////////////////////////////////////////////////////////////// ClockEdge::ClockEdge(Clock *clock, - RiseFall *rf) : + const RiseFall *rf) : clock_(clock), rf_(rf), - name_(stringPrint("%s %s", clock_->name(), rf_->asString())), + name_(stringPrint("%s %s", clock_->name(), rf_->to_string().c_str())), time_(0.0), index_(clock_->index() * RiseFall::index_count + rf_->index()) { @@ -671,7 +671,7 @@ InterClockUncertainty::removeUncertainty(const RiseFallBoth *src_rf, } const RiseFallMinMax * -InterClockUncertainty::uncertainties(RiseFall *src_rf) const +InterClockUncertainty::uncertainties(const RiseFall *src_rf) const { return &uncertainties_[src_rf->index()]; } diff --git a/sdc/CycleAccting.cc b/sdc/CycleAccting.cc index b25e500f..6ac5f875 100644 --- a/sdc/CycleAccting.cc +++ b/sdc/CycleAccting.cc @@ -79,10 +79,10 @@ CycleAcctings::reportClkToClkMaxCycleWarnings(Report *report) // duplicate warnings between different src/tgt clk edges. ClockPairSet clk_warnings; for (Clock *src_clk : *sdc_->clocks()) { - for (RiseFall *src_rf : RiseFall::range()) { + for (const RiseFall *src_rf : RiseFall::range()) { ClockEdge *src = src_clk->edge(src_rf); for (Clock *tgt_clk : *sdc_->clocks()) { - for (RiseFall *tgt_rf : RiseFall::range()) { + for (const RiseFall *tgt_rf : RiseFall::range()) { ClockEdge *tgt = tgt_clk->edge(tgt_rf); CycleAccting probe(src, tgt); CycleAccting *acct = cycle_acctings_.findKey(&probe); @@ -320,7 +320,7 @@ CycleAccting::setHoldAccting(int src_cycle, } void -CycleAccting::setAccting(TimingRole *role, +CycleAccting::setAccting(const TimingRole *role, int src_cycle, int tgt_cycle, float delay, diff --git a/sdc/DataCheck.cc b/sdc/DataCheck.cc index 7a2065bb..15a839ba 100644 --- a/sdc/DataCheck.cc +++ b/sdc/DataCheck.cc @@ -80,7 +80,7 @@ DataCheck::empty() const } void -DataCheck::marginIsOneValue(SetupHold *setup_hold, +DataCheck::marginIsOneValue(const SetupHold *setup_hold, // Return values. float &value, bool &one_value) const diff --git a/sdc/ExceptionPath.cc b/sdc/ExceptionPath.cc index fa5f6587..3f265c65 100644 --- a/sdc/ExceptionPath.cc +++ b/sdc/ExceptionPath.cc @@ -320,7 +320,7 @@ ExceptionPath::fromThruToString(const Network *network) const string str; if (min_max_ != MinMaxAll::all()) { str += " -"; - str += min_max_->asString(); + str += min_max_->to_string(); } if (from_) diff --git a/sdc/PortDelay.cc b/sdc/PortDelay.cc index 4e576260..e2381216 100644 --- a/sdc/PortDelay.cc +++ b/sdc/PortDelay.cc @@ -81,7 +81,7 @@ PortDelay::setNetworkLatencyIncluded(bool included) network_latency_included_ = included; } -RiseFall * +const RiseFall * PortDelay::refTransition() const { // Reference pin transition is the clock transition. diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc index 95a34e60..2e46416f 100644 --- a/sdc/Sdc.cc +++ b/sdc/Sdc.cc @@ -3836,7 +3836,7 @@ Sdc::exceptionToInvalid(const Pin *pin) if (port) { LibertyCell *cell = port->libertyCell(); for (TimingArcSet *arc_set : cell->timingArcSets(nullptr, port)) { - TimingRole *role = arc_set->role(); + const TimingRole *role = arc_set->role(); if (role->genericRole() == TimingRole::regClkToQ()) return true; } diff --git a/sdc/Sdc.i b/sdc/Sdc.i index 4291dcb4..81d94240 100644 --- a/sdc/Sdc.i +++ b/sdc/Sdc.i @@ -1433,6 +1433,6 @@ slew(const RiseFall *rf, %extend ClockEdge { Clock *clock() { return self->clock(); } -RiseFall *transition() { return self->transition(); } +const RiseFall *transition() { return self->transition(); } float time() { return self->time(); } } diff --git a/sdc/Sdc.tcl b/sdc/Sdc.tcl index 6cb745fc..de5d7c9a 100644 --- a/sdc/Sdc.tcl +++ b/sdc/Sdc.tcl @@ -43,131 +43,7 @@ proc_redirect read_sdc { set echo [info exists flags(-echo)] set filename [file nativename [lindex $args 0]] set prev_filename [info script] - try { - info script $filename - source_ $filename $echo 0 - } finally { - info script $prev_filename - } -} - -################################################################ - -# The builtin Tcl "source" command is redefined by sta. -# This rename provides a mechanism to refer to the original TCL -# command. -# Protected so this file can be reloaded without blowing up. -if { ![info exists renamed_source] } { - rename source builtin_source - set renamed_source 1 -} - -set ::sta_continue_on_error 0 - -define_cmd_args "source" \ - {[-echo] [-verbose] filename [> filename] [>> filename]} - -# Override source to support -echo and return codes. -proc_redirect source { - parse_key_args "source" args keys {-encoding} flags {-echo -verbose} - if { [llength $args] != 1 } { - cmd_usage_error "source" - } - set echo [info exists flags(-echo)] - set verbose [info exists flags(-verbose)] - set filename [file nativename [lindex $args 0]] - set prev_filename [info script] - try { - info script $filename - source_ $filename $echo $verbose - } finally { - info script $prev_filename - } -} - -proc source_ { filename echo verbose } { - global sta_continue_on_error - variable sdc_file - variable sdc_line - if [catch {open $filename r} stream] { - sta_error 340 "cannot open '$filename'." - } else { - if { [file extension $filename] == ".gz" } { - if { [info commands zlib] == "" } { - sta_error 339 "tcl version > 8.6 required for zlib support." - } - zlib push gunzip $stream - } - # Save file and line in recursive call to source. - if { [info exists sdc_file] } { - set sdc_file_save $sdc_file - set sdc_line_save $sdc_line - } - set sdc_file $filename - set sdc_line 1 - set cmd "" - set error {} - while {![eof $stream]} { - gets $stream line - if { $line != "" } { - if {$echo} { - report_line $line - } - } - append cmd $line "\n" - if { [string index $line end] != "\\" \ - && [info complete $cmd] } { - set error {} - set error_code [catch {uplevel \#0 $cmd} result] - # cmd consumed - set cmd "" - # Flush results printed outside tcl to stdout/stderr. - fflush - switch $error_code { - 0 { if { $verbose && $result != "" } { report_line $result } } - 1 { set error $result } - 2 { set error {invoked "return" outside of a proc.} } - 3 { set error {invoked "break" outside of a loop.} } - 4 { set error {invoked "continue" outside of a loop.} } - } - if { $error != {} } { - if { $sta_continue_on_error } { - # Only prepend error message with file/line once. - if { [string first "Error" $error] == 0 } { - report_line $error - } else { - report_line "Error: [file tail $sdc_file], $sdc_line $error" - } - set error {} - } else { - break - } - } - } - incr sdc_line - } - close $stream - if { $cmd != {} } { - sta_error 341 "incomplete command at end of file." - } - set error_sdc_file $sdc_file - set error_sdc_line $sdc_line - if { [info exists sdc_file_save] } { - set sdc_file $sdc_file_save - set sdc_line $sdc_line_save - } else { - unset sdc_file - unset sdc_line - } - if { $error != {} } { - # Only prepend error message with file/line once. - if { [string first "Error" $error] == 0 } { - error $error - } else { - error "Error: [file tail $error_sdc_file], $error_sdc_line $error" - } - } - } + include_file $filename $echo 0 } ################################################################ @@ -1355,15 +1231,8 @@ proc group_path { args } { } proc check_exception_pins { from to } { - variable sdc_file - variable sdc_line - if { [info exists sdc_file] } { - set file $sdc_file - set line $sdc_line - } else { - set file "" - set line 0 - } + set file [sdc_filename] + set line [sdc_file_line] check_exception_from_pins $from $file $line check_exception_to_pins $to $file $line } diff --git a/sdc/WriteSdc.cc b/sdc/WriteSdc.cc index 5f985cee..93f55ba9 100644 --- a/sdc/WriteSdc.cc +++ b/sdc/WriteSdc.cc @@ -1180,7 +1180,7 @@ void WriteSdc::writeDisabledEdgeSense(Edge *edge) const { gzprintf(stream_, "set_disable_timing "); - const char *sense = timingSenseString(edge->sense()); + const char *sense = to_string(edge->sense()); string filter; stringPrint(filter, "sense == %s", sense); writeGetTimingArcs(edge, filter.c_str()); @@ -1451,9 +1451,9 @@ WriteSdc::writeDataCheck(DataCheck *check) const void WriteSdc::writeDataCheck(DataCheck *check, - RiseFallBoth *from_rf, - RiseFallBoth *to_rf, - SetupHold *setup_hold, + const RiseFallBoth *from_rf, + const RiseFallBoth *to_rf, + const SetupHold *setup_hold, float margin) const { const char *from_key = "-from"; diff --git a/sdc/WriteSdcPvt.hh b/sdc/WriteSdcPvt.hh index b75f34f9..90392d9c 100644 --- a/sdc/WriteSdcPvt.hh +++ b/sdc/WriteSdcPvt.hh @@ -121,9 +121,9 @@ public: void writeDataChecks() const; void writeDataCheck(DataCheck *check) const; void writeDataCheck(DataCheck *check, - RiseFallBoth *from_rf, - RiseFallBoth *to_rf, - SetupHold *setup_hold, + const RiseFallBoth *from_rf, + const RiseFallBoth *to_rf, + const SetupHold *setup_hold, float margin) const; void writeEnvironment() const; void writeOperatingConditions() const; diff --git a/sdf/ReportAnnotation.cc b/sdf/ReportAnnotation.cc index 36798f25..76ce7a4c 100644 --- a/sdf/ReportAnnotation.cc +++ b/sdf/ReportAnnotation.cc @@ -93,7 +93,7 @@ protected: int index, int &total, int &annotated_total); - void reportCheckCount(TimingRole *role, + void reportCheckCount(const TimingRole *role, int &total, int &annotated_total); int roleIndex(const TimingRole *role, @@ -284,14 +284,14 @@ ReportAnnotated::reportCheckCounts() } void -ReportAnnotated::reportCheckCount(TimingRole *role, +ReportAnnotated::reportCheckCount(const TimingRole *role, int &total, int &annotated_total) { int index = role->index(); if (edge_count_[index] > 0) { string title; - stringPrint(title, "cell %s arcs", role->asString()); + stringPrint(title, "cell %s arcs", role->to_string().c_str()); reportCount(title.c_str(), index, total, annotated_total); } } @@ -478,13 +478,13 @@ ReportAnnotated::reportArcs(Vertex *vertex, while (edge_iter.hasNext() && (max_lines_ == 0 || i < max_lines_)) { Edge *edge = edge_iter.next(); - TimingRole *role = edge->role(); + const TimingRole *role = edge->role(); const Pin *to_pin = edge->to(graph_)->pin(); if (graph_->delayAnnotated(edge) == report_annotated && report_role_[roleIndex(role, from_pin, to_pin)]) { const char *role_name; if (role->isTimingCheck()) - role_name = role->asString(); + role_name = role->to_string().c_str(); else if (role->isWire()) { if (network_->isTopLevelPort(from_pin)) role_name = "primary input net"; diff --git a/sdf/SdfParse.yy b/sdf/SdfParse.yy index ee7ba2c5..04ebad21 100644 --- a/sdf/SdfParse.yy +++ b/sdf/SdfParse.yy @@ -66,7 +66,7 @@ sta::SdfParse::error(const location_type &loc, sta::SdfTriple *triple; sta::SdfTripleSeq *delval_list; sta::SdfPortSpec *port_spec; - sta::Transition *transition; + const sta::Transition *transition; } %token DELAYFILE SDFVERSION DESIGN DATE VENDOR PROGRAM PVERSION diff --git a/sdf/SdfReader.cc b/sdf/SdfReader.cc index d3f8a6dc..10eaac7d 100644 --- a/sdf/SdfReader.cc +++ b/sdf/SdfReader.cc @@ -430,7 +430,7 @@ SdfReader::findPort(const Cell *cell, } void -SdfReader::timingCheck(TimingRole *role, +SdfReader::timingCheck(const TimingRole *role, SdfPortSpec *data_edge, SdfPortSpec *clk_edge, SdfTriple *triple) @@ -450,7 +450,7 @@ SdfReader::timingCheck(TimingRole *role, } void -SdfReader::timingCheck1(TimingRole *role, +SdfReader::timingCheck1(const TimingRole *role, Port *data_port, SdfPortSpec *data_edge, Port *clk_port, @@ -498,7 +498,7 @@ SdfReader::timingCheck1(TimingRole *role, network_->cellName(instance_), network_->name(data_port), network_->name(clk_port), - role->asString()); + role->to_string().c_str()); } } } @@ -509,7 +509,7 @@ SdfReader::annotateCheckEdges(Pin *data_pin, SdfPortSpec *data_edge, Pin *clk_pin, SdfPortSpec *clk_edge, - TimingRole *sdf_role, + const TimingRole *sdf_role, SdfTriple *triple, bool match_generic) { @@ -600,8 +600,8 @@ SdfReader::timingCheckSetupHold1(SdfPortSpec *data_edge, SdfPortSpec *clk_edge, SdfTriple *setup_triple, SdfTriple *hold_triple, - TimingRole *setup_role, - TimingRole *hold_role) + const TimingRole *setup_role, + const TimingRole *hold_role) { const string *data_port_name = data_edge->port(); const string *clk_port_name = clk_edge->port(); @@ -754,7 +754,7 @@ SdfReader::setEdgeArcDelaysCondUse(Edge *edge, float **values = triple->values(); float *value_min = values[triple_min_index_]; float *value_max = values[triple_max_index_]; - MinMax *min, *max; + const MinMax *min, *max; if (cond_use_ == MinMaxAll::min()) { min = MinMax::min(); max = MinMax::min(); @@ -826,7 +826,7 @@ SdfReader::condMatch(const string *sdf_cond, } SdfPortSpec * -SdfReader::makePortSpec(Transition *tr, +SdfReader::makePortSpec(const Transition *tr, const string *port, const string *cond) { diff --git a/sdf/SdfReaderPvt.hh b/sdf/SdfReaderPvt.hh index 64b00eaf..c85c8fdd 100644 --- a/sdf/SdfReaderPvt.hh +++ b/sdf/SdfReaderPvt.hh @@ -92,7 +92,7 @@ public: SdfTripleSeq *triples, const string *cond, bool condelse); - void timingCheck(TimingRole *role, + void timingCheck(const TimingRole *role, SdfPortSpec *data_edge, SdfPortSpec *clk_edge, SdfTriple *triple); @@ -112,8 +112,8 @@ public: SdfPortSpec *clk_edge, SdfTriple *setup_triple, SdfTriple *hold_triple, - TimingRole *setup_role, - TimingRole *hold_role); + const TimingRole *setup_role, + const TimingRole *hold_role); void timingCheckNochange(SdfPortSpec *data_edge, SdfPortSpec *clk_edge, SdfTriple *before_triple, @@ -132,7 +132,7 @@ public: void deleteTriple(SdfTriple *triple); SdfTripleSeq *makeTripleSeq(); void deleteTripleSeq(SdfTripleSeq *triples); - SdfPortSpec *makePortSpec(Transition *tr, + SdfPortSpec *makePortSpec(const Transition *tr, const string *port, const string *cond); SdfPortSpec *makeCondPortSpec(const string *cond_port); @@ -160,14 +160,14 @@ private: const char *filename); Edge *findCheckEdge(Pin *from_pin, Pin *to_pin, - TimingRole *sdf_role, + const TimingRole *sdf_role, const string *cond_start, const string *cond_end); Edge *findWireEdge(Pin *from_pin, Pin *to_pin); bool condMatch(const string *sdf_cond, const char *lib_cond); - void timingCheck1(TimingRole *role, + void timingCheck1(const TimingRole *role, Port *data_port, SdfPortSpec *data_edge, Port *clk_port, @@ -177,7 +177,7 @@ private: SdfPortSpec *data_edge, Pin *clk_pin, SdfPortSpec *clk_edge, - TimingRole *sdf_role, + const TimingRole *sdf_role, SdfTriple *triple, bool match_generic); Pin *findPin(const string *name); diff --git a/sdf/SdfWriter.cc b/sdf/SdfWriter.cc index 0f6f0083..34641e3f 100644 --- a/sdf/SdfWriter.cc +++ b/sdf/SdfWriter.cc @@ -104,7 +104,7 @@ protected: const char *sdfEdge(const Transition *tr); void writeArcDelays(Edge *edge); void writeSdfTriple(RiseFallMinMax &delays, - RiseFall *rf); + const RiseFall *rf); void writeSdfTriple(float min, float max); void writeSdfDelay(double delay); @@ -176,11 +176,13 @@ SdfWriter::write(const char *filename, timescale_ = default_lib->units()->timeUnit()->scale(); corner_ = corner; - MinMax *min_max; + const MinMax *min_max; const DcalcAnalysisPt *dcalc_ap; + min_max = MinMax::min(); dcalc_ap = corner_->findDcalcAnalysisPt(min_max); arc_delay_min_index_ = dcalc_ap->index(); + min_max = MinMax::max(); dcalc_ap = corner_->findDcalcAnalysisPt(min_max); arc_delay_max_index_ = dcalc_ap->index(); @@ -376,7 +378,7 @@ SdfWriter::writeIopaths(const Instance *inst, VertexOutEdgeIterator edge_iter(from_vertex, graph_); while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); - TimingRole *role = edge->role(); + const TimingRole *role = edge->role(); if (role == TimingRole::combinational() || role == TimingRole::tristateEnable() || role == TimingRole::regClkToQ() @@ -437,7 +439,7 @@ SdfWriter::writeArcDelays(Edge *edge) RiseFallMinMax delays; TimingArcSet *arc_set = edge->timingArcSet(); for (TimingArc *arc : arc_set->arcs()) { - RiseFall *rf = arc->toEdge()->asRiseFall(); + const RiseFall *rf = arc->toEdge()->asRiseFall(); ArcDelay min_delay = graph_->arcDelay(edge, arc, arc_delay_min_index_); delays.setValue(rf, MinMax::min(), delayAsFloat(min_delay)); @@ -470,7 +472,7 @@ SdfWriter::writeArcDelays(Edge *edge) void SdfWriter::writeSdfTriple(RiseFallMinMax &delays, - RiseFall *rf) + const RiseFall *rf) { float min = delays.value(rf, MinMax::min()); float max = delays.value(rf, MinMax::max()); @@ -513,7 +515,7 @@ SdfWriter::writeTimingChecks(const Instance *inst, VertexOutEdgeIterator edge_iter(vertex, graph_); while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); - TimingRole *role = edge->role(); + const TimingRole *role = edge->role(); const char *sdf_check = nullptr; if (role == TimingRole::setup()) sdf_check = "SETUP"; @@ -590,8 +592,8 @@ SdfWriter::writeCheck(Edge *edge, TimingArc *arcs[RiseFall::index_count][RiseFall::index_count] = {{nullptr, nullptr}, {nullptr, nullptr}}; for (TimingArc *arc : arc_set->arcs()) { - RiseFall *clk_rf = arc->fromEdge()->asRiseFall(); - RiseFall *data_rf = arc->toEdge()->asRiseFall();; + const RiseFall *clk_rf = arc->fromEdge()->asRiseFall(); + const RiseFall *data_rf = arc->toEdge()->asRiseFall();; arcs[clk_rf->index()][data_rf->index()] = arc; } diff --git a/search/Bfs.cc b/search/Bfs.cc index fcec71ca..a67785aa 100644 --- a/search/Bfs.cc +++ b/search/Bfs.cc @@ -89,7 +89,7 @@ BfsIterator::clear() } void -BfsIterator::reportEntries(const Network *network) +BfsIterator::reportEntries() { Level level = first_level_; while (levelLessOrEqual(level, last_level_)) { @@ -98,7 +98,7 @@ BfsIterator::reportEntries(const Network *network) report_->reportLine("Level %d", level); for (Vertex *vertex : level_vertices) { if (vertex) - report_->reportLine(" %s", vertex->name(network)); + report_->reportLine(" %s", vertex->to_string(this).c_str()); } } incrLevel(level); @@ -262,7 +262,8 @@ BfsIterator::findNext(Level to_level) void BfsIterator::enqueue(Vertex *vertex) { - debugPrint(debug_, "bfs", 2, "enqueue %s", vertex->name(sdc_network_)); + debugPrint(debug_, "bfs", 2, "enqueue %s", + vertex->to_string(this).c_str()); if (!vertex->bfsInQueue(bfs_index_)) { Level level = vertex->level(); LockGuard lock(queue_lock_); @@ -295,12 +296,12 @@ BfsIterator::checkInQueue(Vertex *vertex) if (vertex->bfsInQueue(bfs_index_)) return; else - printf("extra %s\n", vertex->name(sdc_network_)); + printf("extra %s\n", vertex->to_string(this).c_str()); } } } if (vertex->bfsInQueue(bfs_index_)) - printf("missing %s\n", vertex->name(sdc_network_)); + printf("missing %s\n", vertex->to_string(this).c_str()); } void diff --git a/search/CheckMaxSkews.cc b/search/CheckMaxSkews.cc index e2da8420..3496fb0c 100644 --- a/search/CheckMaxSkews.cc +++ b/search/CheckMaxSkews.cc @@ -30,7 +30,7 @@ #include "Network.hh" #include "Graph.hh" #include "Clock.hh" -#include "PathVertex.hh" +#include "Path.hh" #include "PathAnalysisPt.hh" #include "Search.hh" @@ -195,17 +195,17 @@ CheckMaxSkews:: visitMaxSkewChecks(Vertex *vertex, Vertex *ref_vertex = edge->from(graph); TimingArcSet *arc_set = edge->timingArcSet(); for (TimingArc *arc : arc_set->arcs()) { - RiseFall *clk_rf = arc->fromEdge()->asRiseFall(); - RiseFall *ref_rf = arc->toEdge()->asRiseFall(); + const RiseFall *clk_rf = arc->fromEdge()->asRiseFall(); + const RiseFall *ref_rf = arc->toEdge()->asRiseFall(); VertexPathIterator clk_path_iter(vertex, clk_rf, clk_min_max, search); while (clk_path_iter.hasNext()) { - PathVertex *clk_path = clk_path_iter.next(); + Path *clk_path = clk_path_iter.next(); if (clk_path->isClock(search)) { const PathAnalysisPt *clk_ap = clk_path->pathAnalysisPt(sta_); PathAnalysisPt *ref_ap = clk_ap->tgtClkAnalysisPt(); VertexPathIterator ref_path_iter(ref_vertex, ref_rf, ref_ap, sta_); while (ref_path_iter.hasNext()) { - PathVertex *ref_path = ref_path_iter.next(); + Path *ref_path = ref_path_iter.next(); if (ref_path->isClock(search)) { MaxSkewCheck check(clk_path, ref_path, arc, edge); visitor->visit(check, sta_); @@ -220,8 +220,8 @@ CheckMaxSkews:: visitMaxSkewChecks(Vertex *vertex, //////////////////////////////////////////////////////////////// -MaxSkewCheck::MaxSkewCheck(PathVertex *clk_path, - PathVertex *ref_path, +MaxSkewCheck::MaxSkewCheck(Path *clk_path, + Path *ref_path, TimingArc *check_arc, Edge *check_edge) : clk_path_(clk_path), @@ -234,34 +234,34 @@ MaxSkewCheck::MaxSkewCheck(PathVertex *clk_path, Pin * MaxSkewCheck::clkPin(const StaState *sta) const { - return clk_path_.pin(sta); + return clk_path_->pin(sta); } Pin * MaxSkewCheck::refPin(const StaState *sta) const { - return ref_path_.pin(sta); + return ref_path_->pin(sta); } ArcDelay MaxSkewCheck::maxSkew(const StaState *sta) const { Search *search = sta->search(); - return search->deratedDelay(ref_path_.vertex(sta), + return search->deratedDelay(ref_path_->vertex(sta), check_arc_, check_edge_, false, - clk_path_.pathAnalysisPt(sta)); + clk_path_->pathAnalysisPt(sta)); } Delay -MaxSkewCheck::skew(const StaState *sta) const +MaxSkewCheck::skew() const { - return Delay(clk_path_.arrival(sta) - ref_path_.arrival(sta)); + return Delay(clk_path_->arrival() - ref_path_->arrival()); } Slack MaxSkewCheck::slack(const StaState *sta) const { - return maxSkew(sta) - skew(sta); + return maxSkew(sta) - skew(); } //////////////////////////////////////////////////////////////// diff --git a/search/CheckMaxSkews.hh b/search/CheckMaxSkews.hh index 3fd937f5..4f40ffbb 100644 --- a/search/CheckMaxSkews.hh +++ b/search/CheckMaxSkews.hh @@ -28,7 +28,7 @@ #include "Delay.hh" #include "StaState.hh" #include "SearchClass.hh" -#include "PathRef.hh" +#include "Path.hh" namespace sta { @@ -57,22 +57,22 @@ protected: class MaxSkewCheck { public: - MaxSkewCheck(PathVertex *clk_path, - PathVertex *ref_path, + MaxSkewCheck(Path *clk_path, + Path *ref_path, TimingArc *check_arc, Edge *check_edge); - const PathVertex *clkPath() const { return &clk_path_; } + const Path *clkPath() const { return clk_path_; } Pin *clkPin(const StaState *sta) const; - const PathVertex *refPath() const { return &ref_path_; } + const Path *refPath() const { return ref_path_; } Pin *refPin(const StaState *sta) const; - Delay skew(const StaState *sta) const; + Delay skew() const; ArcDelay maxSkew(const StaState *sta) const; Slack slack(const StaState *sta) const; TimingArc *checkArc() const { return check_arc_; } private: - PathVertex clk_path_; - PathVertex ref_path_; + Path *clk_path_; + Path *ref_path_; TimingArc *check_arc_; Edge *check_edge_; }; diff --git a/search/CheckMinPulseWidths.cc b/search/CheckMinPulseWidths.cc index eb4821a4..85fcb071 100644 --- a/search/CheckMinPulseWidths.cc +++ b/search/CheckMinPulseWidths.cc @@ -35,8 +35,7 @@ #include "GraphDelayCalc.hh" #include "ClkInfo.hh" #include "Tag.hh" -#include "PathVertex.hh" -#include "PathRef.hh" +#include "Path.hh" #include "Corner.hh" #include "PathAnalysisPt.hh" #include "SearchPred.hh" @@ -246,12 +245,12 @@ visitMinPulseWidthChecks(MinPulseWidthCheckVisitor *visitor) { Graph *graph = sta_->graph(); Debug *debug = sta_->debug(); - Network *sdc_network = sta_->network(); VertexIterator vertex_iter(graph); while (vertex_iter.hasNext()) { Vertex *vertex = vertex_iter.next(); if (isClkEnd(vertex, graph)) { - debugPrint(debug, "mpw", 1, "check mpw %s", vertex->name(sdc_network)); + debugPrint(debug, "mpw", 1, "check mpw %s", + vertex->to_string(sta_).c_str()); visitMinPulseWidthChecks(vertex, visitor); } } @@ -275,10 +274,9 @@ visitMinPulseWidthChecks(Vertex *vertex, minPulseWidth(path, sta_, min_width, exists); if (exists) { MinPulseWidthCheck check(path); - PathVertex close_path; - check.closePath(sta_, close_path); + Path *close_path = check.closePath(sta_); // Don't bother visiting if nobody is home. - if (!close_path.isNull()) + if (close_path) visitor->visit(check, sta_); } } @@ -289,7 +287,7 @@ visitMinPulseWidthChecks(Vertex *vertex, //////////////////////////////////////////////////////////////// MinPulseWidthCheck::MinPulseWidthCheck() : - open_path_() + open_path_(nullptr) { } @@ -301,31 +299,29 @@ MinPulseWidthCheck::MinPulseWidthCheck(Path *open_path) : MinPulseWidthCheck * MinPulseWidthCheck::copy() { - return new MinPulseWidthCheck(&open_path_); + return new MinPulseWidthCheck(open_path_); } Pin * MinPulseWidthCheck::pin(const StaState *sta) const { - return open_path_.pin(sta); + return open_path_->pin(sta); } const RiseFall * MinPulseWidthCheck::openTransition(const StaState *sta) const { - return open_path_.transition(sta); + return open_path_->transition(sta); } -void -MinPulseWidthCheck::closePath(const StaState *sta, - // Return value. - PathVertex &close) const +Path * +MinPulseWidthCheck::closePath(const StaState *sta) const { - PathAnalysisPt *open_ap = open_path_.pathAnalysisPt(sta); + PathAnalysisPt *open_ap = open_path_->pathAnalysisPt(sta); PathAnalysisPt *close_ap = open_ap->tgtClkAnalysisPt(); - const RiseFall *open_rf = open_path_.transition(sta); + const RiseFall *open_rf = open_path_->transition(sta); const RiseFall *close_rf = open_rf->opposite(); - Tag *open_tag = open_path_.tag(sta); + Tag *open_tag = open_path_->tag(sta); ClkInfo *open_clk_info = open_tag->clkInfo(); ClkInfo close_clk_info(open_clk_info->clkEdge()->opposite(), open_clk_info->clkSrc(), @@ -335,7 +331,7 @@ MinPulseWidthCheck::closePath(const StaState *sta, open_clk_info->pulseClkSense(), delay_zero, 0.0, nullptr, open_clk_info->pathAPIndex(), - open_clk_info->crprClkPath(), + open_clk_info->crprClkPath(sta), sta); Tag close_tag(0, close_rf->index(), @@ -347,34 +343,33 @@ MinPulseWidthCheck::closePath(const StaState *sta, open_tag->states(), false, sta); debugPrint(sta->debug(), "mpw", 3, " open %s", - open_tag->asString(sta)); + open_tag->to_string(sta).c_str()); debugPrint(sta->debug(), "mpw", 3, " close %s", - close_tag.asString(sta)); - VertexPathIterator close_iter(open_path_.vertex(sta), close_rf, + close_tag.to_string(sta).c_str()); + VertexPathIterator close_iter(open_path_->vertex(sta), close_rf, close_ap, sta); while (close_iter.hasNext()) { - PathVertex *close_path = close_iter.next(); + Path *close_path = close_iter.next(); if (tagMatchNoPathAp(close_path->tag(sta), &close_tag)) { debugPrint(sta->debug(), "mpw", 3, " match %s", - close_path->tag(sta)->asString(sta)); - close = close_path; - break; + close_path->tag(sta)->to_string(sta).c_str()); + return close_path; } } + return nullptr; } Arrival -MinPulseWidthCheck::openArrival(const StaState *sta) const +MinPulseWidthCheck::openArrival(const StaState *) const { - return open_path_.arrival(sta); + return open_path_->arrival(); } Arrival MinPulseWidthCheck::closeArrival(const StaState *sta) const { - PathVertex close; - closePath(sta, close); - return close.arrival(sta); + Path *close = closePath(sta); + return close->arrival(); } Arrival @@ -392,13 +387,13 @@ MinPulseWidthCheck::closeDelay(const StaState *sta) const const ClockEdge * MinPulseWidthCheck::openClkEdge(const StaState *sta) const { - return open_path_.clkEdge(sta->search()); + return open_path_->clkEdge(sta->search()); } const ClockEdge * MinPulseWidthCheck::closeClkEdge(const StaState *sta) const { - Tag *open_tag = open_path_.tag(sta); + Tag *open_tag = open_path_->tag(sta); ClkInfo *open_clk_info = open_tag->clkInfo(); return open_clk_info->clkEdge()->opposite(); } @@ -418,7 +413,7 @@ Arrival MinPulseWidthCheck::width(const StaState *sta) const { return closeArrival(sta) + closeOffset(sta) - - open_path_.arrival(sta) + - open_path_->arrival() + checkCrpr(sta); } @@ -427,7 +422,7 @@ MinPulseWidthCheck::minWidth(const StaState *sta) const { float min_width; bool exists; - minPulseWidth(&open_path_, sta, min_width, exists); + minPulseWidth(open_path_, sta, min_width, exists); return min_width; } @@ -469,10 +464,9 @@ Crpr MinPulseWidthCheck::checkCrpr(const StaState *sta) const { CheckCrpr *check_crpr = sta->search()->checkCrpr(); - PathVertex close; - closePath(sta, close); - if (!close.isNull()) - return check_crpr->checkCrpr(openPath(), &close); + Path *close = closePath(sta); + if (close) + return check_crpr->checkCrpr(openPath(), close); else return 0.0; } @@ -486,7 +480,7 @@ MinPulseWidthCheck::slack(const StaState *sta) const Corner * MinPulseWidthCheck::corner(const StaState *sta) const { - return open_path_.pathAnalysisPt(sta)->corner(); + return open_path_->pathAnalysisPt(sta)->corner(); } //////////////////////////////////////////////////////////////// diff --git a/search/CheckMinPulseWidths.hh b/search/CheckMinPulseWidths.hh index 21773cd5..8c6abeac 100644 --- a/search/CheckMinPulseWidths.hh +++ b/search/CheckMinPulseWidths.hh @@ -27,7 +27,7 @@ #include "SdcClass.hh" #include "SearchClass.hh" #include "StaState.hh" -#include "PathRef.hh" +#include "Path.hh" namespace sta { @@ -75,13 +75,11 @@ public: Arrival width(const StaState *sta) const; float minWidth(const StaState *sta) const; Slack slack(const StaState *sta) const; - Path *openPath() { return &open_path_; } + Path *openPath() { return open_path_; } Corner *corner(const StaState *sta) const; - const Path *openPath() const { return &open_path_; } + const Path *openPath() const { return open_path_; } Arrival openArrival(const StaState *sta) const; - void closePath(const StaState *sta, - // Return value. - PathVertex &close) const; + Path *closePath(const StaState *sta) const; Arrival closeArrival(const StaState *sta) const; Arrival openDelay(const StaState *sta) const; Arrival closeDelay(const StaState *sta) const; @@ -92,7 +90,7 @@ public: protected: // Open path of the pulse. - PathRef open_path_; + Path *open_path_; }; class MinPulseWidthSlackLess diff --git a/search/CheckSlewLimits.cc b/search/CheckSlewLimits.cc index 1bb36662..2cc392ca 100644 --- a/search/CheckSlewLimits.cc +++ b/search/CheckSlewLimits.cc @@ -34,7 +34,7 @@ #include "GraphDelayCalc.hh" #include "StaState.hh" #include "Corner.hh" -#include "PathVertex.hh" +#include "Path.hh" #include "PortDirection.hh" #include "Search.hh" #include "ClkNetwork.hh" diff --git a/search/CheckTiming.cc b/search/CheckTiming.cc index e90f73de..f6496356 100644 --- a/search/CheckTiming.cc +++ b/search/CheckTiming.cc @@ -38,7 +38,7 @@ #include "Bfs.hh" #include "Search.hh" #include "Genclks.hh" -#include "PathVertex.hh" +#include "Path.hh" #include "Sim.hh" namespace sta { @@ -246,9 +246,11 @@ CheckTiming::checkUnconstraintedOutputs(PinSet &unconstrained_ends) while (pin_iter->hasNext()) { Pin *pin = pin_iter->next(); PortDirection *dir = network_->direction(pin); + Vertex *vertex = graph_->pinLoadVertex(pin); if (dir->isAnyOutput() - && !((hasClkedDepature(pin) - && hasClkedArrival(graph_->pinLoadVertex(pin))) + && !vertex->isConstant() + && !((hasClkedDepature(pin) + && hasClkedArrival(vertex)) || hasMaxDelay(pin))) unconstrained_ends.insert(pin); } @@ -294,14 +296,16 @@ CheckTiming::checkUnconstrainedSetups(PinSet &unconstrained_ends) VertexIterator vertex_iter(graph_); while (vertex_iter.hasNext()) { Vertex *vertex = vertex_iter.next(); - VertexInEdgeIterator edge_iter(vertex, graph_); - while (edge_iter.hasNext()) { - Edge *edge = edge_iter.next(); - if (edge->role() == TimingRole::setup() - && (!search_->isClock(edge->from(graph_)) - || !hasClkedArrival(edge->to(graph_)))) { - unconstrained_ends.insert(vertex->pin()); - break; + if (!vertex->isConstant()) { + VertexInEdgeIterator edge_iter(vertex, graph_); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + if (edge->role() == TimingRole::setup() + && (!search_->isClock(edge->from(graph_)) + || !hasClkedArrival(edge->to(graph_)))) { + unconstrained_ends.insert(vertex->pin()); + break; + } } } } @@ -312,7 +316,7 @@ CheckTiming::hasClkedArrival(Vertex *vertex) { VertexPathIterator path_iter(vertex, this); while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); + Path *path = path_iter.next(); if (path->clock(this)) return true; } diff --git a/search/ClkDelays.hh b/search/ClkDelays.hh index 1eba8bf5..1b394914 100644 --- a/search/ClkDelays.hh +++ b/search/ClkDelays.hh @@ -27,7 +27,7 @@ #include "MinMax.hh" #include "StaState.hh" #include "Transition.hh" -#include "PathVertex.hh" +#include "Path.hh" namespace sta { @@ -43,7 +43,7 @@ public: Delay &delay, float &internal_latency, Delay &latency, - PathVertex &path, + Path &path, bool &exists) const; void latency(const RiseFall *src_rf, const RiseFall *end_rf, @@ -51,28 +51,28 @@ public: // Return values. Delay &delay, bool &exists) const; - static Delay latency(PathVertex *clk_path, + static Delay latency(Path *clk_path, StaState *sta); void setLatency(const RiseFall *src_rf, const RiseFall *end_rf, const MinMax *min_max, - PathVertex *path, + Path *path, bool include_internal_latency, StaState *sta); private: - static float insertionDelay(PathVertex *clk_path, + static float insertionDelay(Path *clk_path, StaState *sta); - static float delay(PathVertex *clk_path, + static float delay(Path *clk_path, StaState *sta); - static float clkTreeDelay(PathVertex *clk_path, + static float clkTreeDelay(Path *clk_path, StaState *sta); Delay insertion_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count]; Delay delay_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count]; float internal_latency_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count]; Delay latency_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count]; - PathVertex path_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count]; + Path path_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count]; bool exists_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count]; }; diff --git a/search/ClkInfo.cc b/search/ClkInfo.cc index ca7559e9..e7112255 100644 --- a/search/ClkInfo.cc +++ b/search/ClkInfo.cc @@ -53,12 +53,12 @@ ClkInfo::ClkInfo(const ClockEdge *clk_edge, float latency, ClockUncertainties *uncertainties, PathAPIndex path_ap_index, - PathVertexPtr &crpr_clk_path, + Path *crpr_clk_path, const StaState *sta) : clk_edge_(clk_edge), clk_src_(clk_src), gen_clk_src_(gen_clk_src), - crpr_clk_path_(crpr_clk_path), + crpr_clk_path_(is_propagated ? crpr_clk_path : nullptr), uncertainties_(uncertainties), insertion_(insertion), latency_(latency), @@ -87,7 +87,7 @@ ClkInfo::findHash(const StaState *sta) hashIncr(hash_, network->vertexId(clk_src_)); if (gen_clk_src_) hashIncr(hash_, network->vertexId(gen_clk_src_)); - hashIncr(hash_, crprClkVertexId()); + hashIncr(hash_, crprClkVertexId(sta)); if (uncertainties_) { float uncertainty; bool exists; @@ -108,12 +108,24 @@ ClkInfo::findHash(const StaState *sta) } VertexId -ClkInfo::crprClkVertexId() const +ClkInfo::crprClkVertexId(const StaState *sta) const { if (crpr_clk_path_.isNull()) - return 0; + return vertex_id_null; else - return crpr_clk_path_.vertexId(); + return crpr_clk_path_.vertexId(sta); +} + +Path * +ClkInfo::crprClkPath(const StaState *sta) +{ + return Path::vertexPath(crpr_clk_path_, sta); +} + +const Path * +ClkInfo::crprClkPath(const StaState *sta) const +{ + return Path::vertexPath(crpr_clk_path_, sta); } const char * @@ -124,7 +136,7 @@ ClkInfo::asString(const StaState *sta) const string result; PathAnalysisPt *path_ap = corners->findPathAnalysisPt(path_ap_index_); - result += path_ap->pathMinMax()->asString(); + result += path_ap->pathMinMax()->to_string(); result += "/"; result += std::to_string(path_ap_index_); @@ -162,7 +174,7 @@ ClkInfo::clock() const return nullptr; } -RiseFall * +const RiseFall * ClkInfo::pulseClkSense() const { if (is_pulse_clk_) @@ -213,8 +225,9 @@ clkInfoEqual(const ClkInfo *clk_info1, && clk_info1->clkSrc() == clk_info2->clkSrc() && clk_info1->genClkSrc() == clk_info2->genClkSrc() && (!crpr_on - || (PathVertexPtr::equal(clk_info1->crprClkPath(), - clk_info2->crprClkPath()))) + || Path::equal(clk_info1->crprClkPath(sta), + clk_info2->crprClkPath(sta), + sta)) && ((uncertainties1 == nullptr && uncertainties2 == nullptr) || (uncertainties1 && uncertainties2 @@ -279,9 +292,9 @@ clkInfoCmp(const ClkInfo *clk_info1, bool crpr_on = sta->sdc()->crprActive(); if (crpr_on) { - const PathVertexPtr &crpr_path1 = clk_info1->crprClkPath(); - const PathVertexPtr &crpr_path2 = clk_info2->crprClkPath(); - int path_cmp = PathVertexPtr::cmp(crpr_path1, crpr_path2); + const Path *crpr_path1 = clk_info1->crprClkPath(sta); + const Path *crpr_path2 = clk_info2->crprClkPath(sta); + int path_cmp = Path::cmp(crpr_path1, crpr_path2, sta); if (path_cmp != 0) return path_cmp; } diff --git a/search/ClkInfo.hh b/search/ClkInfo.hh index e7a548fd..8d1d82d1 100644 --- a/search/ClkInfo.hh +++ b/search/ClkInfo.hh @@ -26,12 +26,12 @@ #include "Transition.hh" #include "SearchClass.hh" -#include "PathVertexPtr.hh" #include "Sdc.hh" +#include "Path.hh" namespace sta { -class PathVertex; +class Path; class ClkInfo { @@ -46,7 +46,7 @@ public: float latency, ClockUncertainties *uncertainties, PathAPIndex path_ap_index, - PathVertexPtr &crpr_clk_path, + Path *crpr_clk_path, const StaState *sta); ~ClkInfo(); const char *asString(const StaState *sta) const; @@ -56,7 +56,7 @@ public: bool isPropagated() const { return is_propagated_; } const Pin *genClkSrc() const { return gen_clk_src_; } bool isPulseClk() const { return is_pulse_clk_; } - RiseFall *pulseClkSense() const; + const RiseFall *pulseClkSense() const; int pulseClkSenseTrIndex() const { return pulse_clk_sense_; } float latency() const { return latency_; } Arrival &insertion() { return insertion_; } @@ -65,9 +65,9 @@ public: PathAPIndex pathAPIndex() const { return path_ap_index_; } // Clock path used for crpr resolution. // Null for clocks because the path cannot point to itself. - PathVertexPtr &crprClkPath() { return crpr_clk_path_; } - const PathVertexPtr &crprClkPath() const { return crpr_clk_path_; } - VertexId crprClkVertexId() const; + Path *crprClkPath(const StaState *sta); + const Path *crprClkPath(const StaState *sta) const; + VertexId crprClkVertexId(const StaState *sta) const; bool hasCrprClkPin() const { return !crpr_clk_path_.isNull(); } bool refsFilter(const StaState *sta) const; // This clk_info/tag is used for a generated clock source path. @@ -81,7 +81,7 @@ private: const ClockEdge *clk_edge_; const Pin *clk_src_; const Pin *gen_clk_src_; - PathVertexPtr crpr_clk_path_; + Path crpr_clk_path_; ClockUncertainties *uncertainties_; Arrival insertion_; float latency_; diff --git a/search/ClkLatency.cc b/search/ClkLatency.cc index 334d3e56..52edbe42 100644 --- a/search/ClkLatency.cc +++ b/search/ClkLatency.cc @@ -33,7 +33,7 @@ #include "Network.hh" #include "Clock.hh" #include "Graph.hh" -#include "PathVertex.hh" +#include "Path.hh" #include "StaState.hh" #include "Search.hh" #include "PathAnalysisPt.hh" @@ -88,7 +88,7 @@ ClkLatency::reportClkLatency(const Clock *clk, report_->reportLine("Clock %s", clk->name()); for (const RiseFall *src_rf : RiseFall::range()) { for (const RiseFall *end_rf : RiseFall::range()) { - PathVertex path_min; + Path path_min; Delay insertion_min; Delay delay_min; float internal_latency_min; @@ -97,7 +97,7 @@ ClkLatency::reportClkLatency(const Clock *clk, clk_delays.delay(src_rf, end_rf, MinMax::min(), insertion_min, delay_min, internal_latency_min, latency_min, path_min, exists_min); - PathVertex path_max; + Path path_max; Delay insertion_max; Delay delay_max; float internal_latency_max; @@ -153,7 +153,7 @@ ClkLatency::findClkDelays(ConstClockSeq &clks, for (Vertex *clk_vertex : *graph_->regClkVertices()) { VertexPathIterator path_iter(clk_vertex, this); while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); + Path *path = path_iter.next(); const ClockEdge *path_clk_edge = path->clkEdge(this); const PathAnalysisPt *path_ap = path->pathAnalysisPt(this); if (path_clk_edge @@ -206,7 +206,7 @@ ClkDelays::delay(const RiseFall *src_rf, Delay &delay, float &lib_clk_delay, Delay &latency, - PathVertex &path, + Path &path, bool &exists) const { int src_rf_index = src_rf->index(); @@ -239,7 +239,7 @@ void ClkDelays::setLatency(const RiseFall *src_rf, const RiseFall *end_rf, const MinMax *min_max, - PathVertex *path, + Path *path, bool include_internal_latency, StaState *sta) { @@ -267,7 +267,7 @@ ClkDelays::setLatency(const RiseFall *src_rf, } Delay -ClkDelays::latency(PathVertex *clk_path, +ClkDelays::latency(Path *clk_path, StaState *sta) { @@ -278,16 +278,16 @@ ClkDelays::latency(PathVertex *clk_path, } float -ClkDelays::delay(PathVertex *clk_path, +ClkDelays::delay(Path *clk_path, StaState *sta) { - Arrival arrival = clk_path->arrival(sta); + Arrival arrival = clk_path->arrival(); const ClockEdge *path_clk_edge = clk_path->clkEdge(sta); return delayAsFloat(arrival) - path_clk_edge->time(); } float -ClkDelays::insertionDelay(PathVertex *clk_path, +ClkDelays::insertionDelay(Path *clk_path, StaState *sta) { const ClockEdge *clk_edge = clk_path->clkEdge(sta); @@ -302,7 +302,7 @@ ClkDelays::insertionDelay(PathVertex *clk_path, } float -ClkDelays::clkTreeDelay(PathVertex *clk_path, +ClkDelays::clkTreeDelay(Path *clk_path, StaState *sta) { const Vertex *vertex = clk_path->vertex(sta); diff --git a/search/ClkLatency.hh b/search/ClkLatency.hh index 8f4e0933..3a7d0385 100644 --- a/search/ClkLatency.hh +++ b/search/ClkLatency.hh @@ -30,7 +30,7 @@ #include "StaState.hh" #include "Transition.hh" #include "SearchClass.hh" -#include "PathVertex.hh" +#include "Path.hh" #include "ClkDelays.hh" namespace sta { diff --git a/search/ClkSkew.cc b/search/ClkSkew.cc index 7b9ae64b..0c8cabcb 100644 --- a/search/ClkSkew.cc +++ b/search/ClkSkew.cc @@ -38,7 +38,7 @@ #include "Graph.hh" #include "Sdc.hh" #include "Bfs.hh" -#include "PathVertex.hh" +#include "Path.hh" #include "StaState.hh" #include "PathAnalysisPt.hh" #include "SearchPred.hh" @@ -55,14 +55,14 @@ class ClkSkew { public: ClkSkew(); - ClkSkew(PathVertex *src_path, - PathVertex *tgt_path, + ClkSkew(Path *src_path, + Path *tgt_path, bool include_internal_latency, StaState *sta); ClkSkew(const ClkSkew &clk_skew); void operator=(const ClkSkew &clk_skew); - PathVertex *srcPath() { return &src_path_; } - PathVertex *tgtPath() { return &tgt_path_; } + Path *srcPath() { return src_path_; } + Path *tgtPath() { return tgt_path_; } float srcLatency(const StaState *sta); float tgtLatency(const StaState *sta); float srcInternalClkLatency(const StaState *sta); @@ -75,23 +75,25 @@ public: const StaState *sta); private: - float clkTreeDelay(PathVertex &clk_path, + float clkTreeDelay(Path *clk_path, const StaState *sta); - PathVertex src_path_; - PathVertex tgt_path_; + Path *src_path_; + Path *tgt_path_; bool include_internal_latency_; float skew_; }; ClkSkew::ClkSkew() : + src_path_(nullptr), + tgt_path_(nullptr), include_internal_latency_(false), skew_(0.0) { } -ClkSkew::ClkSkew(PathVertex *src_path, - PathVertex *tgt_path, +ClkSkew::ClkSkew(Path *src_path, + Path *tgt_path, bool include_internal_latency, StaState *sta) : src_path_(src_path), @@ -124,8 +126,8 @@ ClkSkew::operator=(const ClkSkew &clk_skew) float ClkSkew::srcLatency(const StaState *sta) { - Arrival src_arrival = src_path_.arrival(sta); - return delayAsFloat(src_arrival) - src_path_.clkEdge(sta)->time() + Arrival src_arrival = src_path_->arrival(); + return delayAsFloat(src_arrival) - src_path_->clkEdge(sta)->time() + clkTreeDelay(src_path_, sta); } @@ -138,8 +140,8 @@ ClkSkew::srcInternalClkLatency(const StaState *sta) float ClkSkew::tgtLatency(const StaState *sta) { - Arrival tgt_arrival = tgt_path_.arrival(sta); - return delayAsFloat(tgt_arrival) - tgt_path_.clkEdge(sta)->time() + Arrival tgt_arrival = tgt_path_->arrival(); + return delayAsFloat(tgt_arrival) - tgt_path_->clkEdge(sta)->time() + clkTreeDelay(tgt_path_, sta); } @@ -150,16 +152,16 @@ ClkSkew::tgtInternalClkLatency(const StaState *sta) } float -ClkSkew::clkTreeDelay(PathVertex &clk_path, +ClkSkew::clkTreeDelay(Path *clk_path, const StaState *sta) { if (include_internal_latency_) { - const Vertex *vertex = clk_path.vertex(sta); + const Vertex *vertex = clk_path->vertex(sta); const Pin *pin = vertex->pin(); const LibertyPort *port = sta->network()->libertyPort(pin); - const MinMax *min_max = clk_path.minMax(sta); - const RiseFall *rf = clk_path.transition(sta); - float slew = delayAsFloat(clk_path.slew(sta)); + const MinMax *min_max = clk_path->minMax(sta); + const RiseFall *rf = clk_path->transition(sta); + float slew = delayAsFloat(clk_path->slew(sta)); return port->clkTreeDelay(slew, rf, min_max); } else @@ -170,17 +172,17 @@ Crpr ClkSkew::crpr(const StaState *sta) { CheckCrpr *check_crpr = sta->search()->checkCrpr(); - return check_crpr->checkCrpr(&src_path_, &tgt_path_); + return check_crpr->checkCrpr(src_path_, tgt_path_); } float ClkSkew::uncertainty(const StaState *sta) { - TimingRole *check_role = (src_path_.minMax(sta) == SetupHold::max()) + const TimingRole *check_role = (src_path_->minMax(sta) == SetupHold::max()) ? TimingRole::setup() : TimingRole::hold(); // Uncertainty decreases slack, but increases skew. - return -PathEnd::checkTgtClkUncertainty(&tgt_path_, tgt_path_.clkEdge(sta), + return -PathEnd::checkTgtClkUncertainty(tgt_path_, tgt_path_->clkEdge(sta), check_role, sta); } @@ -240,8 +242,8 @@ ClkSkews::reportClkSkew(ClkSkew &clk_skew, int digits) { Unit *time_unit = units_->timeUnit(); - PathVertex *src_path = clk_skew.srcPath(); - PathVertex *tgt_path = clk_skew.tgtPath(); + Path *src_path = clk_skew.srcPath(); + Path *tgt_path = clk_skew.tgtPath(); float src_latency = clk_skew.srcLatency(this); float tgt_latency = clk_skew.tgtLatency(this); float src_internal_clk_latency = clk_skew.srcInternalClkLatency(this); @@ -253,7 +255,7 @@ ClkSkews::reportClkSkew(ClkSkew &clk_skew, report_->reportLine("%7s source latency %s %s", time_unit->asString(src_latency, digits), sdc_network_->pathName(src_path->pin(this)), - src_path->transition(this)->asString()); + src_path->transition(this)->to_string().c_str()); if (src_internal_clk_latency != 0.0) report_->reportLine("%7s source internal clock delay", time_unit->asString(src_internal_clk_latency, digits)); @@ -263,7 +265,7 @@ ClkSkews::reportClkSkew(ClkSkew &clk_skew, report_->reportLine("%7s target latency %s %s", time_unit->asString(-tgt_latency, digits), sdc_network_->pathName(tgt_path->pin(this)), - tgt_path->transition(this)->asString()); + tgt_path->transition(this)->to_string().c_str()); if (tgt_internal_clk_latency != 0.0) report_->reportLine("%7s target internal clock delay", time_unit->asString(-tgt_internal_clk_latency, digits)); @@ -352,7 +354,7 @@ ClkSkews::hasClkPaths(Vertex *vertex) { VertexPathIterator path_iter(vertex, this); while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); + Path *path = path_iter.next(); const Clock *path_clk = path->clock(this); if (clk_set_.find(path_clk) != clk_set_.end()) return true; @@ -389,7 +391,7 @@ ClkSkews::findClkSkewFrom(Vertex *src_vertex, VertexInEdgeIterator edge_iter(end, graph_); while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); - TimingRole *role = edge->role(); + const TimingRole *role = edge->role(); if (role->isTimingCheck() && ((setup_hold_ == SetupHold::max() && role->genericRole() == TimingRole::setup()) @@ -417,7 +419,7 @@ ClkSkews::findClkSkew(Vertex *src_vertex, const SetupHold *tgt_min_max = setup_hold_->opposite(); VertexPathIterator src_iter(src_vertex, this); while (src_iter.hasNext()) { - PathVertex *src_path = src_iter.next(); + Path *src_path = src_iter.next(); const Clock *src_clk = src_path->clock(this); if (src_rf->matches(src_path->transition(this)) && src_path->minMax(this) == setup_hold_ @@ -427,7 +429,7 @@ ClkSkews::findClkSkew(Vertex *src_vertex, || src_corner == corner_) { VertexPathIterator tgt_iter(tgt_vertex, this); while (tgt_iter.hasNext()) { - PathVertex *tgt_path = tgt_iter.next(); + Path *tgt_path = tgt_iter.next(); const Clock *tgt_clk = tgt_path->clock(this); if (tgt_clk == src_clk && tgt_path->isClock(this) @@ -439,14 +441,14 @@ ClkSkews::findClkSkew(Vertex *src_vertex, debugPrint(debug_, "clk_skew", 2, "%s %s %s -> %s %s %s crpr = %s skew = %s", network_->pathName(src_path->pin(this)), - src_path->transition(this)->asString(), + src_path->transition(this)->to_string().c_str(), time_unit->asString(probe.srcLatency(this)), network_->pathName(tgt_path->pin(this)), - tgt_path->transition(this)->asString(), + tgt_path->transition(this)->to_string().c_str(), time_unit->asString(probe.tgtLatency(this)), delayAsString(probe.crpr(this), this), time_unit->asString(probe.skew())); - if (clk_skew.srcPath()->isNull() + if (clk_skew.srcPath() == nullptr || abs(probe.skew()) > abs(clk_skew.skew())) clk_skew = probe; } @@ -497,7 +499,7 @@ FanOutSrchPred::FanOutSrchPred(const StaState *sta) : bool FanOutSrchPred::searchThru(Edge *edge) { - TimingRole *role = edge->role(); + const TimingRole *role = edge->role(); return SearchPred1::searchThru(edge) && (role == TimingRole::wire() || role == TimingRole::combinational() diff --git a/search/ClkSkew.hh b/search/ClkSkew.hh index f9b89fd6..712e7b8b 100644 --- a/search/ClkSkew.hh +++ b/search/ClkSkew.hh @@ -32,7 +32,7 @@ #include "Transition.hh" #include "SearchClass.hh" #include "SearchPred.hh" -#include "PathVertex.hh" +#include "Path.hh" namespace sta { diff --git a/search/Corner.cc b/search/Corner.cc index 2d1ce8ea..0ed7834c 100644 --- a/search/Corner.cc +++ b/search/Corner.cc @@ -144,14 +144,14 @@ Corners::makeParasiticAnalysisPts(bool per_corner) parasitic_analysis_pts_.resize(corners_.size() * MinMax::index_count); for (Corner *corner : corners_) { corner->setParasiticAnalysisPtcount(MinMax::index_count); - for (MinMax *min_max : MinMax::range()) { + for (const MinMax *min_max : MinMax::range()) { int mm_index = min_max->index(); int ap_index = corner->index() * MinMax::index_count + mm_index; int ap_index_max = corner->index() * MinMax::index_count + MinMax::max()->index(); string ap_name = corner->name(); ap_name += "_"; - ap_name += min_max->asString(); + ap_name += min_max->to_string(); ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(ap_name.c_str(), ap_index, ap_index_max); parasitic_analysis_pts_[ap_index] = ap; @@ -163,10 +163,10 @@ Corners::makeParasiticAnalysisPts(bool per_corner) // shared corner, per min/max parasitic_analysis_pts_.resize(MinMax::index_count); int ap_index_max = MinMax::max()->index(); - for (MinMax *min_max : MinMax::range()) { + for (const MinMax *min_max : MinMax::range()) { int mm_index = min_max->index(); int ap_index = mm_index; - ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(min_max->asString(), + ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(min_max->to_string().c_str(), ap_index, ap_index_max); parasitic_analysis_pts_[ap_index] = ap; @@ -360,17 +360,12 @@ Corners::findPathAnalysisPt(PathAPIndex path_index) const Corner::Corner(const char *name, int index) : - name_(stringCopy(name)), + name_(name), index_(index), path_analysis_pts_(MinMax::index_count) { } -Corner::~Corner() -{ - stringDelete(name_); -} - ParasiticAnalysisPt * Corner::findParasiticAnalysisPt(const MinMax *min_max) const { diff --git a/search/Crpr.cc b/search/Crpr.cc index ef35c772..ea819248 100644 --- a/search/Crpr.cc +++ b/search/Crpr.cc @@ -32,8 +32,6 @@ #include "Network.hh" #include "Graph.hh" #include "Sdc.hh" -#include "PathVertex.hh" -#include "PathPrev.hh" #include "Path.hh" #include "PathAnalysisPt.hh" #include "ClkInfo.hh" @@ -54,60 +52,26 @@ CheckCrpr::CheckCrpr(StaState *sta) : { } -void -CheckCrpr::clkPathPrev(const PathVertex *path, - PathVertex &prev) - -{ - Vertex *vertex = path->vertex(this); - int arrival_index; - bool exists; - path->arrivalIndex(arrival_index, exists); - PathPrev *prevs = graph_->prevPaths(vertex); - if (prevs) - prev.init(prevs[arrival_index], this); - else - criticalError(2200, "missing prev paths"); -} - -PathVertex -CheckCrpr::clkPathPrev(Vertex *vertex, - int arrival_index) -{ - PathPrev *prevs = graph_->prevPaths(vertex); - if (prevs) - return PathVertex(prevs[arrival_index], this); - else { - criticalError(2201, "missing prev paths"); - return PathVertex(); - } -} - -//////////////////////////////////////////////////////////////// - // Find the maximum possible crpr (clock min/max delta delay) for a // path from it's ClkInfo. Arrival CheckCrpr::maxCrpr(ClkInfo *clk_info) { - const PathVertexPtr &crpr_clk_path = clk_info->crprClkPath(); - if (!crpr_clk_path.isNull()) { - PathVertex crpr_clk_vpath(crpr_clk_path, this); - if (!crpr_clk_vpath.isNull()) { - Arrival other_arrival = otherMinMaxArrival(&crpr_clk_vpath); - float crpr_diff = abs(delayAsFloat(crpr_clk_vpath.arrival(this), - EarlyLate::late(), - this) - - delayAsFloat(other_arrival, EarlyLate::early(), - this)); - return crpr_diff; - } + const Path *crpr_clk_path = clk_info->crprClkPath(this); + if (crpr_clk_path) { + Arrival other_arrival = otherMinMaxArrival(crpr_clk_path); + float crpr_diff = abs(delayAsFloat(crpr_clk_path->arrival(), + EarlyLate::late(), + this) + - delayAsFloat(other_arrival, EarlyLate::early(), + this)); + return crpr_diff; } return 0.0F; } Arrival -CheckCrpr::otherMinMaxArrival(const PathVertex *path) +CheckCrpr::otherMinMaxArrival(const Path *path) { PathAnalysisPt *other_ap = path->pathAnalysisPt(this)->tgtClkAnalysisPt(); Tag *tag = path->tag(this); @@ -115,18 +79,18 @@ CheckCrpr::otherMinMaxArrival(const PathVertex *path) path->transition(this), other_ap, this); while (other_iter.hasNext()) { - PathVertex *other = other_iter.next(); + Path *other = other_iter.next(); if (tagMatchCrpr(other->tag(this), tag)) - return other->arrival(this); + return other->arrival(); } // No corresponding path found. // Match the arrival so the difference is zero. - return path->arrival(this); + return path->arrival(); } Crpr CheckCrpr::checkCrpr(const Path *src_path, - const PathVertex *tgt_clk_path) + const Path *tgt_clk_path) { Crpr crpr; Pin *crpr_pin; @@ -136,7 +100,7 @@ CheckCrpr::checkCrpr(const Path *src_path, void CheckCrpr::checkCrpr(const Path *src_path, - const PathVertex *tgt_clk_path, + const Path *tgt_clk_path, // Return values. Crpr &crpr, Pin *&crpr_pin) @@ -152,7 +116,7 @@ CheckCrpr::checkCrpr(const Path *src_path, void CheckCrpr::checkCrpr1(const Path *src_path, - const PathVertex *tgt_clk_path, + const Path *tgt_clk_path, bool same_pin, // Return values. Crpr &crpr, @@ -165,17 +129,11 @@ CheckCrpr::checkCrpr1(const Path *src_path, ClkInfo *tgt_clk_info = tgt_clk_path->tag(this)->clkInfo(); const Clock *src_clk = src_clk_info->clock(); const Clock *tgt_clk = tgt_clk_info->clock(); - PathVertex src_clk_path1; - const PathVertexPtr &src_crpr_clk_path = src_clk_info->crprClkPath(); - const PathVertex *src_clk_path = nullptr; - if (src_tag->isClock()) { - src_clk_path1.init(src_path->vertex(this), src_path->tag(this), this); - src_clk_path = &src_clk_path1; - } - else if (!src_crpr_clk_path.isNull()) { - src_clk_path1.init(src_crpr_clk_path, this); - src_clk_path = &src_clk_path1; - } + const Path *src_clk_path = nullptr; + if (src_tag->isClock()) + src_clk_path = src_path; + else + src_clk_path = src_clk_info->crprClkPath(this); const MinMax *src_clk_min_max = src_clk_path ? src_clk_path->minMax(this) : src_path->minMax(this); if (src_clk && tgt_clk @@ -186,45 +144,40 @@ CheckCrpr::checkCrpr1(const Path *src_path, // For path from latches that are borrowing the enable path // is from the opposite min/max of the data. && src_clk_min_max != tgt_clk_path->minMax(this) - && (src_clk_path != nullptr + && (src_clk_path || src_clk->isGenerated())) { // Src path from input port clk path can only be from generated clk path. - PathVertex port_clk_path; if (src_clk_path == nullptr) { - portClkPath(src_clk_info->clkEdge(), - src_clk_info->clkSrc(), - src_path->pathAnalysisPt(this), - port_clk_path); - src_clk_path = &port_clk_path; + src_clk_path = portClkPath(src_clk_info->clkEdge(), + src_clk_info->clkSrc(), + src_path->pathAnalysisPt(this)); } findCrpr(src_clk_path, tgt_clk_path, same_pin, crpr, crpr_pin); } } // Find the clk path for an input/output port. -void +Path * CheckCrpr::portClkPath(const ClockEdge *clk_edge, const Pin *clk_src_pin, - const PathAnalysisPt *path_ap, - // Return value. - PathVertex &genclk_path) + const PathAnalysisPt *path_ap) { Vertex *clk_vertex = graph_->pinDrvrVertex(clk_src_pin); VertexPathIterator path_iter(clk_vertex, clk_edge->transition(), path_ap, this); while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); + Path *path = path_iter.next(); if (path->clkEdge(this) == clk_edge && path->isClock(this)) { - genclk_path = path; - break; + return path; } } + return nullptr; } void -CheckCrpr::findCrpr(const PathVertex *src_clk_path, - const PathVertex *tgt_clk_path, +CheckCrpr::findCrpr(const Path *src_clk_path, + const Path *tgt_clk_path, bool same_pin, // Return values. Crpr &crpr, @@ -232,35 +185,33 @@ CheckCrpr::findCrpr(const PathVertex *src_clk_path, { crpr = 0.0; crpr_pin = nullptr; - const PathVertex *src_clk_path1 = src_clk_path; - const PathVertex *tgt_clk_path1 = tgt_clk_path; - PathVertexSeq src_gclk_paths, tgt_gclk_paths; + const Path *src_clk_path1 = src_clk_path; + const Path *tgt_clk_path1 = tgt_clk_path; if (src_clk_path1->clkInfo(this)->clkSrc() != tgt_clk_path1->clkInfo(this)->clkSrc()) { // Push src/tgt genclk src paths into a vector, // The last genclk src path is at index 0. - genClkSrcPaths(src_clk_path1, src_gclk_paths); - genClkSrcPaths(tgt_clk_path1, tgt_gclk_paths); + ConstPathSeq src_gclk_paths = genClkSrcPaths(src_clk_path1); + ConstPathSeq tgt_gclk_paths = genClkSrcPaths(tgt_clk_path1); // Search from the first gen clk toward the end // of the path to find a common root pin. int i = src_gclk_paths.size() - 1; int j = tgt_gclk_paths.size() - 1; for (; i >= 0 && j >= 0; i--, j--) { - PathVertex &src_path = src_gclk_paths[i]; - PathVertex &tgt_path = tgt_gclk_paths[j]; - if (src_path.clkInfo(this)->clkSrc() - == tgt_path.clkInfo(this)->clkSrc()) { - src_clk_path1 = &src_gclk_paths[i]; - tgt_clk_path1 = &tgt_gclk_paths[j]; + const Path *src_path = src_gclk_paths[i]; + const Path *tgt_path = tgt_gclk_paths[j]; + if (src_path->clkInfo(this)->clkSrc() + == tgt_path->clkInfo(this)->clkSrc()) { + src_clk_path1 = src_gclk_paths[i]; + tgt_clk_path1 = tgt_gclk_paths[j]; } else break; } } - const PathVertex *src_clk_path2 = src_clk_path1; - const PathVertex *tgt_clk_path2 = tgt_clk_path1; - PathVertex src_prev, tgt_prev; - // src_clk_path and tgt_clk_path are now in the same (gen)clk src path. + const Path *src_clk_path2 = src_clk_path1; + const Path *tgt_clk_path2 = tgt_clk_path1; + // src_clk_path2 and tgt_clk_path2 are now in the same (gen)clk src path. // Use the vertex levels to back up the deeper path to see if they // overlap. int src_level = src_clk_path2->vertex(this)->level(); @@ -268,21 +219,19 @@ CheckCrpr::findCrpr(const PathVertex *src_clk_path, while (src_clk_path2->pin(this) != tgt_clk_path2->pin(this)) { int level_diff = src_level - tgt_level; if (level_diff >= 0) { - clkPathPrev(src_clk_path2, src_prev); - if (src_prev.isNull()) + src_clk_path2 = src_clk_path2->prevPath(); + if (src_clk_path2 == nullptr) break; - src_clk_path2 = &src_prev; src_level = src_clk_path2->vertex(this)->level(); } if (level_diff <= 0) { - clkPathPrev(tgt_clk_path2, tgt_prev); - if (tgt_prev.isNull()) + tgt_clk_path2 = tgt_clk_path2->prevPath(); + if (tgt_clk_path2 == nullptr) break; - tgt_clk_path2 = &tgt_prev; tgt_level = tgt_clk_path2->vertex(this)->level(); } } - if (!src_clk_path2->isNull() && !tgt_clk_path2->isNull() + if (src_clk_path2 && tgt_clk_path2 && (src_clk_path2->transition(this) == tgt_clk_path2->transition(this) || same_pin)) { debugPrint(debug_, "crpr", 2, "crpr pin %s", @@ -292,30 +241,31 @@ CheckCrpr::findCrpr(const PathVertex *src_clk_path, } } -void -CheckCrpr::genClkSrcPaths(const PathVertex *path, - PathVertexSeq &gclk_paths) +ConstPathSeq +CheckCrpr::genClkSrcPaths(const Path *path) { + ConstPathSeq gclk_paths; ClkInfo *clk_info = path->clkInfo(this); const ClockEdge *clk_edge = clk_info->clkEdge(); const Pin *clk_src = clk_info->clkSrc(); PathAnalysisPt *path_ap = path->pathAnalysisPt(this); gclk_paths.push_back(path); + Genclks *genclks = search_->genclks(); while (clk_edge->clock()->isGenerated()) { - PathVertex genclk_path = - search_->genclks()->srcPath(clk_edge, clk_src, path_ap); - if (genclk_path.isNull()) + Path *genclk_path = genclks->srcPath(clk_edge, clk_src, path_ap); + if (genclk_path == nullptr) break; - clk_info = genclk_path.clkInfo(this); + clk_info = genclk_path->clkInfo(this); clk_src = clk_info->clkSrc(); clk_edge = clk_info->clkEdge(); gclk_paths.push_back(genclk_path); } + return gclk_paths; } Crpr -CheckCrpr::findCrpr1(const PathVertex *src_clk_path, - const PathVertex *tgt_clk_path) +CheckCrpr::findCrpr1(const Path *src_clk_path, + const Path *tgt_clk_path) { if (pocv_enabled_) { // Remove variation on the common path. @@ -323,8 +273,8 @@ CheckCrpr::findCrpr1(const PathVertex *src_clk_path, // sigma of the common clock path. const EarlyLate *src_el = src_clk_path->minMax(this); const EarlyLate *tgt_el = tgt_clk_path->minMax(this); - Arrival src_arrival = src_clk_path->arrival(this); - Arrival tgt_arrival = tgt_clk_path->arrival(this); + Arrival src_arrival = src_clk_path->arrival(); + Arrival tgt_arrival = tgt_clk_path->arrival(); float src_clk_time = src_clk_path->clkEdge(this)->time(); float tgt_clk_time = tgt_clk_path->clkEdge(this)->time(); float crpr_mean = abs(delayAsFloat(src_arrival) - src_clk_time @@ -352,10 +302,10 @@ CheckCrpr::findCrpr1(const PathVertex *src_clk_path, } float -CheckCrpr::crprArrivalDiff(const PathVertex *path) +CheckCrpr::crprArrivalDiff(const Path *path) { Arrival other_arrival = otherMinMaxArrival(path); - float crpr_diff = abs(delayAsFloat(path->arrival(this)) + float crpr_diff = abs(delayAsFloat(path->arrival()) - delayAsFloat(other_arrival)); return crpr_diff; } @@ -407,13 +357,12 @@ CheckCrpr::outputDelayCrpr1(const Path *src_path, && tgt_clk->isGenerated() && tgt_clk->isPropagated() && crprPossible(src_clk, tgt_clk)) { - PathVertex tgt_genclk_path; - portClkPath(tgt_clk_edge, tgt_clk_edge->clock()->defaultPin(), tgt_path_ap, - tgt_genclk_path); - PathVertex src_clk_path(src_path->clkInfo(this)->crprClkPath(), this); - if (!src_clk_path.isNull()) { - findCrpr(&src_clk_path, &tgt_genclk_path, same_pin, crpr, crpr_pin); - } + Path *tgt_genclk_path = portClkPath(tgt_clk_edge, + tgt_clk_edge->clock()->defaultPin(), + tgt_path_ap); + Path *src_clk_path = src_path->clkInfo(this)->crprClkPath(this); + if (src_clk_path) + findCrpr(src_clk_path, tgt_genclk_path, same_pin, crpr, crpr_pin); } } diff --git a/search/Crpr.hh b/search/Crpr.hh index 26bcc4c4..bed17295 100644 --- a/search/Crpr.hh +++ b/search/Crpr.hh @@ -42,9 +42,9 @@ public: Arrival maxCrpr(ClkInfo *clk_info); // Timing check CRPR. Crpr checkCrpr(const Path *src_clk_path, - const PathVertex *tgt_clk_path); + const Path *tgt_clk_path); void checkCrpr(const Path *src_path, - const PathVertex *tgt_clk_path, + const Path *tgt_clk_path, // Return values. Crpr &crpr, Pin *&crpr_pin); @@ -57,18 +57,12 @@ public: Crpr &crpr, Pin *&crpr_pin); - // Previous clk path when crpr is enabled. - PathVertex clkPathPrev(const PathVertex *path); - // For Search::reportArrivals. - PathVertex clkPathPrev(Vertex *vertex, - int arrival_index); - private: - void clkPathPrev(const PathVertex *path, - PathVertex &prev); - Arrival otherMinMaxArrival(const PathVertex *path); + void clkPathPrev(const Path *path, + Path &prev); + Arrival otherMinMaxArrival(const Path *path); void checkCrpr1(const Path *src_path, - const PathVertex *tgt_clk_path, + const Path *tgt_clk_path, bool same_pin, // Return values. Crpr &crpr, @@ -82,22 +76,19 @@ private: Pin *&crpr_pin); bool crprPossible(const Clock *clk1, const Clock *clk2); - void genClkSrcPaths(const PathVertex *path, - PathVertexSeq &gclk_paths); - void findCrpr(const PathVertex *src_clk_path, - const PathVertex *tgt_clk_path, + ConstPathSeq genClkSrcPaths(const Path *path); + void findCrpr(const Path *src_clk_path, + const Path *tgt_clk_path, bool same_pin, // Return values. Crpr &crpr, Pin *&common_pin); - void portClkPath(const ClockEdge *clk_edge, - const Pin *clk_src_pin, - const PathAnalysisPt *path_ap, - // Return value. - PathVertex &port_clk_path); - Crpr findCrpr1(const PathVertex *src_clk_path, - const PathVertex *tgt_clk_path); - float crprArrivalDiff(const PathVertex *path); + Path *portClkPath(const ClockEdge *clk_edge, + const Pin *clk_src_pin, + const PathAnalysisPt *path_ap); + Crpr findCrpr1(const Path *src_clk_path, + const Path *tgt_clk_path); + float crprArrivalDiff(const Path *path); }; } // namespace diff --git a/search/FindRegister.cc b/search/FindRegister.cc index 32da6eec..66f9b553 100644 --- a/search/FindRegister.cc +++ b/search/FindRegister.cc @@ -76,7 +76,7 @@ FindRegClkPred::searchFrom(const Vertex *from_vertex) bool FindRegClkPred::searchThru(Edge *edge) { - TimingRole *role = edge->role(); + const TimingRole *role = edge->role(); return (role->isWire() || role == TimingRole::combinational()) && SearchPred1::searchThru(edge); @@ -281,13 +281,13 @@ FindRegVisitor::findInferedSequential(LibertyCell *cell, const RiseFall *clk_rf1 = clk_rf->asRiseFall(); for (TimingArcSet *arc_set : cell->timingArcSets()) { TimingArc *arc = *arc_set->arcs().begin(); - RiseFall *arc_clk_rf = arc->fromEdge()->asRiseFall(); + const RiseFall *arc_clk_rf = arc->fromEdge()->asRiseFall(); bool tr_matches = (clk_rf == RiseFallBoth::riseFall() || (arc_clk_rf == clk_rf1 && clk_sense == TimingSense::positive_unate) || (arc_clk_rf == clk_rf1->opposite() && clk_sense == TimingSense::negative_unate)); - TimingRole *role = arc_set->role(); + const TimingRole *role = arc_set->role(); if (tr_matches && ((role == TimingRole::regClkToQ() && edge_triggered) @@ -306,7 +306,7 @@ FindRegVisitor::hasTimingCheck(LibertyCell *cell, LibertyPort *d) { for (TimingArcSet *arc_set : cell->timingArcSets(clk, d)) { - TimingRole *role = arc_set->role(); + const TimingRole *role = arc_set->role(); if (role->isTimingCheck()) return true; } @@ -542,7 +542,7 @@ FindRegClkPins::matchPin(Pin *pin) LibertyPort *port = network_->libertyPort(pin); LibertyCell *cell = port->libertyCell(); for (TimingArcSet *arc_set : cell->timingArcSets(port, nullptr)) { - TimingRole *role = arc_set->role(); + const TimingRole *role = arc_set->role(); if (role == TimingRole::regClkToQ() || role == TimingRole::latchEnToQ()) return true; @@ -598,7 +598,7 @@ FindRegAsyncPins::matchPin(Pin *pin) LibertyPort *port = network_->libertyPort(pin); LibertyCell *cell = port->libertyCell(); for (TimingArcSet *arc_set : cell->timingArcSets(port, nullptr)) { - TimingRole *role = arc_set->role(); + const TimingRole *role = arc_set->role(); if (role == TimingRole::regSetClr()) return true; } @@ -645,7 +645,7 @@ FindRegOutputPins::matchPin(Pin *pin) LibertyPort *port = network_->libertyPort(pin); LibertyCell *cell = port->libertyCell(); for (TimingArcSet *arc_set : cell->timingArcSets(nullptr, port)) { - TimingRole *role = arc_set->role(); + const TimingRole *role = arc_set->role(); if (role == TimingRole::regClkToQ() || role == TimingRole::latchEnToQ() || role == TimingRole::latchDtoQ()) diff --git a/search/GatedClk.cc b/search/GatedClk.cc index 7e3ea00f..804cee9d 100644 --- a/search/GatedClk.cc +++ b/search/GatedClk.cc @@ -238,11 +238,11 @@ GatedClk::functionClkOperands(FuncExpr *root_expr, } } -RiseFall * +const RiseFall * GatedClk::gatedClkActiveTrans(LogicValue active_value, const MinMax *min_max) const { - RiseFall *leading_rf; + const RiseFall *leading_rf; switch (active_value) { case LogicValue::one: case LogicValue::unknown: diff --git a/search/GatedClk.hh b/search/GatedClk.hh index f69c3b81..8f63307d 100644 --- a/search/GatedClk.hh +++ b/search/GatedClk.hh @@ -46,8 +46,8 @@ public: void gatedClkEnables(Vertex *clk_vertex, // Return value. PinSet &enable_pins); - RiseFall *gatedClkActiveTrans(LogicValue active_value, - const MinMax *min_max) const; + const RiseFall *gatedClkActiveTrans(LogicValue active_value, + const MinMax *min_max) const; protected: void isClkGatingFunc(FuncExpr *func, diff --git a/search/Genclks.cc b/search/Genclks.cc index 573dcf0f..f36a150c 100644 --- a/search/Genclks.cc +++ b/search/Genclks.cc @@ -40,7 +40,7 @@ #include "Corner.hh" #include "PathAnalysisPt.hh" #include "Levelize.hh" -#include "PathVertexPtr.hh" +#include "Path.hh" #include "Search.hh" namespace sta { @@ -137,7 +137,7 @@ Genclks::fanins(const Clock *clk) } Vertex * -Genclks::srcPathVertex(const Pin *pin) const +Genclks::srcPath(const Pin *pin) const { bool is_bidirect = network_->direction(pin)->isBidirect(); // Insertion delay is to the driver vertex for clks defined on @@ -155,7 +155,7 @@ Genclks::clkPinMaxLevel(const Clock *clk) const { Level max_level = 0; for (const Pin *pin : clk->leafPins()) { - Vertex *vertex = srcPathVertex(pin); + Vertex *vertex = srcPath(pin); max_level = max(max_level, vertex->level()); } return max_level; @@ -209,9 +209,7 @@ Genclks::ensureInsertionDelays() // insertion delay, so sort the clocks by source pin level. sort(gclks, ClockPinMaxLevelLess(this)); - ClockSeq::Iterator gclk_iter(gclks); - while (gclk_iter.hasNext()) { - Clock *gclk = gclk_iter.next(); + for (Clock *gclk : gclks) { if (gclk->masterClk()) { findInsertionDelays(gclk); recordSrcPaths(gclk); @@ -252,7 +250,7 @@ bool GenClkMasterSearchPred::searchThru(Edge *edge) { const Sdc *sdc = sta_->sdc(); - TimingRole *role = edge->role(); + const TimingRole *role = edge->role(); // Propagate clocks through constants. return !(edge->role()->isTimingCheck() || edge->isDisabledLoop() @@ -420,7 +418,7 @@ Genclks::findFanin(Clock *gclk, if (!fanins->hasKey(vertex)) { fanins->insert(vertex); debugPrint(debug_, "genclk", 2, "gen clk %s fanin %s", - gclk->name(), vertex->name(sdc_network_)); + gclk->name(), vertex->to_string(this).c_str()); iter.enqueueAdjacentVertices(vertex); } } @@ -546,7 +544,7 @@ Genclks::makeGenclkInfo(Clock *gclk) VertexSet *fanins = new VertexSet(graph_); findFanin(gclk, fanins); GenclkInfo *genclk_info = new GenclkInfo(gclk, gclk_level, fanins, - src_filter); + src_filter); genclk_info_map_.insert(gclk, genclk_info); return genclk_info; } @@ -629,9 +627,8 @@ Genclks::findLatchFdbkEdges(Vertex *from_vertex, Edge *edge = edge_iter.next(); Vertex *to_vertex = edge->to(graph_); if (path_vertices.hasKey(to_vertex)) { - debugPrint(debug_, "genclk", 2, " found feedback edge %s -> %s", - from_vertex->name(sdc_network_), - to_vertex->name(sdc_network_)); + debugPrint(debug_, "genclk", 2, " found feedback edge %s", + edge->to_string(this).c_str()); if (fdbk_edges == nullptr) fdbk_edges = new EdgeSet; fdbk_edges->insert(edge); @@ -684,12 +681,12 @@ Genclks::seedSrcPins(Clock *gclk, for (auto path_ap : corners_->pathAnalysisPts()) { const MinMax *min_max = path_ap->pathMinMax(); const EarlyLate *early_late = min_max; - for (auto rf : RiseFall::range()) { - Tag *tag = makeTag(gclk, master_clk, master_pin, rf, src_filter, - path_ap); + for (const RiseFall *rf : RiseFall::range()) { + Tag *tag = makeTag(gclk, master_clk, master_pin, rf, + src_filter, path_ap); Arrival insert = search_->clockInsertion(master_clk, master_pin, rf, min_max, early_late, path_ap); - tag_bldr.setArrival(tag, insert, nullptr); + tag_bldr.setArrival(tag, insert); } } search_->setVertexArrivals(vertex, &tag_bldr); @@ -824,7 +821,7 @@ GenclkSrcArrivalVisitor::visit(Vertex *vertex) { Genclks *genclks = search_->genclks(); debugPrint(debug_, "genclk", 2, "find gen clk insert arrival %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); tag_bldr_->init(vertex); has_fanin_one_ = graph_->hasFaninOne(vertex); genclks->copyGenClkSrcPaths(vertex, tag_bldr_); @@ -854,22 +851,14 @@ void Genclks::copyGenClkSrcPaths(Vertex *vertex, TagGroupBldr *tag_bldr) { - Arrival *arrivals = graph_->arrivals(vertex); - if (arrivals) { - PathPrev *prev_paths = graph_->prevPaths(vertex); + Path *paths = graph_->paths(vertex); + if (paths) { TagGroup *tag_group = search_->tagGroup(vertex); if (tag_group) { - ArrivalMap::Iterator arrival_iter(tag_group->arrivalMap()); - while (arrival_iter.hasNext()) { - Tag *tag; - int arrival_index; - arrival_iter.next(tag, arrival_index); + for (auto const [tag, path_index] : *tag_group->pathIndexMap()) { if (tag->isGenClkSrcPath()) { - Arrival arrival = arrivals[arrival_index]; - PathPrev *prev_path = prev_paths - ? &prev_paths[arrival_index] - : nullptr; - tag_bldr->setArrival(tag, arrival, prev_path); + Path &path = paths[path_index]; + tag_bldr->insertPath(path); } } } @@ -881,11 +870,14 @@ Genclks::copyGenClkSrcPaths(Vertex *vertex, void Genclks::clearSrcPaths() { - genclk_src_paths_.deleteArrayContents(); + for (auto const & [clk_pin, src_paths] : genclk_src_paths_) { + for (const Path &src_path : src_paths) + delete src_path.prevPath(); + } genclk_src_paths_.clear(); } -int +size_t Genclks::srcPathIndex(const RiseFall *clk_rf, const PathAnalysisPt *path_ap) const { @@ -903,40 +895,49 @@ Genclks::recordSrcPaths(Clock *gclk) bool has_edges = gclk->edges() != nullptr; for (const Pin *gclk_pin : gclk->leafPins()) { - PathVertexPtr *src_paths = new PathVertexPtr[path_count]; - genclk_src_paths_.insert(ClockPinPair(gclk, gclk_pin), src_paths); - - Vertex *gclk_vertex = srcPathVertex(gclk_pin); + vector &src_paths = genclk_src_paths_[ClockPinPair(gclk, gclk_pin)]; + src_paths.resize(path_count); + Vertex *gclk_vertex = srcPath(gclk_pin); bool found_src_paths = false; VertexPathIterator path_iter(gclk_vertex, this); while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); + Path *path = path_iter.next(); const ClockEdge *src_clk_edge = path->clkEdge(this); if (src_clk_edge && matchesSrcFilter(path, gclk)) { const EarlyLate *early_late = path->minMax(this); - RiseFall *src_clk_rf = src_clk_edge->transition(); + const RiseFall *src_clk_rf = src_clk_edge->transition(); const RiseFall *rf = path->transition(this); bool inverting_path = (rf != src_clk_rf); const PathAnalysisPt *path_ap = path->pathAnalysisPt(this); - int path_index = srcPathIndex(rf, path_ap); - PathVertexPtr &src_path = src_paths[path_index]; + size_t path_index = srcPathIndex(rf, path_ap); + Path &src_path = src_paths[path_index]; if ((!divide_by_1 || (inverting_path == invert)) && (!has_edges || src_clk_rf == gclk->masterClkEdgeTr(rf)) && (src_path.isNull() - || delayGreater(path->arrival(this), - src_path.arrival(this), + || delayGreater(path->arrival(), + src_path.arrival(), early_late, this))) { debugPrint(debug_, "genclk", 2, " %s insertion %s %s %s", network_->pathName(gclk_pin), - early_late->asString(), - rf->asString(), - delayAsString(path->arrival(this), this)); - src_path.init(path, this); - found_src_paths = true; + early_late->to_string().c_str(), + rf->to_string().c_str(), + delayAsString(path->arrival(), this)); + delete src_path.prevPath(); + src_path = *path; + Path *prev_copy = &src_path; + Path *p = path->prevPath(); + while (p) { + Path *copy = new Path(p); + copy->setIsEnum(true); + prev_copy->setPrevPath(copy); + prev_copy = copy; + p = p->prevPath(); + } + found_src_paths = true; } } } @@ -973,8 +974,8 @@ Genclks::matchesSrcFilter(Path *path, return false; } -PathVertex -Genclks::srcPath(Path *clk_path) const +Path * +Genclks::srcPath(const Path *clk_path) const { const Pin *src_pin = clk_path->pin(this); const ClockEdge *clk_edge = clk_path->clkEdge(this); @@ -985,7 +986,7 @@ Genclks::srcPath(Path *clk_path) const insert_ap); } -PathVertex +Path * Genclks::srcPath(const ClockEdge *clk_edge, const Pin *src_pin, const PathAnalysisPt *path_ap) const @@ -993,20 +994,52 @@ Genclks::srcPath(const ClockEdge *clk_edge, return srcPath(clk_edge->clock(), src_pin, clk_edge->transition(), path_ap); } -PathVertex +Path * Genclks::srcPath(const Clock *gclk, const Pin *src_pin, const RiseFall *rf, const PathAnalysisPt *path_ap) const { - PathVertexPtr *src_paths = - genclk_src_paths_.findKey(ClockPinPair(gclk, src_pin)); - if (src_paths) { - int path_index = srcPathIndex(rf, path_ap); - return PathVertex(src_paths[path_index], this); + auto itr = genclk_src_paths_.find(ClockPinPair(gclk, src_pin)); + if (itr != genclk_src_paths_.end()) { + vector src_paths = itr->second; + if (!src_paths.empty()) { + size_t path_index = srcPathIndex(rf, path_ap); + Path &src_path = src_paths[path_index]; + if (!src_path.isNull()) { + Path *src_vpath = Path::vertexPath(src_path, this); + return src_vpath; + } + } + } + return nullptr; +} + +void +Genclks::updateSrcPathPrevs() +{ + for (auto const & [clk_pin, src_paths] : genclk_src_paths_) { + for (const Path &src_path : src_paths) { + if (!src_path.isNull()) { + const Path *p = &src_path; + while (p) { + Path *src_vpath = Path::vertexPath(p->vertex(this), + p->tag(this), this); + Path *prev_path = p->prevPath(); + if (prev_path) { + Path *prev_vpath = Path::vertexPath(prev_path->vertex(this), + prev_path->tag(this), this); + src_vpath->setPrevPath(prev_vpath); + src_vpath->setPrevEdgeArc(p->prevEdge(this), + p->prevArc(this), this); + } + p = p->prevPath(); + } + debugPrint(debug_, "genclk", 3, "repaired src path prev %s", + src_path.to_string(this).c_str()); + } + } } - else - return PathVertex(); } Arrival @@ -1017,9 +1050,9 @@ Genclks::insertionDelay(const Clock *clk, const PathAnalysisPt *path_ap) const { PathAnalysisPt *insert_ap = path_ap->insertionAnalysisPt(early_late); - PathVertex src_path = srcPath(clk, pin, rf, insert_ap); - if (!src_path.isNull()) - return src_path.arrival(this); + Path *src_path = srcPath(clk, pin, rf, insert_ap); + if (src_path) + return src_path->arrival(); else return 0.0; } diff --git a/search/Genclks.hh b/search/Genclks.hh index 7d662e1b..c063d31b 100644 --- a/search/Genclks.hh +++ b/search/Genclks.hh @@ -50,7 +50,7 @@ public: }; typedef Map GenclkInfoMap; -typedef Map GenclkSrcPathMap; +typedef Map, ClockPinPairLess> GenclkSrcPathMap; class Genclks : public StaState { @@ -71,19 +71,20 @@ public: const EarlyLate *early_late, const PathAnalysisPt *path_ap) const; // Generated clock source path for a clock path root. - PathVertex srcPath(Path *clk_path) const; + Path *srcPath(const Path *clk_path) const; // Generated clock source path. - PathVertex srcPath(const ClockEdge *clk_edge, - const Pin *src_pin, - const PathAnalysisPt *path_ap) const; - PathVertex srcPath(const Clock *clk, - const Pin *src_pin, - const RiseFall *rf, - const PathAnalysisPt *path_ap) const; - Vertex *srcPathVertex(const Pin *pin) const; + Path *srcPath(const ClockEdge *clk_edge, + const Pin *src_pin, + const PathAnalysisPt *path_ap) const; + Path *srcPath(const Clock *clk, + const Pin *src_pin, + const RiseFall *rf, + const PathAnalysisPt *path_ap) const; + Vertex *srcPath(const Pin *pin) const; Level clkPinMaxLevel(const Clock *clk) const; void copyGenClkSrcPaths(Vertex *vertex, TagGroupBldr *tag_bldr); + void updateSrcPathPrevs(); private: void findInsertionDelays(); @@ -94,8 +95,8 @@ private: void seedClkVertices(Clock *clk, BfsBkwdIterator &iter, VertexSet *fanins); - int srcPathIndex(const RiseFall *clk_rf, - const PathAnalysisPt *path_ap) const; + size_t srcPathIndex(const RiseFall *clk_rf, + const PathAnalysisPt *path_ap) const; bool matchesSrcFilter(Path *path, const Clock *gclk) const; void seedSrcPins(Clock *gclk, @@ -129,7 +130,6 @@ private: VertexSet &visited_vertices, EdgeSet *&fdbk_edges); - bool found_insertion_delays_; GenclkSrcPathMap genclk_src_paths_; GenclkInfoMap genclk_info_map_; diff --git a/search/Latches.cc b/search/Latches.cc index 947243ac..171df269 100644 --- a/search/Latches.cc +++ b/search/Latches.cc @@ -49,8 +49,8 @@ Latches::Latches(StaState *sta) : void Latches::latchRequired(const Path *data_path, - const PathVertex *enable_path, - const PathVertex *disable_path, + const Path *enable_path, + const Path *disable_path, const MultiCyclePath *mcp, const PathDelay *path_delay, Arrival src_clk_latency, @@ -61,7 +61,7 @@ Latches::latchRequired(const Path *data_path, Arrival &adjusted_data_arrival, Delay &time_given_to_startpoint) const { - const Arrival data_arrival = data_path->arrival(this); + const Arrival data_arrival = data_path->arrival(); float max_delay = 0.0; bool ignore_clk_latency = false; if (path_delay) { @@ -149,8 +149,8 @@ Latches::latchRequired(const Path *data_path, void Latches::latchBorrowInfo(const Path *data_path, - const PathVertex *enable_path, - const PathVertex *disable_path, + const Path *enable_path, + const Path *disable_path, const ArcDelay &margin, bool ignore_clk_latency, // Return values. @@ -213,8 +213,8 @@ Latches::latchBorrowInfo(const Path *data_path, void Latches::latchRequired(const Path *data_path, - const PathVertex *enable_path, - const PathVertex *disable_path, + const Path *enable_path, + const Path *disable_path, const PathAnalysisPt *path_ap, // Return values. Required &required, @@ -243,33 +243,29 @@ Latches::latchRequired(const Path *data_path, } // Find the latch enable open/close path from the close/open path. -void +Path * Latches::latchEnableOtherPath(const Path *path, - const PathAnalysisPt *tgt_clk_path_ap, - // Return value. - PathVertex &other_path) const + const PathAnalysisPt *tgt_clk_path_ap) const { Vertex *vertex = path->vertex(this); const ClockEdge *clk_edge = path->clkEdge(this); const ClockEdge *other_clk_edge = path->clkInfo(this)->isPulseClk() ? clk_edge:clk_edge->opposite(); - RiseFall *other_rf = path->transition(this)->opposite(); + const RiseFall *other_rf = path->transition(this)->opposite(); VertexPathIterator path_iter(vertex, other_rf, tgt_clk_path_ap, this); while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); + Path *path = path_iter.next(); if (path->isClock(this) && path->clkEdge(this) == other_clk_edge) { - other_path = path; - break; + return path; } } + return nullptr; } -void +Path * Latches::latchEnablePath(const Path *q_path, - const Edge *d_q_edge, - // Return value. - PathVertex &enable_path) const + const Edge *d_q_edge) const { const ClockEdge *en_clk_edge = q_path->clkEdge(this); @@ -283,15 +279,15 @@ Latches::latchEnablePath(const Path *q_path, if (state == LatchEnableState::enabled) { VertexPathIterator path_iter(en_vertex, en_rf, tgt_clk_path_ap, this); while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); + Path *path = path_iter.next(); const ClockEdge *clk_edge = path->clkEdge(this); if (path->isClock(this) && clk_edge == en_clk_edge) { - enable_path = path; - break; + return path; } } } + return nullptr; } // The arrival time for a latch D->Q edge is clipped to the window of @@ -324,7 +320,7 @@ Latches::latchOutArrival(const Path *data_path, if (!(excpt && excpt->isFalse())) { arc_delay = search_->deratedDelay(data_vertex, d_q_arc, d_q_edge, false, path_ap); - q_arrival = data_path->arrival(this) + arc_delay; + q_arrival = data_path->arrival() + arc_delay; q_tag = data_path->tag(this); } } @@ -334,7 +330,7 @@ Latches::latchOutArrival(const Path *data_path, VertexPathIterator enable_iter(enable_vertex, enable_rf, tgt_clk_path_ap, this); while (enable_iter.hasNext()) { - PathVertex *enable_path = enable_iter.next(); + Path *enable_path = enable_iter.next(); ClkInfo *en_clk_info = enable_path->clkInfo(this); const ClockEdge *en_clk_edge = en_clk_info->clkEdge(); if (enable_path->isClock(this)) { @@ -342,12 +338,11 @@ Latches::latchOutArrival(const Path *data_path, // D->Q is disabled when if there is a path delay -to D or EN clk. if (!(excpt && (excpt->isFalse() || excpt->isPathDelay()))) { - PathVertex disable_path; - latchEnableOtherPath(enable_path, tgt_clk_path_ap, disable_path); + Path *disable_path = latchEnableOtherPath(enable_path, tgt_clk_path_ap); Delay borrow, time_given_to_startpoint; Arrival adjusted_data_arrival; Required required; - latchRequired(data_path, enable_path, &disable_path, path_ap, + latchRequired(data_path, enable_path, disable_path, path_ap, required, borrow, adjusted_data_arrival, time_given_to_startpoint); if (delayGreater(borrow, 0.0, this)) { @@ -357,7 +352,7 @@ Latches::latchOutArrival(const Path *data_path, q_arrival = adjusted_data_arrival + arc_delay; // Tag switcheroo - data passing thru gets latch enable tag. // States and path ap come from Q, everything else from enable. - PathVertex *crpr_clk_path = + Path *crpr_clk_path = sdc_->crprActive() ? enable_path : nullptr; ClkInfo *q_clk_info = search_->findClkInfo(en_clk_edge, @@ -371,7 +366,7 @@ Latches::latchOutArrival(const Path *data_path, en_clk_info->uncertainties(), path_ap, crpr_clk_path); - RiseFall *q_rf = d_q_arc->toEdge()->asRiseFall(); + const RiseFall *q_rf = d_q_arc->toEdge()->asRiseFall(); ExceptionStateSet *states = nullptr; // Latch data pin is a valid exception -from pin. if (sdc_->exceptionFromStates(data_path->pin(this), @@ -448,24 +443,23 @@ Latches::latchTimeGivenToStartpoint(const Path *d_path, const Edge *d_q_edge, // Return values. Arrival &time_given, - PathVertex &enable_path) const + Path *&enable_path) const { - latchEnablePath(q_path, d_q_edge, enable_path); - if (!enable_path.isNull() - && enable_path.isClock(this)) { + enable_path = latchEnablePath(q_path, d_q_edge); + if (enable_path + && enable_path->isClock(this)) { const PathAnalysisPt *path_ap = q_path->pathAnalysisPt(this); const PathAnalysisPt *tgt_clk_path_ap = path_ap->tgtClkAnalysisPt(); - PathVertex disable_path; - latchEnableOtherPath(enable_path.path(), tgt_clk_path_ap, disable_path); + Path *disable_path = latchEnableOtherPath(enable_path, tgt_clk_path_ap); Delay borrow; Required required; Arrival adjusted_data_arrival; - latchRequired(d_path, &enable_path, &disable_path, path_ap, + latchRequired(d_path, enable_path, disable_path, path_ap, required, borrow, adjusted_data_arrival, time_given); } else { time_given = 0.0; - enable_path.init(); + enable_path = nullptr; } } @@ -517,7 +511,7 @@ Latches::latchDtoQEnable(const Edge *d_q_edge, } LatchEnableState -Latches::latchDtoQState(Edge *edge) const +Latches::latchDtoQState(const Edge *edge) const { const Vertex *from_vertex = edge->from(graph_); const Pin *from_pin = from_vertex->pin(); @@ -532,7 +526,7 @@ Latches::latchDtoQState(Edge *edge) const // Latch D->Q arc looks combinational when the enable pin is disabled // or constant. bool -Latches::isLatchDtoQ(Edge *edge) const +Latches::isLatchDtoQ(const Edge *edge) const { return edge->role() == TimingRole::latchDtoQ() && latchDtoQState(edge) == LatchEnableState::enabled; diff --git a/search/Latches.hh b/search/Latches.hh index 4f14fc2d..689e1685 100644 --- a/search/Latches.hh +++ b/search/Latches.hh @@ -43,10 +43,10 @@ public: const Edge *d_q_edge, // Return values. Arrival &time_given, - PathVertex &enable_path) const; + Path *&enable_path) const; void latchRequired(const Path *data_path, - const PathVertex *enable_path, - const PathVertex *disable_path, + const Path *enable_path, + const Path *disable_path, const MultiCyclePath *mcp, const PathDelay *path_delay, Arrival src_clk_latency, @@ -57,8 +57,8 @@ public: Arrival &adjusted_data_arrival, Delay &time_given_to_startpoint) const; void latchRequired(const Path *data_path, - const PathVertex *enable_path, - const PathVertex *disable_path, + const Path *enable_path, + const Path *disable_path, const PathAnalysisPt *path_ap, // Return values. Required &required, @@ -66,8 +66,8 @@ public: Arrival &adjusted_data_arrival, Delay &time_given_to_startpoint) const; void latchBorrowInfo(const Path *data_path, - const PathVertex *enable_path, - const PathVertex *disable_path, + const Path *enable_path, + const Path *disable_path, const ArcDelay &margin, bool ignore_clk_latency, // Return values. @@ -79,7 +79,7 @@ public: Crpr &crpr_diff, Delay &max_borrow, bool &borrow_limit_exists) const; - bool isLatchDtoQ(Edge *edge) const; + bool isLatchDtoQ(const Edge *edge) const; // Find the latch EN->Q edge for a D->Q edge. void latchDtoQEnable(const Edge *d_q_edge, const Instance *inst, @@ -87,15 +87,11 @@ public: Vertex *&enable_vertex, const RiseFall *&enable_rf, LatchEnableState &state) const; - LatchEnableState latchDtoQState(Edge *d_q_edge) const; - void latchEnableOtherPath(const Path *path, - const PathAnalysisPt *tgt_clk_path_ap, - // Return value. - PathVertex &other_path) const; - void latchEnablePath(const Path *q_path, - const Edge *d_q_edge, - // Return value. - PathVertex &enable_path) const; + LatchEnableState latchDtoQState(const Edge *d_q_edge) const; + Path *latchEnableOtherPath(const Path *path, + const PathAnalysisPt *tgt_clk_path_ap) const; + Path *latchEnablePath(const Path *q_path, + const Edge *d_q_edge) const; void latchOutArrival(const Path *data_path, const TimingArc *d_q_arc, const Edge *d_q_edge, diff --git a/search/Levelize.cc b/search/Levelize.cc index 48dcad2c..0cc5ac52 100644 --- a/search/Levelize.cc +++ b/search/Levelize.cc @@ -157,7 +157,8 @@ Levelize::findRoots() Vertex *vertex = vertex_iter.next(); setLevel(vertex, 0); if (isRoot(vertex)) { - debugPrint(debug_, "levelize", 2, "root %s", vertex->name(sdc_network_)); + debugPrint(debug_, "levelize", 2, "root %s", + vertex->to_string(this).c_str()); roots_->insert(vertex); if (hasFanout(vertex, search_pred_, graph_)) // Color roots with no fanout black so that they are @@ -219,7 +220,7 @@ Levelize::visit(Vertex *vertex, { Pin *from_pin = vertex->pin(); debugPrint(debug_, "levelize", 3, "level %d %s", - level, vertex->name(sdc_network_)); + level, vertex->to_string(this).c_str()); vertex->setColor(LevelColor::gray); setLevel(vertex, level); max_level_ = max(level, max_level_); @@ -269,8 +270,8 @@ Levelize::reportPath(EdgeSeq &path) const while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); if (first_edge) - report_->reportLine(" %s", edge->from(graph_)->name(network_)); - report_->reportLine(" %s", edge->to(graph_)->name(network_)); + report_->reportLine(" %s", edge->from(graph_)->to_string(this).c_str()); + report_->reportLine(" %s", edge->to(graph_)->to_string(this).c_str()); first_edge = false; } } @@ -279,10 +280,9 @@ void Levelize::recordLoop(Edge *edge, EdgeSeq &path) { - debugPrint(debug_, "levelize", 2, "Loop edge %s -> %s (%s)", - edge->from(graph_)->name(sdc_network_), - edge->to(graph_)->name(sdc_network_), - edge->role()->asString()); + debugPrint(debug_, "levelize", 2, "Loop edge %s (%s)", + edge->to_string(this).c_str(), + edge->role()->to_string().c_str()); // Do not record loops if they have been invalidated. if (loops_) { EdgeSeq *loop_edges = loopEdges(path, edge); @@ -313,16 +313,14 @@ Levelize::loopEdges(EdgeSeq &path, if (from_pin == loop_pin) copy = true; if (copy) { - debugPrint(debug_, "loop", 2, " %s -> %s", - edge->from(graph_)->name(sdc_network_), - edge->to(graph_)->name(sdc_network_)); + debugPrint(debug_, "loop", 2, " %s", + edge->to_string(this).c_str()); loop_edges->push_back(edge); loop_edges_.insert(edge); } } - debugPrint(debug_, "loop", 2, " %s -> %s", - closing_edge->from(graph_)->name(sdc_network_), - closing_edge->to(graph_)->name(sdc_network_)); + debugPrint(debug_, "loop", 2, " %s", + closing_edge->to_string(this).c_str()); loop_edges->push_back(closing_edge); loop_edges_.insert(closing_edge); return loop_edges; @@ -388,7 +386,7 @@ void Levelize::invalidFrom(Vertex *vertex) { debugPrint(debug_, "levelize", 1, "level invalid from %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); VertexInEdgeIterator edge_iter(vertex, graph_); while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); @@ -410,7 +408,7 @@ void Levelize::relevelizeFrom(Vertex *vertex) { debugPrint(debug_, "levelize", 1, "invalid relevelize from %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); relevelize_from_->insert(vertex); levels_valid_ = false; } @@ -440,7 +438,7 @@ Levelize::relevelize() { for (Vertex *vertex : *relevelize_from_) { debugPrint(debug_, "levelize", 1, "relevelize from %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); if (search_pred_->searchFrom(vertex)) { if (isRoot(vertex)) { setLevel(vertex, 0); @@ -490,7 +488,7 @@ GraphLoop::isCombinational() const EdgeSeq::Iterator edge_iter(edges_); while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); - TimingRole *role = edge->role(); + const TimingRole *role = edge->role(); if (!(role == TimingRole::wire() || role == TimingRole::combinational() || role == TimingRole::tristateEnable() @@ -501,17 +499,17 @@ GraphLoop::isCombinational() const } void -GraphLoop::report(Report *report, - Network *network, - Graph *graph) const +GraphLoop::report(const StaState *sta) const { + Graph *graph = sta->graph(); + Report *report = sta->report(); bool first_edge = true; EdgeSeq::Iterator loop_edge_iter(edges_); while (loop_edge_iter.hasNext()) { Edge *edge = loop_edge_iter.next(); if (first_edge) - report->reportLine(" %s", edge->from(graph)->name(network)); - report->reportLine(" %s", edge->to(graph)->name(network)); + report->reportLine(" %s", edge->from(graph)->to_string(sta).c_str()); + report->reportLine(" %s", edge->to(graph)->to_string(graph).c_str()); first_edge = false; } } diff --git a/search/Levelize.hh b/search/Levelize.hh index 2c089ddb..8cc3118f 100644 --- a/search/Levelize.hh +++ b/search/Levelize.hh @@ -104,9 +104,7 @@ public: ~GraphLoop(); EdgeSeq *edges() { return edges_; } bool isCombinational() const; - void report(Report *report, - Network *network, - Graph *graph) const; + void report(const StaState *sta) const; private: EdgeSeq *edges_; diff --git a/search/MakeTimingModel.cc b/search/MakeTimingModel.cc index 9de20759..88e6accb 100644 --- a/search/MakeTimingModel.cc +++ b/search/MakeTimingModel.cc @@ -146,7 +146,7 @@ MakeTimingModel::makeLibrary() LibertyLibrary *default_lib = network_->defaultLibertyLibrary(); *library_->units() = *default_lib->units(); - for (RiseFall *rf : RiseFall::range()) { + for (const RiseFall *rf : RiseFall::range()) { library_->setInputThreshold(rf, default_lib->inputThreshold(rf)); library_->setOutputThreshold(rf, default_lib->outputThreshold(rf)); library_->setSlewLowerThreshold(rf, default_lib->slewLowerThreshold(rf)); @@ -280,7 +280,7 @@ MakeEndTimingArcs::visit(PathEnd *path_end) Network *network = sta_->network(); Debug *debug = sta_->debug(); const MinMax *min_max = path_end->minMax(sta_); - Arrival data_delay = src_path->arrival(sta_); + Arrival data_delay = src_path->arrival(); Delay clk_latency = path_end->targetClkDelay(sta_); ArcDelay check_margin = path_end->margin(sta_); Delay margin = min_max == MinMax::max() @@ -292,7 +292,7 @@ MakeEndTimingArcs::visit(PathEnd *path_end) network->pathName(src_path->pin(sta_)), tgt_clk_edge->name(), path_end->typeName(), - min_max->asString(), + min_max->to_string().c_str(), delayAsString(margin, sta_)); if (debug->check("make_timing_model", 3)) sta_->reportPathEnd(path_end); @@ -335,8 +335,8 @@ MakeTimingModel::findTimingFromInput(Port *input_port) if (!sta_->isClockSrc(input_pin)) { MakeEndTimingArcs end_visitor(sta_); OutputPinDelays output_delays; - for (RiseFall *input_rf : RiseFall::range()) { - RiseFallBoth *input_rf1 = input_rf->asRiseFallBoth(); + for (const RiseFall *input_rf : RiseFall::range()) { + const RiseFallBoth *input_rf1 = input_rf->asRiseFallBoth(); sta_->setInputDelay(input_pin, input_rf1, sdc_->defaultArrivalClock(), sdc_->defaultArrivalClockEdge()->transition(), @@ -377,11 +377,11 @@ MakeTimingModel::findOutputDelays(const RiseFall *input_rf, Vertex *output_vertex = graph_->pinLoadVertex(output_pin); VertexPathIterator path_iter(output_vertex, this); while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); + Path *path = path_iter.next(); if (search_->matchesFilter(path, nullptr)) { const RiseFall *output_rf = path->transition(sta_); const MinMax *min_max = path->minMax(sta_); - Arrival delay = path->arrival(sta_); + Arrival delay = path->arrival(); OutputDelays &delays = output_pin_delays[output_pin]; delays.delays.mergeValue(output_rf, min_max, delayAsFloat(delay, min_max, sta_)); @@ -398,10 +398,10 @@ MakeTimingModel::makeSetupHoldTimingArcs(const Pin *input_pin, const ClockEdgeDelays &clk_margins) { for (const auto& [clk_edge, margins] : clk_margins) { - for (MinMax *min_max : MinMax::range()) { + for (const MinMax *min_max : MinMax::range()) { bool setup = (min_max == MinMax::max()); TimingArcAttrsPtr attrs = nullptr; - for (RiseFall *input_rf : RiseFall::range()) { + for (const RiseFall *input_rf : RiseFall::range()) { float margin; bool exists; margins.value(input_rf, min_max, margin, exists); @@ -426,8 +426,10 @@ MakeTimingModel::makeSetupHoldTimingArcs(const Pin *input_pin, for (const Pin *clk_pin : clk_edge->clock()->pins()) { LibertyPort *clk_port = modelPort(clk_pin); if (clk_port) { - RiseFall *clk_rf = clk_edge->transition(); - TimingRole *role = setup ? TimingRole::setup() : TimingRole::hold(); + const RiseFall *clk_rf = clk_edge->transition(); + const TimingRole *role = setup + ? TimingRole::setup() + : TimingRole::hold(); lib_builder_->makeFromTransitionArcs(cell_, clk_port, input_port, nullptr, clk_rf, role, attrs); @@ -444,8 +446,8 @@ MakeTimingModel::makeInputOutputTimingArcs(const Pin *input_pin, { for (const auto& [output_pin, output_delays] : output_pin_delays) { TimingArcAttrsPtr attrs = nullptr; - for (RiseFall *output_rf : RiseFall::range()) { - MinMax *min_max = MinMax::max(); + for (const RiseFall *output_rf : RiseFall::range()) { + const MinMax *min_max = MinMax::max(); float delay; bool exists; output_delays.delays.value(output_rf, min_max, delay, exists); @@ -486,12 +488,12 @@ MakeTimingModel::findClkedOutputPaths() Vertex *output_vertex = graph_->pinLoadVertex(output_pin); VertexPathIterator path_iter(output_vertex, this); while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); + Path *path = path_iter.next(); const ClockEdge *clk_edge = path->clkEdge(sta_); if (clk_edge) { const RiseFall *output_rf = path->transition(sta_); const MinMax *min_max = path->minMax(sta_); - Arrival delay = path->arrival(sta_); + Arrival delay = path->arrival(); RiseFallMinMax &delays = clk_delays[clk_edge]; delays.mergeValue(output_rf, min_max, delayAsFloat(delay, min_max, sta_)); @@ -501,9 +503,9 @@ MakeTimingModel::findClkedOutputPaths() for (const Pin *clk_pin : clk_edge->clock()->pins()) { LibertyPort *clk_port = modelPort(clk_pin); if (clk_port) { - RiseFall *clk_rf = clk_edge->transition(); + const RiseFall *clk_rf = clk_edge->transition(); TimingArcAttrsPtr attrs = nullptr; - for (RiseFall *output_rf : RiseFall::range()) { + for (const RiseFall *output_rf : RiseFall::range()) { float delay = delays.value(output_rf, min_max_) - clk_edge->time(); TimingModel *gate_model = makeGateModelTable(output_pin, delay, output_rf); if (attrs == nullptr) @@ -567,7 +569,7 @@ MakeTimingModel::makeClkTreePaths(LibertyPort *lib_port, const RiseFall *end_rf = (sense == TimingSense::positive_unate) ? clk_rf : clk_rf->opposite(); - PathVertex clk_path; + Path clk_path; Delay insertion, delay, latency; float lib_clk_delay; bool exists; @@ -582,7 +584,7 @@ MakeTimingModel::makeClkTreePaths(LibertyPort *lib_port, } if (attrs) { attrs->setTimingSense(sense); - TimingRole *role = (min_max == MinMax::min()) + const TimingRole *role = (min_max == MinMax::min()) ? TimingRole::clockTreePathMin() : TimingRole::clockTreePathMax(); lib_builder_->makeClockTreePathArcs(cell_, lib_port, role, min_max, attrs); diff --git a/search/MakeTimingModelPvt.hh b/search/MakeTimingModelPvt.hh index eb102073..babd247a 100644 --- a/search/MakeTimingModelPvt.hh +++ b/search/MakeTimingModelPvt.hh @@ -108,7 +108,7 @@ private: const Corner *corner_; LibertyLibrary *library_; LibertyCell *cell_; - MinMax *min_max_; + const MinMax *min_max_; LibertyBuilder *lib_builder_; // Output driver table model template to model template. Map template_map_; diff --git a/search/Path.cc b/search/Path.cc index c592a418..b2b76f37 100644 --- a/search/Path.cc +++ b/search/Path.cc @@ -33,28 +33,213 @@ #include "Corner.hh" #include "PathAnalysisPt.hh" #include "Tag.hh" -#include "PathRef.hh" +#include "TagGroup.hh" +#include "Search.hh" namespace sta { -const char * -Path::name(const StaState *sta) const +Path::Path() : + prev_path_(nullptr), + arrival_(0.0), + required_(0.0), + vertex_id_(vertex_id_null), + tag_index_(tag_index_null), + is_enum_(false), + prev_arc_idx_(0) { - const Network *network = sta->network(); - Vertex *vertex1 = vertex(sta); - if (vertex1) { - const char *vertex_name = vertex1->name(network); - const char *tr_str = transition(sta)->asString(); - const PathAnalysisPt *path_ap = pathAnalysisPt(sta); - int ap_index = path_ap->index(); - const char *min_max = path_ap->pathMinMax()->asString(); - TagIndex tag_index = tagIndex(sta); - return stringPrintTmp("%s %s %s/%d %d", - vertex_name, tr_str, min_max, - ap_index, tag_index); +} + +Path::Path(Path *path) : + prev_path_(path ? path->prev_path_ : nullptr), + arrival_(path ? path->arrival_ : 0.0), + required_(path ? path->required_ : 0.0), + vertex_id_(path ? path->vertex_id_ : vertex_id_null), + tag_index_(path ? path->tag_index_ : tag_index_null), + is_enum_(path ? path->is_enum_ : false), + prev_arc_idx_(path ? path->prev_arc_idx_ : 0) +{ +} + +Path::Path(Vertex *vertex, + Tag *tag, + const StaState *sta) : + prev_path_(nullptr), + arrival_(0.0), + required_(0.0), + tag_index_(tag->index()), + is_enum_(false), + prev_arc_idx_(0) +{ + const Graph *graph = sta->graph(); + vertex_id_ = graph->id(vertex); +} + +Path::Path(Vertex *vertex, + Tag *tag, + Arrival arrival, + Path *prev_path, + Edge *prev_edge, + TimingArc *prev_arc, + const StaState *sta) : + prev_path_(prev_path), + arrival_(arrival), + required_(0.0), + tag_index_(tag->index()), + is_enum_(false) +{ + const Graph *graph = sta->graph(); + if (prev_path) { + prev_edge_id_ = graph->id(prev_edge); + prev_arc_idx_ = prev_arc->index(); + } + else { + vertex_id_ = graph->id(vertex); + prev_arc_idx_ = 0; + } +} + +Path::Path(Vertex *vertex, + Tag *tag, + Arrival arrival, + Path *prev_path, + Edge *prev_edge, + TimingArc *prev_arc, + bool is_enum, + const StaState *sta) : + prev_path_(prev_path), + arrival_(arrival), + required_(0.0), + tag_index_(tag->index()), + is_enum_(is_enum) +{ + const Graph *graph = sta->graph(); + if (prev_path) { + prev_edge_id_ = graph->id(prev_edge); + prev_arc_idx_ = prev_arc->index(); + } + else { + vertex_id_ = graph->id(vertex); + prev_arc_idx_ = 0; + } +} + +Path:: ~Path() +{ + if (is_enum_ && prev_path_ && prev_path_->is_enum_) + delete prev_path_; +} + +void +Path::init(Vertex *vertex, + Arrival arrival, + const StaState *sta) +{ + const Graph *graph = sta->graph(); + vertex_id_ = graph->id(vertex); + tag_index_ = tag_index_null, + prev_path_ = nullptr; + prev_arc_idx_ = 0; + arrival_ = arrival; + required_ = 0.0; + is_enum_ = false; +} + +void +Path::init(Vertex *vertex, + Tag *tag, + const StaState *sta) +{ + const Graph *graph = sta->graph(); + vertex_id_ = graph->id(vertex); + tag_index_ = tag->index(), + prev_path_ = nullptr; + prev_arc_idx_ = 0; + arrival_ = 0.0; + required_ = 0.0; + is_enum_ = false; +} + +void +Path::init(Vertex *vertex, + Tag *tag, + Arrival arrival, + const StaState *sta) +{ + const Graph *graph = sta->graph(); + vertex_id_ = graph->id(vertex); + tag_index_ = tag->index(), + prev_path_ = nullptr; + prev_arc_idx_ = 0; + arrival_ = arrival; + required_ = 0.0; + is_enum_ = false; +} + +void +Path::init(Vertex *vertex, + Tag *tag, + Arrival arrival, + Path *prev_path, + Edge *prev_edge, + TimingArc *prev_arc, + const StaState *sta) +{ + const Graph *graph = sta->graph(); + tag_index_ = tag->index(), + prev_path_ = prev_path; + if (prev_path) { + prev_edge_id_ = graph->id(prev_edge); + prev_arc_idx_ = prev_arc->index(); + } + else { + vertex_id_ = graph->id(vertex); + prev_arc_idx_ = 0; + } + arrival_ = arrival; + required_ = 0.0; + is_enum_ = false; +} + +string +Path::to_string(const StaState *sta) const +{ + const PathAnalysisPt *path_ap = pathAnalysisPt(sta); + return stringPrintTmp("%s %s %s/%d %d", + vertex(sta)->to_string(sta).c_str(), + transition(sta)->to_string().c_str(), + path_ap->pathMinMax()->to_string().c_str(), + path_ap->index(), + tagIndex(sta)); +} + +bool +Path::isNull() const +{ + return vertex_id_ == vertex_id_null; +} + +Vertex * +Path::vertex(const StaState *sta) const +{ + const Graph *graph = sta->graph(); + if (prev_path_) { + const Edge *edge = graph->edge(prev_edge_id_); + return edge->to(graph); + } + else + return graph->vertex(vertex_id_); +} + +VertexId +Path::vertexId(const StaState *sta) const +{ + const Graph *graph = sta->graph(); + if (prev_path_) { + const Edge *edge = graph->edge(prev_edge_id_); + return edge->to(); } else - return "NULL"; + return vertex_id_; } Pin * @@ -63,10 +248,31 @@ Path::pin(const StaState *sta) const return vertex(sta)->pin(); } -TagIndex -Path::tagIndex(const StaState *sta) const +Tag * +Path::tag(const StaState *sta) const { - return tag(sta)->index(); + const Search *search = sta->search(); + return search->tag(tag_index_); +} + +void +Path::setTag(Tag *tag) +{ + tag_index_ = tag->index(); +} + +TagIndex +Path::tagIndex(const StaState *) const +{ + return tag_index_; +} + +size_t +Path::pathIndex(const StaState *sta) const +{ + Vertex *vertex = this->vertex(sta); + Path *paths = vertex->paths(); + return this - paths; } ClkInfo * @@ -118,80 +324,187 @@ Path::slew(const StaState *sta) const dcalcAnalysisPt(sta)->index()); } +const RiseFall * +Path::transition(const StaState *sta) const +{ + return tag(sta)->transition(); +} + int Path::rfIndex(const StaState *sta) const { return transition(sta)->index(); } -void -Path::initArrival(const StaState *sta) +PathAnalysisPt * +Path::pathAnalysisPt(const StaState *sta) const { - setArrival(delayInitValue(minMax(sta)), sta); -} - -bool -Path::arrivalIsInitValue(const StaState *sta) const -{ - return delayIsInitValue(arrival(sta), minMax(sta)); + return tag(sta)->pathAnalysisPt(sta); } void -Path::initRequired(const StaState *sta) +Path::setArrival(Arrival arrival) { - setRequired(delayInitValue(minMax(sta)->opposite()), sta); + arrival_ = arrival; } -bool -Path::requiredIsInitValue(const StaState *sta) const +void +Path::setRequired(const Required &required) { - return delayIsInitValue(required(sta), minMax(sta)->opposite()); + required_ = required; } Slack Path::slack(const StaState *sta) const { if (minMax(sta) == MinMax::max()) - return required(sta) - arrival(sta); + return required_ - arrival_; else - return arrival(sta) - required(sta); + return arrival_ - required_; +} + +Path * +Path::prevPath() const +{ + return prev_path_; } void -Path::prevPath(const StaState *sta, - // Return values. - PathRef &prev_path) const +Path::setPrevPath(Path *prev_path) { - TimingArc *prev_arc; - prevPath(sta, prev_path, prev_arc); + prev_path_ = prev_path; +} + +void +Path::clearPrevPath(const StaState *sta) +{ + // Preserve vertex ID for path when prev edge is no longer valid. + if (prev_path_) { + const Graph *graph = sta->graph(); + const Edge *prev_edge = graph->edge(prev_edge_id_); + vertex_id_ = prev_edge->to(); + prev_arc_idx_ = 0; + } + prev_path_ = nullptr; } TimingArc * Path::prevArc(const StaState *sta) const { - PathRef prev_path; - TimingArc *prev_arc; - prevPath(sta, prev_path, prev_arc); - return prev_arc; + if (prev_path_) { + const Graph *graph = sta->graph(); + const Edge *edge = graph->edge(prev_edge_id_); + TimingArcSet *arc_set = edge->timingArcSet(); + return arc_set->findTimingArc(prev_arc_idx_); + } + else + return nullptr; } Edge * -Path::prevEdge(const TimingArc *prev_arc, - const StaState *sta) const +Path::prevEdge(const StaState *sta) const { - if (prev_arc) { - TimingArcSet *arc_set = prev_arc->set(); - VertexInEdgeIterator edge_iter(vertex(sta), sta->graph()); - while (edge_iter.hasNext()) { - Edge *edge = edge_iter.next(); - if (edge->timingArcSet() == arc_set) - return edge; + if (prev_path_) { + const Graph *graph = sta->graph(); + return graph->edge(prev_edge_id_); + } + else + return nullptr; +} + +Vertex * +Path::prevVertex(const StaState *sta) const +{ + if (prev_path_) { + const Graph *graph = sta->graph(); + return graph->edge(prev_edge_id_)->from(graph); + } + else + return nullptr; +} + +void +Path::setPrevEdgeArc(Edge *prev_edge, + TimingArc *prev_arc, + const StaState *sta) +{ + if (prev_edge) { + const Graph *graph = sta->graph(); + prev_edge_id_ = graph->id(prev_edge); + prev_arc_idx_ = prev_arc->index(); + } + else + prev_arc_idx_ = 0; +} + +void +Path::checkPrevPaths(const StaState *sta) const +{ + const Path *path = this; + while (path) { + path->checkPrevPath(sta); + path = path->prevPath(); + } +} + +void +Path::checkPrevPath(const StaState *sta) const +{ + if (prev_path_ && !prev_path_->isNull()) { + Graph *graph = sta->graph(); + Edge *edge = prevEdge(sta); + Vertex *prev_vertex = prev_path_->vertex(sta); + Vertex *prev_edge_vertex = edge->from(graph); + if (prev_vertex != prev_edge_vertex) { + Network *network = sta->network(); + sta->report()->reportLine("path %s prev path corrupted %s vs %s.", + to_string(sta).c_str(), + prev_vertex->name(network), + prev_edge_vertex->name(network)); } } +} + +void +Path::setIsEnum(bool is_enum) +{ + is_enum_ = is_enum; +} + +//////////////////////////////////////////////////////////////// + +Path * +Path::vertexPath(const Path &path, + const StaState *sta) +{ + if (!path.isNull()) { + Vertex *vertex = path.vertex(sta); + Tag *tag = path.tag(sta); + return vertexPath(vertex, tag, sta); + } return nullptr; } -//////////////////////////////////////////////////////////////// +Path * +Path::vertexPath(const Vertex *vertex, + Tag *tag, + const StaState *sta) +{ + const Search *search = sta->search(); + TagGroup *tag_group = search->tagGroup(vertex); + if (tag_group) { + size_t path_index; + bool exists; + tag_group->pathIndex(tag, path_index, exists); + if (exists) { + Path *paths = vertex->paths(); + Path &src_vpath = paths[path_index]; + if (!src_vpath.isNull()) + return &src_vpath; + } + } + return nullptr; +} int Path::cmpPinTrClk(const Path *path1, @@ -256,11 +569,9 @@ Path::equal(const Path *path1, const Path *path2, const StaState *sta) { - bool path1_null = (path1 == nullptr || path1->isNull()); - bool path2_null = (path2 == nullptr || path2->isNull()); - return (path1_null && path2_null) - || (!path1_null - && !path2_null + return (path1 == nullptr && path2 == nullptr) + || (path1 + && path2 && path1->vertexId(sta) == path2->vertexId(sta) // Tag equal implies transition and path ap equal. && path1->tagIndex(sta) == path2->tagIndex(sta)); @@ -340,27 +651,27 @@ Path::cmpAll(const Path *path1, const Path *path2, const StaState *sta) { - PathRef p1(path1); - PathRef p2(path2); - while (!p1.isNull() - && !p2.isNull()) { - int cmp = Path::cmp(&p1, &p2, sta); + const Path *p1 = path1; + const Path *p2 = path2; + while (p1 && p2) { + int cmp = Path::cmp(p1, p2, sta); if (cmp != 0) return cmp; - TimingArc *prev_arc1, *prev_arc2; - p1.prevPath(sta, p1, prev_arc1); - p2.prevPath(sta, p2, prev_arc2); - if (equal(&p1, path1, sta)) + TimingArc *prev_arc1 = p1->prevArc(sta); + TimingArc *prev_arc2 = p2->prevArc(sta); + p1 = p1->prevPath(); + p2 = p2->prevPath(); + if (equal(p1, path1, sta)) // Equivalent latch loops. return 0; if ((prev_arc1 && prev_arc1->role()->isLatchDtoQ()) || (prev_arc2 && prev_arc2->role()->isLatchDtoQ())) break; } - if (p1.isNull() && p2.isNull()) + if (p1 == nullptr && p2 == nullptr) return 0; - else if (p1.isNull() && !p2.isNull()) + else if (p1 == nullptr && p2 != nullptr) return -1; else return 1; @@ -374,4 +685,160 @@ Path::lessAll(const Path *path1, return cmpAll(path1, path2, sta) < 0; } +//////////////////////////////////////////////////////////////// + +VertexPathIterator::VertexPathIterator(Vertex *vertex, + const StaState *sta) : + search_(sta->search()), + //filtered_(false), + rf_(nullptr), + path_ap_(nullptr), + min_max_(nullptr), + paths_(vertex->paths()), + path_count_(0), + //path_index_(0), + next_(nullptr) +{ + TagGroup *tag_group = search_->tagGroup(vertex); + if (tag_group) { + path_count_ = tag_group->pathCount(); + path_iter_.init(tag_group->pathIndexMap()); + findNext(); + } +} + +// Iterate over vertex paths with the same transition and +// analysis pt but different but different tags. +VertexPathIterator::VertexPathIterator(Vertex *vertex, + const RiseFall *rf, + const PathAnalysisPt *path_ap, + const StaState *sta) : + search_(sta->search()), + //filtered_(true), + rf_(rf), + path_ap_(path_ap), + min_max_(nullptr), + paths_(vertex->paths()), + //path_count_(0), + //path_index_(0), + next_(nullptr) +{ + TagGroup *tag_group = search_->tagGroup(vertex); + if (tag_group) { + path_count_ = tag_group->pathCount(); + path_iter_.init(tag_group->pathIndexMap()); + findNext(); + } +} + +VertexPathIterator::VertexPathIterator(Vertex *vertex, + const RiseFall *rf, + const MinMax *min_max, + const StaState *sta) : + search_(sta->search()), + //filtered_(true), + rf_(rf), + path_ap_(nullptr), + min_max_(min_max), + paths_(vertex->paths()), + //path_count_(0), + //path_index_(0), + next_(nullptr) +{ + TagGroup *tag_group = search_->tagGroup(vertex); + if (tag_group) { + path_count_ = tag_group->pathCount(); + path_iter_.init(tag_group->pathIndexMap()); + findNext(); + } +} + +VertexPathIterator::VertexPathIterator(Vertex *vertex, + const RiseFall *rf, + const PathAnalysisPt *path_ap, + const MinMax *min_max, + const StaState *sta) : + search_(sta->search()), + //filtered_(true), + rf_(rf), + path_ap_(path_ap), + min_max_(min_max), + paths_(vertex->paths()), + //path_count_(0), + //path_index_(0), + next_(nullptr) +{ + TagGroup *tag_group = search_->tagGroup(vertex); + if (tag_group) { + path_count_ = tag_group->pathCount(); + path_iter_.init(tag_group->pathIndexMap()); + findNext(); + } +} + +VertexPathIterator::~VertexPathIterator() +{ +} + +bool +VertexPathIterator::hasNext() +{ + return next_ != nullptr; +} + +#if 0 +void +VertexPathIterator::findNext() +{ + while (path_index_ < path_count_) { + Path *path = &paths_[path_index_++]; + if (filtered_) { + const Tag *tag = path->tag(search_); + if ((rf_ == nullptr + || tag->rfIndex() == rf_->index()) + && (path_ap_ == nullptr + || tag->pathAPIndex() == path_ap_->index()) + && (min_max_ == nullptr + || tag->pathAnalysisPt(search_)->pathMinMax() == min_max_)) { + next_ = path; + return; + } + } + else { + next_ = path; + return; + } + } + next_ = nullptr; +} +#endif + +void +VertexPathIterator::findNext() +{ + while (path_iter_.hasNext()) { + Tag *tag; + size_t path_index; + path_iter_.next(tag, path_index); + if ((rf_ == nullptr + || tag->rfIndex() == rf_->index()) + && (path_ap_ == nullptr + || tag->pathAPIndex() == path_ap_->index()) + && (min_max_ == nullptr + || tag->pathAnalysisPt(search_)->pathMinMax() == min_max_)) { + next_ = &paths_[path_index]; + return; + } + } + next_ = nullptr; +} + +Path * +VertexPathIterator::next() +{ + Path *path = next_; + findNext(); + return path; +} + } // namespace diff --git a/search/PathAnalysisPt.cc b/search/PathAnalysisPt.cc index ddcb09fc..e137ff76 100644 --- a/search/PathAnalysisPt.cc +++ b/search/PathAnalysisPt.cc @@ -42,6 +42,15 @@ PathAnalysisPt::PathAnalysisPt(Corner *corner, { } +string +PathAnalysisPt::to_string() const +{ + string name = corner_->name(); + name += '/'; + name += path_min_max_->to_string(); + return name; +} + void PathAnalysisPt::setTgtClkAnalysisPt(PathAnalysisPt *path_ap) { diff --git a/search/PathEnd.cc b/search/PathEnd.cc index 9bca45d6..203b3d52 100644 --- a/search/PathEnd.cc +++ b/search/PathEnd.cc @@ -55,31 +55,32 @@ PathEnd::PathEnd(Path *path) : PathEnd::~PathEnd() { - path_.deleteRep(); + if (path_->isEnum()) + delete path_; } void -PathEnd::setPath(const Path *path) +PathEnd::setPath(Path *path) { - path_.init(path); + path_ = path; } Vertex * PathEnd::vertex(const StaState *sta) const { - return path_.vertex(sta); + return path_->vertex(sta); } const MinMax * PathEnd::minMax(const StaState *sta) const { - return path_.pathAnalysisPt(sta)->pathMinMax(); + return path_->pathAnalysisPt(sta)->pathMinMax(); } const EarlyLate * PathEnd::pathEarlyLate(const StaState *sta) const { - return path_.pathAnalysisPt(sta)->pathMinMax(); + return path_->pathAnalysisPt(sta)->pathMinMax(); } const EarlyLate * @@ -91,31 +92,31 @@ PathEnd::clkEarlyLate(const StaState *sta) const const RiseFall * PathEnd::transition(const StaState *sta) const { - return path_.transition(sta); + return path_->transition(sta); } PathAPIndex PathEnd::pathIndex(const StaState *sta) const { - return path_.pathAnalysisPtIndex(sta); + return path_->pathAnalysisPtIndex(sta); } PathAnalysisPt * PathEnd::pathAnalysisPt(const StaState *sta) const { - return path_.pathAnalysisPt(sta); + return path_->pathAnalysisPt(sta); } const ClockEdge * PathEnd::sourceClkEdge(const StaState *sta) const { - return path_.clkEdge(sta); + return path_->clkEdge(sta); } Arrival -PathEnd::dataArrivalTime(const StaState *sta) const +PathEnd::dataArrivalTime(const StaState *) const { - return path_.arrival(sta); + return path_->arrival(); } Arrival @@ -133,7 +134,7 @@ PathEnd::requiredTimeOffset(const StaState *sta) const const RiseFall * PathEnd::targetClkEndTrans(const StaState *sta) const { - const PathVertex *clk_path = targetClkPath(); + const Path *clk_path = targetClkPath(); if (clk_path) return clk_path->transition(sta); else { @@ -229,19 +230,19 @@ PathEnd::targetClkMcpAdjustment(const StaState *) const return 0.0; } -TimingRole * +const TimingRole * PathEnd::checkRole(const StaState *) const { return nullptr; } -PathVertex * +Path * PathEnd::targetClkPath() { return nullptr; } -const PathVertex * +const Path * PathEnd::targetClkPath() const { return nullptr; @@ -303,7 +304,7 @@ PathEnd::exceptPathCmp(const PathEnd *path_end, //////////////////////////////////////////////////////////////// Delay -PathEnd::checkTgtClkDelay(const PathVertex *tgt_clk_path, +PathEnd::checkTgtClkDelay(const Path *tgt_clk_path, const ClockEdge *tgt_clk_edge, const TimingRole *check_role, const StaState *sta) @@ -315,7 +316,7 @@ PathEnd::checkTgtClkDelay(const PathVertex *tgt_clk_path, } void -PathEnd::checkTgtClkDelay(const PathVertex *tgt_clk_path, +PathEnd::checkTgtClkDelay(const Path *tgt_clk_path, const ClockEdge *tgt_clk_edge, const TimingRole *check_role, const StaState *sta, @@ -340,7 +341,7 @@ PathEnd::checkTgtClkDelay(const PathVertex *tgt_clk_path, || check_role->isDataCheck()) { // Propagated clock. Propagated arrival is seeded with // early_late==path_min_max insertion delay. - Arrival clk_arrival = tgt_clk_path->arrival(sta); + Arrival clk_arrival = tgt_clk_path->arrival(); Delay path_insertion = search->clockInsertion(tgt_clk, tgt_src_pin, tgt_clk_rf, min_max, min_max, tgt_path_ap); @@ -359,7 +360,7 @@ PathEnd::checkTgtClkDelay(const PathVertex *tgt_clk_path, float PathEnd::checkClkUncertainty(const ClockEdge *src_clk_edge, const ClockEdge *tgt_clk_edge, - const PathVertex *tgt_clk_path, + const Path *tgt_clk_path, const TimingRole *check_role, const StaState *sta) { @@ -375,12 +376,12 @@ PathEnd::checkClkUncertainty(const ClockEdge *src_clk_edge, } float -PathEnd::checkTgtClkUncertainty(const PathVertex *tgt_clk_path, +PathEnd::checkTgtClkUncertainty(const Path *tgt_clk_path, const ClockEdge *tgt_clk_edge, const TimingRole *check_role, const StaState *sta) { - MinMax *min_max = check_role->pathMinMax(); + const MinMax *min_max = check_role->pathMinMax(); ClockUncertainties *uncertainties = nullptr; if (tgt_clk_path && tgt_clk_path->isClock(sta)) uncertainties = tgt_clk_path->clkInfo(sta)->uncertainties(); @@ -455,7 +456,7 @@ PathEndUnconstrained::PathEndUnconstrained(Path *path) : PathEnd * PathEndUnconstrained::copy() { - return new PathEndUnconstrained(path_.path()); + return new PathEndUnconstrained(path_); } bool @@ -510,7 +511,7 @@ PathEndUnconstrained::typeName() const //////////////////////////////////////////////////////////////// PathEndClkConstrained::PathEndClkConstrained(Path *path, - PathVertex *clk_path) : + Path *clk_path) : PathEnd(path), clk_path_(clk_path), crpr_(0.0), @@ -519,7 +520,7 @@ PathEndClkConstrained::PathEndClkConstrained(Path *path, } PathEndClkConstrained::PathEndClkConstrained(Path *path, - PathVertex *clk_path, + Path *clk_path, Crpr crpr, bool crpr_valid) : PathEnd(path), @@ -530,9 +531,9 @@ PathEndClkConstrained::PathEndClkConstrained(Path *path, } void -PathEndClkConstrained::setPath(const Path *path) +PathEndClkConstrained::setPath(Path *path) { - path_.init(path); + path_ = path; crpr_valid_ = false; } @@ -559,33 +560,27 @@ PathEndClkConstrained::sourceClkOffset(const ClockEdge *src_clk_edge, Arrival PathEndClkConstrained::sourceClkLatency(const StaState *sta) const { - ClkInfo *clk_info = path_.clkInfo(sta); + ClkInfo *clk_info = path_->clkInfo(sta); return clk_info->latency(); } Arrival PathEndClkConstrained::sourceClkInsertionDelay(const StaState *sta) const { - ClkInfo *clk_info = path_.clkInfo(sta); + ClkInfo *clk_info = path_->clkInfo(sta); return clk_info->insertion(); } -PathVertex * +Path * PathEndClkConstrained::targetClkPath() { - if (clk_path_.isNull()) - return nullptr; - else - return &clk_path_; + return clk_path_; } -const PathVertex * +const Path * PathEndClkConstrained::targetClkPath() const { - if (clk_path_.isNull()) - return nullptr; - else - return &clk_path_; + return clk_path_; } float @@ -602,8 +597,8 @@ PathEndClkConstrained::targetClkOffset(const StaState *sta) const const ClockEdge * PathEndClkConstrained::targetClkEdge(const StaState *sta) const { - if (!clk_path_.isNull()) - return clk_path_.clkEdge(sta); + if (clk_path_) + return clk_path_->clkEdge(sta); else return nullptr; } @@ -708,7 +703,7 @@ PathEndClkConstrained::crpr(const StaState *sta) const { if (!crpr_valid_) { CheckCrpr *check_crpr = sta->search()->checkCrpr(); - crpr_ = check_crpr->checkCrpr(path_.path(), targetClkPath()); + crpr_ = check_crpr->checkCrpr(path_, targetClkPath()); crpr_valid_ = true; } return crpr_; @@ -751,7 +746,7 @@ PathEndClkConstrained::exceptPathCmp(const PathEnd *path_end, if (cmp == 0) { const PathEndClkConstrained *path_end2 = dynamic_cast(path_end); - const PathVertex *clk_path2 = path_end2->targetClkPath(); + const Path *clk_path2 = path_end2->targetClkPath(); return Path::cmp(targetClkPath(), clk_path2, sta); } else @@ -761,7 +756,7 @@ PathEndClkConstrained::exceptPathCmp(const PathEnd *path_end, //////////////////////////////////////////////////////////////// PathEndClkConstrainedMcp::PathEndClkConstrainedMcp(Path *path, - PathVertex *clk_path, + Path *clk_path, MultiCyclePath *mcp) : PathEndClkConstrained(path, clk_path), mcp_(mcp) @@ -769,7 +764,7 @@ PathEndClkConstrainedMcp::PathEndClkConstrainedMcp(Path *path, } PathEndClkConstrainedMcp::PathEndClkConstrainedMcp(Path *path, - PathVertex *clk_path, + Path *clk_path, MultiCyclePath *mcp, Crpr crpr, bool crpr_valid) : @@ -781,7 +776,7 @@ PathEndClkConstrainedMcp::PathEndClkConstrainedMcp(Path *path, float PathEndClkConstrainedMcp::targetClkMcpAdjustment(const StaState *sta) const { - return checkMcpAdjustment(path_.path(), targetClkEdge(sta), sta); + return checkMcpAdjustment(path_, targetClkEdge(sta), sta); } float @@ -887,8 +882,8 @@ PathEndClkConstrainedMcp::findHoldMcps(const ClockEdge *tgt_clk_edge, const StaState *sta) const { - Pin *pin = path_.pin(sta); - const RiseFall *rf = path_.transition(sta); + Pin *pin = path_->pin(sta); + const RiseFall *rf = path_->transition(sta); // Mcp may be setup, hold or setup_hold, since all match min paths. const MinMaxAll *mcp_min_max = mcp_->minMax(); Search *search = sta->search(); @@ -896,7 +891,7 @@ PathEndClkConstrainedMcp::findHoldMcps(const ClockEdge *tgt_clk_edge, hold_mcp = mcp_; setup_mcp = dynamic_cast(search->exceptionTo(ExceptionPathType::multi_cycle, - path_.path(), pin, rf, + path_, pin, rf, tgt_clk_edge, MinMax::max(), true, false)); @@ -905,7 +900,7 @@ PathEndClkConstrainedMcp::findHoldMcps(const ClockEdge *tgt_clk_edge, setup_mcp = mcp_; hold_mcp = dynamic_cast(search->exceptionTo(ExceptionPathType::multi_cycle, - path_.path(), pin, rf, + path_, pin, rf, tgt_clk_edge, MinMax::min(), true, false)); @@ -937,7 +932,7 @@ PathEndClkConstrainedMcp::exceptPathCmp(const PathEnd *path_end, PathEndCheck::PathEndCheck(Path *path, TimingArc *check_arc, Edge *check_edge, - PathVertex *clk_path, + Path *clk_path, MultiCyclePath *mcp, const StaState *) : PathEndClkConstrainedMcp(path, clk_path, mcp), @@ -949,7 +944,7 @@ PathEndCheck::PathEndCheck(Path *path, PathEndCheck::PathEndCheck(Path *path, TimingArc *check_arc, Edge *check_edge, - PathVertex *clk_path, + Path *clk_path, MultiCyclePath *mcp, Crpr crpr, bool crpr_valid) : @@ -962,8 +957,8 @@ PathEndCheck::PathEndCheck(Path *path, PathEnd * PathEndCheck::copy() { - return new PathEndCheck(path_.path(), check_arc_, check_edge_, - &clk_path_, mcp_, crpr_, crpr_valid_); + return new PathEndCheck(path_, check_arc_, check_edge_, + clk_path_, mcp_, crpr_, crpr_valid_); } PathEnd::Type @@ -990,7 +985,7 @@ PathEndCheck::reportShort(const ReportPath *report) const report->reportShort(this); } -TimingRole * +const TimingRole * PathEndCheck::checkRole(const StaState *) const { return check_edge_->role(); @@ -999,7 +994,7 @@ PathEndCheck::checkRole(const StaState *) const ArcDelay PathEndCheck::margin(const StaState *sta) const { - return sta->search()->deratedDelay(clk_path_.vertex(sta), + return sta->search()->deratedDelay(clk_path_->vertex(sta), check_arc_, check_edge_, false, pathAnalysisPt(sta)); } @@ -1028,20 +1023,20 @@ PathEndCheck::clkSkew(const StaState *sta) { return sourceClkDelay(sta) - targetClkDelay(sta) - crpr(sta) // Uncertainty decreases slack, but increases skew. - - checkTgtClkUncertainty(&clk_path_, clk_path_.clkEdge(sta), checkRole(sta), sta); + - checkTgtClkUncertainty(clk_path_, clk_path_->clkEdge(sta), + checkRole(sta), sta); } Delay PathEndCheck::sourceClkDelay(const StaState *sta) const { - PathExpanded expanded(&path_, sta); - PathRef src_clk_path; - expanded.clkPath(src_clk_path); - if (!src_clk_path.isNull()) { - ClkInfo *src_clk_info = path_.tag(sta)->clkInfo(); + PathExpanded expanded(path_, sta); + const Path *src_clk_path = expanded.clkPath(); + if (src_clk_path) { + ClkInfo *src_clk_info = path_->tag(sta)->clkInfo(); if (src_clk_info->isPropagated()) { // Propagated clock. Propagated arrival is seeded with insertion delay. - Arrival clk_arrival = src_clk_path.arrival(sta); + Arrival clk_arrival = src_clk_path->arrival(); const ClockEdge *src_clk_edge = src_clk_info->clkEdge(); Delay insertion = sourceClkInsertionDelay(sta); return delayRemove(clk_arrival - src_clk_edge->time(), insertion); @@ -1072,16 +1067,16 @@ PathEndCheck::macroClkTreeDelay(const StaState *sta) const const ClockEdge *tgt_clk_edge = targetClkEdge(sta); const Clock *tgt_clk = tgt_clk_edge->clock(); const Network *network = sta->network(); - const Pin *clk_pin = clk_path_.pin(sta); + const Pin *clk_pin = clk_path_->pin(sta); const Instance *inst = network->instance(clk_pin); const LibertyCell *inst_cell = network->libertyCell(inst); if (tgt_clk->isIdeal() && inst_cell && inst_cell->isMacro()) { LibertyPort *clk_port = network->libertyPort(clk_pin); if (clk_port) { - const MinMax *min_max = clk_path_.minMax(sta); - const RiseFall *rf = clk_path_.transition(sta); - float slew = delayAsFloat(clk_path_.slew(sta)); + const MinMax *min_max = clk_path_->minMax(sta); + const RiseFall *rf = clk_path_->transition(sta); + float slew = delayAsFloat(clk_path_->slew(sta)); return clk_port->clkTreeDelay(slew, rf, min_max); } } @@ -1093,7 +1088,7 @@ PathEndCheck::macroClkTreeDelay(const StaState *sta) const PathEndLatchCheck::PathEndLatchCheck(Path *path, TimingArc *check_arc, Edge *check_edge, - PathVertex *disable_path, + Path *disable_path, MultiCyclePath *mcp, PathDelay *path_delay, const StaState *sta) : @@ -1102,23 +1097,22 @@ PathEndLatchCheck::PathEndLatchCheck(Path *path, path_delay_(path_delay), src_clk_arrival_(0.0) { - PathVertex enable_path; Latches *latches = sta->latches(); - latches->latchEnableOtherPath(disable_path, - disable_path->pathAnalysisPt(sta), - enable_path); + Path *enable_path = + latches->latchEnableOtherPath(disable_path, + disable_path->pathAnalysisPt(sta)); clk_path_ = enable_path; Search *search = sta->search(); // Same as PathEndPathDelay::findRequired. if (path_delay_ && ignoreClkLatency(sta)) - src_clk_arrival_ = search->pathClkPathArrival(&path_); + src_clk_arrival_ = search->pathClkPathArrival(path_); } PathEndLatchCheck::PathEndLatchCheck(Path *path, TimingArc *check_arc, Edge *check_edge, - PathVertex *clk_path, - PathVertex *disable_path, + Path *clk_path, + Path *disable_path, MultiCyclePath *mcp, PathDelay *path_delay, Delay src_clk_arrival, @@ -1134,8 +1128,8 @@ PathEndLatchCheck::PathEndLatchCheck(Path *path, PathEnd * PathEndLatchCheck::copy() { - return new PathEndLatchCheck(path_.path(), check_arc_, check_edge_, - &clk_path_, &disable_path_, mcp_, path_delay_, + return new PathEndLatchCheck(path_, check_arc_, check_edge_, + clk_path_, disable_path_, mcp_, path_delay_, src_clk_arrival_, crpr_, crpr_valid_); } @@ -1151,22 +1145,16 @@ PathEndLatchCheck::typeName() const return "latch_check"; } -PathVertex * +Path * PathEndLatchCheck::latchDisable() { - if (disable_path_.isNull()) - return nullptr; - else - return &disable_path_; + return disable_path_; } -const PathVertex * +const Path * PathEndLatchCheck::latchDisable() const { - if (disable_path_.isNull()) - return nullptr; - else - return &disable_path_; + return disable_path_; } void @@ -1188,15 +1176,15 @@ PathEndLatchCheck::sourceClkOffset(const StaState *sta) const return pathDelaySrcClkOffset(path_, path_delay_, src_clk_arrival_, sta); else return PathEndClkConstrained::sourceClkOffset(sourceClkEdge(sta), - disable_path_.clkEdge(sta), + disable_path_->clkEdge(sta), TimingRole::setup(), sta); } -TimingRole * +const TimingRole * PathEndLatchCheck::checkRole(const StaState *sta) const { - if (clk_path_.clkInfo(sta)->isPulseClk()) + if (clk_path_->clkInfo(sta)->isPulseClk()) // Pulse latches use register cycle accounting. return TimingRole::setup(); else @@ -1211,7 +1199,7 @@ PathEndLatchCheck::requiredTime(const StaState *sta) const Required required; Arrival borrow, adjusted_data_arrival, time_given_to_startpoint; Latches *latches = sta->latches(); - latches->latchRequired(path_.path(), targetClkPath(), latchDisable(), + latches->latchRequired(path_, targetClkPath(), latchDisable(), mcp_, path_delay_, src_clk_arrival_, margin(sta), required, borrow, adjusted_data_arrival, time_given_to_startpoint); @@ -1224,7 +1212,7 @@ PathEndLatchCheck::borrow(const StaState *sta) const Latches *latches = sta->latches(); Required required; Arrival borrow, adjusted_data_arrival, time_given_to_startpoint; - latches->latchRequired(path_.path(), targetClkPath(), latchDisable(), + latches->latchRequired(path_, targetClkPath(), latchDisable(), mcp_, path_delay_, src_clk_arrival_, margin(sta), required, borrow, adjusted_data_arrival, time_given_to_startpoint); @@ -1240,7 +1228,7 @@ PathEndLatchCheck::latchRequired(const StaState *sta, Delay &time_given_to_startpoint) const { Latches *latches = sta->latches(); - latches->latchRequired(path_.path(), targetClkPath(), latchDisable(), + latches->latchRequired(path_, targetClkPath(), latchDisable(), mcp_, path_delay_, src_clk_arrival_, margin(sta), required, borrow, adjusted_data_arrival, time_given_to_startpoint); @@ -1259,7 +1247,7 @@ PathEndLatchCheck::latchBorrowInfo(const StaState *sta, bool &borrow_limit_exists) const { Latches *latches = sta->latches(); - latches->latchBorrowInfo(path_.path(), targetClkPath(), latchDisable(), + latches->latchBorrowInfo(path_, targetClkPath(), latchDisable(), margin(sta), path_delay_ && ignoreClkLatency(sta), nom_pulse_width, open_latency, @@ -1272,9 +1260,9 @@ Arrival PathEndLatchCheck::targetClkWidth(const StaState *sta) const { const Search *search = sta->search(); - Arrival disable_arrival = search->clkPathArrival(&disable_path_); - Arrival enable_arrival = search->clkPathArrival(&clk_path_); - ClkInfo *enable_clk_info = clk_path_.clkInfo(sta); + Arrival disable_arrival = search->clkPathArrival(disable_path_); + Arrival enable_arrival = search->clkPathArrival(clk_path_); + ClkInfo *enable_clk_info = clk_path_->clkInfo(sta); if (enable_clk_info->isPulseClk()) return disable_arrival - enable_arrival; else { @@ -1297,8 +1285,8 @@ PathEndLatchCheck::exceptPathCmp(const PathEnd *path_end, dynamic_cast(path_end); const TimingArc *check_arc2 = path_end2->check_arc_; if (check_arc_ == check_arc2) { - const Path *disable_path2 = path_end2->disable_path_.path(); - return Path::cmp(disable_path_.path(), disable_path2, sta); + const Path *disable_path2 = path_end2->disable_path_; + return Path::cmp(disable_path_, disable_path2, sta); } else if (check_arc_ < check_arc2) return -1; @@ -1319,7 +1307,7 @@ PathEndLatchCheck::ignoreClkLatency(const StaState *sta) const PathEndOutputDelay::PathEndOutputDelay(OutputDelay *output_delay, Path *path, - PathVertex *clk_path, + Path *clk_path, MultiCyclePath *mcp, const StaState *) : // No target clk_path_ for output delays. @@ -1330,7 +1318,7 @@ PathEndOutputDelay::PathEndOutputDelay(OutputDelay *output_delay, PathEndOutputDelay::PathEndOutputDelay(OutputDelay *output_delay, Path *path, - PathVertex *clk_path, + Path *clk_path, MultiCyclePath *mcp, Crpr crpr, bool crpr_valid) : @@ -1342,7 +1330,7 @@ PathEndOutputDelay::PathEndOutputDelay(OutputDelay *output_delay, PathEnd * PathEndOutputDelay::copy() { - return new PathEndOutputDelay(output_delay_, path_.path(), &clk_path_, + return new PathEndOutputDelay(output_delay_, path_, clk_path_, mcp_, crpr_, crpr_valid_); } @@ -1373,7 +1361,7 @@ PathEndOutputDelay::reportShort(const ReportPath *report) const ArcDelay PathEndOutputDelay::margin(const StaState *sta) const { - return outputDelayMargin(output_delay_, path_.path(), sta); + return outputDelayMargin(output_delay_, path_, sta); } float @@ -1390,10 +1378,10 @@ PathEnd::outputDelayMargin(OutputDelay *output_delay, return -margin; } -TimingRole * +const TimingRole * PathEndOutputDelay::checkRole(const StaState *sta) const { - if (path_.minMax(sta) == MinMax::max()) + if (path_->minMax(sta) == MinMax::max()) return TimingRole::outputSetup(); else return TimingRole::outputHold(); @@ -1402,8 +1390,8 @@ PathEndOutputDelay::checkRole(const StaState *sta) const const ClockEdge * PathEndOutputDelay::targetClkEdge(const StaState *sta) const { - if (!clk_path_.isNull()) - return clk_path_.clkEdge(sta); + if (clk_path_) + return clk_path_->clkEdge(sta); else return output_delay_->clkEdge(); } @@ -1411,7 +1399,7 @@ PathEndOutputDelay::targetClkEdge(const StaState *sta) const Arrival PathEndOutputDelay::targetClkArrivalNoCrpr(const StaState *sta) const { - if (!clk_path_.isNull()) + if (clk_path_) return PathEndClkConstrained::targetClkArrivalNoCrpr(sta); else { const ClockEdge *tgt_clk_edge = targetClkEdge(sta); @@ -1419,7 +1407,7 @@ PathEndOutputDelay::targetClkArrivalNoCrpr(const StaState *sta) const return targetClkTime(sta) + tgtClkDelay(tgt_clk_edge, check_role, sta) + targetClkUncertainty(sta) - + checkMcpAdjustment(path_.path(), tgt_clk_edge, sta); + + checkMcpAdjustment(path_, tgt_clk_edge, sta); } } @@ -1428,7 +1416,7 @@ PathEndOutputDelay::crpr(const StaState *sta) const { if (!crpr_valid_) { CheckCrpr *check_crpr = sta->search()->checkCrpr(); - crpr_ = check_crpr->outputDelayCrpr(path_.path(), targetClkEdge(sta)); + crpr_ = check_crpr->outputDelayCrpr(path_, targetClkEdge(sta)); crpr_valid_ = true; } return crpr_; @@ -1437,7 +1425,7 @@ PathEndOutputDelay::crpr(const StaState *sta) const Delay PathEndOutputDelay::targetClkDelay(const StaState *sta) const { - if (!clk_path_.isNull()) + if (clk_path_) return PathEndClkConstrained::targetClkDelay(sta); else return tgtClkDelay(targetClkEdge(sta), checkRole(sta), sta); @@ -1465,10 +1453,10 @@ PathEndOutputDelay::tgtClkDelay(const ClockEdge *tgt_clk_edge, // Early late: setup early, hold late. const EarlyLate *early_late = check_role->tgtClkEarlyLate(); // Latency min_max depends on bc_wc or ocv. - const PathAnalysisPt *path_ap = path_.pathAnalysisPt(sta); + const PathAnalysisPt *path_ap = path_->pathAnalysisPt(sta); const MinMax *latency_min_max = path_ap->tgtClkAnalysisPt()->pathMinMax(); Clock *tgt_clk = tgt_clk_edge->clock(); - RiseFall *tgt_clk_rf = tgt_clk_edge->transition(); + const RiseFall *tgt_clk_rf = tgt_clk_edge->transition(); if (!output_delay_->sourceLatencyIncluded()) insertion = sta->search()->clockInsertion(tgt_clk, tgt_clk->defaultPin(), @@ -1488,7 +1476,7 @@ PathEndOutputDelay::tgtClkDelay(const ClockEdge *tgt_clk_edge, Delay PathEndOutputDelay::targetClkInsertionDelay(const StaState *sta) const { - if (!clk_path_.isNull()) + if (clk_path_) return PathEndClkConstrained::targetClkInsertionDelay(sta); else { Arrival insertion, latency; @@ -1521,8 +1509,8 @@ PathEndOutputDelay::exceptPathCmp(const PathEnd *path_end, //////////////////////////////////////////////////////////////// PathEndGatedClock::PathEndGatedClock(Path *gating_ref, - PathVertex *clk_path, - TimingRole *check_role, + Path *clk_path, + const TimingRole *check_role, MultiCyclePath *mcp, ArcDelay margin, const StaState *) : @@ -1533,8 +1521,8 @@ PathEndGatedClock::PathEndGatedClock(Path *gating_ref, } PathEndGatedClock::PathEndGatedClock(Path *gating_ref, - PathVertex *clk_path, - TimingRole *check_role, + Path *clk_path, + const TimingRole *check_role, MultiCyclePath *mcp, ArcDelay margin, Crpr crpr, @@ -1548,7 +1536,7 @@ PathEndGatedClock::PathEndGatedClock(Path *gating_ref, PathEnd * PathEndGatedClock::copy() { - return new PathEndGatedClock(path_.path(), &clk_path_, check_role_, + return new PathEndGatedClock(path_, clk_path_, check_role_, mcp_, margin_, crpr_, crpr_valid_); } @@ -1564,7 +1552,7 @@ PathEndGatedClock::typeName() const return "gated_clk"; } -TimingRole * +const TimingRole * PathEndGatedClock::checkRole(const StaState *) const { return check_role_; @@ -1590,7 +1578,7 @@ PathEndGatedClock::exceptPathCmp(const PathEnd *path_end, if (cmp == 0) { const PathEndGatedClock *path_end2 = dynamic_cast(path_end); - TimingRole *check_role2 = path_end2->check_role_; + const TimingRole *check_role2 = path_end2->check_role_; if (check_role_ == check_role2) return 0; else if (check_role_ < check_role2) @@ -1606,59 +1594,52 @@ PathEndGatedClock::exceptPathCmp(const PathEnd *path_end, PathEndDataCheck::PathEndDataCheck(DataCheck *check, Path *data_path, - PathVertex *data_clk_path, + Path *data_clk_path, MultiCyclePath *mcp, const StaState *sta) : PathEndClkConstrainedMcp(data_path, nullptr, mcp), data_clk_path_(data_clk_path), check_(check) { - clkPath(data_clk_path, sta, clk_path_); + clk_path_ = clkPath(data_clk_path, sta); } // PathExpanded::expand() and PathExpanded::clkPath(). -void -PathEndDataCheck::clkPath(PathVertex *path, - const StaState *sta, - // Return value. - PathVertex &clk_path) +Path * +PathEndDataCheck::clkPath(Path *path, + const StaState *sta) { - PathVertex p(path); - while (!p.isNull()) { - PathVertex prev_path; - TimingArc *prev_arc; - p.prevPath(sta, prev_path, prev_arc); + Path *p = path; + while (p) { + Path *prev_path = p->prevPath(); + TimingArc *prev_arc = p->prevArc(sta); - if (p.isClock(sta)) { - clk_path = p; - return; - } + if (p->isClock(sta)) + return p; if (prev_arc) { - TimingRole *prev_role = prev_arc->role(); + const TimingRole *prev_role = prev_arc->role(); if (prev_role == TimingRole::regClkToQ() || prev_role == TimingRole::latchEnToQ()) { - p.prevPath(sta, prev_path, prev_arc); - clk_path = prev_path; - return; + prev_path = p->prevPath(); + return prev_path; } else if (prev_role == TimingRole::latchDtoQ()) { const Latches *latches = sta->latches(); - Edge *prev_edge = p.prevEdge(prev_arc, sta); - PathVertex enable_path; - latches->latchEnablePath(&p, prev_edge, enable_path); - clk_path = enable_path; - return; + Edge *prev_edge = p->prevEdge(sta); + Path *enable_path = latches->latchEnablePath(p, prev_edge); + return enable_path; } } p = prev_path; } + return nullptr; } PathEndDataCheck::PathEndDataCheck(DataCheck *check, Path *data_path, - PathVertex *data_clk_path, - PathVertex *clk_path, + Path *data_clk_path, + Path *clk_path, MultiCyclePath *mcp, Crpr crpr, bool crpr_valid) : @@ -1671,8 +1652,8 @@ PathEndDataCheck::PathEndDataCheck(DataCheck *check, PathEnd * PathEndDataCheck::copy() { - return new PathEndDataCheck(check_, path_.path(), &data_clk_path_, - &clk_path_, mcp_, crpr_, crpr_valid_); + return new PathEndDataCheck(check_, path_, data_clk_path_, + clk_path_, mcp_, crpr_, crpr_valid_); } PathEnd::Type @@ -1691,14 +1672,14 @@ const ClockEdge * PathEndDataCheck::targetClkEdge(const StaState *sta) const { // clk_path_ can be null if data_clk_path is from an input port. - return data_clk_path_.clkEdge(sta); + return data_clk_path_->clkEdge(sta); } Arrival PathEndDataCheck::requiredTimeNoCrpr(const StaState *sta) const { - Arrival data_clk_arrival = data_clk_path_.arrival(sta); - float data_clk_time = data_clk_path_.clkEdge(sta)->time(); + Arrival data_clk_arrival = data_clk_path_->arrival(); + float data_clk_time = data_clk_path_->clkEdge(sta)->time(); Arrival data_clk_delay = data_clk_arrival - data_clk_time; Arrival tgt_clk_arrival = targetClkTime(sta) + data_clk_delay @@ -1717,17 +1698,17 @@ PathEndDataCheck::margin(const StaState *sta) const { float margin; bool margin_exists; - check_->margin(data_clk_path_.transition(sta), - path_.transition(sta), - path_.minMax(sta), + check_->margin(data_clk_path_->transition(sta), + path_->transition(sta), + path_->minMax(sta), margin, margin_exists); return margin; } -TimingRole * +const TimingRole * PathEndDataCheck::checkRole(const StaState *sta) const { - if (path_.minMax(sta) == MinMax::max()) + if (path_->minMax(sta) == MinMax::max()) return TimingRole::dataCheckSetup(); else return TimingRole::dataCheckHold(); @@ -1794,7 +1775,7 @@ PathEndPathDelay::PathEndPathDelay(PathDelay *path_delay, PathEndPathDelay::PathEndPathDelay(PathDelay *path_delay, Path *path, - PathVertex *clk_path, + Path *clk_path, TimingArc *check_arc, Edge *check_edge, const StaState *sta) : @@ -1809,7 +1790,7 @@ PathEndPathDelay::PathEndPathDelay(PathDelay *path_delay, PathEndPathDelay::PathEndPathDelay(PathDelay *path_delay, Path *path, - PathVertex *clk_path, + Path *clk_path, TimingArc *check_arc, Edge *check_edge, OutputDelay *output_delay, @@ -1828,7 +1809,7 @@ PathEndPathDelay::PathEndPathDelay(PathDelay *path_delay, PathEnd * PathEndPathDelay::copy() { - return new PathEndPathDelay(path_delay_, path_.path(), &clk_path_, + return new PathEndPathDelay(path_delay_, path_, clk_path_, check_arc_, check_edge_, output_delay_, src_clk_arrival_, crpr_, crpr_valid_); } @@ -1850,7 +1831,7 @@ PathEndPathDelay::findSrcClkArrival(const StaState *sta) { if (ignoreClkLatency(sta)) { Search *search = sta->search(); - src_clk_arrival_ = search->pathClkPathArrival(&path_); + src_clk_arrival_ = search->pathClkPathArrival(path_); } else src_clk_arrival_ = 0.0; @@ -1875,7 +1856,7 @@ PathEndPathDelay::pathDelayMarginIsExternal() const return check_arc_ == nullptr; } -TimingRole * +const TimingRole * PathEndPathDelay::checkRole(const StaState *sta) const { if (check_edge_) @@ -1895,7 +1876,7 @@ PathEndPathDelay::margin(const StaState *sta) const pathAnalysisPt(sta)); } else if (output_delay_) - return outputDelayMargin(output_delay_, path_.path(), sta); + return outputDelayMargin(output_delay_, path_, sta); else return delay_zero; } @@ -1914,13 +1895,13 @@ PathEnd::clkSkew(const StaState *) // Helper shared by PathEndLatchCheck. float -PathEnd::pathDelaySrcClkOffset(const PathRef &path, +PathEnd::pathDelaySrcClkOffset(const Path *path, PathDelay *path_delay, Arrival src_clk_arrival, const StaState *sta) { float offset = 0.0; - const ClockEdge *clk_edge = path.clkEdge(sta); + const ClockEdge *clk_edge = path->clkEdge(sta); if (clk_edge) { if (ignoreClkLatency(path, path_delay, sta)) offset = -delayAsFloat(src_clk_arrival); @@ -1933,18 +1914,18 @@ PathEnd::pathDelaySrcClkOffset(const PathRef &path, } bool -PathEnd::ignoreClkLatency(const PathRef &path, +PathEnd::ignoreClkLatency(const Path *path, PathDelay *path_delay, const StaState *sta) { - return path_delay->ignoreClkLatency() && !path.isClock(sta); + return path_delay->ignoreClkLatency() && !path->isClock(sta); } const ClockEdge * PathEndPathDelay::targetClkEdge(const StaState *sta) const { - if (!clk_path_.isNull()) - return clk_path_.clkEdge(sta); + if (clk_path_) + return clk_path_->clkEdge(sta); else if (output_delay_) return output_delay_->clkEdge(); else @@ -1968,8 +1949,8 @@ PathEndPathDelay::targetClkArrivalNoCrpr(const StaState *sta) const if (tgt_clk_edge) return targetClkDelay(sta) + targetClkUncertainty(sta); - else if (!clk_path_.isNull()) - return clk_path_.arrival(sta); + else if (clk_path_) + return clk_path_->arrival(); else return 0.0; } @@ -1985,8 +1966,8 @@ PathEndPathDelay::requiredTime(const StaState *sta) const { float delay = path_delay_->delay(); if (path_delay_->ignoreClkLatency()) { - Required src_offset = path_.isClock(sta) - ? path_.clkEdge(sta)->time() + Required src_offset = path_->isClock(sta) + ? path_->clkEdge(sta)->time() : src_clk_arrival_; return src_offset + delay + ((minMax(sta) == MinMax::max()) ? -margin(sta) : margin(sta)); diff --git a/search/PathEnum.cc b/search/PathEnum.cc index a8dd572c..48601683 100644 --- a/search/PathEnum.cc +++ b/search/PathEnum.cc @@ -36,8 +36,7 @@ #include "Tag.hh" #include "Search.hh" #include "PathEnd.hh" -#include "PathRef.hh" -#include "PathEnumed.hh" +#include "Path.hh" namespace sta { @@ -104,8 +103,8 @@ deleteDiversionPathEnd(Diversion *div) //////////////////////////////////////////////////////////////// -PathEnum::PathEnum(int group_path_count, - int endpoint_path_count, +PathEnum::PathEnum(size_t group_path_count, + size_t endpoint_path_count, bool unique_pins, bool cmp_slack, const StaState *sta) : @@ -125,9 +124,9 @@ void PathEnum::insert(PathEnd *path_end) { debugPrint(debug_, "path_enum", 1, "insert %s", - path_end->path()->name(this)); + path_end->path()->to_string(this).c_str()); debugPrint(debug_, "path_enum", 2, "diversion %s %s %s", - path_end->path()->name(this), + path_end->path()->to_string(this).c_str(), cmp_slack_ ? "slack" : "delay", delayAsString(cmp_slack_ ? path_end->slack(this) : path_end->dataArrivalTime(this), this)); @@ -182,7 +181,7 @@ PathEnum::findNext() if (debug_->check("path_enum", 2)) { Path *path = path_end->path(); report_->reportLine("path_enum: next path %s delay %s slack %s", - path->name(this), + path->to_string(this).c_str(), delayAsString(path_end->dataArrivalTime(this), this), delayAsString(path_end->slack(this), this)); reportDiversionPath(div); @@ -203,7 +202,7 @@ PathEnum::findNext() // so we are done with it. debugPrint(debug_, "path_enum", 1, "endpoint_path_count reached for %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); deleteDiversionPathEnd(div); } } @@ -214,17 +213,16 @@ PathEnum::reportDiversionPath(Diversion *div) { PathEnd *path_end = div->pathEnd(); Path *path = path_end->path(); - PathRef p; - path->prevPath(this, p); + Path *p = path->prevPath(); Path *after_div = div->divPath(); - while (!p.isNull()) { + while (p) { report_->reportLine("path_enum: %s %s%s", - p.name(this), - delayAsString(p.arrival(this), this), - Path::equal(&p, after_div, this) ? " <-diversion" : ""); - if (network_->isLatchData(p.pin(this))) + p->to_string(this).c_str(), + delayAsString(p->arrival(), this), + Path::equal(p, after_div, this) ? " <-diversion" : ""); + if (network_->isLatchData(p->pin(this))) break; - p.prevPath(this, p); + p = p->prevPath(); } } @@ -234,19 +232,19 @@ class PathEnumFaninVisitor : public PathVisitor { public: PathEnumFaninVisitor(PathEnd *path_end, - PathRef &before_div, + Path *before_div, bool unique_pins, PathEnum *path_enum); virtual VertexVisitor *copy() const; virtual void visit(Vertex *) {} // Not used. - void visitFaninPathsThru(Vertex *vertex, + void visitFaninPathsThru(Path *before_div, Vertex *prev_vertex, TimingArc *prev_arc); virtual bool visitFromToPath(const Pin *from_pin, Vertex *from_vertex, const RiseFall *from_rf, Tag *from_tag, - PathVertex *from_path, + Path *from_path, const Arrival &from_arrival, Edge *edge, TimingArc *arc, @@ -260,16 +258,18 @@ public: private: void makeDivertedPathEnd(Path *after_div, + Edge *div_edge, TimingArc *div_arc, // Return values. PathEnd *&div_end, - PathEnumed *&after_div_copy); - void reportDiversion(TimingArc *div_arc, + Path *&after_div_copy); + void reportDiversion(const Edge *edge, + const TimingArc *div_arc, Path *after_div); PathEnd *path_end_; Slack path_end_slack_; - PathRef &before_div_; + Path *before_div_; bool unique_pins_; int before_div_rf_index_; Tag *before_div_tag_; @@ -282,7 +282,7 @@ private: }; PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end, - PathRef &before_div, + Path *before_div, bool unique_pins, PathEnum *path_enum) : PathVisitor(path_enum), @@ -290,27 +290,28 @@ PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end, path_end_slack_(path_end->slack(this)), before_div_(before_div), unique_pins_(unique_pins), - before_div_rf_index_(before_div_.rfIndex(this)), - before_div_tag_(before_div_.tag(this)), - before_div_ap_index_(before_div_.pathAnalysisPtIndex(this)), - before_div_arrival_(before_div_.arrival(this)), + before_div_rf_index_(before_div_->rfIndex(this)), + before_div_tag_(before_div_->tag(this)), + before_div_ap_index_(before_div_->pathAnalysisPtIndex(this)), + before_div_arrival_(before_div_->arrival()), path_enum_(path_enum), crpr_active_(sdc_->crprActive()) { } void -PathEnumFaninVisitor::visitFaninPathsThru(Vertex *vertex, +PathEnumFaninVisitor::visitFaninPathsThru(Path *before_div, Vertex *prev_vertex, TimingArc *prev_arc) { - before_div_rf_index_ = before_div_.rfIndex(this); - before_div_tag_ = before_div_.tag(this); - before_div_ap_index_ = before_div_.pathAnalysisPtIndex(this); - before_div_arrival_ = before_div_.arrival(this); + before_div_ = before_div; + before_div_rf_index_ = before_div_->rfIndex(this); + before_div_tag_ = before_div_->tag(this); + before_div_ap_index_ = before_div_->pathAnalysisPtIndex(this); + before_div_arrival_ = before_div_->arrival(); prev_arc_ = prev_arc; prev_vertex_ = prev_vertex; - visitFaninPaths(vertex); + visitFaninPaths(before_div_->vertex(this)); } VertexVisitor * @@ -325,7 +326,7 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *, Vertex *from_vertex, const RiseFall *, Tag *, - PathVertex *from_path, + Path *from_path, const Arrival &, Edge *edge, TimingArc *arc, @@ -338,9 +339,9 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *, const PathAnalysisPt *path_ap) { debugPrint(debug_, "path_enum", 3, "visit fanin %s -> %s %s %s", - from_path->name(this), - to_vertex->name(network_), - to_rf->asString(), + from_path->to_string(this).c_str(), + to_vertex->to_string(this).c_str(), + to_rf->to_string().c_str(), delayAsString(search_->deratedDelay(from_vertex, arc, edge, false,path_ap), this)); // These paths fanin to before_div_ so we know to_vertex matches. @@ -351,13 +352,13 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *, && tagMatchNoCrpr(to_tag, before_div_tag_)) { if (crpr_active_) { PathEnd *div_end; - PathEnumed *after_div_copy; + Path *after_div_copy; // Make the diverted path end to check slack with from_path crpr. - makeDivertedPathEnd(from_path, arc, div_end, after_div_copy); + makeDivertedPathEnd(from_path, edge, arc, div_end, after_div_copy); if (div_end) { // Only enumerate paths with greater slack. if (delayGreaterEqual(div_end->slack(this), path_end_slack_, this)) { - reportDiversion(arc, from_path); + reportDiversion(edge, arc, from_path); path_enum_->makeDiversion(div_end, after_div_copy); } else @@ -367,9 +368,9 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *, // Only enumerate slower/faster paths. else if (delayLessEqual(to_arrival, before_div_arrival_, min_max, this)) { PathEnd *div_end; - PathEnumed *after_div_copy; - makeDivertedPathEnd(from_path, arc, div_end, after_div_copy); - reportDiversion(arc, from_path); + Path *after_div_copy; + makeDivertedPathEnd(from_path, edge, arc, div_end, after_div_copy); + reportDiversion(edge, arc, from_path); path_enum_->makeDiversion(div_end, after_div_copy); } } @@ -378,14 +379,15 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *, void PathEnumFaninVisitor::makeDivertedPathEnd(Path *after_div, + Edge *div_edge, TimingArc *div_arc, // Return values. PathEnd *&div_end, - PathEnumed *&after_div_copy) + Path *&after_div_copy) { - PathEnumed *div_path; - path_enum_->makeDivertedPath(path_end_->path(), &before_div_, after_div, - div_arc, div_path, after_div_copy); + Path *div_path; + path_enum_->makeDivertedPath(path_end_->path(), before_div_, after_div, + div_edge, div_arc, div_path, after_div_copy); if (after_div_copy) { div_end = path_end_->copy(); div_end->setPath(div_path); @@ -395,7 +397,8 @@ PathEnumFaninVisitor::makeDivertedPathEnd(Path *after_div, } void -PathEnumFaninVisitor::reportDiversion(TimingArc *div_arc, +PathEnumFaninVisitor::reportDiversion(const Edge *div_edge, + const TimingArc *div_arc, Path *after_div) { if (debug_->check("path_enum", 3)) { @@ -404,21 +407,20 @@ PathEnumFaninVisitor::reportDiversion(TimingArc *div_arc, Arrival path_delay = path_enum_->cmp_slack_ ? path_end_->slack(this) : path_end_->dataArrivalTime(this); - Arrival div_delay = path_delay - path_enum_->divSlack(&before_div_, - after_div, - div_arc, path_ap); - PathRef div_prev; - before_div_.prevPath(this, div_prev); + Arrival div_delay = path_delay - path_enum_->divSlack(before_div_, + after_div, div_edge, + div_arc, path_ap); + Path *div_prev = before_div_->prevPath(); report_->reportLine("path_enum: diversion %s %s %s -> %s", - path->name(this), + path->to_string(this).c_str(), path_enum_->cmp_slack_ ? "slack" : "delay", delayAsString(path_delay, this), delayAsString(div_delay, this)); report_->reportLine("path_enum: from %s -> %s", - div_prev.name(this), - before_div_.name(this)); + div_prev->to_string(this).c_str(), + before_div_->to_string(this).c_str()); report_->reportLine("path_enum: to %s", - after_div->name(this)); + after_div->to_string(this).c_str()); } } @@ -431,13 +433,13 @@ PathEnumFaninVisitor::reportDiversion(TimingArc *div_arc, // <--...--before_div<--...--path<---path_end void PathEnum::makeDiversion(PathEnd *div_end, - PathEnumed *after_div_copy) + Path *after_div_copy) { Diversion *div = new Diversion(div_end, after_div_copy); div_queue_.push(div); div_count_++; - if (static_cast(div_queue_.size()) > group_path_count_ * 2) + if (div_queue_.size() > group_path_count_ * 2) // We have more potenial paths than we will need. pruneDiversionQueue(); } @@ -447,7 +449,7 @@ PathEnum::pruneDiversionQueue() { debugPrint(debug_, "path_enum", 2, "prune queue"); VertexPathCountMap path_counts; - int end_count = 0; + size_t end_count = 0; // Collect endpoint_path_count diversions per vertex. DiversionSeq divs; while (!div_queue_.empty()) { @@ -476,11 +478,11 @@ PathEnum::pruneDiversionQueue() Arrival PathEnum::divSlack(Path *before_div, Path *after_div, - TimingArc *div_arc, + const Edge *div_edge, + const TimingArc *div_arc, const PathAnalysisPt *path_ap) { - Arrival arc_arrival = before_div->arrival(this); - Edge *div_edge = divEdge(before_div, div_arc); + Arrival arc_arrival = before_div->arrival(); if (div_edge) { ArcDelay div_delay = search_->deratedDelay(div_edge->from(graph_), div_arc, div_edge, @@ -494,45 +496,30 @@ PathEnum::divSlack(Path *before_div, } } -Edge * -PathEnum::divEdge(Path *before_div, - TimingArc *div_arc) -{ - TimingArcSet *arc_set = div_arc->set(); - VertexInEdgeIterator edge_iter(before_div->vertex(this), graph_); - while (edge_iter.hasNext()) { - Edge *edge = edge_iter.next(); - if (edge->timingArcSet() == arc_set) - return edge; - } - return nullptr; -} - // Make diversions for all arcs that merge into path for paths // starting at "before" to the beginning of the path. void PathEnum::makeDiversions(PathEnd *path_end, Path *before) { - PathRef path(before); - PathRef prev_path; - TimingArc *prev_arc; - path.prevPath(this, prev_path, prev_arc); + Path *path = before; + Path *prev_path = path->prevPath(); + TimingArc *prev_arc = path->prevArc(this); PathEnumFaninVisitor fanin_visitor(path_end, path, unique_pins_, this); - while (prev_arc + while (prev_path // Do not enumerate paths in the clk network. - && !path.isClock(this)) { + && !path->isClock(this)) { // Fanin visitor does all the work. // While visiting the fanins the fanin_visitor finds the // previous path and arc as well as diversions. - fanin_visitor.visitFaninPathsThru(path.vertex(this), - prev_path.vertex(this), prev_arc); + fanin_visitor.visitFaninPathsThru(path, prev_path->vertex(this), prev_arc); // Do not enumerate beyond latch D to Q edges. // This breaks latch loop paths. if (prev_arc->role() == TimingRole::latchDtoQ()) break; - path.init(prev_path); - path.prevPath(this, prev_path, prev_arc); + path = prev_path; + prev_path = path->prevPath(); + prev_arc = path->prevArc(this); } } @@ -540,47 +527,52 @@ void PathEnum::makeDivertedPath(Path *path, Path *before_div, Path *after_div, + Edge *div_edge, TimingArc *div_arc, // Returned values. - PathEnumed *&div_path, - PathEnumed *&after_div_copy) + Path *&div_path, + Path *&after_div_copy) { div_path = nullptr; after_div_copy = nullptr; // Copy the diversion path. bool found_div = false; - PathEnumedSeq copies; - PathRef p(path); + PathSeq copies; + Path *p = path; bool first = true; - PathEnumed *prev_copy = nullptr; - while (!p.isNull()) { - PathRef prev; - TimingArc *prev_arc; - p.prevPath(this, prev, prev_arc); - PathEnumed *copy = new PathEnumed(p.vertexId(this), - p.tagIndex(this), - p.arrival(this), - nullptr, // prev_path made in next pass. - prev_arc); + Path *prev_copy = nullptr; + while (p) { + // prev_path made in next pass. + Path *copy = new Path(p->vertex(this), + p->tag(this), + p->arrival(), + // Replaced on next pass. + p->prevPath(), + p->prevEdge(this), + p->prevArc(this), + true, this); if (prev_copy) prev_copy->setPrevPath(copy); copies.push_back(copy); - if (Path::equal(&p, after_div, this)) + if (Path::equal(p, after_div, this)) after_div_copy = copy; if (first) div_path = copy; - else if (network_->isLatchData(p.pin(this))) + else if (network_->isLatchData(p->pin(this))) break; - if (Path::equal(&p, before_div, this)) { - copy->setPrevArc(div_arc); + if (Path::equal(p, before_div, this)) { + // Replaced on next pass. + copy->setPrevPath(after_div); + copy->setPrevEdgeArc(div_edge, div_arc, this); // Update the delays forward from before_div to the end of the path. updatePathHeadDelays(copies, after_div); - p.init(after_div); + p = after_div; found_div = true; } else - p.init(prev); + p = p->prevPath(); + prev_copy = copy; first = false; } @@ -589,27 +581,27 @@ PathEnum::makeDivertedPath(Path *path, } void -PathEnum::updatePathHeadDelays(PathEnumedSeq &paths, +PathEnum::updatePathHeadDelays(PathSeq &paths, Path *after_div) { Tag *prev_tag = after_div->tag(this); ClkInfo *prev_clk_info = prev_tag->clkInfo(); Arrival prev_arrival = search_->clkPathArrival(after_div); for (int i = paths.size() - 1; i >= 0; i--) { - PathEnumed *path = paths[i]; + Path *path = paths[i]; TimingArc *arc = path->prevArc(this); - Edge *edge = path->prevEdge(arc, this); + Edge *edge = path->prevEdge(this); if (edge) { PathAnalysisPt *path_ap = path->pathAnalysisPt(this); ArcDelay arc_delay = search_->deratedDelay(edge->from(graph_), arc, edge, false, path_ap); Arrival arrival = prev_arrival + arc_delay; debugPrint(debug_, "path_enum", 5, "update arrival %s %s %s -> %s", - path->vertex(this)->name(network_), - path->tag(this)->asString(this), - delayAsString(path->arrival(this), this), + path->vertex(this)->to_string(this).c_str(), + path->tag(this)->to_string(this).c_str(), + delayAsString(path->arrival(), this), delayAsString(arrival, this)); - path->setArrival(arrival, this); + path->setArrival(arrival); prev_arrival = arrival; if (sdc_->crprActive() // D->Q paths use the EN->Q clk info so no need to update. diff --git a/search/PathEnum.hh b/search/PathEnum.hh index 859cef80..b48b0d32 100644 --- a/search/PathEnum.hh +++ b/search/PathEnum.hh @@ -36,11 +36,9 @@ namespace sta { class Diversion; class PathEnumFaninVisitor; -class PathEnumed; class DiversionGreater; typedef Vector DiversionSeq; -typedef Vector PathEnumedSeq; typedef std::priority_queue DiversionQueue; @@ -60,8 +58,8 @@ private: class PathEnum : public Iterator, StaState { public: - PathEnum(int group_path_count, - int endpoint_path_count, + PathEnum(size_t group_path_count, + size_t endpoint_path_count, bool unique_pins, bool cmp_slack, const StaState *sta); @@ -75,29 +73,29 @@ private: void makeDiversions(PathEnd *path_end, Path *before); void makeDiversion(PathEnd *div_end, - PathEnumed *after_div_copy); + Path *after_div_copy); void makeDivertedPath(Path *path, Path *before_div, Path *after_div, + Edge *div_edge, TimingArc *div_arc, // Returned values. - PathEnumed *&div_path, - PathEnumed *&after_div_copy); - void updatePathHeadDelays(PathEnumedSeq &path, + Path *&div_path, + Path *&after_div_copy); + void updatePathHeadDelays(PathSeq &path, Path *after_div); Arrival divSlack(Path *path, Path *after_div, - TimingArc *div_arc, + const Edge *div_edge, + const TimingArc *div_arc, const PathAnalysisPt *path_ap); void reportDiversionPath(Diversion *div); void pruneDiversionQueue(); - Edge *divEdge(Path *before_div, - TimingArc *div_arc); void findNext(); bool cmp_slack_; - int group_path_count_; - int endpoint_path_count_; + size_t group_path_count_; + size_t endpoint_path_count_; bool unique_pins_; DiversionQueue div_queue_; int div_count_; diff --git a/search/PathEnumed.cc b/search/PathEnumed.cc deleted file mode 100644 index 3c0adc87..00000000 --- a/search/PathEnumed.cc +++ /dev/null @@ -1,192 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2025, Parallax Software, Inc. -// -// 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 . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#include "PathEnumed.hh" - -#include "Set.hh" -#include "Graph.hh" -#include "Corner.hh" -#include "Search.hh" -#include "Tag.hh" -#include "PathRef.hh" - -namespace sta { - -PathEnumed:: PathEnumed(VertexId vertex_id, - TagIndex tag_index, - Arrival arrival, - PathEnumed *prev_path, - TimingArc *prev_arc) : - Path(), - prev_path_(prev_path), - prev_arc_(prev_arc), - arrival_(arrival), - vertex_id_(vertex_id), - tag_index_(tag_index) -{ -} - -void -deletePathEnumed(PathEnumed *path) -{ - while (path) { - PathEnumed *prev = path->prevPathEnumed(); - delete path; - path = prev; - } -} - -void -PathEnumed::setRef(PathRef *ref) const -{ - ref->init(const_cast(this)); -} - -Vertex * -PathEnumed::vertex(const StaState *sta) const -{ - const Graph *graph = sta->graph(); - return graph->vertex(vertex_id_); -} - -VertexId -PathEnumed::vertexId(const StaState *) const -{ - return vertex_id_; -} - -Tag * -PathEnumed::tag(const StaState *sta) const -{ - const Search *search = sta->search(); - return search->tag(tag_index_); -} - -void -PathEnumed::setTag(Tag *tag) -{ - tag_index_ = tag->index(); -} - -const RiseFall * -PathEnumed::transition(const StaState *sta) const -{ - return tag(sta)->transition(); -} - -int -PathEnumed::trIndex(const StaState *sta) const -{ - return tag(sta)->rfIndex(); -} - -PathAnalysisPt * -PathEnumed::pathAnalysisPt(const StaState *sta) const -{ - const Corners *corners = sta->corners(); - return corners->findPathAnalysisPt(pathAnalysisPtIndex(sta)); -} - -PathAPIndex -PathEnumed::pathAnalysisPtIndex(const StaState *sta) const -{ - return tag(sta)->pathAPIndex(); -} - -Arrival -PathEnumed::arrival(const StaState *) const -{ - return arrival_; -} - -void -PathEnumed::setArrival(Arrival arrival, - const StaState *) -{ - arrival_ = arrival; -} - -const Required & -PathEnumed::required(const StaState *sta) const -{ - // Required times are never needed for enumerated paths. - sta->report()->critical(1380, "enumerated path required time"); - return delay_zero; -} - -void -PathEnumed::setRequired(const Required &, - const StaState *sta) -{ - // Required times are never needed for enumerated paths. - sta->report()->critical(1381, "enumerated path required time"); -} - -Path * -PathEnumed::prevPath(const StaState *) const -{ - return prev_path_; -} - -void -PathEnumed::prevPath(const StaState *, - // Return values. - PathRef &prev_path, - TimingArc *&prev_arc) const -{ - if (prev_path_) { - prev_path_->setRef(prev_path); - prev_arc = prev_arc_; - } - else { - prev_path.init(); - prev_arc = nullptr; - } -} - -TimingArc * -PathEnumed::prevArc(const StaState *) const -{ - return prev_arc_; -} - -PathEnumed * -PathEnumed::prevPathEnumed() const -{ - return prev_path_; -} - -void -PathEnumed::setPrevPath(PathEnumed *prev) -{ - prev_path_ = prev; -} - -void -PathEnumed::setPrevArc(TimingArc *arc) -{ - prev_arc_ = arc; -} - -} // namespace diff --git a/search/PathEnumed.hh b/search/PathEnumed.hh deleted file mode 100644 index 8613ed69..00000000 --- a/search/PathEnumed.hh +++ /dev/null @@ -1,80 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2025, Parallax Software, Inc. -// -// 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 . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#pragma once - -#include "Path.hh" - -namespace sta { - -// Implements Path API for paths returned by PathEnum. -class PathEnumed : public Path -{ -public: - PathEnumed(VertexId vertex_id, - TagIndex tag_index, - Arrival arrival, - PathEnumed *prev_path, - TimingArc *prev_arc); - virtual void setRef(PathRef *ref) const; - virtual bool isNull() const { return vertex_id_ == 0; } - virtual Vertex *vertex(const StaState *sta) const; - virtual VertexId vertexId(const StaState *sta) const; - virtual Tag *tag(const StaState *sta) const; - virtual const RiseFall *transition(const StaState *sta) const; - virtual int trIndex(const StaState *) const; - virtual PathAnalysisPt *pathAnalysisPt(const StaState *sta) const; - virtual PathAPIndex pathAnalysisPtIndex(const StaState *sta) const; - virtual Arrival arrival(const StaState *sta) const; - virtual void setArrival(Arrival arrival, const StaState *sta); - virtual const Required &required(const StaState *sta) const; - virtual void setRequired(const Required &required, - const StaState *sta); - virtual Path *prevPath(const StaState *sta) const; - virtual void prevPath(const StaState *sta, - // Return values. - PathRef &prev_path, - TimingArc *&prev_arc) const; - virtual TimingArc *prevArc(const StaState *sta) const; - PathEnumed *prevPathEnumed() const; - void setPrevPath(PathEnumed *prev); - void setPrevArc(TimingArc *arc); - void setTag(Tag *tag); - - using Path::setRef; - using Path::prevPath; - -protected: - // Pointer to previous path. - // A path is traversed by following prev_path/arcs. - PathEnumed *prev_path_; - TimingArc *prev_arc_; - Arrival arrival_; - VertexId vertex_id_; - TagIndex tag_index_; -}; - -void deletePathEnumed(PathEnumed *path); - -} // namespace diff --git a/search/PathExpanded.cc b/search/PathExpanded.cc index 93c54946..c9cb4b74 100644 --- a/search/PathExpanded.cc +++ b/search/PathExpanded.cc @@ -29,7 +29,7 @@ #include "Network.hh" #include "Clock.hh" #include "Search.hh" -#include "PathRef.hh" +#include "Path.hh" #include "Latches.hh" #include "Genclks.hh" @@ -61,35 +61,32 @@ PathExpanded::expand(const Path *path, bool expand_genclks) { const Latches *latches = sta_->latches(); - // Push the paths from the end into an array of PathRefs. - PathRef p(path); - PathRef last_path; + // Push the paths from the end into an array of Paths. + const Path *p = path; + const Path *last_path = nullptr; size_t i = 0; bool found_start = false; - while (!p.isNull()) { - PathRef prev_path; - TimingArc *prev_arc; - p.prevPath(sta_, prev_path, prev_arc); + while (p) { + const Path *prev_path = p->prevPath(); + const TimingArc *prev_arc = p->prevArc(sta_); if (!found_start) { if (prev_arc) { - TimingRole *prev_role = prev_arc->role(); + const TimingRole *prev_role = prev_arc->role(); if (prev_role == TimingRole::regClkToQ() || prev_role == TimingRole::latchEnToQ()) { start_index_ = i; found_start = true; } else if (prev_role == TimingRole::latchDtoQ()) { - Edge *prev_edge = p.prevEdge(prev_arc, sta_); + const Edge *prev_edge = p->prevEdge(sta_); if (prev_edge && latches->isLatchDtoQ(prev_edge)) { start_index_ = i; found_start = true; paths_.push_back(p); - prev_arcs_.push_back(prev_arc); // Push latch D path. paths_.push_back(prev_path); - prev_arcs_.push_back(nullptr); // This breaks latch loop paths. break; } @@ -97,43 +94,37 @@ PathExpanded::expand(const Path *path, } } paths_.push_back(p); - prev_arcs_.push_back(prev_arc); - last_path.init(p); - p.init(prev_path); + last_path = p; + p = prev_path; i++; } if (!found_start) start_index_ = i - 1; if (expand_genclks) - expandGenclk(&last_path); + expandGenclk(last_path); } void -PathExpanded::expandGenclk(PathRef *clk_path) +PathExpanded::expandGenclk(const Path *clk_path) { - if (!clk_path->isNull()) { + if (clk_path) { const Clock *src_clk = clk_path->clock(sta_); if (src_clk && src_clk->isGenerated()) { - PathVertex src_path = sta_->search()->genclks()->srcPath(clk_path); - if (!src_path.isNull()) { + const Path *src_path = sta_->search()->genclks()->srcPath(clk_path); + if (src_path) { // The head of the genclk src path is already in paths_, // so skip past it. - PathRef prev_path; - TimingArc *prev_arc; - src_path.prevPath(sta_, prev_path, prev_arc); - - PathRef p(prev_path); - PathRef last_path; - while (!p.isNull()) { - p.prevPath(sta_, prev_path, prev_arc); - + Path *prev_path = src_path->prevPath(); + Path *p = prev_path; + Path *last_path = nullptr; + while (p) { + prev_path = p->prevPath(); paths_.push_back(p); - prev_arcs_.push_back(prev_arc); - last_path.init(p); - p.init(prev_path); + last_path = p; + p = prev_path; } - expandGenclk(&last_path); + expandGenclk(last_path); } } } @@ -153,91 +144,84 @@ PathExpanded::startIndex() const return pathsIndex(start_index_); } -const PathRef * +const Path * PathExpanded::path(size_t index) const { if (index < paths_.size()) - return &paths_[pathsIndex(index)]; + return paths_[pathsIndex(index)]; else return nullptr; } -TimingArc * -PathExpanded::prevArc(size_t index) const -{ - return prev_arcs_[pathsIndex(index)]; -} - -const PathRef * +const Path * PathExpanded::startPath() const { - return &paths_[start_index_]; + return paths_[start_index_]; } -const PathRef * +const Path * PathExpanded::endPath() const { - return &paths_[0]; + return paths_[0]; } -TimingArc * +const TimingArc * PathExpanded::startPrevArc() const { - return prev_arcs_[start_index_]; + return paths_[start_index_]->prevArc(sta_); } -const PathRef * +const Path * PathExpanded::startPrevPath() const { size_t start1 = start_index_ + 1; if (start1 < paths_.size()) - return &paths_[start1]; + return paths_[start1]; else return nullptr; } -void -PathExpanded::clkPath(PathRef &clk_path) const +const Path * +PathExpanded::clkPath() const { const Latches *latches = sta_->latches(); - const PathRef *start = startPath(); + const Path *start = startPath(); const TimingArc *prev_arc = startPrevArc(); if (start && prev_arc) { - TimingRole *role = prev_arc->role(); + const TimingRole *role = prev_arc->role(); if (role == TimingRole::latchDtoQ()) { - Edge *prev_edge = start->prevEdge(prev_arc, sta_); + Edge *prev_edge = start->prevEdge(sta_); if (prev_edge && latches->isLatchDtoQ(prev_edge)) { - PathVertex enable_path; - latches->latchEnablePath(start, prev_edge, enable_path); - clk_path.init(enable_path); + return latches->latchEnablePath(start, prev_edge); } } else if (role == TimingRole::regClkToQ() || role == TimingRole::latchEnToQ()) { - const PathRef *start_prev = startPrevPath(); + const Path *start_prev = startPrevPath(); if (start_prev) - clk_path.init(start_prev); + return start_prev; } } else if (start && start->isClock(sta_)) - clk_path.init(start); + return start; + return nullptr; } void PathExpanded::latchPaths(// Return values. - const PathRef *&d_path, - const PathRef *&q_path, + const Path *&d_path, + const Path *&q_path, Edge *&d_q_edge) const { d_path = nullptr; q_path = nullptr; d_q_edge = nullptr; - const PathRef *start = startPath(); + const Path *start = startPath(); const TimingArc *prev_arc = startPrevArc(); if (start && prev_arc && prev_arc->role() == TimingRole::latchDtoQ()) { - Edge *prev_edge = start->prevEdge(prev_arc, sta_); + Edge *prev_edge = start->prevEdge(sta_); // This breaks latch loop paths. if (prev_edge && sta_->latches()->isLatchDtoQ(prev_edge)) { diff --git a/search/PathGroup.cc b/search/PathGroup.cc index 482936cb..857eac11 100644 --- a/search/PathGroup.cc +++ b/search/PathGroup.cc @@ -46,7 +46,7 @@ namespace sta { -int PathGroup::group_path_count_max = std::numeric_limits::max(); +size_t PathGroup::group_path_count_max = std::numeric_limits::max(); PathGroup * PathGroup::makePathGroupSlack(const char *name, @@ -74,8 +74,8 @@ PathGroup::makePathGroupArrival(const char *name, } PathGroup::PathGroup(const char *name, - int group_path_count, - int endpoint_path_count, + size_t group_path_count, + size_t endpoint_path_count, bool unique_pins, float slack_min, float slack_max, @@ -148,7 +148,7 @@ PathGroup::enumMinSlackUnderMin(PathEnd *path_end) path->transition(sta_), other_ap, sta_); while (other_iter.hasNext()) { - PathVertex *other = other_iter.next(); + Path *other = other_iter.next(); if (tagMatchCrpr(other->tag(sta_), tag)) { PathEnd *end_min = path_end->copy(); end_min->setPath(other); @@ -168,7 +168,7 @@ PathGroup::insert(PathEnd *path_end) LockGuard lock(lock_); path_ends_.push_back(path_end); if (group_path_count_ != group_path_count_max - && static_cast(path_ends_.size()) > group_path_count_ * 2) + && path_ends_.size() > group_path_count_ * 2) prune(); } @@ -177,7 +177,7 @@ PathGroup::prune() { sort(); VertexPathCountMap path_counts; - int end_count = 0; + size_t end_count = 0; for (unsigned i = 0; i < path_ends_.size(); i++) { PathEnd *path_end = path_ends_[i]; Vertex *vertex = path_end->vertex(sta_); @@ -220,7 +220,7 @@ PathGroup::iterator() void PathGroup::ensureSortedMaxPaths() { - if (static_cast(path_ends_.size()) > group_path_count_) + if (path_ends_.size() > group_path_count_) prune(); else sort(); @@ -411,9 +411,11 @@ PathGroups::pathGroup(const PathEnd *path_end) const { const MinMax *min_max = path_end->minMax(this); int mm_index = min_max->index(); - // GroupPaths have precedence. GroupPath *group_path = groupPathTo(path_end); - if (group_path) { + if (path_end->isUnconstrained()) + return unconstrained_[mm_index]; + // GroupPaths have precedence. + else if (group_path) { if (group_path->isDefault()) return path_delay_[mm_index]; else { @@ -446,8 +448,6 @@ PathGroups::pathGroup(const PathEnd *path_end) const else return path_delay_[mm_index]; } - else if (path_end->isUnconstrained()) - return unconstrained_[mm_index]; else { report_->critical(1390, "unknown path end type"); return nullptr; @@ -716,7 +716,6 @@ void MakePathEndsAll::vertexEnd(Vertex *) { Debug *debug = sta_->debug(); - Network *network = sta_->network(); PathGroupEndsMap::Iterator group_iter(ends_); while (group_iter.hasNext()) { PathGroup *group; @@ -734,9 +733,9 @@ MakePathEndsAll::vertexEnd(Vertex *) // PathEnum will peel the others. if (!unique_ends.hasKey(path_end)) { debugPrint(debug, "path_enum", 5, "insert %s %s %s %d", - path_end->vertex(sta_)->name(network), + path_end->vertex(sta_)->to_string(sta_).c_str(), path_end->typeName(), - path_end->transition(sta_)->asString(), + path_end->transition(sta_)->to_string().c_str(), path_end->path()->tag(sta_)->index()); // Give the group a copy of the path end because // it may delete it during pruning. @@ -749,9 +748,9 @@ MakePathEndsAll::vertexEnd(Vertex *) } else debugPrint(debug, "path_enum", 5, "prune %s %s %s %d", - path_end->vertex(sta_)->name(network), + path_end->vertex(sta_)->to_string(sta_).c_str(), path_end->typeName(), - path_end->transition(sta_)->asString(), + path_end->transition(sta_)->to_string().c_str(), path_end->path()->tag(sta_)->index()); } // Clear ends for next vertex. diff --git a/search/PathPrev.cc b/search/PathPrev.cc deleted file mode 100644 index 8de8d78a..00000000 --- a/search/PathPrev.cc +++ /dev/null @@ -1,246 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2025, Parallax Software, Inc. -// -// 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 . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#include "PathPrev.hh" - -#include "Graph.hh" -#include "TimingArc.hh" -#include "SearchClass.hh" -#include "Tag.hh" -#include "TagGroup.hh" -#include "Search.hh" -#include "PathAnalysisPt.hh" -#include "PathVertex.hh" - -namespace sta { - -PathPrev::PathPrev() -{ - init(); -} - -void -PathPrev::init() -{ - prev_edge_id_ = edge_id_null; - prev_arc_idx_ = 0; - prev_tag_index_ = tag_index_null; -} - -void -PathPrev::init(const PathPrev *path) -{ - if (path) { - prev_edge_id_ = path->prev_edge_id_; - prev_arc_idx_ = path->prev_arc_idx_; - prev_tag_index_ = path->prev_tag_index_; - } - else - init(); -} - -void -PathPrev::init(const PathPrev &path) -{ - prev_edge_id_ = path.prev_edge_id_; - prev_arc_idx_ = path.prev_arc_idx_; - prev_tag_index_ = path.prev_tag_index_; -} - -void -PathPrev::init(const PathVertex *path, - const Edge *prev_edge, - const TimingArc *prev_arc, - const StaState *sta) -{ - if (path == nullptr || path->isNull()) - init(); - else { - const Graph *graph = sta->graph(); - prev_edge_id_ = graph->id(prev_edge); - prev_arc_idx_ = prev_arc->index(); - prev_tag_index_ = path->tag(sta)->index(); - } -} - -const char * -PathPrev::name(const StaState *sta) const -{ - const Network *network = sta->network(); - const Search *search = sta->search(); - Vertex *vertex = this->vertex(sta); - if (vertex) { - const char *vertex_name = vertex->name(network); - const Tag *tag = this->tag(search); - const RiseFall *rf = tag->transition(); - const char *rf_str = rf->asString(); - const PathAnalysisPt *path_ap = tag->pathAnalysisPt(sta); - int ap_index = path_ap->index(); - const char *min_max = path_ap->pathMinMax()->asString(); - TagIndex tag_index = tag->index(); - return stringPrintTmp("%s %s %s/%d %d", - vertex_name, rf_str, min_max, - ap_index, tag_index); - } - else - return "NULL"; -} - -bool -PathPrev::isNull() const -{ - return prev_edge_id_ == edge_id_null; -} - -VertexId -PathPrev::vertexId(const StaState *sta) const -{ - if (prev_edge_id_ == edge_id_null) - return vertex_id_null; - else { - const Graph *graph = sta->graph(); - const Edge *edge = graph->edge(prev_edge_id_); - return edge->from(); - } -} - -Vertex * -PathPrev::vertex(const StaState *sta) const -{ - if (prev_edge_id_ == edge_id_null) - return nullptr; - else { - const Graph *graph = sta->graph(); - const Edge *edge = graph->edge(prev_edge_id_); - return edge->from(graph); - } -} - -Edge * -PathPrev::prevEdge(const StaState *sta) const -{ - if (prev_edge_id_ == edge_id_null) - return nullptr; - else { - const Graph *graph = sta->graph(); - return graph->edge(prev_edge_id_); - } -} - -TimingArc * -PathPrev::prevArc(const StaState *sta) const -{ - if (prev_edge_id_ == edge_id_null) - return nullptr; - else { - const Graph *graph = sta->graph(); - const Edge *edge = graph->edge(prev_edge_id_); - TimingArcSet *arc_set = edge->timingArcSet(); - return arc_set->findTimingArc(prev_arc_idx_); - } -} - -Tag * -PathPrev::tag(const StaState *sta) const -{ - const Search *search = sta->search(); - return search->tag(prev_tag_index_); -} - -Arrival -PathPrev::arrival(const StaState *sta) const -{ - Graph *graph = sta->graph(); - const Search *search = sta->search(); - Tag *tag = search->tag(prev_tag_index_); - Vertex *vertex = this->vertex(sta); - TagGroup *tag_group = search->tagGroup(vertex); - if (tag_group) { - int arrival_index; - bool arrival_exists; - tag_group->arrivalIndex(tag, arrival_index, arrival_exists); - if (!arrival_exists) - sta->report()->critical(1420, "tag group missing tag"); - Arrival *arrivals = graph->arrivals(vertex); - if (arrivals) - return arrivals[arrival_index]; - else - sta->report()->critical(1421, "missing arrivals"); - } - else - sta->report()->error(1422, "missing arrivals."); - return 0.0; -} - -void -PathPrev::prevPath(const StaState *sta, - // Return values. - PathRef &prev_path, - TimingArc *&prev_arc) const -{ - PathVertex path_vertex(this, sta); - path_vertex.prevPath(sta, prev_path, prev_arc); -} - -//////////////////////////////////////////////////////////////// - -bool -PathPrev::equal(const PathPrev *path1, - const PathPrev *path2) -{ - return path1->prev_edge_id_ == path2->prev_edge_id_ - && path1->prev_tag_index_ == path2->prev_tag_index_; -} - -bool -PathPrev::equal(const PathPrev &path1, - const PathPrev &path2) -{ - return path1.prev_edge_id_ == path2.prev_edge_id_ - && path1.prev_tag_index_ == path2.prev_tag_index_; -} - -int -PathPrev::cmp(const PathPrev &path1, - const PathPrev &path2) -{ - EdgeId edge_id1 = path1.prev_edge_id_; - EdgeId edge_id2 = path2.prev_edge_id_; - if (edge_id1 == edge_id2) { - TagIndex tag_index1 = path1.prev_tag_index_; - TagIndex tag_index2 = path2.prev_tag_index_; - if (tag_index1 == tag_index2) - return 0; - else if (tag_index1 < tag_index2) - return -1; - else - return 1; - } - else if (edge_id1 < edge_id2) - return -1; - else - return 1; -} - -} // namespace diff --git a/search/PathRef.cc b/search/PathRef.cc deleted file mode 100644 index 74bb0aae..00000000 --- a/search/PathRef.cc +++ /dev/null @@ -1,284 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2025, Parallax Software, Inc. -// -// 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 . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#include "PathRef.hh" - -#include "Graph.hh" -#include "TagGroup.hh" -#include "PathEnumed.hh" -#include "PathVertex.hh" -#include "Search.hh" - - -namespace sta { - -PathRef::PathRef() : - path_enumed_(nullptr) -{ -} - -PathRef::PathRef(const Path *path) : - path_enumed_(nullptr) -{ - if (path) - path->setRef(this); -} - -PathRef::PathRef(const PathRef &path) : - path_vertex_(path.path_vertex_), - path_enumed_(path.path_enumed_) -{ -} - -PathRef::PathRef(const PathRef *path) : - path_vertex_(path->path_vertex_), - path_enumed_(path->path_enumed_) -{ -} - -PathRef::PathRef(const PathVertex &path) : - path_vertex_(&path), - path_enumed_(nullptr) -{ -} - -void -PathRef::init() -{ - path_vertex_.init(); - path_enumed_ = nullptr; -} - -void -PathRef::init(const PathRef &path) -{ - path_vertex_ = path.path_vertex_; - path_enumed_ = path.path_enumed_; -} - -void -PathRef::init(const PathRef *path) -{ - path_vertex_ = path->path_vertex_; - path_enumed_ = path->path_enumed_; -} - -void -PathRef::init(const PathVertex *path) -{ - path_vertex_ = path; -} - -void -PathRef::init(const PathVertex &path) -{ - path_vertex_ = path; -} - -void -PathRef::init(const PathPrev &path, - const StaState *sta) -{ - int arrival_index = 0; - TagIndex tag_index = path.tagIndex(); - Tag *tag = nullptr; - if (tag_index != tag_index_null) { - const Search *search = sta->search(); - tag = search->tag(tag_index); - Vertex *vertex = path.vertex(sta); - TagGroup *tag_group = search->tagGroup(vertex); - if (tag_group) { - bool arrival_exists; - tag_group->arrivalIndex(tag, arrival_index, arrival_exists); - } - } - path_vertex_.init(path.vertex(sta), tag, arrival_index); -} - -void -PathRef::init(Vertex *vertex, - Tag *tag, - int arrival_index) -{ - path_vertex_.init(vertex, tag, arrival_index); - path_enumed_ = nullptr; -} - -void -PathRef::init(PathEnumed *path) -{ - path_enumed_ = path; -} - -void -PathRef::setRef(PathRef *ref) const -{ - ref->path_vertex_ = path_vertex_; - ref->path_enumed_ = path_enumed_; -} - -void -PathRef::deleteRep() -{ - if (path_enumed_) - deletePathEnumed(path_enumed_); -} - -bool -PathRef::isNull() const -{ - return path_enumed_ == nullptr - && path_vertex_.isNull(); -} - -Vertex * -PathRef::vertex(const StaState *sta) const -{ - if (path_enumed_) - return path_enumed_->vertex(sta); - else - return path_vertex_.vertex(sta); -} - -VertexId -PathRef::vertexId(const StaState *sta) const -{ - if (path_enumed_) - return path_enumed_->vertexId(sta); - else - return path_vertex_.vertexId(sta); -} - -Tag * -PathRef::tag(const StaState *sta) const -{ - if (path_enumed_) - return path_enumed_->tag(sta); - else - return path_vertex_.tag(sta); -} - -TagIndex -PathRef::tagIndex(const StaState *sta) const -{ - if (path_enumed_) - return path_enumed_->tagIndex(sta); - else - return path_vertex_.tagIndex(sta); -} - -const RiseFall * -PathRef::transition(const StaState *sta) const -{ - if (path_enumed_) - return path_enumed_->transition(sta); - else - return path_vertex_.transition(sta); -} - -int -PathRef::rfIndex(const StaState *sta) const -{ - if (path_enumed_) - return path_enumed_->rfIndex(sta); - else - return path_vertex_.rfIndex(sta); -} - -PathAnalysisPt * -PathRef::pathAnalysisPt(const StaState *sta) const -{ - if (path_enumed_) - return path_enumed_->pathAnalysisPt(sta); - else - return path_vertex_.pathAnalysisPt(sta); -} - -PathAPIndex -PathRef::pathAnalysisPtIndex(const StaState *sta) const -{ - if (path_enumed_) - return path_enumed_->pathAnalysisPtIndex(sta); - else - return path_vertex_.pathAnalysisPtIndex(sta); -} - -Arrival -PathRef::arrival(const StaState *sta) const -{ - if (path_enumed_) - return path_enumed_->arrival(sta); - else - return path_vertex_.arrival(sta); -} - -void -PathRef::setArrival(Arrival arrival, - const StaState *sta) -{ - if (path_enumed_) - return path_enumed_->setArrival(arrival, sta); - else - return path_vertex_.setArrival(arrival, sta); -} - -const Required & -PathRef::required(const StaState *sta) const -{ - if (path_enumed_) - return path_enumed_->required(sta); - else - return path_vertex_.required(sta); -} - -void -PathRef::setRequired(const Required &required, - const StaState *sta) -{ - if (path_enumed_) - return path_enumed_->setRequired(required, sta); - else - return path_vertex_.setRequired(required, sta); -} - -void -PathRef::prevPath(const StaState *sta, - // Return values. - PathRef &prev_path, - TimingArc *&prev_arc) const -{ - if (path_enumed_) - path_enumed_->prevPath(sta, prev_path, prev_arc); - else - path_vertex_.prevPath(sta, prev_path, prev_arc); -} - -void -PathRef::arrivalIndex(int &arrival_index, - bool &arrival_exists) const -{ - return path_vertex_.arrivalIndex(arrival_index, arrival_exists); -} - -} // namespace diff --git a/search/PathVertex.cc b/search/PathVertex.cc deleted file mode 100644 index 9efcc03e..00000000 --- a/search/PathVertex.cc +++ /dev/null @@ -1,628 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2025, Parallax Software, Inc. -// -// 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 . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#include "PathVertex.hh" - -#include - -#include "Fuzzy.hh" -#include "Graph.hh" -#include "ExceptionPath.hh" -#include "Sdc.hh" -#include "GraphDelayCalc.hh" -#include "Corner.hh" -#include "Tag.hh" -#include "TagGroup.hh" -#include "PathAnalysisPt.hh" -#include "PathRef.hh" -#include "PathPrev.hh" -#include "PathVertexPtr.hh" -#include "Search.hh" - -namespace sta { - -PathVertex::PathVertex() : - vertex_(nullptr), - tag_(nullptr), - arrival_index_(0) -{ -} - -PathVertex::PathVertex(const PathVertex &path) : - vertex_(path.vertex_), - tag_(path.tag_), - arrival_index_(path.arrival_index_) -{ -} - -PathVertex::PathVertex(const PathVertex *path) : - vertex_(nullptr), - tag_(nullptr), - arrival_index_(0) -{ - if (path) { - vertex_ = path->vertex_; - tag_ = path->tag_; - arrival_index_ = path->arrival_index_; - } -} - -PathVertex::PathVertex(Vertex *vertex, - Tag *tag, - const StaState *sta) -{ - init(vertex, tag, sta); -} - -PathVertex::PathVertex(Vertex *vertex, - Tag *tag, - int arrival_index) : - vertex_(vertex), - tag_(tag), - arrival_index_(arrival_index) -{ -} - -PathVertex::PathVertex(const PathPrev *path, - const StaState *sta) -{ - if (path) - init(path->vertex(sta), path->tag(sta), sta); - else - init(); -} - -PathVertex::PathVertex(const PathPrev &path, - const StaState *sta) -{ - if (path.isNull()) - init(); - else - init(path.vertex(sta), path.tag(sta), sta); -} - -PathVertex::PathVertex(const PathVertexPtr &path, - const StaState *sta) -{ - if (path.isNull()) - init(); - else - init(path.vertex(sta), path.tag(sta), sta); -} - -void -PathVertex::init() -{ - vertex_ = nullptr; - tag_ = nullptr; - arrival_index_ = 0; -} - -void -PathVertex::init(Vertex *vertex, - Tag *tag, - const StaState *sta) -{ - vertex_ = nullptr; - tag_ = nullptr; - arrival_index_ = 0; - const Search *search = sta->search(); - TagGroup *tag_group = search->tagGroup(vertex); - if (tag_group) { - bool arrival_exists; - tag_group->arrivalIndex(tag, arrival_index_, arrival_exists); - if (arrival_exists) { - vertex_ = vertex; - tag_ = tag; - } - } -} - -void -PathVertex::init(Vertex *vertex, - Tag *tag, - int arrival_index) -{ - vertex_ = vertex; - tag_ = tag; - arrival_index_ = arrival_index; -} - -void -PathVertex::init(const PathPrev *path, - const StaState *sta) -{ - if (path) - init(path->vertex(sta), path->tag(sta), sta); - else - init(); -} - -void -PathVertex::init(const PathPrev &path, - const StaState *sta) -{ - if (!path.isNull()) - init(path.vertex(sta), path.tag(sta), sta); - else - init(); -} - -void -PathVertex::init(const PathVertexPtr &path, - const StaState *sta) -{ - if (!path.isNull()) - init(path.vertex(sta), path.tag(sta), sta); - else - init(); -} - -void -PathVertex::operator=(const PathVertex &path) -{ - vertex_ = path.vertex_; - tag_ = path.tag_; - arrival_index_ = path.arrival_index_; -} - -bool -PathVertex::isNull() const -{ - return tag_ == nullptr; -} - -void -PathVertex::setRef(PathRef *ref) const -{ - ref->init(vertex_, tag_, arrival_index_); -} - -VertexId -PathVertex::vertexId(const StaState *sta) const -{ - const Graph *graph = sta->graph(); - return graph->id(vertex_); -} - -TagIndex -PathVertex::tagIndex(const StaState *) const -{ - return tag_->index(); -} - -const RiseFall * -PathVertex::transition(const StaState *) const -{ - return tag_->transition(); -} - -int -PathVertex::rfIndex(const StaState *) const -{ - return tag_->rfIndex(); -} - -PathAnalysisPt * -PathVertex::pathAnalysisPt(const StaState *sta) const -{ - return tag_->pathAnalysisPt(sta); -} - -PathAPIndex -PathVertex::pathAnalysisPtIndex(const StaState *) const -{ - return tag_->pathAPIndex(); -} - -void -PathVertex::arrivalIndex(int &arrival_index, - bool &arrival_exists) const -{ - if (tag_) { - arrival_index = arrival_index_; - arrival_exists = true; - } - else - arrival_exists = false; -} - -void -PathVertex::setArrivalIndex(int arrival_index) -{ - arrival_index_ = arrival_index; -} - -Arrival -PathVertex::arrival(const StaState *sta) const -{ - Arrival *arrivals = sta->graph()->arrivals(vertex_); - if (arrivals) - return arrivals[arrival_index_]; - else { - sta->report()->error(1400, "missing arrivals."); - return 0.0; - } -} - -void -PathVertex::setArrival(Arrival arrival, - const StaState *sta) -{ - if (tag_) { - Arrival *arrivals = sta->graph()->arrivals(vertex_); - if (arrivals) - arrivals[arrival_index_] = arrival; - else - sta->report()->error(1401, "missing arrivals."); - } -} - -const Required & -PathVertex::required(const StaState *sta) const -{ - if (tag_) { - Required *requireds = sta->graph()->requireds(vertex_); - if (requireds) - return requireds[arrival_index_]; - } - return delayInitValue(minMax(sta)->opposite()); -} - -void -PathVertex::setRequired(const Required &required, - const StaState *sta) -{ - Graph *graph = sta->graph(); - Required *requireds = graph->requireds(vertex_); - if (requireds == nullptr) { - const Search *search = sta->search(); - TagGroup *tag_group = search->tagGroup(vertex_); - if (tag_group) { - int arrival_count = tag_group->arrivalCount(); - requireds = graph->makeRequireds(vertex_, arrival_count); - } - else - sta->report()->error(1402, "missing requireds."); - } - requireds[arrival_index_] = required; -} - -bool -PathVertex::equal(const PathVertex *path1, - const PathVertex *path2) -{ - return path1->vertex_ == path2->vertex_ - && path1->tag_ == path2->tag_; -} - -//////////////////////////////////////////////////////////////// - -// EvalPred but search to clk source pin. -class PrevPred2 : public SearchPred0 -{ -public: - explicit PrevPred2(const StaState *sta); - virtual bool searchThru(Edge *edge); -}; - -PrevPred2::PrevPred2(const StaState *sta) : - SearchPred0(const_cast(sta)) -{ -} - -bool -PrevPred2::searchThru(Edge *edge) -{ - const Sdc *sdc = sta_->sdc(); - TimingRole *role = edge->role(); - return SearchPred0::searchThru(edge) - && (sdc->dynamicLoopBreaking() - || !edge->isDisabledLoop()) - && !role->isTimingCheck(); -} - -class PrevPathVisitor : public PathVisitor -{ -public: - PrevPathVisitor(const Path *path, - SearchPred *pred, - const StaState *sta); - virtual VertexVisitor *copy() const; - virtual void visit(Vertex *) {} - virtual bool visitFromToPath(const Pin *from_pin, - Vertex *from_vertex, - const RiseFall *from_rf, - Tag *from_tag, - PathVertex *from_path, - const Arrival &from_arrival, - Edge *edge, - TimingArc *arc, - ArcDelay arc_delay, - Vertex *to_vertex, - const RiseFall *to_rf, - Tag *to_tag, - Arrival &to_arrival, - const MinMax *min_max, - const PathAnalysisPt *path_ap); - PathVertex &prevPath() { return prev_path_; } - TimingArc *prevArc() const { return prev_arc_; } - -protected: - Tag *unfilteredTag(const Tag *tag) const; - - const Path *path_; - Arrival path_arrival_; - Tag *path_tag_; - int path_rf_index_; - PathAPIndex path_ap_index_; - PathVertex prev_path_; - TimingArc *prev_arc_; - float dcalc_tol_; -}; - -PrevPathVisitor::PrevPathVisitor(const Path *path, - SearchPred *pred, - const StaState *sta) : - PathVisitor(pred, sta), - path_(path), - path_arrival_(path->arrival(sta)), - path_tag_(path->tag(sta)), - path_rf_index_(path->rfIndex(sta)), - path_ap_index_(path->pathAnalysisPtIndex(sta)), - prev_path_(), - prev_arc_(nullptr), - dcalc_tol_(sta->graphDelayCalc()->incrementalDelayTolerance()) -{ -} - -VertexVisitor * -PrevPathVisitor::copy() const -{ - return new PrevPathVisitor(path_, pred_, this); -} - -bool -PrevPathVisitor::visitFromToPath(const Pin *, - Vertex *, - const RiseFall *, - Tag *from_tag, - PathVertex *from_path, - const Arrival &, - Edge *, - TimingArc *arc, - ArcDelay, - Vertex *, - const RiseFall *to_rf, - Tag *to_tag, - Arrival &to_arrival, - const MinMax *, - const PathAnalysisPt *path_ap) -{ - PathAPIndex path_ap_index = path_ap->index(); - if (to_rf->index() == path_rf_index_ - && path_ap_index == path_ap_index_ - && delayEqual(to_arrival, path_arrival_) - && (tagMatch(to_tag, path_tag_, this) - // If the filter exception became active searching from - // from_path to to_path the tag includes the filter, but - // to_vertex still has paths from previous searches that do - // not have the filter. - || (!from_tag->isFilter() - && to_tag->isFilter() - && tagMatch(unfilteredTag(to_tag), path_tag_, this)))) { - int arrival_index; - bool arrival_exists; - from_path->arrivalIndex(arrival_index, arrival_exists); - if (arrival_exists) { - prev_path_ = from_path; - prev_arc_ = arc; - // Stop looking for the previous path/arc. - return false; - } - } - return true; -} - -Tag * -PrevPathVisitor::unfilteredTag(const Tag *tag) const -{ - ExceptionStateSet *unfiltered_states = nullptr; - const ExceptionStateSet *states = tag->states(); - ExceptionStateSet::ConstIterator state_iter(states); - while (state_iter.hasNext()) { - ExceptionState *state = state_iter.next(); - ExceptionPath *except = state->exception(); - if (!except->isFilter()) { - if (unfiltered_states == nullptr) - unfiltered_states = new ExceptionStateSet(); - unfiltered_states->insert(state); - } - } - return search_->findTag(tag->transition(), - corners_->findPathAnalysisPt(tag->pathAPIndex()), - tag->clkInfo(), - tag->isClock(), - tag->inputDelay(), - tag->isSegmentStart(), - unfiltered_states, true); -} - -//////////////////////////////////////////////////////////////// - -void -PathVertex::prevPath(const StaState *sta, - // Return values. - PathVertex &prev_path, - TimingArc *&prev_arc) const -{ - PrevPred2 pred(sta); - PrevPathVisitor visitor(this, &pred, sta); - visitor.visitFaninPaths(vertex(sta)); - prev_path = visitor.prevPath(); - prev_arc = visitor.prevArc(); -} - -void -PathVertex::prevPath(const StaState *sta, - // Return values. - PathVertex &prev_path) const -{ - PrevPred2 pred(sta); - PrevPathVisitor visitor(this, &pred, sta); - visitor.visitFaninPaths(vertex(sta)); - prev_path = visitor.prevPath(); -} - -void -PathVertex::prevPath(const StaState *sta, - // Return values. - PathRef &prev_path, - TimingArc *&prev_arc) const -{ - const Graph *graph = sta->graph(); - Vertex *vertex = this->vertex(graph); - PathPrev *prev_paths = vertex->prevPaths(); - if (prev_paths) { - PathPrev &prev = prev_paths[arrival_index_]; - prev_path.init(prev, sta); - prev_arc = prev.isNull() ? nullptr : prev.prevArc(sta); - } - else { - PathVertex prev; - prevPath(sta, prev, prev_arc); - prev.setRef(prev_path); - } -} - -//////////////////////////////////////////////////////////////// - -VertexPathIterator::VertexPathIterator(Vertex *vertex, - const StaState *sta) : - search_(sta->search()), - vertex_(vertex), - rf_(nullptr), - path_ap_(nullptr), - min_max_(nullptr) -{ - TagGroup *tag_group = search_->tagGroup(vertex); - if (tag_group) { - arrival_iter_.init(tag_group->arrivalMap()); - findNext(); - } -} - -// Iterate over vertex paths with the same transition and -// analysis pt but different but different tags. -VertexPathIterator::VertexPathIterator(Vertex *vertex, - const RiseFall *rf, - const PathAnalysisPt *path_ap, - const StaState *sta) : - search_(sta->search()), - vertex_(vertex), - rf_(rf), - path_ap_(path_ap), - min_max_(nullptr) -{ - TagGroup *tag_group = search_->tagGroup(vertex); - if (tag_group) { - arrival_iter_.init(tag_group->arrivalMap()); - findNext(); - } -} - -VertexPathIterator::VertexPathIterator(Vertex *vertex, - const RiseFall *rf, - const MinMax *min_max, - const StaState *sta) : - search_(sta->search()), - vertex_(vertex), - rf_(rf), - path_ap_(nullptr), - min_max_(min_max) -{ - TagGroup *tag_group = search_->tagGroup(vertex); - if (tag_group) { - arrival_iter_.init(tag_group->arrivalMap()); - findNext(); - } -} - -VertexPathIterator::VertexPathIterator(Vertex *vertex, - const RiseFall *rf, - const PathAnalysisPt *path_ap, - const MinMax *min_max, - const StaState *sta) : - search_(sta->search()), - vertex_(vertex), - rf_(rf), - path_ap_(path_ap), - min_max_(min_max) -{ - TagGroup *tag_group = search_->tagGroup(vertex); - if (tag_group) { - arrival_iter_.init(tag_group->arrivalMap()); - findNext(); - } -} - -VertexPathIterator::~VertexPathIterator() -{ -} - -bool -VertexPathIterator::hasNext() -{ - return !next_.isNull(); -} - -void -VertexPathIterator::findNext() -{ - while (arrival_iter_.hasNext()) { - Tag *tag; - int arrival_index; - arrival_iter_.next(tag, arrival_index); - if ((rf_ == nullptr - || tag->rfIndex() == rf_->index()) - && (path_ap_ == nullptr - || tag->pathAPIndex() == path_ap_->index()) - && (min_max_ == nullptr - || tag->pathAnalysisPt(search_)->pathMinMax() == min_max_)) { - next_.init(vertex_, tag, arrival_index); - return; - } - } - next_.init(); -} - -PathVertex * -VertexPathIterator::next() -{ - path_ = next_; - findNext(); - return &path_; -} - -} // namespace diff --git a/search/PathVertexPtr.cc b/search/PathVertexPtr.cc deleted file mode 100644 index 16fc7d9d..00000000 --- a/search/PathVertexPtr.cc +++ /dev/null @@ -1,201 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2025, Parallax Software, Inc. -// -// 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 . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#include "PathVertexPtr.hh" - -#include "Graph.hh" -#include "TimingArc.hh" -#include "SearchClass.hh" -#include "Tag.hh" -#include "TagGroup.hh" -#include "Search.hh" -#include "PathAnalysisPt.hh" -#include "PathVertex.hh" - -namespace sta { - -PathVertexPtr::PathVertexPtr() : - vertex_id_(vertex_id_null), - tag_index_(tag_index_null) -{ -} - -PathVertexPtr::PathVertexPtr(const PathVertex *path, - const StaState *sta) -{ - init(path, sta); -} - -void -PathVertexPtr::init() -{ - vertex_id_ = vertex_id_null; - tag_index_ = tag_index_null; -} - -void -PathVertexPtr::init(const PathVertexPtr *path) -{ - if (path) { - vertex_id_ = path->vertex_id_; - tag_index_ = path->tag_index_; - } - else { - vertex_id_ = vertex_id_null; - tag_index_ = tag_index_null; - } -} - -void -PathVertexPtr::init(const PathVertexPtr &path) -{ - vertex_id_ = path.vertex_id_; - tag_index_ = path.tag_index_; -} - -void -PathVertexPtr::init(const PathVertex *path, - const StaState *sta) -{ - if (path == nullptr || path->isNull()) - init(); - else { - vertex_id_ = path->vertexId(sta); - tag_index_ = path->tagIndex(sta); - } -} - -const char * -PathVertexPtr::name(const StaState *sta) const -{ - const Network *network = sta->network(); - const Search *search = sta->search(); - Vertex *vertex = this->vertex(sta); - if (vertex) { - const char *vertex_name = vertex->name(network); - const Tag *tag = this->tag(search); - const RiseFall *rf = tag->transition(); - const char *rf_str = rf->asString(); - const PathAnalysisPt *path_ap = tag->pathAnalysisPt(sta); - int ap_index = path_ap->index(); - const char *min_max = path_ap->pathMinMax()->asString(); - TagIndex tag_index = tag->index(); - return stringPrintTmp("%s %s %s/%d %d", - vertex_name, rf_str, min_max, - ap_index, tag_index); - } - else - return "NULL"; -} - -bool -PathVertexPtr::isNull() const -{ - return vertex_id_ == vertex_id_null; -} - -Vertex * -PathVertexPtr::vertex(const StaState *sta) const -{ - if (vertex_id_ == vertex_id_null) - return nullptr; - else { - const Graph *graph = sta->graph(); - return graph->vertex(vertex_id_); - } -} - -Tag * -PathVertexPtr::tag(const StaState *sta) const -{ - const Search *search = sta->search(); - return search->tag(tag_index_); -} - -Arrival -PathVertexPtr::arrival(const StaState *sta) const -{ - const Vertex *vertex = this->vertex(sta); - Arrival *arrivals = sta->graph()->arrivals(vertex); - if (arrivals) { - const Search *search = sta->search(); - TagGroup *tag_group = search->tagGroup(vertex); - Tag *tag = this->tag(sta); - int arrival_index; - bool arrival_exists; - tag_group->arrivalIndex(tag, arrival_index, arrival_exists); - if (arrival_exists) - return arrivals[arrival_index]; - else { - sta->report()->error(1403, "missing arrival."); - return 0.0; - } - } - else { - sta->report()->error(1404, "missing arrivals."); - return 0.0; - } -} - -//////////////////////////////////////////////////////////////// - -bool -PathVertexPtr::equal(const PathVertexPtr *path1, - const PathVertexPtr *path2) -{ - return path1->vertex_id_ == path2->vertex_id_ - && path1->tag_index_ == path2->tag_index_; -} - -bool -PathVertexPtr::equal(const PathVertexPtr &path1, - const PathVertexPtr &path2) -{ - return path1.vertex_id_ == path2.vertex_id_ - && path1.tag_index_ == path2.tag_index_; -} - -int -PathVertexPtr::cmp(const PathVertexPtr &path1, - const PathVertexPtr &path2) -{ - VertexId vertex_id1 = path1.vertex_id_; - VertexId vertex_id2 = path2.vertex_id_; - if (vertex_id1 == vertex_id2) { - TagIndex tag_index1 = path1.tagIndex(); - TagIndex tag_index2 = path2.tagIndex(); - if (tag_index1 == tag_index2) - return 0; - else if (tag_index1 < tag_index2) - return -1; - else - return 1; - } - else if (vertex_id1 < vertex_id2) - return -1; - else - return 1; -} - -} // namespace diff --git a/search/Property.cc b/search/Property.cc index de8b2b80..9c3f598a 100644 --- a/search/Property.cc +++ b/search/Property.cc @@ -37,7 +37,7 @@ #include "Corner.hh" #include "PathEnd.hh" #include "PathExpanded.hh" -#include "PathRef.hh" +#include "Path.hh" #include "power/Power.hh" #include "Sta.hh" @@ -318,9 +318,9 @@ PropertyValue::PropertyValue(ClockSet *value) : } } -PropertyValue::PropertyValue(PathRefSeq *value) : - type_(type_path_refs), - path_refs_(new PathRefSeq(*value)), +PropertyValue::PropertyValue(ConstPathSeq *value) : + type_(type_paths), + paths_(new ConstPathSeq(*value)), unit_(nullptr) { } @@ -384,8 +384,8 @@ PropertyValue::PropertyValue(const PropertyValue &value) : case Type::type_clks: clks_ = value.clks_ ? new ClockSeq(*value.clks_) : nullptr; break; - case Type::type_path_refs: - path_refs_ = value.path_refs_ ? new PathRefSeq(*value.path_refs_) : nullptr; + case Type::type_paths: + paths_ = value.paths_ ? new ConstPathSeq(*value.paths_) : nullptr; break; case Type::type_pwr_activity: pwr_activity_ = value.pwr_activity_; @@ -450,8 +450,8 @@ PropertyValue::PropertyValue(PropertyValue &&value) : // Steal the value. value.clks_ = nullptr; break; - case Type::type_path_refs: - path_refs_ = value.path_refs_; + case Type::type_paths: + paths_ = value.paths_; // Steal the value. value.clks_ = nullptr; break; @@ -473,8 +473,8 @@ PropertyValue::~PropertyValue() case Type::type_pins: delete pins_; break; - case Type::type_path_refs: - delete path_refs_; + case Type::type_paths: + delete paths_; break; default: break; @@ -535,8 +535,8 @@ PropertyValue::operator=(const PropertyValue &value) case Type::type_clks: clks_ = value.clks_ ? new ClockSeq(*value.clks_) : nullptr; break; - case Type::type_path_refs: - path_refs_ = value.path_refs_ ? new PathRefSeq(*value.path_refs_) : nullptr; + case Type::type_paths: + paths_ = value.paths_ ? new ConstPathSeq(*value.paths_) : nullptr; break; case Type::type_pwr_activity: pwr_activity_ = value.pwr_activity_; @@ -602,8 +602,8 @@ PropertyValue::operator=(PropertyValue &&value) clks_ = value.clks_; value.clks_ = nullptr; break; - case Type::type_path_refs: - path_refs_ = value.path_refs_; + case Type::type_paths: + paths_ = value.paths_; value.clks_ = nullptr; break; case Type::type_pwr_activity: @@ -650,7 +650,7 @@ PropertyValue::asString(const Network *network) const case Type::type_none: case Type::type_pins: case Type::type_clks: - case Type::type_path_refs: + case Type::type_paths: case Type::type_pwr_activity: return nullptr; } @@ -1147,12 +1147,7 @@ getProperty(Edge *edge, Sta *sta) { if (stringEqual(property, "full_name")) { - Network *network = sta->cmdNetwork(); - Graph *graph = sta->ensureGraph(); - const char *from = edge->from(graph)->name(network); - const char *to = edge->to(graph)->name(network); - string full_name; - stringPrint(full_name, "%s -> %s", from, to); + string full_name = edge->to_string(sta); return PropertyValue(full_name); } if (stringEqual(property, "delay_min_fall")) @@ -1164,7 +1159,7 @@ getProperty(Edge *edge, else if (stringEqual(property, "delay_max_rise")) return edgeDelayProperty(edge, RiseFall::rise(), MinMax::max(), sta); else if (stringEqual(property, "sense")) - return PropertyValue(timingSenseString(edge->sense())); + return PropertyValue(to_string(edge->sense())); else if (stringEqual(property, "from_pin")) return PropertyValue(edge->from(sta->graph())->pin()); else if (stringEqual(property, "to_pin")) @@ -1183,7 +1178,7 @@ edgeDelayProperty(Edge *edge, bool delay_exists = false; TimingArcSet *arc_set = edge->timingArcSet(); for (TimingArc *arc : arc_set->arcs()) { - RiseFall *to_rf = arc->toEdge()->asRiseFall(); + const RiseFall *to_rf = arc->toEdge()->asRiseFall(); if (to_rf == rf) { for (const Corner *corner : *sta->corners()) { DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max); @@ -1271,10 +1266,10 @@ getProperty(PathEnd *end, return PropertyValue(delayPropertyValue(end->slack(sta), sta)); else if (stringEqual(property, "points")) { PathExpanded expanded(end->path(), sta); - PathRefSeq paths; + ConstPathSeq paths; for (size_t i = expanded.startIndex(); i < expanded.size(); i++) { - const PathRef *path = expanded.path(i); - paths.push_back(*path); + const Path *path = expanded.path(i); + paths.push_back(path); } return PropertyValue(&paths); } @@ -1283,16 +1278,16 @@ getProperty(PathEnd *end, } PropertyValue -getProperty(PathRef *path, +getProperty(Path *path, const char *property, Sta *sta) { if (stringEqual(property, "pin")) return PropertyValue(path->pin(sta)); else if (stringEqual(property, "arrival")) - return PropertyValue(delayPropertyValue(path->arrival(sta), sta)); + return PropertyValue(delayPropertyValue(path->arrival(), sta)); else if (stringEqual(property, "required")) - return PropertyValue(delayPropertyValue(path->required(sta), sta)); + return PropertyValue(delayPropertyValue(path->required(), sta)); else if (stringEqual(property, "slack")) return PropertyValue(delayPropertyValue(path->slack(sta), sta)); else diff --git a/search/ReportPath.cc b/search/ReportPath.cc index bd23c47d..5a895a3e 100644 --- a/search/ReportPath.cc +++ b/search/ReportPath.cc @@ -48,13 +48,12 @@ #include "GraphDelayCalc.hh" #include "ClkInfo.hh" #include "Tag.hh" -#include "PathVertex.hh" #include "PathAnalysisPt.hh" #include "PathGroup.hh" #include "CheckMinPulseWidths.hh" #include "CheckMinPeriods.hh" #include "CheckMaxSkews.hh" -#include "PathRef.hh" +#include "Path.hh" #include "Search.hh" #include "PathExpanded.hh" #include "Latches.hh" @@ -479,8 +478,8 @@ ReportPath::reportFull(const PathEndCheck *end) const string ReportPath::checkRoleString(const PathEnd *end) const { - const char *check_role = end->checkRole(this)->asString(); - return stdstrPrint("library %s time", check_role); + return stdstrPrint("library %s time", + end->checkRole(this)->to_string().c_str()); } void @@ -494,9 +493,8 @@ ReportPath::reportEndpoint(const PathEndCheck *end) const const TimingRole *check_generic_role = check_role->genericRole(); if (check_role == TimingRole::recovery() || check_role == TimingRole::removal()) { - const char *check_role_name = check_role->asString(); auto reason = stdstrPrint("%s check against %s-edge clock %s", - check_role_name, + check_role->to_string().c_str(), rise_fall, clk_name.c_str()); reportEndpoint(inst_name, reason); @@ -724,12 +722,11 @@ ReportPath::reportFull(const PathEndPathDelay *end) const reportBlankLine(); ArcDelay margin = end->margin(this); - MinMax *min_max = path_delay->minMax()->asMinMax(); + const MinMax *min_max = path_delay->minMax()->asMinMax(); if (min_max == MinMax::max()) margin = -margin; - const char *min_max_str = min_max->asString(); - auto delay_msg = stdstrPrint("%s_delay", min_max_str); + string delay_msg = min_max->to_string() + "_delay"; float delay = path_delay->delay(); reportLine(delay_msg.c_str(), delay, delay, early_late); if (!path_delay->ignoreClkLatency()) { @@ -925,7 +922,7 @@ ReportPath::reportFull(const PathEndDataCheck *end) const // It is like a target because crpr and uncertainty are reported. // It is always propagated, even if the clock is ideal. reportTgtClk(end, 0.0, true); - const PathVertex *data_clk_path = end->dataClkPath(); + const Path *data_clk_path = end->dataClkPath(); if (!data_clk_path->isClock(this)) { // Report the path from the clk network to the data check. PathExpanded clk_expanded(data_clk_path, this); @@ -1037,7 +1034,7 @@ string ReportPath::pathStartpoint(const PathEnd *end, const PathExpanded &expanded) const { - const PathRef *start = expanded.startPath(); + const Path *start = expanded.startPath(); Pin *pin = start->pin(graph_); const char *pin_name = cmd_network_->pathName(pin); if (network_->isTopLevelPort(pin)) { @@ -1092,7 +1089,7 @@ ReportPath::reportJson(const PathEnd *end, stringAppend(result, " \"path_group\": \"%s\",\n", search_->pathGroup(end)->name()); stringAppend(result, " \"path_type\": \"%s\",\n", - end->minMax(this)->asString()); + end->minMax(this)->to_string().c_str()); PathExpanded expanded(end->path(), this); const Pin *startpoint = expanded.startPath()->vertex(this)->pin(); @@ -1103,7 +1100,7 @@ ReportPath::reportJson(const PathEnd *end, sdc_network_->pathName(endpoint)); const ClockEdge *src_clk_edge = end->sourceClkEdge(this); - const PathVertex *tgt_clk_path = end->targetClkPath(); + const Path *tgt_clk_path = end->targetClkPath(); if (src_clk_edge) { stringAppend(result, " \"source_clock\": \"%s\",\n", src_clk_edge->clock()->name()); @@ -1181,7 +1178,7 @@ ReportPath::reportJson(const PathExpanded &expanded, { stringAppend(result, "%*s\"%s\": [\n", indent, "", path_name); for (size_t i = 0; i < expanded.size(); i++) { - const PathRef *path = expanded.path(i); + const Path *path = expanded.path(i); const Pin *pin = path->vertex(this)->pin(); const Net *net = network_->net(pin); const Instance *inst = network_->instance(pin); @@ -1238,7 +1235,7 @@ ReportPath::reportJson(const PathExpanded &expanded, stringAppend(result, "%*s \"arrival\": %.3e,\n", indent, "", - delayAsFloat(path->arrival(this))); + delayAsFloat(path->arrival())); if (is_driver) stringAppend(result, "%*s \"capacitance\": %.3e,\n", indent, "", @@ -1587,12 +1584,12 @@ ReportPath::reportShort(const MaxSkewCheck *check) const TimingArc *check_arc = check->checkArc(); auto what = stdstrPrint("%s (%s->%s)", clk_pin_name, - check_arc->fromEdge()->asString(), - check_arc->toEdge()->asString()); + check_arc->fromEdge()->to_string().c_str(), + check_arc->toEdge()->to_string().c_str()); reportDescription(what.c_str(), line); const EarlyLate *early_late = EarlyLate::early(); reportSpaceFieldDelay(check->maxSkew(this), early_late, line); - reportSpaceFieldDelay(check->skew(this), early_late, line); + reportSpaceFieldDelay(check->skew(), early_late, line); reportSpaceSlack(check->slack(this), line); report_->reportLineString(line); } @@ -1621,7 +1618,7 @@ ReportPath::reportVerbose(const MaxSkewCheck *check) const reportDashLine(); reportLine("allowable skew", check->maxSkew(this), EarlyLate::early()); - reportLine("actual skew", check->skew(this), EarlyLate::late()); + reportLine("actual skew", check->skew(), EarlyLate::late()); reportDashLine(); reportSlack(check->slack(this)); } @@ -1629,7 +1626,7 @@ ReportPath::reportVerbose(const MaxSkewCheck *check) const // Based on reportTgtClk. void ReportPath::reportSkewClkPath(const char *arrival_msg, - const PathVertex *clk_path) const + const Path *clk_path) const { const ClockEdge *clk_edge = clk_path->clkEdge(this); const Clock *clk = clk_edge->clock(); @@ -1735,7 +1732,7 @@ ReportPath::reportLimitVerbose(const ReportField *field, } report_->reportLineString(line); - line = min_max->asString(); + line = min_max->to_string(); line += ' '; line += field->name(); line += ' '; @@ -1767,9 +1764,9 @@ ReportPath::reportStartpoint(const PathEnd *end, const PathExpanded &expanded) const { const Path *path = end->path(); - const PathRef *start = expanded.startPath(); + const Path *start = expanded.startPath(); const TimingArc *prev_arc = expanded.startPrevArc(); - const Edge *prev_edge = start->prevEdge(prev_arc, this); + const Edge *prev_edge = start->prevEdge(this); const Pin *pin = start->pin(graph_); const ClockEdge *clk_edge = path->clkEdge(this); const Clock *clk = path->clock(search_); @@ -1795,10 +1792,9 @@ ReportPath::reportStartpoint(const PathEnd *end, const char *inst_name = cmd_network_->pathName(inst); if (clk_edge) { const RiseFall *clk_rf = clk_edge->transition(); - PathRef clk_path; - expanded.clkPath(clk_path); - bool clk_inverted = !clk_path.isNull() - && clk_rf != clk_path.transition(this); + const Path *clk_path = expanded.clkPath(); + bool clk_inverted = clk_path + && clk_rf != clk_path->transition(this); string clk_name = clkName(clk, clk_inverted); const char *reg_desc = edgeRegLatchDesc(prev_edge, prev_arc); auto reason = stdstrPrint("%s clocked by %s", reg_desc, clk_name.c_str()); @@ -1830,8 +1826,8 @@ ReportPath::reportStartpoint(const PathEnd *end, bool ReportPath::pathFromClkPin(const PathExpanded &expanded) const { - const PathRef *start = expanded.startPath(); - const PathRef *end = expanded.endPath(); + const Path *start = expanded.startPath(); + const Path *end = expanded.endPath(); const Pin *start_pin = start->pin(graph_); return pathFromClkPin(end, start_pin); } @@ -1946,7 +1942,7 @@ ReportPath::reportGroup(const PathEnd *end) const report_->reportLineString(line); line = "Path Type: "; - line += end->minMax(this)->asString(); + line += end->minMax(this)->to_string(); report_->reportLineString(line); if (corners_->multiCorner()) { @@ -1961,8 +1957,7 @@ ReportPath::reportGroup(const PathEnd *end) const string ReportPath::checkRoleReason(const PathEnd *end) const { - const char *setup_hold = end->checkRole(this)->asString(); - return stdstrPrint("%s time", setup_hold); + return stdstrPrint("%s time", end->checkRole(this)->to_string().c_str()); } string @@ -1998,7 +1993,7 @@ ReportPath::clkRegLatchDesc(const PathEnd *end) const while (iter.hasNext()) { Edge *edge = iter.next(); TimingArcSet *arc_set = edge->timingArcSet(); - TimingRole *role = arc_set->role(); + const TimingRole *role = arc_set->role(); if (role == TimingRole::regClkToQ() || role == TimingRole::latchEnToQ()) { const RiseFall *arc_rf = arc_set->isRisingFallingEdge(); @@ -2053,7 +2048,7 @@ ReportPath::reportSrcClkAndPath(const Path *path, const MinMax *min_max = path->minMax(this); if (clk_edge) { Clock *clk = clk_edge->clock(); - RiseFall *clk_rf = clk_edge->transition(); + const RiseFall *clk_rf = clk_edge->transition(); float clk_time = clk_edge->time() + time_offset; if (clk == sdc_->defaultArrivalClock()) { if (!is_path_delay) { @@ -2069,13 +2064,12 @@ ReportPath::reportSrcClkAndPath(const Path *path, bool path_from_input = false; bool input_has_ref_path = false; Arrival clk_delay, clk_end_time; - PathRef clk_path; - expanded.clkPath(clk_path); + const Path *clk_path = expanded.clkPath(); const RiseFall *clk_end_rf; - if (!clk_path.isNull()) { - clk_end_time = search_->clkPathArrival(&clk_path) + time_offset; + if (clk_path) { + clk_end_time = search_->clkPathArrival(clk_path) + time_offset; clk_delay = clk_end_time - clk_time; - clk_end_rf = clk_path.transition(this); + clk_end_rf = clk_path->transition(this); } else { // Path from input port or clk used as data. @@ -2083,16 +2077,16 @@ ReportPath::reportSrcClkAndPath(const Path *path, clk_delay = clk_insertion + clk_latency; clk_end_time = clk_time + clk_delay; - const PathRef *first_path = expanded.startPath(); + const Path *first_path = expanded.startPath(); const InputDelay *input_delay = pathInputDelay(first_path); if (input_delay) { path_from_input = true; const Pin *ref_pin = input_delay->refPin(); if (ref_pin && clk->isPropagated()) { - PathRef ref_path; + Path ref_path; pathInputDelayRefPath(first_path, input_delay, ref_path); if (!ref_path.isNull()) { - const Arrival &ref_end_time = ref_path.arrival(this); + const Arrival &ref_end_time = ref_path.arrival(); clk_delay = ref_end_time - clk_time; clk_end_time = ref_end_time + time_offset; input_has_ref_path = true; @@ -2105,8 +2099,7 @@ ReportPath::reportSrcClkAndPath(const Path *path, bool clk_used_as_data = pathFromClkPin(expanded); bool is_prop = isPropagated(path); const EarlyLate *early_late = min_max; - if (reportGenClkSrcPath(clk_path.isNull() ? nullptr : &clk_path, - clk, clk_rf, min_max, early_late) + if (reportGenClkSrcPath(clk_path, clk, clk_rf, min_max, early_late) && !(path_from_input && !input_has_ref_path)) { reportClkLine(clk, clk_name.c_str(), clk_end_rf, clk_time, min_max); @@ -2137,7 +2130,7 @@ ReportPath::reportSrcClkAndPath(const Path *path, reportPath1(path, expanded, true, time_offset); else { Arrival clk_arrival = clk_end_time; - Arrival end_arrival = path->arrival(this) + time_offset; + Arrival end_arrival = path->arrival() + time_offset; Delay clk_delay = end_arrival - clk_arrival; reportLine("clock network delay", clk_delay, end_arrival, early_late); @@ -2211,7 +2204,7 @@ ReportPath::reportTgtClk(const PathEnd *end, const MinMax *min_max = path_ap->pathMinMax(); const Path *clk_path = end->targetClkPath(); reportClkLine(clk, clk_name.c_str(), clk_end_rf, prev_time, clk_time, min_max); - TimingRole *check_role = end->checkRole(this); + const TimingRole *check_role = end->checkRole(this); if (is_prop && reportClkPath()) { float time_offset = prev_time + end->targetClkOffset(this) @@ -2395,10 +2388,10 @@ ReportPath::reportGenClkSrcPath1(const Clock *clk, { PathAnalysisPt *insert_ap = path_ap->insertionAnalysisPt(early_late); const MinMax *min_max = path_ap->pathMinMax(); - PathVertex src_path = - search_->genclks()->srcPath(clk, clk_pin, clk_rf, insert_ap); - if (!src_path.isNull()) { - ClkInfo *src_clk_info = src_path.clkInfo(search_); + Path *src_path = search_->genclks()->srcPath(clk, clk_pin, + clk_rf, insert_ap); + if (src_path) { + ClkInfo *src_clk_info = src_path->clkInfo(this); const ClockEdge *src_clk_edge = src_clk_info->clkEdge(); const Clock *src_clk = src_clk_info->clock(); if (src_clk) { @@ -2419,12 +2412,12 @@ ReportPath::reportGenClkSrcPath1(const Clock *clk, early_late, path_ap); reportClkSrcLatency(insertion, gclk_time, early_late); } - PathExpanded src_expanded(&src_path, this); - reportPath4(&src_path, src_expanded, skip_first_path, false, + PathExpanded src_expanded(src_path, this); + reportPath4(src_path, src_expanded, skip_first_path, false, clk_used_as_data, gclk_time); if (!clk->isPropagated()) reportLine("clock network delay (ideal)", 0.0, - src_path.arrival(this), min_max); + src_path->arrival(), min_max); } } else { @@ -2433,7 +2426,7 @@ ReportPath::reportGenClkSrcPath1(const Clock *clk, else if (!clk_used_as_data) reportLine("clock network delay (ideal)", 0.0, gclk_time, min_max); } - return !src_path.isNull(); + return src_path != nullptr; } void @@ -2610,22 +2603,21 @@ ReportPath::reportPath1(const Path *path, bool clk_used_as_data, float time_offset) const { - const PathRef *d_path, *q_path; + const Path *d_path, *q_path; Edge *d_q_edge; expanded.latchPaths(d_path, q_path, d_q_edge); if (d_path) { Arrival latch_time_given, latch_enable_time; - PathVertex latch_enable_path; + Path *latch_enable_path; latches_->latchTimeGivenToStartpoint(d_path, q_path, d_q_edge, - latch_time_given, - latch_enable_path); - if (!latch_enable_path.isNull()) { - const EarlyLate *early_late = latch_enable_path.minMax(this); - latch_enable_time = search_->clkPathArrival(&latch_enable_path); + latch_time_given, latch_enable_path); + if (latch_enable_path) { + const EarlyLate *early_late = latch_enable_path->minMax(this); + latch_enable_time = search_->clkPathArrival(latch_enable_path); if (reportClkPath()) { - PathExpanded enable_expanded(&latch_enable_path, this); + PathExpanded enable_expanded(latch_enable_path, this); // Report the path to the latch enable. - reportPath2(&latch_enable_path, enable_expanded, false, + reportPath2(latch_enable_path, enable_expanded, false, time_offset); } Arrival time = latch_enable_time + latch_time_given; @@ -2689,8 +2681,8 @@ ReportPath::reportPath4(const Path *path, Arrival prev_time(0.0); if (skip_first_path) { path_first_index = 1; - const PathRef *start = expanded.path(0); - prev_time = start->arrival(this) + time_offset; + const Path *start = expanded.path(0); + prev_time = start->arrival() + time_offset; } size_t path_last_index = expanded.size() - 1; if (skip_last_path @@ -2719,15 +2711,14 @@ ReportPath::reportPath5(const Path *path, const MinMax *min_max = path->minMax(this); DcalcAnalysisPt *dcalc_ap = path->pathAnalysisPt(this)->dcalcAnalysisPt(); DcalcAPIndex ap_index = dcalc_ap->index(); - PathRef clk_path; - expanded.clkPath(clk_path); - Vertex *clk_start = clk_path.vertex(this); + const Path *clk_path = expanded.clkPath(); + Vertex *clk_start = clk_path ? clk_path->vertex(this) : nullptr; for (size_t i = path_first_index; i <= path_last_index; i++) { - const PathRef *path1 = expanded.path(i); - TimingArc *prev_arc = expanded.prevArc(i); + const Path *path1 = expanded.path(i); + const TimingArc *prev_arc = path1->prevArc(this); Vertex *vertex = path1->vertex(this); Pin *pin = vertex->pin(); - Arrival time = path1->arrival(this) + time_offset; + Arrival time = path1->arrival() + time_offset; Delay incr = 0.0; const char *line_case = nullptr; bool is_clk_start = path1->vertex(this) == clk_start; @@ -2747,7 +2738,7 @@ ReportPath::reportPath5(const Path *path, // First path. reportInputExternalDelay(path1, time_offset); size_t next_index = i + 1; - const PathRef *next_path = expanded.path(next_index); + const Path *next_path = expanded.path(next_index); if (network_->isTopLevelPort(pin) && next_path && !nextArcAnnotated(next_path, next_index, expanded, ap_index) @@ -2756,7 +2747,7 @@ ReportPath::reportPath5(const Path *path, // The delay calculator annotates wire delays on the edges // from the input to the loads. Report the wire delay on the // input pin instead. - Arrival next_time = next_path->arrival(this) + time_offset; + Arrival next_time = next_path->arrival() + time_offset; incr = delayIncr(next_time, time, min_max); time = next_time; line_case = "input_drive"; @@ -2785,7 +2776,7 @@ ReportPath::reportPath5(const Path *path, time = search_->clkPathArrival(path1) + time_offset; if (src_clk_edge) { Clock *src_clk = src_clk_edge->clock(); - RiseFall *src_clk_rf = src_clk_edge->transition(); + const RiseFall *src_clk_rf = src_clk_edge->transition(); slew = src_clk->slew(src_clk_rf, min_max); } } @@ -2799,7 +2790,7 @@ ReportPath::reportPath5(const Path *path, time = prev_time; const ClockEdge *src_clk_edge = path->clkEdge(this); const Clock *src_clk = src_clk_edge->clock(); - RiseFall *src_clk_rf = src_clk_edge->transition(); + const RiseFall *src_clk_rf = src_clk_edge->transition(); slew = src_clk->slew(src_clk_rf, min_max); line_case = "clk_ideal"; } @@ -2833,7 +2824,7 @@ ReportPath::reportPath5(const Path *path, prev_time = time; } else { - reportHierPinsThru(path1, prev_arc); + reportHierPinsThru(path1); if (report_input_pin_ || (i == 0) || (i == path_last_index) @@ -2852,11 +2843,10 @@ ReportPath::reportPath5(const Path *path, } void -ReportPath::reportHierPinsThru(const Path *path, - const TimingArc *prev_arc) const +ReportPath::reportHierPinsThru(const Path *path) const { if (report_hier_pins_) { - const Edge *prev_edge = path->prevEdge(prev_arc, this); + const Edge *prev_edge = path->prevEdge(this); if (prev_edge && prev_edge->isWire()) { for (const Pin *hpin : hierPinsThruEdge(prev_edge, network_, graph_)) { const string what = descriptionField(hpin); @@ -2880,13 +2870,13 @@ ReportPath::delayIncr(Delay time, } bool -ReportPath::nextArcAnnotated(const PathRef *next_path, +ReportPath::nextArcAnnotated(const Path *next_path, size_t next_index, const PathExpanded &expanded, DcalcAPIndex ap_index) const { - TimingArc *arc = expanded.prevArc(next_index); - Edge *edge = next_path->prevEdge(arc, this); + const TimingArc *arc = expanded.path(next_index)->prevArc(this); + Edge *edge = next_path->prevEdge(this); return graph_->arcDelayAnnotated(edge, arc, ap_index); } @@ -2983,13 +2973,13 @@ ReportPath::reportInputExternalDelay(const Path *first_path, const Pin *first_pin = first_path->pin(graph_); if (!pathFromClkPin(first_path, first_pin)) { const RiseFall *rf = first_path->transition(this); - Arrival time = first_path->arrival(this) + time_offset; + Arrival time = first_path->arrival() + time_offset; const EarlyLate *early_late = first_path->minMax(this); InputDelay *input_delay = pathInputDelay(first_path); if (input_delay) { const Pin *ref_pin = input_delay->refPin(); if (ref_pin) { - PathRef ref_path; + Path ref_path; pathInputDelayRefPath(first_path, input_delay, ref_path); if (!ref_path.isNull() && reportClkPath()) { PathExpanded ref_expanded(&ref_path, this); @@ -3018,7 +3008,7 @@ void ReportPath::pathInputDelayRefPath(const Path *path, const InputDelay *input_delay, // Return value. - PathRef &ref_path) const + Path &ref_path) const { const Pin *ref_pin = input_delay->refPin(); const RiseFall *ref_rf = input_delay->refTransition(); @@ -3028,10 +3018,10 @@ ReportPath::pathInputDelayRefPath(const Path *path, const ClockEdge *clk_edge = path->clkEdge(this); VertexPathIterator path_iter(ref_vertex, ref_rf, path_ap, this); while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); + Path *path = path_iter.next(); if (path->isClock(this) && path->clkEdge(this) == clk_edge) { - ref_path.init(path); + ref_path = path; break; } } @@ -3460,7 +3450,7 @@ const char * ReportPath::edgeRegLatchDesc(const Edge *first_edge, const TimingArc *first_arc) const { - TimingRole *role = first_arc->role(); + const TimingRole *role = first_arc->role(); if (role == TimingRole::latchDtoQ()) { Instance *inst = network_->instance(first_edge->to(graph_)->pin()); LibertyCell *cell = network_->libertyCell(inst); diff --git a/search/ReportPath.hh b/search/ReportPath.hh index 10ef2d0e..4f3a6812 100644 --- a/search/ReportPath.hh +++ b/search/ReportPath.hh @@ -326,8 +326,7 @@ protected: bool report_clk_path, Arrival prev_time, float time_offset) const; - void reportHierPinsThru(const Path *path, - const TimingArc *prev_arc) const; + void reportHierPinsThru(const Path *path) const; void reportInputExternalDelay(const Path *path, float time_offset) const; void reportLine(const char *what, @@ -426,7 +425,7 @@ protected: const MinMax *min_max) const; const char *mpwCheckHiLow(const MinPulseWidthCheck *check) const; void reportSkewClkPath(const char *arrival_msg, - const PathVertex *clk_path) const; + const Path *clk_path) const; const char *edgeRegLatchDesc(const Edge *edge, const TimingArc *arc) const; const char *checkRegLatchDesc(const TimingRole *role, @@ -434,7 +433,7 @@ protected: const char *regDesc(const RiseFall *clk_rf) const; const char *latchDesc(const RiseFall *clk_rf) const; void pathClkPath(const Path *path, - const PathRef &clk_path) const; + const Path &clk_path) const; bool isPropagated(const Path *clk_path) const; bool isPropagated(const Path *clk_path, const Clock *clk) const; @@ -443,10 +442,10 @@ protected: const Pin *start_pin) const; void latchPaths(const Path *path, // Return values. - PathRef &d_path, - PathRef &q_path, + Path &d_path, + Path &q_path, Edge *&d_q_edge) const; - bool nextArcAnnotated(const PathRef *next_path, + bool nextArcAnnotated(const Path *next_path, size_t next_index, const PathExpanded &expanded, DcalcAPIndex ap_index) const; @@ -458,7 +457,7 @@ protected: void pathInputDelayRefPath(const Path *path, const InputDelay *input_delay, // Return value. - PathRef &ref_path) const; + Path &ref_path) const; const char *asRisingFalling(const RiseFall *rf) const; const char *asRiseFall(const RiseFall *rf) const; Delay delayIncr(Delay time, diff --git a/search/Search.cc b/search/Search.cc index 97acec66..a8b14824 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -54,9 +54,7 @@ #include "Bfs.hh" #include "Corner.hh" #include "Sim.hh" -#include "PathVertex.hh" -#include "PathPrev.hh" -#include "PathRef.hh" +#include "Path.hh" #include "ClkInfo.hh" #include "Tag.hh" #include "TagGroup.hh" @@ -94,7 +92,7 @@ bool EvalPred::searchThru(Edge *edge) { const Sdc *sdc = sta_->sdc(); - TimingRole *role = edge->role(); + const TimingRole *role = edge->role(); return SearchPred0::searchThru(edge) && (sdc->dynamicLoopBreaking() || !edge->isDisabledLoop()) @@ -142,11 +140,7 @@ DynLoopSrchPred::hasPendingLoopPaths(Edge *edge, Corners *corners = search->corners(); Vertex *from_vertex = edge->from(graph); TagGroup *prev_tag_group = search->tagGroup(from_vertex); - ArrivalMap::Iterator arrival_iter(tag_bldr_->arrivalMap()); - while (arrival_iter.hasNext()) { - Tag *from_tag; - int arrival_index; - arrival_iter.next(from_tag, arrival_index); + for (auto const [from_tag, path_index] : tag_bldr_->pathIndexMap()) { if (from_tag->isLoop()) { // Loop false path exceptions apply to rise/fall edges so to_rf // does not matter. @@ -255,7 +249,6 @@ Search::init(StaState *sta) path_groups_ = nullptr; endpoints_ = nullptr; invalid_endpoints_ = nullptr; - always_save_prev_paths_ = true; filter_ = nullptr; filter_from_ = nullptr; filter_to_ = nullptr; @@ -274,6 +267,7 @@ Search::initVars() Search::~Search() { + deletePathGroups(); deletePaths(); deleteTags(); delete tag_set_; @@ -299,7 +293,6 @@ Search::~Search() delete genclks_; delete filtered_arrivals_; deleteFilter(); - deletePathGroups(); } void @@ -433,6 +426,8 @@ Search::deletePathsIncr(Vertex *vertex) void Search::deletePaths(Vertex *vertex) { + debugPrint(debug_, "search", 4, "delete paths %s", + vertex->name(network_)); TagGroup *tag_group = tagGroup(vertex); if (tag_group) graph_->deletePaths(vertex); @@ -450,8 +445,8 @@ Search::findPathEnds(ExceptionFrom *from, bool unconstrained, const Corner *corner, const MinMaxAll *min_max, - int group_path_count, - int endpoint_path_count, + size_t group_path_count, + size_t endpoint_path_count, bool unique_pins, float slack_min, float slack_max, @@ -490,9 +485,6 @@ Search::findFilteredArrivals(ExceptionFrom *from, bool thru_latches) { unconstrained_paths_ = unconstrained; - // Delete results from last findPathEnds. - // Filtered arrivals are deleted by Sta::searchPreamble. - deletePathGroups(); checkFromThrusTo(from, thrus, to); filter_from_ = from; filter_to_ = to; @@ -544,7 +536,7 @@ Search::deleteFilteredArrivals() if (!filtered_arrivals_->empty()) { report_->reportLine("Filtered verticies mismatch"); for (Vertex *vertex : *filtered_arrivals_) - report_->reportLine(" %s", vertex->name(network_)); + report_->reportLine(" %s", vertex->to_string(this).c_str()); } } filtered_arrivals_->clear(); @@ -618,6 +610,7 @@ Search::findFilteredArrivals(bool thru_latches) int arrival_count = arrival_iter_->visitParallel(max_level, arrival_visitor_); deleteTagsPrev(); + genclks_->updateSrcPathPrevs(); debugPrint(debug_, "search", 1, "found %d arrivals", arrival_count); } arrivals_exist_ = true; @@ -725,6 +718,20 @@ Search::deleteVertexBefore(Vertex *vertex) invalid_endpoints_->erase(vertex); } +void +Search::deleteEdgeBefore(Edge *edge) +{ + Vertex *from = edge->from(graph_); + Vertex *to = edge->to(graph_); + arrivalInvalid(to); + requiredInvalid(from); + VertexPathIterator path_iter(to, graph_); + while (path_iter.hasNext()) { + Path *path = path_iter.next(); + path->clearPrevPath(this); + } +} + bool Search::arrivalsValid() { @@ -740,6 +747,7 @@ Search::arrivalsInvalid() // Delete paths to make sure no state is left over. // For example, set_disable_timing strands a vertex, which means // the search won't revisit it to clear the previous arrival. + deletePathGroups(); deletePaths(); deleteTags(); genclks_->clear(); @@ -777,7 +785,7 @@ Search::arrivalInvalid(Vertex *vertex) { if (arrivals_exist_) { debugPrint(debug_, "search", 2, "arrival invalid %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); if (!arrival_iter_->inQueue(vertex)) { // Lock for StaDelayCalcObserver called by delay calc threads. LockGuard lock(invalid_arrivals_lock_); @@ -840,7 +848,7 @@ Search::requiredInvalid(Vertex *vertex) { if (requireds_exist_) { debugPrint(debug_, "search", 2, "required invalid %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); if (!required_iter_->inQueue(vertex)) { // Lock for StaDelayCalcObserver called by delay calc threads. LockGuard lock(invalid_arrivals_lock_); @@ -865,6 +873,7 @@ Search::findClkArrivals() arrival_visitor_->init(false, &search_clk); arrival_iter_->visitParallel(levelize_->maxLevel(), arrival_visitor_); deleteTagsPrev(); + genclks_->updateSrcPathPrevs(); arrivals_exist_ = true; stats.report("Find clk arrivals"); } @@ -1036,6 +1045,7 @@ Search::findArrivals1(Level level) Stats stats(debug_, report_); int arrival_count = arrival_iter_->visitParallel(level, arrival_visitor_); deleteTagsPrev(); + genclks_->updateSrcPathPrevs(); stats.report("Find arrivals"); if (arrival_iter_->empty() && invalid_arrivals_->empty()) { @@ -1043,7 +1053,7 @@ Search::findArrivals1(Level level) arrivals_at_endpoints_exist_ = true; } arrivals_exist_ = true; - debugPrint(debug_, "search", 1, "found %u arrivals", arrival_count); + debugPrint(debug_, "search", 1, "found %d arrivals", arrival_count); } void @@ -1066,8 +1076,7 @@ Search::findArrivalsSeed() //////////////////////////////////////////////////////////////// ArrivalVisitor::ArrivalVisitor(const StaState *sta) : - PathVisitor(nullptr, sta), - always_save_prev_paths_(true) + PathVisitor(nullptr, sta) { init0(); init(true); @@ -1104,8 +1113,6 @@ ArrivalVisitor::init(bool always_to_endpoints, always_to_endpoints_ = always_to_endpoints; pred_ = pred; crpr_active_ = sdc_->crprActive(); - if (search_) - always_save_prev_paths_ = search_->alwaysSavePrevPaths(); } @@ -1132,7 +1139,7 @@ void ArrivalVisitor::visit(Vertex *vertex) { debugPrint(debug_, "search", 2, "find arrivals %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); Pin *pin = vertex->pin(); tag_bldr_->init(vertex); has_fanin_one_ = graph_->hasFaninOne(vertex); @@ -1144,6 +1151,8 @@ ArrivalVisitor::visit(Vertex *vertex) if (crpr_active_ && search_->crprPathPruningEnabled() && !vertex->crprPathPruningDisabled() + // No crpr for ideal clocks. + && tag_bldr_->hasPropagatedClk() && !has_fanin_one_) pruneCrprArrivals(); @@ -1185,9 +1194,7 @@ ArrivalVisitor::visit(Vertex *vertex) || arrivals_changed) search_->arrivalIterator()->enqueueAdjacentVertices(vertex, adj_pred_); if (arrivals_changed) { - debugPrint(debug_, "search", 4, "arrival changed"); - // Only update arrivals when delays change by more than - // fuzzyEqual can distinguish. + debugPrint(debug_, "search", 4, "arrivals changed"); search_->setVertexArrivals(vertex, tag_bldr_); search_->tnsInvalid(vertex); constrainedRequiredsInvalid(vertex, is_clk); @@ -1237,28 +1244,21 @@ bool Search::arrivalsChanged(Vertex *vertex, TagGroupBldr *tag_bldr) { - Arrival *arrivals1 = graph_->arrivals(vertex); - PathPrev *prev_paths1 = graph_->prevPaths(vertex); - if (arrivals1) { + Path *paths1 = graph_->paths(vertex); + if (paths1) { TagGroup *tag_group = tagGroup(vertex); if (tag_group == nullptr - || tag_group->arrivalMap()->size() != tag_bldr->arrivalMap()->size()) + || tag_group->pathCount() != tag_bldr->pathCount()) return true; - ArrivalMap::Iterator arrival_iter1(tag_group->arrivalMap()); - while (arrival_iter1.hasNext()) { - Tag *tag1; - int arrival_index1; - arrival_iter1.next(tag1, arrival_index1); - Arrival &arrival1 = arrivals1[arrival_index1]; - Tag *tag2; - Arrival arrival2; - int arrival_index2; - tag_bldr->tagMatchArrival(tag1, tag2, arrival2, arrival_index2); - if (tag2 != tag1 - || !delayEqual(arrival1, arrival2) - || (prev_paths1 - && !PathPrev::equal(prev_paths1[arrival_index1], - tag_bldr->prevPath(arrival_index2)))) + for (auto const [tag1, path_index1] : *tag_group->pathIndexMap()) { + Path *path1 = &paths1[path_index1]; + Path *path2 = tag_bldr->tagMatchPath(tag1); + if (path2 == nullptr + || path1->tag(this) != path2->tag(this) + || !delayEqual(path1->arrival(), path2->arrival()) + || path1->prevEdge(this) != path2->prevEdge(this) + || path1->prevArc(this) != path2->prevArc(this) + || path1->prevPath() != path2->prevPath()) return true; } return false; @@ -1268,11 +1268,11 @@ Search::arrivalsChanged(Vertex *vertex, } bool -ArrivalVisitor::visitFromToPath(const Pin *, +ArrivalVisitor::visitFromToPath(const Pin * /* from_pin */, Vertex *from_vertex, const RiseFall *from_rf, Tag *from_tag, - PathVertex *from_path, + Path *from_path, const Arrival &from_arrival, Edge *edge, TimingArc *arc, @@ -1285,50 +1285,38 @@ ArrivalVisitor::visitFromToPath(const Pin *, const PathAnalysisPt *) { debugPrint(debug_, "search", 3, " %s", - from_vertex->name(sdc_network_)); + from_vertex->to_string(this).c_str()); debugPrint(debug_, "search", 3, " %s -> %s %s", - from_rf->asString(), - to_rf->asString(), - min_max->asString()); + from_rf->to_string().c_str(), + to_rf->to_string().c_str(), + min_max->to_string().c_str()); debugPrint(debug_, "search", 3, " from tag: %s", - from_tag->asString(this)); + from_tag->to_string(this).c_str()); debugPrint(debug_, "search", 3, " to tag : %s", - to_tag->asString(this)); + to_tag->to_string(this).c_str()); ClkInfo *to_clk_info = to_tag->clkInfo(); bool to_is_clk = to_tag->isClock(); - Arrival arrival; - int arrival_index; - Tag *tag_match; - tag_bldr_->tagMatchArrival(to_tag, tag_match, arrival, arrival_index); - if (tag_match == nullptr - || delayGreater(to_arrival, arrival, min_max, this)) { + Path *match; + size_t path_index; + tag_bldr_->tagMatchPath(to_tag, match, path_index); + if (match == nullptr + || delayGreater(to_arrival, match->arrival(), min_max, this)) { debugPrint(debug_, "search", 3, " %s + %s = %s %s %s", delayAsString(from_arrival, this), delayAsString(arc_delay, this), delayAsString(to_arrival, this), min_max == MinMax::max() ? ">" : "<", - tag_match ? delayAsString(arrival, this) : "MIA"); - PathPrev prev_path; - bool always_save_prev_paths = true; - bool save_prev = always_save_prev_paths - || to_tag->isClock() - || to_tag->isGenClkSrcPath(); - if (save_prev) - prev_path.init(from_path, edge, arc, this); - tag_bldr_->setMatchArrival(to_tag, tag_match, - to_arrival, arrival_index, - &prev_path); + match ? delayAsString(match->arrival(), this) : "MIA"); + tag_bldr_->setMatchPath(match, path_index, to_tag, to_arrival, from_path, edge, arc); if (crpr_active_ && !has_fanin_one_ && to_clk_info->hasCrprClkPin() && !to_is_clk) { - tag_bldr_no_crpr_->tagMatchArrival(to_tag, tag_match, - arrival, arrival_index); - if (tag_match == nullptr - || delayGreater(to_arrival, arrival, min_max, this)) { - tag_bldr_no_crpr_->setMatchArrival(to_tag, tag_match, - to_arrival, arrival_index, - &prev_path); + tag_bldr_no_crpr_->tagMatchPath(to_tag, match, path_index); + if (match == nullptr + || delayGreater(to_arrival, match->arrival(), min_max, this)) { + tag_bldr_no_crpr_->setMatchPath(match, path_index, to_tag, to_arrival, + from_path, edge, arc); } } } @@ -1339,43 +1327,40 @@ void ArrivalVisitor::pruneCrprArrivals() { CheckCrpr *crpr = search_->checkCrpr(); - ArrivalMap *arrival_map = tag_bldr_->arrivalMap(); - for (auto arrival_itr = arrival_map->cbegin(); arrival_itr != arrival_map->cend(); ) { - Tag *tag = arrival_itr->first; - int arrival_index = arrival_itr->second; + PathIndexMap &path_index_map = tag_bldr_->pathIndexMap(); + for (auto path_itr = path_index_map.cbegin(); path_itr != path_index_map.cend(); ) { + Tag *tag = path_itr->first; + size_t path_index = path_itr->second; ClkInfo *clk_info = tag->clkInfo(); bool deleted_tag = false; if (!tag->isClock() && clk_info->hasCrprClkPin()) { PathAnalysisPt *path_ap = tag->pathAnalysisPt(this); const MinMax *min_max = path_ap->pathMinMax(); - Tag *tag_no_crpr; - Arrival max_arrival; - int max_arrival_index; - tag_bldr_no_crpr_->tagMatchArrival(tag, tag_no_crpr, - max_arrival, max_arrival_index); - if (tag_no_crpr) { - ClkInfo *clk_info_no_crpr = tag_no_crpr->clkInfo(); + Path *path_no_crpr = tag_bldr_no_crpr_->tagMatchPath(tag); + if (path_no_crpr) { + Arrival max_arrival = path_no_crpr->arrival(); + ClkInfo *clk_info_no_crpr = path_no_crpr->clkInfo(this); Arrival max_crpr = crpr->maxCrpr(clk_info_no_crpr); Arrival max_arrival_max_crpr = (min_max == MinMax::max()) ? max_arrival - max_crpr : max_arrival + max_crpr; debugPrint(debug_, "search", 4, " cmp %s %s - %s = %s", - tag->asString(this), + tag->to_string(this).c_str(), delayAsString(max_arrival, this), delayAsString(max_crpr, this), delayAsString(max_arrival_max_crpr, this)); - Arrival arrival = tag_bldr_->arrival(arrival_index); + Arrival arrival = tag_bldr_->arrival(path_index); if (delayGreater(max_arrival_max_crpr, arrival, min_max, this)) { debugPrint(debug_, "search", 3, " pruned %s", - tag->asString(this)); - arrival_itr = arrival_map->erase(arrival_itr); + tag->to_string(this).c_str()); + path_itr = path_index_map.erase(path_itr); deleted_tag = true; } } } if (!deleted_tag) - arrival_itr++; + path_itr++; } } @@ -1504,8 +1489,9 @@ Search::seedArrival(Vertex *vertex) } } else { - debugPrint(debug_, "search", 2, "arrival enqueue %s", - network_->pathName(pin)); + debugPrint(debug_, "search", 4, "arrival enqueue %s %u", + network_->pathName(pin), + vertex->level()); arrival_iter_->enqueue(vertex); } } @@ -1588,7 +1574,7 @@ Search::seedClkArrival(const Pin *pin, uncertainties = clk->uncertainties(); // Propagate liberty "pulse_clock" transition to transitive fanout. LibertyPort *port = network_->libertyPort(pin); - RiseFall *pulse_clk_sense = (port ? port->pulseClkSense() : nullptr); + const RiseFall *pulse_clk_sense = (port ? port->pulseClkSense() : nullptr); ClkInfo *clk_info = findClkInfo(clk_edge, pin, is_propagated, nullptr, false, pulse_clk_sense, insertion, latency, uncertainties, path_ap, nullptr); @@ -1597,7 +1583,7 @@ Search::seedClkArrival(const Pin *pin, sdc_->exceptionFromClkStates(pin,rf,clk,rf,min_max,states); Tag *tag = findTag(rf, path_ap, clk_info, true, nullptr, false, states, true); Arrival arrival(clk_edge->time() + insertion); - tag_bldr->setArrival(tag, arrival, nullptr); + tag_bldr->setArrival(tag, arrival); } void @@ -1614,7 +1600,7 @@ Search::seedClkDataArrival(const Pin *pin, if (tag) { // Data arrivals include insertion delay. Arrival arrival(clk_edge->time() + insertion); - tag_bldr->setArrival(tag, arrival, nullptr); + tag_bldr->setArrival(tag, arrival); } } @@ -1651,12 +1637,12 @@ Search::makeUnclkedPaths(Vertex *vertex, const Pin *pin = vertex->pin(); for (PathAnalysisPt *path_ap : corners_->pathAnalysisPts()) { const MinMax *min_max = path_ap->pathMinMax(); - for (RiseFall *rf : RiseFall::range()) { + for (const RiseFall *rf : RiseFall::range()) { Tag *tag = fromUnclkedInputTag(pin, rf, min_max, path_ap, is_segment_start, require_exception); if (tag) { - tag_bldr->setArrival(tag, delay_zero, nullptr); + tag_bldr->setArrival(tag, delay_zero); search_from = true; } } @@ -1806,7 +1792,7 @@ Search::seedInputDelayArrival(const Pin *pin, input_delay ? "arrival seed input arrival %s" : "arrival seed input %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); const ClockEdge *clk_edge = nullptr; const Pin *ref_pin = nullptr; if (input_delay) { @@ -1867,7 +1853,7 @@ Search::inputDelayRefPinArrival(Path *ref_path, Clock *clk = clk_edge->clock(); if (clk->isPropagated()) { ClkInfo *clk_info = ref_path->clkInfo(this); - ref_arrival = delayAsFloat(ref_path->arrival(this)); + ref_arrival = delayAsFloat(ref_path->arrival()); ref_insertion = delayAsFloat(clk_info->insertion()); ref_latency = clk_info->latency(); } @@ -1894,7 +1880,7 @@ Search::seedInputDelayArrival(const Pin *pin, PathAnalysisPt *path_ap, TagGroupBldr *tag_bldr) { - for (RiseFall *rf : RiseFall::range()) { + for (const RiseFall *rf : RiseFall::range()) { if (input_delay) { float delay; bool exists; @@ -1928,7 +1914,7 @@ Search::seedInputDelayArrival(const Pin *pin, Tag *tag = inputDelayTag(pin, rf, clk_edge, clk_insertion, clk_latency, input_delay, is_segment_start, min_max, path_ap); if (tag) - tag_bldr->setArrival(tag, arrival, nullptr); + tag_bldr->setArrival(tag, arrival); } void @@ -1946,7 +1932,7 @@ Search::inputDelayClkArrival(InputDelay *input_delay, if (input_delay && clk_edge) { clk_arrival = clk_edge->time(); Clock *clk = clk_edge->clock(); - RiseFall *clk_rf = clk_edge->transition(); + const RiseFall *clk_rf = clk_edge->transition(); if (!input_delay->sourceLatencyIncluded()) { const EarlyLate *early_late = min_max; clk_insertion = delayAsFloat(clockInsertion(clk, clk->defaultPin(), @@ -1975,7 +1961,7 @@ Search::inputDelayTag(const Pin *pin, { Clock *clk = nullptr; const Pin *clk_pin = nullptr; - RiseFall *clk_rf = nullptr; + const RiseFall *clk_rf = nullptr; bool is_propagated = false; ClockUncertainties *clk_uncertainties = nullptr; if (clk_edge) { @@ -2053,7 +2039,7 @@ PathVisitor::visitFanoutPaths(Vertex *from_vertex) if (pred_->searchTo(to_vertex) && pred_->searchThru(edge)) { debugPrint(debug_, "search", 3, " %s", - to_vertex->name(network_)); + to_vertex->to_string(this).c_str()); if (!visitEdge(from_pin, from_vertex, edge, to_pin, to_vertex)) break; } @@ -2073,7 +2059,7 @@ PathVisitor::visitEdge(const Pin *from_pin, TimingArcSet *arc_set = edge->timingArcSet(); VertexPathIterator from_iter(from_vertex, search_); while (from_iter.hasNext()) { - PathVertex *from_path = from_iter.next(); + Path *from_path = from_iter.next(); PathAnalysisPt *path_ap = from_path->pathAnalysisPt(this); const MinMax *min_max = path_ap->pathMinMax(); const RiseFall *from_rf = from_path->transition(this); @@ -2096,7 +2082,7 @@ bool PathVisitor::visitArc(const Pin *from_pin, Vertex *from_vertex, const RiseFall *from_rf, - PathVertex *from_path, + Path *from_path, Edge *edge, TimingArc *arc, const Pin *to_pin, @@ -2105,7 +2091,7 @@ PathVisitor::visitArc(const Pin *from_pin, PathAnalysisPt *path_ap) { if (arc) { - RiseFall *to_rf = arc->toEdge()->asRiseFall(); + const RiseFall *to_rf = arc->toEdge()->asRiseFall(); if (searchThru(from_vertex, from_rf, edge, to_vertex, to_rf)) return visitFromPath(from_pin, from_vertex, from_rf, from_path, edge, arc, to_pin, to_vertex, to_rf, @@ -2118,7 +2104,7 @@ bool PathVisitor::visitFromPath(const Pin *from_pin, Vertex *from_vertex, const RiseFall *from_rf, - PathVertex *from_path, + Path *from_path, Edge *edge, TimingArc *arc, const Pin *to_pin, @@ -2133,7 +2119,7 @@ PathVisitor::visitFromPath(const Pin *from_pin, Tag *to_tag = nullptr; const ClockEdge *clk_edge = from_clk_info->clkEdge(); const Clock *clk = from_clk_info->clock(); - Arrival from_arrival = from_path->arrival(this); + Arrival from_arrival = from_path->arrival(); ArcDelay arc_delay = 0.0; Arrival to_arrival; if (from_clk_info->isGenClkSrcPath()) { @@ -2156,13 +2142,18 @@ PathVisitor::visitFromPath(const Pin *from_pin, || !gclk->combinational()) && fanins->hasKey(to_vertex) && !(fdbk_edges && fdbk_edges->hasKey(edge))) { - to_tag = search_->thruClkTag(from_path, from_tag, true, edge, to_rf, + arc_delay = search_->deratedDelay(from_vertex, arc, edge, + true, path_ap); + const PathAnalysisPt *path_ap_opp = + path_ap->corner()->findPathAnalysisPt(min_max->opposite()); + Delay arc_delay_opp = search_->deratedDelay(from_vertex, arc, edge, + true, path_ap_opp); + bool arc_delay_min_max_eq = fuzzyEqual(arc_delay, arc_delay_opp); + to_tag = search_->thruClkTag(from_path, from_vertex, from_tag, true, + edge, to_rf, arc_delay_min_max_eq, min_max, path_ap); - if (to_tag) { - arc_delay = search_->deratedDelay(from_vertex, arc, edge, true, - path_ap); + if (to_tag) to_arrival = from_arrival + arc_delay; - } } } } @@ -2195,7 +2186,8 @@ PathVisitor::visitFromPath(const Pin *from_pin, && from_tag->isClock())) { const RiseFall *clk_rf = clk_edge ? clk_edge->transition() : nullptr; ClkInfo *to_clk_info = from_clk_info; - if (network_->direction(to_pin)->isInternal()) + if (from_clk_info->crprClkPath(this) == nullptr + || network_->direction(to_pin)->isInternal()) to_clk_info = search_->clkInfoWithCrprClkPath(from_clk_info, from_path, path_ap); to_tag = search_->fromRegClkTag(from_pin, from_rf, clk, clk_rf, @@ -2240,8 +2232,15 @@ PathVisitor::visitFromPath(const Pin *from_pin, || role == TimingRole::tristateDisable())); arc_delay = search_->deratedDelay(from_vertex, arc, edge, to_propagates_clk, path_ap); - to_tag = search_->thruClkTag(from_path, from_tag, to_propagates_clk, - edge, to_rf, min_max, path_ap); + const PathAnalysisPt *path_ap_opp = + path_ap->corner()->findPathAnalysisPt(min_max->opposite()); + Delay arc_delay_opp = search_->deratedDelay(from_vertex, arc, edge, + to_propagates_clk, path_ap_opp); + bool arc_delay_min_max_eq = fuzzyEqual(arc_delay, arc_delay_opp); + to_tag = search_->thruClkTag(from_path, from_vertex, from_tag, + to_propagates_clk, edge, to_rf, + arc_delay_min_max_eq, + min_max, path_ap); to_arrival = from_arrival + arc_delay; } } @@ -2293,7 +2292,7 @@ Search::clkPathArrival(const Path *clk_path, + clk_info->latency(); } else - return clk_path->arrival(this); + return clk_path->arrival(); } Arrival @@ -2301,9 +2300,9 @@ Search::pathClkPathArrival(const Path *path) const { ClkInfo *clk_info = path->clkInfo(this); if (clk_info->isPropagated()) { - PathRef src_clk_path = pathClkPathArrival1(path); - if (!src_clk_path.isNull()) - return clkPathArrival(&src_clk_path); + const Path *src_clk_path = pathClkPathArrival1(path); + if (src_clk_path) + return clkPathArrival(src_clk_path); } // Check for input arrival clock. const ClockEdge *clk_edge = path->clkEdge(this); @@ -2313,34 +2312,30 @@ Search::pathClkPathArrival(const Path *path) const } // PathExpanded::expand() and PathExpanded::clkPath(). -PathRef +const Path * Search::pathClkPathArrival1(const Path *path) const { - PathRef p(path); - while (!p.isNull()) { - PathRef prev_path; - TimingArc *prev_arc; - p.prevPath(this, prev_path, prev_arc); + const Path *p = path; + while (p) { + Path *prev_path = p->prevPath(); + Edge *prev_edge = p->prevEdge(this); - if (p.isClock(this)) + if (p->isClock(this)) return p; - if (prev_arc) { - TimingRole *prev_role = prev_arc->role(); + if (prev_edge) { + const TimingRole *prev_role = prev_edge->role(); if (prev_role == TimingRole::regClkToQ() || prev_role == TimingRole::latchEnToQ()) { - p.prevPath(this, prev_path, prev_arc); - return prev_path; + return p->prevPath(); } else if (prev_role == TimingRole::latchDtoQ()) { - Edge *prev_edge = p.prevEdge(prev_arc, this); - PathVertex enable_path; - latches_->latchEnablePath(&p, prev_edge, enable_path); + Path *enable_path = latches_->latchEnablePath(p, prev_edge); return enable_path; } } - p.init(prev_path); + p = prev_path; } - return PathRef(); + return nullptr; } //////////////////////////////////////////////////////////////// @@ -2390,7 +2385,7 @@ Search::fromRegClkTag(const Pin *from_pin, // Insert from_path as ClkInfo crpr_clk_path. ClkInfo * Search::clkInfoWithCrprClkPath(ClkInfo *from_clk_info, - PathVertex *from_path, + Path *from_path, const PathAnalysisPt *path_ap) { if (sdc_->crprActive()) @@ -2430,12 +2425,15 @@ Search::thruTag(Tag *from_tag, return to_tag; } +// thruTag for clocks. Tag * -Search::thruClkTag(PathVertex *from_path, +Search::thruClkTag(Path *from_path, + Vertex *from_vertex, Tag *from_tag, bool to_propagates_clk, Edge *edge, const RiseFall *to_rf, + bool arc_delay_min_max_eq, const MinMax *min_max, const PathAnalysisPt *path_ap) { @@ -2446,27 +2444,30 @@ Search::thruClkTag(PathVertex *from_path, ClkInfo *from_clk_info = from_tag->clkInfo(); bool from_is_clk = from_tag->isClock(); bool to_is_reg_clk = to_vertex->isRegClk(); - TimingRole *role = edge->role(); + const TimingRole *role = edge->role(); bool to_is_clk = (from_is_clk && to_propagates_clk && (role->isWire() || role == TimingRole::combinational())); - ClkInfo *to_clk_info = thruClkInfo(from_path, from_clk_info, - edge, to_vertex, to_pin, - min_max, path_ap); + ClkInfo *to_clk_info = thruClkInfo(from_path, from_vertex, from_clk_info, from_is_clk, + edge, to_vertex, to_pin, to_is_clk, + arc_delay_min_max_eq, min_max, path_ap); Tag *to_tag = mutateTag(from_tag,from_pin,from_rf,from_is_clk,from_clk_info, to_pin, to_rf, to_is_clk, to_is_reg_clk, false, to_clk_info, nullptr, min_max, path_ap); return to_tag; } -// thruTag for clocks. ClkInfo * -Search::thruClkInfo(PathVertex *from_path, +Search::thruClkInfo(Path *from_path, + Vertex *from_vertex, ClkInfo *from_clk_info, + bool from_is_clk, Edge *edge, Vertex *to_vertex, - const Pin *to_pin, + const Pin *to_pin, + bool to_is_clk, + bool arc_delay_min_max_eq, const MinMax *min_max, const PathAnalysisPt *path_ap) { @@ -2495,16 +2496,25 @@ Search::thruClkInfo(PathVertex *from_path, changed = true; } - PathVertex *to_crpr_clk_path = nullptr; + Path *to_crpr_clk_path = nullptr; if (sdc_->crprActive() - && to_vertex->isRegClk()) { + // Update crpr clk path for combinational paths leaving the clock + // network (ie, tristate en->out) and buffer driving reg clk. + && ((from_is_clk + && !to_is_clk + && !from_vertex->isRegClk()) + || (to_vertex->isRegClk() + // If the wire delay to the reg clk pin is zero, + // leave the crpr_clk_path null to indicate that + // the reg clk path is the crpr clk path. + && arc_delay_min_max_eq))) { to_crpr_clk_path = from_path; changed = true; } // Propagate liberty "pulse_clock" transition to transitive fanout. - RiseFall *from_pulse_sense = from_clk_info->pulseClkSense(); - RiseFall *to_pulse_sense = from_pulse_sense; + const RiseFall *from_pulse_sense = from_clk_info->pulseClkSense(); + const RiseFall *to_pulse_sense = from_pulse_sense; LibertyPort *port = network_->libertyPort(to_pin); if (port && port->pulseClkSense()) { to_pulse_sense = port->pulseClkSense(); @@ -2717,54 +2727,27 @@ Search::setVertexArrivals(Vertex *vertex, deletePathsIncr(vertex); else { TagGroup *prev_tag_group = tagGroup(vertex); - Arrival *prev_arrivals = graph_->arrivals(vertex); - PathPrev *prev_paths = graph_->prevPaths(vertex); - bool save_prev = always_save_prev_paths_ - || tag_bldr->hasClkTag() - || tag_bldr->hasGenClkSrcTag(); - + Path *prev_paths = graph_->paths(vertex); TagGroup *tag_group = findTagGroup(tag_bldr); - int arrival_count = tag_group->arrivalCount(); - bool has_requireds = vertex->hasRequireds(); - // Reuse arrival array if it is the same size. + size_t path_count = tag_group->pathCount(); + // Reuse path array if it is the same size. if (prev_tag_group - && arrival_count == prev_tag_group->arrivalCount()) { - if (save_prev) { - if (prev_paths == nullptr) - prev_paths = graph_->makePrevPaths(vertex, arrival_count); - } - else { - // Prev paths not required. - prev_paths = nullptr; - graph_->deletePrevPaths(vertex); - } - tag_bldr->copyArrivals(tag_group, prev_arrivals, prev_paths); + && path_count == prev_tag_group->pathCount()) { + tag_bldr->copyPaths(tag_group, prev_paths); vertex->setTagGroupIndex(tag_group->index()); if (tag_group->hasFilterTag()) { LockGuard lock(filtered_arrivals_lock_); filtered_arrivals_->insert(vertex); } - - if (has_requireds) { - requiredInvalid(vertex); - if (tag_group != prev_tag_group) - // Requireds can only be reused if the tag group is unchanged. - graph_->deleteRequireds(vertex); - } + requiredInvalid(vertex); } else { if (prev_tag_group) { - graph_->deleteArrivals(vertex); - if (has_requireds) { - requiredInvalid(vertex); - graph_->deleteRequireds(vertex); - } + graph_->deletePaths(vertex); + requiredInvalid(vertex); } - Arrival *arrivals = graph_->makeArrivals(vertex, arrival_count); - prev_paths = nullptr; - if (save_prev) - prev_paths = graph_->makePrevPaths(vertex, arrival_count); - tag_bldr->copyArrivals(tag_group, arrivals, prev_paths); + Path *paths = graph_->makePaths(vertex, path_count); + tag_bldr->copyPaths(tag_group, paths); vertex->setTagGroupIndex(tag_group->index()); if (tag_group->hasFilterTag()) { @@ -2778,58 +2761,40 @@ Search::setVertexArrivals(Vertex *vertex, void Search::reportArrivals(Vertex *vertex) const { - report_->reportLine("Vertex %s", vertex->name(sdc_network_)); + report_->reportLine("Vertex %s", vertex->to_string(this).c_str()); TagGroup *tag_group = tagGroup(vertex); - Arrival *arrivals = graph_->arrivals(vertex); - Required *requireds = graph_->requireds(vertex); - PathPrev *prev_paths = graph_->prevPaths(vertex); if (tag_group) { report_->reportLine("Group %u", tag_group->index()); - ArrivalMap::Iterator arrival_iter(tag_group->arrivalMap()); - while (arrival_iter.hasNext()) { - Tag *tag; - int arrival_index; - arrival_iter.next(tag, arrival_index); - PathAnalysisPt *path_ap = tag->pathAnalysisPt(this); + VertexPathIterator path_iter(vertex, this); + while (path_iter.hasNext()) { + const Path *path = path_iter.next(); + const Tag *tag = path->tag(this); + const PathAnalysisPt *path_ap = tag->pathAnalysisPt(this); const RiseFall *rf = tag->transition(); - const char *req = "?"; - if (requireds) - req = delayAsString(requireds[arrival_index], this); - bool report_clk_prev = false; - const char *clk_prev = ""; - if (report_clk_prev - && tag_group->hasClkTag()) { - PathVertex prev = check_crpr_->clkPathPrev(vertex, arrival_index); - if (!prev.isNull()) - clk_prev = prev.name(this); - } + const char *req = delayAsString(path->required(), this); string prev_str; - if (prev_paths) { - PathPrev &prev = prev_paths[arrival_index]; - if (!prev.isNull()) { - prev_str += prev.name(this); - prev_str += " "; - const Edge *prev_edge = prev.prevEdge(this); - TimingArc *arc = prev.prevArc(this); - prev_str += prev_edge->from(graph_)->name(network_); - prev_str += " "; - prev_str += arc->fromEdge()->asString(); - prev_str += " -> "; - prev_str += prev_edge->to(graph_)->name(network_); - prev_str += " "; - prev_str += arc->toEdge()->asString(); - } - else - prev_str = "NULL"; + Path *prev_path = path->prevPath(); + if (prev_path) { + prev_str += prev_path->to_string(this); + prev_str += " "; + const Edge *prev_edge = path->prevEdge(this); + TimingArc *arc = path->prevArc(this); + prev_str += prev_edge->from(graph_)->to_string(this); + prev_str += " "; + prev_str += arc->fromEdge()->to_string(); + prev_str += " -> "; + prev_str += prev_edge->to(graph_)->to_string(this); + prev_str += " "; + prev_str += arc->toEdge()->to_string(); } - report_->reportLine(" %d %s %s %s / %s %s %s prev %s", - arrival_index, - rf->asString(), - path_ap->pathMinMax()->asString(), - delayAsString(arrivals[arrival_index], this), + else + prev_str = "NULL"; + report_->reportLine(" %s %s %s / %s %s prev %s", + rf->to_string().c_str(), + path_ap->pathMinMax()->to_string().c_str(), + delayAsString(path->arrival(), this), req, - tag->asString(true, false, this), - clk_prev, + tag->to_string(true, false, this).c_str(), prev_str.c_str()); } } @@ -2883,7 +2848,7 @@ Search::reportTagGroups() const } void -Search::reportArrivalCountHistogram() const +Search::reportPathCountHistogram() const { Vector vertex_counts(10); VertexIterator vertex_iter(graph_); @@ -2891,17 +2856,17 @@ Search::reportArrivalCountHistogram() const Vertex *vertex = vertex_iter.next(); TagGroup *tag_group = tagGroup(vertex); if (tag_group) { - size_t arrival_count = tag_group->arrivalCount(); - if (arrival_count >= vertex_counts.size()) - vertex_counts.resize(arrival_count * 2); - vertex_counts[arrival_count]++; + size_t path_count = tag_group->pathCount(); + if (path_count >= vertex_counts.size()) + vertex_counts.resize(path_count * 2); + vertex_counts[path_count]++; } } - for (size_t arrival_count = 0; arrival_count < vertex_counts.size(); arrival_count++) { - int vertex_count = vertex_counts[arrival_count]; + for (size_t path_count = 0; path_count < vertex_counts.size(); path_count++) { + int vertex_count = vertex_counts[path_count]; if (vertex_count > 0) - report_->reportLine("%6lu %6d", arrival_count, vertex_count); + report_->reportLine("%6lu %6d",path_count, vertex_count); } } @@ -2977,7 +2942,7 @@ Search::reportTags() const for (TagIndex i = 0; i < tag_next_; i++) { Tag *tag = tags_[i]; if (tag) - report_->reportLine("%s", tag->asString(this)) ; + report_->reportLine("%s", tag->to_string(this).c_str()) ; } size_t long_hash = 0; for (size_t i = 0; i < tag_set_->bucket_count(); i++) { @@ -3013,19 +2978,18 @@ Search::findClkInfo(const ClockEdge *clk_edge, float latency, ClockUncertainties *uncertainties, const PathAnalysisPt *path_ap, - PathVertex *crpr_clk_path) + Path *crpr_clk_path) { - PathVertexPtr crpr_clk_path_ptr(crpr_clk_path, this); ClkInfo probe(clk_edge, clk_src, is_propagated, gen_clk_src, gen_clk_src_path, pulse_clk_sense, insertion, latency, uncertainties, - path_ap->index(), crpr_clk_path_ptr, this); + path_ap->index(), crpr_clk_path, this); LockGuard lock(clk_info_lock_); ClkInfo *clk_info = clk_info_set_->findKey(&probe); if (clk_info == nullptr) { clk_info = new ClkInfo(clk_edge, clk_src, is_propagated, gen_clk_src, gen_clk_src_path, pulse_clk_sense, insertion, latency, uncertainties, - path_ap->index(), crpr_clk_path_ptr, this); + path_ap->index(), crpr_clk_path, this); clk_info_set_->insert(clk_info); } return clk_info; @@ -3071,7 +3035,7 @@ Search::timingDerate(const Vertex *from_vertex, { PathClkOrData derate_clk_data = is_clk ? PathClkOrData::clk : PathClkOrData::data; - TimingRole *role = edge->role(); + const TimingRole *role = edge->role(); const Pin *pin = from_vertex->pin(); if (role->isWire()) { const RiseFall *rf = arc->toEdge()->asRiseFall(); @@ -3204,6 +3168,7 @@ Search::findRequireds(Level level) seedInvalidRequireds(); int required_count = required_iter_->visitParallel(level, &req_visitor); deleteTagsPrev(); + genclks_->updateSrcPathPrevs(); requireds_exist_ = true; debugPrint(debug_, "search", 1, "found %d requireds", required_count); stats.report("Find requireds"); @@ -3230,7 +3195,7 @@ Search::endpoints() Vertex *vertex = vertex_iter.next(); if (isEndpoint(vertex)) { debugPrint(debug_, "endpoint", 2, "insert %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); endpoints_->insert(vertex); } } @@ -3239,14 +3204,14 @@ Search::endpoints() for (Vertex *vertex : *invalid_endpoints_) { if (isEndpoint(vertex)) { debugPrint(debug_, "endpoint", 2, "insert %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); endpoints_->insert(vertex); } else { if (debug_->check("endpoint", 2) && endpoints_->hasKey(vertex)) report_->reportLine("endpoint: remove %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); endpoints_->erase(vertex); } } @@ -3260,7 +3225,7 @@ Search::endpointInvalid(Vertex *vertex) { if (invalid_endpoints_) { debugPrint(debug_, "endpoint", 2, "invalid %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); invalid_endpoints_->insert(vertex); } } @@ -3368,13 +3333,11 @@ void FindEndRequiredVisitor::visit(PathEnd *path_end) { if (!path_end->isUnconstrained()) { - PathRef &path = path_end->pathRef(); - const MinMax *req_min = path.minMax(sta_)->opposite(); - int arrival_index; - bool arrival_exists; - path.arrivalIndex(arrival_index, arrival_exists); + Path *path = path_end->path(); + const MinMax *min_max = path->minMax(sta_)->opposite(); + size_t path_index = path->pathIndex(sta_); Required required = path_end->requiredTime(sta_); - required_cmp_->requiredSet(arrival_index, required, req_min, sta_); + required_cmp_->requiredSet(path_index, required, min_max, sta_); } } @@ -3382,7 +3345,7 @@ void Search::seedRequired(Vertex *vertex) { debugPrint(debug_, "search", 2, "required seed %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); RequiredCmp required_cmp; FindEndRequiredVisitor seeder(&required_cmp, this); required_cmp.requiredsInit(vertex, this); @@ -3419,31 +3382,27 @@ RequiredCmp::requiredsInit(Vertex *vertex, Search *search = sta->search(); TagGroup *tag_group = search->tagGroup(vertex); if (tag_group) { - requireds_.resize(tag_group->arrivalCount()); - ArrivalMap *arrival_entries = tag_group->arrivalMap(); - ArrivalMap::Iterator arrival_iter(arrival_entries); - while (arrival_iter.hasNext()) { - Tag *tag; - int arrival_index; - arrival_iter.next(tag, arrival_index); + size_t path_count = tag_group->pathCount(); + requireds_.resize(path_count); + for (auto const [tag, path_index] : *tag_group->pathIndexMap()) { PathAnalysisPt *path_ap = tag->pathAnalysisPt(sta); const MinMax *min_max = path_ap->pathMinMax(); - requireds_[arrival_index] = delayInitValue(min_max->opposite()); + requireds_[path_index] = delayInitValue(min_max->opposite()); } } else - requireds_.resize(0); + requireds_.clear(); have_requireds_ = false; } void -RequiredCmp::requiredSet(int arrival_index, - Required required, +RequiredCmp::requiredSet(size_t path_index, + Required &required, const MinMax *min_max, const StaState *sta) { - if (delayGreater(required, requireds_[arrival_index], min_max, sta)) { - requireds_[arrival_index] = required; + if (delayGreater(required, requireds_[path_index], min_max, sta)) { + requireds_[path_index] = required; have_requireds_ = true; } } @@ -3453,53 +3412,26 @@ RequiredCmp::requiredsSave(Vertex *vertex, const StaState *sta) { bool requireds_changed = false; - bool prev_reqs = vertex->hasRequireds(); - if (have_requireds_) { - if (!prev_reqs) - requireds_changed = true; - Debug *debug = sta->debug(); - VertexPathIterator path_iter(vertex, sta); - while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); - int arrival_index; - bool arrival_exists; - path->arrivalIndex(arrival_index, arrival_exists); - Required req = requireds_[arrival_index]; - if (prev_reqs) { - Required prev_req = path->required(sta); - if (!delayEqual(prev_req, req)) { - debugPrint(debug, "search", 3, "required save %s -> %s", - delayAsString(prev_req, sta), - delayAsString(req, sta)); - path->setRequired(req, sta); - requireds_changed = true; - } - } - else { - debugPrint(debug, "search", 3, "required save MIA -> %s", - delayAsString(req, sta)); - path->setRequired(req, sta); - } - } - } - else if (prev_reqs) { - Graph *graph = sta->graph(); - const Search *search = sta->search(); - TagGroup *tag_group = search->tagGroup(vertex); - if (tag_group == nullptr) - requireds_changed = true; - else { - graph->deleteRequireds(vertex); - requireds_changed = true; - } + Debug *debug = sta->debug(); + VertexPathIterator path_iter(vertex, sta); + while (path_iter.hasNext()) { + Path *path = path_iter.next(); + size_t path_index = path->pathIndex(sta); + Required req = requireds_[path_index]; + Required &prev_req = path->required(); + debugPrint(debug, "search", 3, "required save %s -> %s", + delayAsString(prev_req, sta), + delayAsString(req, sta)); + requireds_changed |= !delayEqual(prev_req, req); + path->setRequired(req); } return requireds_changed; } Required -RequiredCmp::required(int arrival_index) +RequiredCmp::required(size_t path_index) { - return requireds_[arrival_index]; + return requireds_[path_index]; } //////////////////////////////////////////////////////////////// @@ -3527,7 +3459,7 @@ void RequiredVisitor::visit(Vertex *vertex) { debugPrint(debug_, "search", 2, "find required %s", - vertex->name(network_)); + vertex->to_string(this).c_str()); required_cmp_->requiredsInit(vertex, this); // Back propagate requireds from fanout. visitFanoutPaths(vertex); @@ -3545,10 +3477,10 @@ RequiredVisitor::visit(Vertex *vertex) bool RequiredVisitor::visitFromToPath(const Pin *, - Vertex *, + Vertex * /* from_vertex */, const RiseFall *from_rf, Tag *from_tag, - PathVertex *from_path, + Path *from_path, const Arrival &, Edge *edge, TimingArc *, @@ -3563,32 +3495,31 @@ RequiredVisitor::visitFromToPath(const Pin *, // Don't propagate required times through latch D->Q edges. if (edge->role() != TimingRole::latchDtoQ()) { debugPrint(debug_, "search", 3, " %s -> %s %s", - from_rf->asString(), - to_rf->asString(), - min_max->asString()); + from_rf->to_string().c_str(), + to_rf->to_string().c_str(), + min_max->to_string().c_str()); debugPrint(debug_, "search", 3, " from tag %2u: %s", from_tag->index(), - from_tag->asString(this)); - int arrival_index; - bool arrival_exists; - from_path->arrivalIndex(arrival_index, arrival_exists); + from_tag->to_string(this).c_str()); + size_t path_index = from_path->pathIndex(this); const MinMax *req_min = min_max->opposite(); TagGroup *to_tag_group = search_->tagGroup(to_vertex); // Check to see if to_tag was pruned. if (to_tag_group && to_tag_group->hasTag(to_tag)) { - PathVertex to_path(to_vertex, to_tag, this); - Required to_required = to_path.required(this); + size_t to_path_index = to_tag_group->pathIndex(to_tag); + Path &to_path = to_vertex->paths()[to_path_index]; + Required &to_required = to_path.required(); Required from_required = to_required - arc_delay; debugPrint(debug_, "search", 3, " to tag %2u: %s", to_tag->index(), - to_tag->asString(this)); + to_tag->to_string(this).c_str()); debugPrint(debug_, "search", 3, " %s - %s = %s %s %s", delayAsString(to_required, this), delayAsString(arc_delay, this), delayAsString(from_required, this), min_max == MinMax::max() ? "<" : ">", - delayAsString(required_cmp_->required(arrival_index), this)); - required_cmp_->requiredSet(arrival_index, from_required, req_min, this); + delayAsString(required_cmp_->required(path_index), this)); + required_cmp_->requiredSet(path_index, from_required, req_min, this); } else { if (search_->crprApproxMissingRequireds()) { @@ -3597,22 +3528,22 @@ RequiredVisitor::visitFromToPath(const Pin *, // as an appromate required. VertexPathIterator to_iter(to_vertex, to_rf, path_ap, this); while (to_iter.hasNext()) { - PathVertex *to_path = to_iter.next(); + Path *to_path = to_iter.next(); Tag *to_path_tag = to_path->tag(this); if (tagMatchNoCrpr(to_path_tag, to_tag)) { - Required to_required = to_path->required(this); + Required to_required = to_path->required(); Required from_required = to_required - arc_delay; debugPrint(debug_, "search", 3, " to tag %2u: %s", to_path_tag->index(), - to_path_tag->asString(this)); + to_path_tag->to_string(this).c_str()); debugPrint(debug_, "search", 3, " %s - %s = %s %s %s", delayAsString(to_required, this), delayAsString(arc_delay, this), delayAsString(from_required, this), min_max == MinMax::max() ? "<" : ">", - delayAsString(required_cmp_->required(arrival_index), + delayAsString(required_cmp_->required(path_index), this)); - required_cmp_->requiredSet(arrival_index, from_required, req_min, this); + required_cmp_->requiredSet(path_index, from_required, req_min, this); break; } } @@ -3676,7 +3607,7 @@ Search::matchesFilter(Path *path, // -from clks const ClockEdge *path_clk_edge = path->clkEdge(this); const Clock *path_clk = path_clk_edge ? path_clk_edge->clock() : nullptr; - RiseFall *path_clk_rf = + const RiseFall *path_clk_rf = path_clk_edge ? path_clk_edge->transition() : nullptr; return filter_from_->clks()->hasKey(const_cast(path_clk)) && filter_from_->transition()->matches(path_clk_rf) @@ -3788,7 +3719,7 @@ Search::tnsInvalid(Vertex *vertex) if ((tns_exists_ || worst_slacks_) && isEndpoint(vertex)) { debugPrint(debug_, "tns", 2, "tns invalid %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); LockGuard lock(tns_lock_); invalid_tns_->insert(vertex); } @@ -3802,7 +3733,7 @@ Search::updateInvalidTns() // Network edits can change endpointedness since tnsInvalid was called. if (isEndpoint(vertex)) { debugPrint(debug_, "tns", 2, "update tns %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); SlackSeq slacks(path_ap_count); wnsSlacks(vertex, slacks); @@ -3852,7 +3783,7 @@ Search::tnsIncr(Vertex *vertex, if (delayLess(slack, 0.0, this)) { debugPrint(debug_, "tns", 3, "tns+ %s %s", delayAsString(slack, this), - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); tns_[path_ap_index] += slack; if (tns_slacks_[path_ap_index].hasKey(vertex)) report_->critical(1513, "tns incr existing vertex"); @@ -3871,7 +3802,7 @@ Search::tnsDecr(Vertex *vertex, && delayLess(slack, 0.0, this)) { debugPrint(debug_, "tns", 3, "tns- %s %s", delayAsString(slack, this), - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); tns_[path_ap_index] -= slack; tns_slacks_[path_ap_index].erase(vertex); } @@ -3932,7 +3863,7 @@ Search::wnsTnsPreamble() for (auto itr = invalid_requireds_->begin(); itr != invalid_requireds_->end(); ) { Vertex *vertex = *itr; debugPrint(debug_, "search", 2, "tns update required %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); if (isEndpoint(vertex)) { seedRequired(vertex); // If the endpoint has fanout it's required time @@ -3994,8 +3925,8 @@ void FindEndSlackVisitor::visit(PathEnd *path_end) { if (!path_end->isUnconstrained()) { - PathRef &path = path_end->pathRef(); - PathAPIndex path_ap_index = path.pathAnalysisPtIndex(sta_); + Path *path = path_end->path(); + PathAPIndex path_ap_index = path->pathAnalysisPtIndex(sta_); Slack slack = path_end->slack(sta_); if (delayLess(slack, slacks_[path_ap_index], sta_)) slacks_[path_ap_index] = slack; diff --git a/search/Search.i b/search/Search.i index 9548941e..25f8c633 100644 --- a/search/Search.i +++ b/search/Search.i @@ -51,11 +51,11 @@ private: ~VertexPathIterator(); }; -class PathRef +class Path { private: - PathRef(); - ~PathRef(); + Path(); + ~Path(); }; class PathEnd @@ -221,44 +221,32 @@ worst_slack_corner(const Corner *corner, return worst_slack; } -PathRef * +Path * vertex_worst_arrival_path(Vertex *vertex, const MinMax *min_max) { Sta *sta = Sta::sta(); sta->ensureLibLinked(); - PathRef path = sta->vertexWorstArrivalPath(vertex, min_max); - if (!path.isNull()) - return new PathRef(path); - else - return nullptr; + return sta->vertexWorstArrivalPath(vertex, min_max); } -PathRef * +Path * vertex_worst_arrival_path_rf(Vertex *vertex, const RiseFall *rf, MinMax *min_max) { Sta *sta = Sta::sta(); sta->ensureLibLinked(); - PathRef path = sta->vertexWorstArrivalPath(vertex, rf, min_max); - if (!path.isNull()) - return new PathRef(path); - else - return nullptr; + return sta->vertexWorstArrivalPath(vertex, rf, min_max); } -PathRef * +Path * vertex_worst_slack_path(Vertex *vertex, const MinMax *min_max) { Sta *sta = Sta::sta(); sta->ensureLibLinked(); - PathRef path = sta->vertexWorstSlackPath(vertex, min_max); - if (!path.isNull()) - return new PathRef(path); - else - return nullptr; + return sta->vertexWorstSlackPath(vertex, min_max); } int @@ -280,9 +268,9 @@ report_tag_arrivals_cmd(Vertex *vertex) } void -report_arrival_count_histogram() +report_path_count_histogram() { - Sta::sta()->search()->reportArrivalCountHistogram(); + Sta::sta()->search()->reportPathCountHistogram(); } int @@ -310,15 +298,9 @@ clk_info_count() } int -arrival_count() +path_count() { - return Sta::sta()->arrivalCount(); -} - -int -required_count() -{ - return Sta::sta()->requiredCount(); + return Sta::sta()->pathCount(); } int @@ -331,11 +313,9 @@ void report_loops() { Sta *sta = Sta::sta(); - Network *network = sta->network(); - Graph *graph = sta->ensureGraph(); Report *report = sta->report(); for (GraphLoop *loop : *sta->graphLoops()) { - loop->report(report, network, graph); + loop->report(sta); report->reportLineString(""); } } @@ -494,13 +474,7 @@ set_report_path_sigmas(bool report_sigmas) } void -delete_path_ref(PathRef *path) -{ - delete path; -} - -void -report_path_cmd(PathRef *path) +report_path_cmd(Path *path) { Sta::sta()->reportPath(path); } @@ -1245,7 +1219,7 @@ path_end_property(PathEnd *end, } PropertyValue -path_ref_property(PathRef *path, +path_ref_property(Path *path, const char *property) { return getProperty(path, property, Sta::sta()); @@ -1275,14 +1249,14 @@ bool is_output_delay() { return self->isOutputDelay(); } bool is_path_delay() { return self->isPathDelay(); } bool is_gated_clock() { return self->isGatedClock(); } Vertex *vertex() { return self->vertex(Sta::sta()); } -PathRef *path() { return &self->pathRef(); } +Path *path() { return self->path(); } RiseFall *end_transition() { return const_cast(self->path()->transition(Sta::sta())); } Slack slack() { return self->slack(Sta::sta()); } ArcDelay margin() { return self->margin(Sta::sta()); } Required data_required_time() { return self->requiredTimeOffset(Sta::sta()); } Arrival data_arrival_time() { return self->dataArrivalTimeOffset(Sta::sta()); } -TimingRole *check_role() { return self->checkRole(Sta::sta()); } +const TimingRole *check_role() { return self->checkRole(Sta::sta()); } MinMax *min_max() { return const_cast(self->minMax(Sta::sta())); } float source_clk_offset() { return self->sourceClkOffset(Sta::sta()); } Arrival source_clk_latency() { return self->sourceClkLatency(Sta::sta()); } @@ -1312,19 +1286,17 @@ Delay clk_skew() { return self->clkSkew(Sta::sta()); } } -%extend PathRef { +%extend Path { float arrival() { - Sta *sta = Sta::sta(); - return delayAsFloat(self->arrival(sta)); + return delayAsFloat(self->arrival()); } float required() { - Sta *sta = Sta::sta(); - return delayAsFloat(self->required(sta)); + return delayAsFloat(self->required()); } float @@ -1341,11 +1313,11 @@ pin() return self->pin(sta); } -const char * +string tag() { Sta *sta = Sta::sta(); - return self->tag(sta)->asString(sta); + return self->tag(sta)->to_string(sta); } // mea_opt3 @@ -1354,12 +1326,10 @@ pins() { Sta *sta = Sta::sta(); PinSeq pins; - PathRef path1(self); - while (!path1.isNull()) { - pins.push_back(path1.vertex(sta)->pin()); - PathRef prev_path; - path1.prevPath(sta, prev_path); - path1.init(prev_path); + Path *path1 = self; + while (path1) { + pins.push_back(path1->vertex(sta)->pin()); + path1 = path1->prevPath(); } return pins; } @@ -1368,11 +1338,10 @@ pins() %extend VertexPathIterator { bool has_next() { return self->hasNext(); } -PathRef * +Path * next() { - Path *path = self->next(); - return new PathRef(path); + return self->next(); } void finish() { delete self; } diff --git a/search/Search.tcl b/search/Search.tcl index 4a9aefb5..6e6aa78c 100644 --- a/search/Search.tcl +++ b/search/Search.tcl @@ -702,12 +702,19 @@ define_cmd_args "report_disabled_edges" {} ################################################################ -define_cmd_args "report_tns" { [-digits digits]} +define_cmd_args "report_tns" {[-min] [-max] [-digits digits]} proc_redirect report_tns { global sta_report_default_digits - parse_key_args "report_tns" args keys {-digits} flags {} + parse_key_args "report_tns" args keys {-digits} flags {-min -max} + set min_max "max" + if { [info exists flags(-min)] } { + set min_max "min" + } + if { [info exists flags(-max)] } { + set min_max "max" + } if [info exists keys(-digits)] { set digits $keys(-digits) check_positive_integer "-digits" $digits @@ -715,32 +722,39 @@ proc_redirect report_tns { set digits $sta_report_default_digits } - report_line "tns [format_time [total_negative_slack_cmd "max"] $digits]" + report_line "tns $min_max [format_time [total_negative_slack_cmd $min_max] $digits]" } ################################################################ -define_cmd_args "report_wns" { [-digits digits]} +define_cmd_args "report_wns" {[-min] [-max] [-digits digits]} proc_redirect report_wns { global sta_report_default_digits - parse_key_args "report_wns" args keys {-digits} flags {} - if [info exists keys(-digits)] { + parse_key_args "report_wns" args keys {-digits} flags {-min -max} + set min_max "max" + if { [info exists flags(-min)] } { + set min_max "min" + } + if { [info exists flags(-max)] } { + set min_max "max" + } + if { [info exists keys(-digits)] } { set digits $keys(-digits) check_positive_integer "-digits" $digits } else { set digits $sta_report_default_digits } - set slack [worst_slack_cmd "max"] + set slack [worst_slack_cmd $min_max] if { $slack > 0.0 } { set slack 0.0 } - report_line "wns [format_time $slack $digits]" + report_line "wns $min_max [format_time $slack $digits]" } -################################################################ +################################################# ############### define_cmd_args "report_worst_slack" {[-min] [-max] [-digits digits]} @@ -756,7 +770,7 @@ proc_redirect report_worst_slack { set digits $sta_report_default_digits } - report_line "worst slack [format_time [worst_slack_cmd $min_max] $digits]" + report_line "worst slack $min_max [format_time [worst_slack_cmd $min_max] $digits]" } ################################################################ @@ -840,7 +854,6 @@ proc_redirect report_path { report_line "Tag: [$path tag]" } report_path_cmd $path - delete_path_ref $path set first 0 } $path_iter finish @@ -851,7 +864,6 @@ proc_redirect report_path { report_line "Tag: [$worst_path tag]" } report_path_cmd $worst_path - delete_path_ref $worst_path } } } diff --git a/search/SearchPred.cc b/search/SearchPred.cc index 03baa5f7..04bb6025 100644 --- a/search/SearchPred.cc +++ b/search/SearchPred.cc @@ -184,8 +184,8 @@ searchThru(const Edge *edge, const TimingArc *arc, const Graph *graph) { - RiseFall *from_rf = arc->fromEdge()->asRiseFall(); - RiseFall *to_rf = arc->toEdge()->asRiseFall(); + const RiseFall *from_rf = arc->fromEdge()->asRiseFall(); + const RiseFall *to_rf = arc->toEdge()->asRiseFall(); // Ignore transitions other than rise/fall. return from_rf && to_rf && searchThru(edge->from(graph), from_rf, edge, edge->to(graph), to_rf); diff --git a/search/Sim.cc b/search/Sim.cc index 783b7547..959b088b 100644 --- a/search/Sim.cc +++ b/search/Sim.cc @@ -78,7 +78,7 @@ Sim::functionSense(const FuncExpr *expr, { debugPrint(debug_, "sim", 4, "find sense pin %s %s", network_->pathName(input_pin), - expr->asString()); + expr->to_string().c_str()); bool increasing, decreasing; { LockGuard lock(bdd_lock_); @@ -103,7 +103,7 @@ Sim::functionSense(const FuncExpr *expr, sense = TimingSense::negative_unate; else sense = TimingSense::non_unate; - debugPrint(debug_, "sim", 4, " %s", timingSenseString(sense)); + debugPrint(debug_, "sim", 4, " %s", to_string(sense)); return sense; } @@ -586,7 +586,7 @@ Sim::evalInstance(const Instance *inst, value = evalExpr(expr, inst); debugPrint(debug_, "sim", 2, " %s tri_en=1 %s = %c", port->name(), - expr->asString(), + expr->to_string().c_str(), logicValueString(value)); } } @@ -601,14 +601,14 @@ Sim::evalInstance(const Instance *inst, value = logicNot(value); debugPrint(debug_, "sim", 2, " %s seq %s = %c", port->name(), - expr->asString(), + expr->to_string().c_str(), logicValueString(value)); } else { value = evalExpr(expr, inst); debugPrint(debug_, "sim", 2, " %s %s = %c", port->name(), - expr->asString(), + expr->to_string().c_str(), logicValueString(value)); } } diff --git a/search/Sta.cc b/search/Sta.cc index 48ad81b4..75b1baf2 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -232,7 +232,6 @@ void initSta() { initElapsedTime(); - TimingRole::init(); PortDirection::init(); initLiberty(); initDelayConstants(); @@ -249,7 +248,6 @@ deleteAllMemory() Sta::setSta(nullptr); } deleteDelayCalcs(); - TimingRole::destroy(); PortDirection::destroy(); deleteLiberty(); } @@ -2488,6 +2486,8 @@ Sta::searchPreamble() findDelays(); updateGeneratedClks(); sdc_->searchPreamble(); + // Delete results from last findPathEnds because they point to filtered arrivals. + search_->deletePathGroups(); search_->deleteFilteredArrivals(); } @@ -2759,82 +2759,82 @@ Sta::vertexPathIterator(Vertex *vertex, return new VertexPathIterator(vertex, rf, min_max, this); } -PathRef +Path * Sta::vertexWorstArrivalPath(Vertex *vertex, const MinMax *min_max) { return vertexWorstArrivalPath(vertex, nullptr, min_max); } -PathRef +Path * Sta::vertexWorstArrivalPath(Vertex *vertex, const RiseFall *rf, const MinMax *min_max) { - PathRef worst_path; + Path *worst_path = nullptr; Arrival worst_arrival = min_max->initValue(); VertexPathIterator path_iter(vertex, rf, min_max, this); while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); - Arrival arrival = path->arrival(this); + Path *path = path_iter.next(); + Arrival arrival = path->arrival(); if (!path->tag(this)->isGenClkSrcPath() && delayGreater(arrival, worst_arrival, min_max, this)) { worst_arrival = arrival; - worst_path.init(path); + worst_path = path; } } return worst_path; } -PathRef +Path * Sta::vertexWorstRequiredPath(Vertex *vertex, const MinMax *min_max) { return vertexWorstRequiredPath(vertex, nullptr, min_max); } -PathRef +Path * Sta::vertexWorstRequiredPath(Vertex *vertex, const RiseFall *rf, const MinMax *min_max) { - PathRef worst_path; + Path *worst_path = nullptr; const MinMax *req_min_max = min_max->opposite(); Arrival worst_req = req_min_max->initValue(); VertexPathIterator path_iter(vertex, rf, min_max, this); while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); - const Required path_req = path->required(this); + Path *path = path_iter.next(); + const Required path_req = path->required(); if (!path->tag(this)->isGenClkSrcPath() && delayGreater(path_req, worst_req, req_min_max, this)) { worst_req = path_req; - worst_path.init(path); + worst_path = path; } } return worst_path; } -PathRef +Path * Sta::vertexWorstSlackPath(Vertex *vertex, const RiseFall *rf, const MinMax *min_max) { - PathRef worst_path; + Path *worst_path = nullptr; Slack min_slack = MinMax::min()->initValue(); VertexPathIterator path_iter(vertex, rf, min_max, this); while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); + Path *path = path_iter.next(); Slack slack = path->slack(this); if (!path->tag(this)->isGenClkSrcPath() && delayLess(slack, min_slack, this)) { min_slack = slack; - worst_path.init(path); + worst_path = path; } } return worst_path; } -PathRef +Path * Sta::vertexWorstSlackPath(Vertex *vertex, const MinMax *min_max) @@ -2891,12 +2891,12 @@ Sta::vertexArrival(Vertex *vertex, VertexPathIterator path_iter(vertex, rf, path_ap, this); while (path_iter.hasNext()) { Path *path = path_iter.next(); - const Arrival &path_arrival = path->arrival(this); + const Arrival &path_arrival = path->arrival(); ClkInfo *clk_info = path->clkInfo(search_); if ((clk_edge == clk_edge_wildcard || clk_info->clkEdge() == clk_edge) && !clk_info->isGenClkSrcPath() - && delayGreater(path->arrival(this), arrival, min_max, this)) + && delayGreater(path->arrival(), arrival, min_max, this)) arrival = path_arrival; } return arrival; @@ -2949,7 +2949,7 @@ Sta::vertexRequired(Vertex *vertex, VertexPathIterator path_iter(vertex, rf, path_ap, min_max, this); while (path_iter.hasNext()) { const Path *path = path_iter.next(); - const Required path_required = path->required(this); + const Required path_required = path->required(); if ((clk_edge == clk_edge_wildcard || path->clkEdge(search_) == clk_edge) && delayGreater(path_required, required, req_min_max, this)) @@ -3019,7 +3019,7 @@ Sta::vertexSlack(Vertex *vertex, const MinMax *min_max) { findRequired(vertex); - MinMax *min = MinMax::min(); + const MinMax *min = MinMax::min(); Slack slack = min->initValue(); VertexPathIterator path_iter(vertex, this); while (path_iter.hasNext()) { @@ -3075,7 +3075,7 @@ Sta::vertexSlack1(Vertex *vertex, const ClockEdge *clk_edge, const PathAnalysisPt *path_ap) { - MinMax *min = MinMax::min(); + const MinMax *min = MinMax::min(); Slack slack = min->initValue(); VertexPathIterator path_iter(vertex, rf, path_ap, this); while (path_iter.hasNext()) { @@ -3177,7 +3177,7 @@ bool MinPeriodEndVisitor::pathIsFromInputPort(PathEnd *path_end) { PathExpanded expanded(path_end->path(), sta_); - const PathRef *start = expanded.startPath(); + const Path *start = expanded.startPath(); Graph *graph = sta_->graph(); const Pin *first_pin = start->pin(graph); Network *network = sta_->network(); @@ -3219,7 +3219,7 @@ Sta::findRequired(Vertex *vertex) int fanout = 0; disableFanoutCrprPruning(vertex, fanout); debugPrint(debug_, "search", 1, "resurrect pruned required %s fanout %d", - vertex->name(sdc_network_), + vertex->to_string(this).c_str(), fanout); // Find fanout arrivals and requireds with pruning disabled. search_->findArrivals(); @@ -3539,14 +3539,14 @@ Sta::pathDcalcAnalysisPt(Path *path) } Vertex * -Sta::maxArrivalCountVertex() const +Sta::maxPathCountVertex() const { Vertex *max_vertex = nullptr; int max_count = 0; VertexIterator vertex_iter(graph_); while (vertex_iter.hasNext()) { Vertex *vertex = vertex_iter.next(); - int count = vertexArrivalCount(vertex); + int count = vertexPathCount(vertex); if (count > max_count) { max_count = count; max_vertex = vertex; @@ -3556,36 +3556,23 @@ Sta::maxArrivalCountVertex() const } int -Sta::vertexArrivalCount(Vertex *vertex) const +Sta::vertexPathCount(Vertex *vertex) const { TagGroup *tag_group = search_->tagGroup(vertex); if (tag_group) - return tag_group->arrivalCount(); + return tag_group->pathCount(); else return 0; } int -Sta::arrivalCount() const +Sta::pathCount() const { int count = 0; VertexIterator vertex_iter(graph_); while (vertex_iter.hasNext()) { Vertex *vertex = vertex_iter.next(); - count += vertexArrivalCount(vertex); - } - return count; -} - -int -Sta::requiredCount() const -{ - int count = 0; - VertexIterator vertex_iter(graph_); - while (vertex_iter.hasNext()) { - Vertex *vertex = vertex_iter.next(); - if (vertex->hasRequireds()) - count += vertexArrivalCount(vertex); + count += vertexPathCount(vertex); } return count; } @@ -3616,7 +3603,7 @@ Sta::setArcDelay(Edge *edge, ArcDelay delay) { ensureGraph(); - for (MinMax *mm : min_max->range()) { + for (const MinMax *mm : min_max->range()) { const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(mm); DcalcAPIndex ap_index = dcalc_ap->index(); graph_->setArcDelay(edge, arc, ap_index, delay); @@ -3639,10 +3626,10 @@ Sta::setAnnotatedSlew(Vertex *vertex, float slew) { ensureGraph(); - for (MinMax *mm : min_max->range()) { + for (const MinMax *mm : min_max->range()) { const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(mm); DcalcAPIndex ap_index = dcalc_ap->index(); - for (RiseFall *rf1 : rf->range()) { + for (const RiseFall *rf1 : rf->range()) { graph_->setSlew(vertex, rf1, ap_index, slew); // Don't let delay calculation clobber the value. vertex->setSlewAnnotated(true, rf1, ap_index); @@ -3703,10 +3690,10 @@ Sta::setPortExtPinCap(const Port *port, const MinMaxAll *min_max, float cap) { - for (RiseFall *rf1 : rf->range()) { - for (MinMax *mm : min_max->range()) { + for (const RiseFall *rf1 : rf->range()) { + for (const MinMax *mm : min_max->range()) { if (corner == nullptr) { - for (Corner *corner : *corners_) + for (const Corner *corner : *corners_) sdc_->setPortExtPinCap(port, rf1, corner, mm, cap); } else @@ -3730,7 +3717,7 @@ Sta::portExtCaps(const Port *port, pin_cap = min_max->initValue(); wire_cap = min_max->initValue(); fanout = min_max->initValueInt(); - for (RiseFall *rf : RiseFall::range()) { + for (const RiseFall *rf : RiseFall::range()) { float pin_cap1, wire_cap1; int fanout1; bool pin_exists1, wire_exists1, fanout_exists1; @@ -3767,10 +3754,10 @@ Sta::setPortExtWireCap(const Port *port, const MinMaxAll *min_max, float cap) { - for (RiseFall *rf1 : rf->range()) { - for (MinMax *mm : min_max->range()) { + for (const RiseFall *rf1 : rf->range()) { + for (const MinMax *mm : min_max->range()) { if (corner == nullptr) { - for (Corner *corner : *corners_) + for (const Corner *corner : *corners_) sdc_->setPortExtWireCap(port, subtract_pin_cap, rf1, corner, mm, cap); } else @@ -3793,9 +3780,9 @@ Sta::setPortExtFanout(const Port *port, const Corner *corner, const MinMaxAll *min_max) { - for (MinMax *mm : min_max->range()) { + for (const MinMax *mm : min_max->range()) { if (corner == nullptr) { - for (Corner *corner : *corners_) + for (const Corner *corner : *corners_) sdc_->setPortExtFanout(port, corner, mm, fanout); } else @@ -3811,9 +3798,9 @@ Sta::setNetWireCap(const Net *net, const MinMaxAll *min_max, float cap) { - for (MinMax *mm : min_max->range()) { + for (const MinMax *mm : min_max->range()) { if (corner == nullptr) { - for (Corner *corner : *corners_) + for (const Corner *corner : *corners_) sdc_->setNetWireCap(net, subtract_pin_cap, corner, mm, cap); } else @@ -3846,7 +3833,7 @@ Sta::connectedCap(const Net *net, pin_cap = min_max->initValue(); wire_cap = min_max->initValue(); for (const Corner *corner : makeCornerSeq(corner)) { - for (RiseFall *rf : RiseFall::range()) { + for (const RiseFall *rf : RiseFall::range()) { float pin_cap1, wire_cap1; connectedCap(drvr_pin, rf, corner, min_max, pin_cap1, wire_cap1); pin_cap = min_max->minMax(pin_cap, pin_cap1); @@ -3880,7 +3867,7 @@ Sta::capacitance(const LibertyPort *port, float cap = min_max->initValue(); for (const Corner *corner : makeCornerSeq(corner)) { const LibertyPort *corner_port = port->cornerPort(corner, min_max); - for (RiseFall *rf : RiseFall::range()) + for (const RiseFall *rf : RiseFall::range()) cap = min_max->minMax(cap, corner_port->capacitance(rf, min_max, op_cond, op_cond)); } return cap; @@ -3994,8 +3981,8 @@ Sta::makePiElmore(Pin *drvr_pin, float rpi, float c1) { - Corner *corner = cmd_corner_; - for (MinMax *mm : min_max->range()) { + const Corner *corner = cmd_corner_; + for (const MinMax *mm : min_max->range()) { ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(mm); parasitics_->makePiElmore(drvr_pin, rf, ap, c2, rpi, c1); } @@ -4026,8 +4013,8 @@ Sta::setElmore(Pin *drvr_pin, const MinMaxAll *min_max, float elmore) { - Corner *corner = cmd_corner_; - for (MinMax *mm : min_max->range()) { + const Corner *corner = cmd_corner_; + for (const MinMax *mm : min_max->range()) { const ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(mm); Parasitic *pi_elmore = parasitics_->findPiElmore(drvr_pin, rf, ap); if (pi_elmore) @@ -4195,6 +4182,8 @@ Sta::makePortPin(const char *port_name, void Sta::makeInstanceAfter(const Instance *inst) { + debugPrint(debug_, "network_edit", 1, "make instance %s", + sdc_network_->pathName(inst)); if (graph_) { LibertyCell *lib_cell = network_->libertyCell(inst); if (lib_cell) { @@ -4367,6 +4356,9 @@ Sta::replaceCellAfter(const Instance *inst) void Sta::connectPinAfter(const Pin *pin) { + debugPrint(debug_, "network_edit", 1, "connect %s to %s", + sdc_network_->pathName(pin), + sdc_network_->pathName(network_->net(pin))); if (graph_) { if (network_->isHierarchical(pin)) { graph_->makeWireEdgesThruPin(pin); @@ -4453,6 +4445,9 @@ Sta::connectLoadPinAfter(Vertex *vertex) void Sta::disconnectPinBefore(const Pin *pin) { + debugPrint(debug_, "network_edit", 1, "disconnect %s from %s", + sdc_network_->pathName(pin), + sdc_network_->pathName(network_->net(pin))); parasitics_->disconnectPinBefore(pin, network_); sdc_->disconnectPinBefore(pin); sim_->disconnectPinBefore(pin); @@ -4500,10 +4495,11 @@ Sta::disconnectPinBefore(const Pin *pin) void Sta::deleteEdge(Edge *edge) { - Vertex *from = edge->from(graph_); + debugPrint(debug_, "network_edit", 1, "delete edge %s -> %s", + edge->from(graph_)->name(sdc_network_), + edge->to(graph_)->name(sdc_network_)); Vertex *to = edge->to(graph_); - search_->arrivalInvalid(to); - search_->requiredInvalid(from); + search_->deleteEdgeBefore(edge); graph_delay_calc_->delayInvalid(to); levelize_->relevelizeFrom(to); levelize_->deleteEdgeBefore(edge); @@ -4514,6 +4510,8 @@ Sta::deleteEdge(Edge *edge) void Sta::deleteNetBefore(const Net *net) { + debugPrint(debug_, "network_edit", 1, "delete net %s", + sdc_network_->pathName(net)); if (graph_) { NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net); while (pin_iter->hasNext()) { @@ -4540,6 +4538,8 @@ Sta::deleteNetBefore(const Net *net) void Sta::deleteInstanceBefore(const Instance *inst) { + debugPrint(debug_, "network_edit", 1, "delete instance %s", + sdc_network_->pathName(inst)); if (network_->isLeaf(inst)) { deleteInstancePinsBefore(inst); deleteLeafInstanceBefore(inst); @@ -4869,7 +4869,7 @@ FanInOutSrchPred::searchThru(Edge *edge) bool FanInOutSrchPred::searchThruRole(Edge *edge) { - TimingRole *role = edge->role(); + const TimingRole *role = edge->role(); return role == TimingRole::wire() || role == TimingRole::combinational() || role == TimingRole::tristateEnable() @@ -4918,7 +4918,7 @@ FaninSrchPred::FaninSrchPred(bool thru_disabled, bool FaninSrchPred::searchThruRole(Edge *edge) { - TimingRole *role = edge->role(); + const TimingRole *role = edge->role(); return role == TimingRole::wire() || role == TimingRole::combinational() || role == TimingRole::tristateEnable() @@ -4994,7 +4994,7 @@ Sta::findFaninPins(Vertex *to, int pin_level) { debugPrint(debug_, "fanin", 1, "%s", - to->name(sdc_network_)); + to->to_string(this).c_str()); if (!visited.hasKey(to)) { visited.insert(to); Pin *to_pin = to->pin(); @@ -5104,7 +5104,7 @@ Sta::findFanoutPins(Vertex *from, int pin_level) { debugPrint(debug_, "fanout", 1, "%s", - from->name(sdc_network_)); + from->to_string(this).c_str()); if (!visited.hasKey(from)) { visited.insert(from); if (!search_->isEndpoint(from, pred) @@ -5715,7 +5715,7 @@ Sta::activity(const Pin *pin) //////////////////////////////////////////////////////////////// void -Sta::writePathSpice(PathRef *path, +Sta::writePathSpice(Path *path, const char *spice_filename, const char *subckt_filename, const char *lib_subckt_filename, diff --git a/search/Tag.cc b/search/Tag.cc index 3b4ac5de..96ea0eda 100644 --- a/search/Tag.cc +++ b/search/Tag.cc @@ -89,16 +89,16 @@ Tag::~Tag() delete states_; } -const char * -Tag::asString(const StaState *sta) const +string +Tag::to_string(const StaState *sta) const { - return asString(true, true, sta); + return to_string(true, true, sta); } -const char * -Tag::asString(bool report_index, - bool report_rf_min_max, - const StaState *sta) const +string +Tag::to_string(bool report_index, + bool report_rf_min_max, + const StaState *sta) const { const Network *network = sta->network(); const Corners *corners = sta->corners(); @@ -111,9 +111,9 @@ Tag::asString(bool report_index, const RiseFall *rf = transition(); PathAnalysisPt *path_ap = corners->findPathAnalysisPt(path_ap_index_); result += " "; - result += rf->asString(); + result += rf->to_string().c_str(); result += " "; - result += path_ap->pathMinMax()->asString(); + result += path_ap->pathMinMax()->to_string(); result += "/"; result += std::to_string(path_ap_index_); } @@ -148,10 +148,10 @@ Tag::asString(bool report_index, result += network->pathName(clk_src); } - const PathVertex crpr_clk_path(clk_info_->crprClkPath(), sta); - if (!crpr_clk_path.isNull()) { + const Path *crpr_clk_path = clk_info_->crprClkPath(sta); + if (crpr_clk_path != nullptr) { result += " crpr_pin "; - result += network->pathName(crpr_clk_path.pin(sta)); + result += network->pathName(crpr_clk_path->pin(sta)); } if (input_delay_) { @@ -178,10 +178,7 @@ Tag::asString(bool report_index, } } } - - char *tmp = makeTmpString(result.size() + 1); - strcpy(tmp, result.c_str()); - return tmp; + return result; } const RiseFall * @@ -280,11 +277,12 @@ Tag::findHash() } size_t -Tag::matchHash(bool match_crpr_clk_pin) const +Tag::matchHash(bool match_crpr_clk_pin, + const StaState *sta) const { if (match_crpr_clk_pin) // match_hash_ with crpr clk pin thrown in. - return hashSum(match_hash_, clk_info_->crprClkVertexId()); + return hashSum(match_hash_, clk_info_->crprClkVertexId(sta)); else return match_hash_; } @@ -421,7 +419,7 @@ tagMatch(const Tag *tag1, && clk_info1->isGenClkSrcPath() == clk_info2->isGenClkSrcPath() && (!match_crpr_clk_pin || !sta->sdc()->crprActive() - || clk_info1->crprClkVertexId() == clk_info2->crprClkVertexId()) + || clk_info1->crprClkVertexId(sta) == clk_info2->crprClkVertexId(sta)) && tagStateEqual(tag1, tag2)); } @@ -482,8 +480,8 @@ tagMatchCmp(const Tag *tag1, if (match_crpr_clk_pin && sta->sdc()->crprActive()) { - VertexId crpr_vertex1 = clk_info1->crprClkVertexId(); - VertexId crpr_vertex2 = clk_info2->crprClkVertexId(); + VertexId crpr_vertex1 = clk_info1->crprClkVertexId(sta); + VertexId crpr_vertex2 = clk_info2->crprClkVertexId(sta); if (crpr_vertex1 < crpr_vertex2) return -1; if (crpr_vertex1 > crpr_vertex2) @@ -676,7 +674,7 @@ TagMatchHash::TagMatchHash(bool match_crpr_clk_pin, size_t TagMatchHash::operator()(const Tag *tag) const { - return tag->matchHash(match_crpr_clk_pin_); + return tag->matchHash(match_crpr_clk_pin_, sta_); } TagMatchEqual::TagMatchEqual(bool match_crpr_clk_pin, diff --git a/search/Tag.hh b/search/Tag.hh index 10c77d5d..00a1bf1b 100644 --- a/search/Tag.hh +++ b/search/Tag.hh @@ -29,7 +29,7 @@ #include "Transition.hh" #include "SdcClass.hh" #include "SearchClass.hh" -#include "PathRef.hh" +#include "Path.hh" namespace sta { @@ -62,10 +62,10 @@ public: bool own_states, const StaState *sta); ~Tag(); - const char *asString(const StaState *sta) const; - const char *asString(bool report_index, - bool report_rf_min_max, - const StaState *sta) const; + string to_string(const StaState *sta) const; + string to_string(bool report_index, + bool report_rf_min_max, + const StaState *sta) const; ClkInfo *clkInfo() const { return clk_info_; } bool isClock() const { return is_clk_; } const ClockEdge *clkEdge() const; @@ -86,7 +86,8 @@ public: bool isFilter() const { return is_filter_; } bool isSegmentStart() const { return is_segment_start_; } size_t hash() const { return hash_; } - size_t matchHash(bool match_crpr_clk_pin) const; + size_t matchHash(bool match_crpr_clk_pin, + const StaState *sta) const; protected: void findHash(); diff --git a/search/TagGroup.cc b/search/TagGroup.cc index 14d6bb89..c7570937 100644 --- a/search/TagGroup.cc +++ b/search/TagGroup.cc @@ -32,66 +32,70 @@ #include "Tag.hh" #include "Corner.hh" #include "Search.hh" -#include "PathPrev.hh" +#include "Path.hh" namespace sta { TagGroup::TagGroup(TagGroupIndex index, - ArrivalMap *arrival_map, + PathIndexMap *path_index_map, bool has_clk_tag, bool has_genclk_src_tag, bool has_filter_tag, bool has_loop_tag) : - arrival_map_(arrival_map), - hash_(arrivalMapHash(arrival_map_)), + path_index_map_(path_index_map), + hash_(pathIndexMapHash(path_index_map)), index_(index), has_clk_tag_(has_clk_tag), has_genclk_src_tag_(has_genclk_src_tag), has_filter_tag_(has_filter_tag), has_loop_tag_(has_loop_tag), - own_arrival_map_(true) + own_path_map_(true) { } TagGroup::TagGroup(TagGroupBldr *tag_bldr) : - arrival_map_(tag_bldr->arrivalMap()), - hash_(arrivalMapHash(arrival_map_)), - own_arrival_map_(false) + path_index_map_(&tag_bldr->pathIndexMap()), + hash_(pathIndexMapHash(path_index_map_)), + own_path_map_(false) { } TagGroup::~TagGroup() { - if (own_arrival_map_) - delete arrival_map_; + if (own_path_map_) + delete path_index_map_; } size_t -TagGroup::arrivalMapHash(ArrivalMap *arrival_map) +TagGroup::pathIndexMapHash(PathIndexMap *path_index_map) { size_t hash = 0; - ArrivalMap::Iterator arrival_iter(arrival_map); - while (arrival_iter.hasNext()) { - Tag *tag; - int arrival_index; - arrival_iter.next(tag, arrival_index); + for (auto const [tag, path_index] : *path_index_map) hash += tag->hash(); - } return hash; } bool TagGroup::hasTag(Tag *tag) const { - return arrival_map_->hasKey(tag); + return path_index_map_->hasKey(tag); +} + +size_t +TagGroup::pathIndex(Tag *tag) const +{ + size_t path_index; + bool exists; + pathIndex(tag, path_index, exists); + return path_index; } void -TagGroup::arrivalIndex(Tag *tag, - int &arrival_index, - bool &exists) const +TagGroup::pathIndex(Tag *tag, + size_t &path_index, + bool &exists) const { - arrival_map_->findKey(tag, arrival_index, exists); + path_index_map_->findKey(tag, path_index, exists); } void @@ -99,29 +103,24 @@ TagGroup::report(const StaState *sta) const { Report *report = sta->report(); report->reportLine("Group %u hash = %zu", index_, hash_); - arrivalMapReport(arrival_map_, sta); + pathIndexMapReport(path_index_map_, sta); } void TagGroup::reportArrivalMap(const StaState *sta) const { - arrivalMapReport(arrival_map_, sta); + pathIndexMapReport(path_index_map_, sta); } void -arrivalMapReport(const ArrivalMap *arrival_map, - const StaState *sta) +pathIndexMapReport(const PathIndexMap *path_index_map, + const StaState *sta) { Report *report = sta->report(); - ArrivalMap::ConstIterator arrival_iter(arrival_map); - while (arrival_iter.hasNext()) { - Tag *tag; - int arrival_index; - arrival_iter.next(tag, arrival_index); - report->reportLine(" %2u %s", - arrival_index, - tag->asString(sta)); - } + for (auto const [tag, path_index] : *path_index_map) + report->reportLine(" %2zu %s", + path_index, + tag->to_string(sta).c_str()); report->reportBlankLine(); } @@ -129,18 +128,18 @@ arrivalMapReport(const ArrivalMap *arrival_map, TagGroupBldr::TagGroupBldr(bool match_crpr_clk_pin, const StaState *sta) : - default_arrival_count_(sta->corners()->count() - * RiseFall::index_count - * MinMax::index_count), - arrival_map_(default_arrival_count_, - TagMatchHash(match_crpr_clk_pin, sta), - TagMatchEqual(match_crpr_clk_pin, sta)), - arrivals_(default_arrival_count_), - prev_paths_(default_arrival_count_), + default_path_count_(sta->corners()->count() + * RiseFall::index_count + * MinMax::index_count), + path_index_map_(default_path_count_, + TagMatchHash(match_crpr_clk_pin, sta), + TagMatchEqual(match_crpr_clk_pin, sta)), + paths_(default_path_count_), has_clk_tag_(false), has_genclk_src_tag_(false), has_filter_tag_(false), has_loop_tag_(false), + has_propagated_clk_(false), sta_(sta) { } @@ -148,16 +147,15 @@ TagGroupBldr::TagGroupBldr(bool match_crpr_clk_pin, bool TagGroupBldr::empty() { - return arrival_map_.empty(); + return path_index_map_.empty(); } void TagGroupBldr::init(Vertex *vertex) { vertex_ = vertex; - arrival_map_.clear(); - arrivals_.clear(); - prev_paths_.clear(); + path_index_map_.clear(); + paths_.clear(); has_clk_tag_ = false; has_genclk_src_tag_ = false; has_filter_tag_ = false; @@ -167,145 +165,152 @@ TagGroupBldr::init(Vertex *vertex) void TagGroupBldr::reportArrivalEntries() const { - arrivalMapReport(&arrival_map_, sta_); + pathIndexMapReport(&path_index_map_, sta_); +} + +Path * +TagGroupBldr::tagMatchPath(Tag *tag) +{ + Path *match; + size_t path_index; + tagMatchPath(tag, match, path_index); + return match; } void -TagGroupBldr::tagMatchArrival(Tag *tag, - // Return values. - Tag *&tag_match, - Arrival &arrival, - int &arrival_index) const +TagGroupBldr::tagMatchPath(Tag *tag, + // Return values. + Path *&match, + size_t &path_index) { // Find matching group tag. // Match is not necessarily equal to original tag because it // must only satisfy tagMatch. bool exists; - arrival_map_.findKey(tag, tag_match, arrival_index, exists); + Tag *tag_match; + path_index_map_.findKey(tag, tag_match, path_index, exists); if (exists) - arrival = arrivals_[arrival_index]; + match = &paths_[path_index]; else { - tag_match = nullptr; - arrival = -1.0; - arrival_index = -1; + match = nullptr; + path_index = 0; } } Arrival -TagGroupBldr::arrival(int arrival_index) const +TagGroupBldr::arrival(size_t path_index) const { - return arrivals_[arrival_index]; + return paths_[path_index].arrival(); } void TagGroupBldr::setArrival(Tag *tag, - const Arrival &arrival, - PathPrev *prev_path) + const Arrival &arrival) { - Tag *tag_match; - Arrival ignore; - int arrival_index; // Find matching group tag (not necessarily equal to original tag). - tagMatchArrival(tag, tag_match, ignore, arrival_index); - setMatchArrival(tag, tag_match, arrival, arrival_index, prev_path); + Path *match; + size_t path_index; + tagMatchPath(tag, match, path_index); + setMatchPath(match, path_index, tag, arrival, nullptr, nullptr, nullptr); } void -TagGroupBldr::setMatchArrival(Tag *tag, - Tag *tag_match, - const Arrival &arrival, - int arrival_index, - PathPrev *prev_path) +TagGroupBldr::setMatchPath(Path *match, + size_t path_index, + Tag *tag, + Arrival arrival, + Path *prev_path, + Edge *prev_edge, + TimingArc *prev_arc) { - if (tag_match) { - // If the group_tag exists there has to be an arrival map entry for it. + if (match) { + Tag *tag_match = match->tag(sta_); + // If the tag match exists there has to be a path map entry for it. if (tag_match != tag) { // Replace tag in arrival map. - arrival_map_.erase(tag_match); - arrival_map_.insert(tag, arrival_index); + path_index_map_.erase(tag_match); + path_index_map_.insert(tag, path_index); } - arrivals_[arrival_index] = arrival; - prev_paths_[arrival_index].init(prev_path); + paths_[path_index].init(vertex_, tag, arrival, prev_path, + prev_edge, prev_arc, sta_); } - else { - arrival_index = arrivals_.size(); - arrival_map_.insert(tag, arrival_index); - arrivals_.push_back(arrival); - if (prev_path) - prev_paths_.push_back(*prev_path); - else - prev_paths_.push_back(PathPrev()); + else + insertPath(tag, arrival, prev_path, prev_edge, prev_arc); +} - if (tag->isClock()) - has_clk_tag_ = true; - if (tag->isGenClkSrcPath()) - has_genclk_src_tag_ = true; - if (tag->isFilter() - || tag->clkInfo()->refsFilter(sta_)) - has_filter_tag_ = true; - if (tag->isLoop()) - has_loop_tag_ = true; - } +void +TagGroupBldr::insertPath(Tag *tag, + Arrival arrival, + Path *prev_path, + Edge *prev_edge, + TimingArc *prev_arc) + +{ + size_t path_index = paths_.size(); + path_index_map_.insert(tag, path_index); + paths_.emplace_back(vertex_, tag, arrival, prev_path, + prev_edge, prev_arc, sta_); + + if (tag->isClock()) + has_clk_tag_ = true; + if (tag->isGenClkSrcPath()) + has_genclk_src_tag_ = true; + if (tag->isFilter() + || tag->clkInfo()->refsFilter(sta_)) + has_filter_tag_ = true; + if (tag->isLoop()) + has_loop_tag_ = true; + if (tag->clkInfo()->isPropagated()) + has_propagated_clk_ = true; +} + +void +TagGroupBldr::insertPath(const Path &path) +{ + insertPath(path.tag(sta_), path.arrival(), path.prevPath(), + path.prevEdge(sta_), path.prevArc(sta_)); } TagGroup * TagGroupBldr::makeTagGroup(TagGroupIndex index, const StaState *sta) { - return new TagGroup(index, makeArrivalMap(sta), + return new TagGroup(index, makePathIndexMap(sta), has_clk_tag_, has_genclk_src_tag_, has_filter_tag_, has_loop_tag_); } -ArrivalMap * -TagGroupBldr::makeArrivalMap(const StaState *sta) +PathIndexMap * +TagGroupBldr::makePathIndexMap(const StaState *sta) { - ArrivalMap *arrival_map = new ArrivalMap(arrival_map_.size(), - TagMatchHash(true, sta), - TagMatchEqual(true, sta)); - int arrival_index = 0; - ArrivalMap::Iterator arrival_iter(arrival_map_); - while (arrival_iter.hasNext()) { - Tag *tag; - int arrival_index1; - arrival_iter.next(tag, arrival_index1); - arrival_map->insert(tag, arrival_index); - arrival_index++; + PathIndexMap *path_index_map = new PathIndexMap(path_index_map_.size(), + TagMatchHash(true, sta), + TagMatchEqual(true, sta)); + + size_t path_index = 0; + for (auto const [tag, path_index1] : path_index_map_) { + path_index_map->insert(tag, path_index); + path_index++; } - return arrival_map; + return path_index_map; } void -TagGroupBldr::copyArrivals(TagGroup *tag_group, - Arrival *arrivals, - PathPrev *prev_paths) +TagGroupBldr::copyPaths(TagGroup *tag_group, + Path *paths) { - ArrivalMap::Iterator arrival_iter1(arrival_map_); - while (arrival_iter1.hasNext()) { - Tag *tag1; - int arrival_index1, arrival_index2; - arrival_iter1.next(tag1, arrival_index1); + for (auto const [tag1, path_index1] : path_index_map_) { + size_t path_index2; bool exists2; - tag_group->arrivalIndex(tag1, arrival_index2, exists2); - if (exists2) { - arrivals[arrival_index2] = arrivals_[arrival_index1]; - if (prev_paths) { - PathPrev *prev_path = &prev_paths_[arrival_index1]; - prev_paths[arrival_index2].init(prev_path); - } - } + tag_group->pathIndex(tag1, path_index2, exists2); + if (exists2) + paths[path_index2] = paths_[path_index1]; else sta_->report()->critical(1351, "tag group missing tag"); } } -PathPrev & -TagGroupBldr::prevPath(int arrival_index) -{ - return prev_paths_[arrival_index]; -} - //////////////////////////////////////////////////////////////// size_t @@ -315,19 +320,15 @@ TagGroupHash::operator()(const TagGroup *group) const } static bool -arrivalMapEqual(const ArrivalMap *arrival_map1, - const ArrivalMap *arrival_map2) +pathIndexMapEqual(const PathIndexMap *path_index_map1, + const PathIndexMap *path_index_map2) { - int arrival_count1 = arrival_map1->size(); - int arrival_count2 = arrival_map2->size(); - if (arrival_count1 == arrival_count2) { - ArrivalMap::ConstIterator arrival_iter1(arrival_map1); - while (arrival_iter1.hasNext()) { - Tag *tag1, *tag2; - int arrival_index1, arrival_index2; - arrival_iter1.next(tag1, arrival_index1); + if (path_index_map1->size() == path_index_map2->size()) { + for (auto const [tag1, path_index1] : *path_index_map1) { + Tag *tag2; + size_t path_index2; bool exists2; - arrival_map2->findKey(tag1, tag2, arrival_index2, exists2); + path_index_map2->findKey(tag1, tag2, path_index2, exists2); if (!exists2 // ArrivalMap equal function is TagMatchEqual, so make sure // the tag is an exact match. @@ -346,8 +347,8 @@ TagGroupEqual::operator()(const TagGroup *tag_group1, { return tag_group1 == tag_group2 || (tag_group1->hash() == tag_group2->hash() - && arrivalMapEqual(tag_group1->arrivalMap(), - tag_group2->arrivalMap())); + && pathIndexMapEqual(tag_group1->pathIndexMap(), + tag_group2->pathIndexMap())); } } // namespace diff --git a/search/TagGroup.hh b/search/TagGroup.hh index 64082d80..2d36aedf 100644 --- a/search/TagGroup.hh +++ b/search/TagGroup.hh @@ -37,13 +37,11 @@ namespace sta { class TagGroupBldr; -typedef Vector PathPrevSeq; - class TagGroup { public: TagGroup(TagGroupIndex index, - ArrivalMap *arrival_map, + PathIndexMap *path_index_map, bool has_clk_tag, bool has_genclk_src_tag, bool has_filter_tag, @@ -59,26 +57,27 @@ public: bool hasGenClkSrcTag() const { return has_genclk_src_tag_; } bool hasFilterTag() const { return has_filter_tag_; } bool hasLoopTag() const { return has_loop_tag_; } - bool ownArrivalMap() const { return own_arrival_map_; } - int arrivalCount() const { return arrival_map_->size(); } - void arrivalIndex(Tag *tag, - int &arrival_index, - bool &exists) const; - ArrivalMap *arrivalMap() const { return arrival_map_; } + bool ownPathMap() const { return own_path_map_; } + size_t pathCount() const { return path_index_map_->size(); } + void pathIndex(Tag *tag, + size_t &path_index, + bool &exists) const; + size_t pathIndex(Tag *tag) const; + PathIndexMap *pathIndexMap() const { return path_index_map_; } bool hasTag(Tag *tag) const; protected: - size_t arrivalMapHash(ArrivalMap *arrival_map); + static size_t pathIndexMapHash(PathIndexMap *path_index_map); - // tag -> arrival index - ArrivalMap *arrival_map_; + // tag -> path index + PathIndexMap *path_index_map_; size_t hash_; unsigned int index_:tag_group_index_bits; bool has_clk_tag_:1; bool has_genclk_src_tag_:1; bool has_filter_tag_:1; bool has_loop_tag_:1; - bool own_arrival_map_:1; + bool own_path_map_:1; }; class TagGroupHash @@ -106,48 +105,56 @@ public: void reportArrivalEntries() const; TagGroup *makeTagGroup(TagGroupIndex index, const StaState *sta); + size_t pathCount() const { return path_index_map_.size();; } bool hasClkTag() const { return has_clk_tag_; } bool hasGenClkSrcTag() const { return has_genclk_src_tag_; } bool hasFilterTag() const { return has_filter_tag_; } bool hasLoopTag() const { return has_loop_tag_; } - void tagMatchArrival(Tag *tag, - // Return values. - Tag *&tag_match, - Arrival &arrival, - int &arrival_index) const; - Arrival arrival(int arrival_index) const; + bool hasPropagatedClk() const { return has_propagated_clk_; } + Path *tagMatchPath(Tag *tag); + void tagMatchPath(Tag *tag, + // Return values. + Path *&match, + size_t &path_index); + Arrival arrival(size_t path_index) const; + // prev_path == hull void setArrival(Tag *tag, - const Arrival &arrival, - PathPrev *prev_path); - void setMatchArrival(Tag *tag, - Tag *tag_match, - const Arrival &arrival, - int arrival_index, - PathPrev *prev_path); - ArrivalMap *arrivalMap() { return &arrival_map_; } - PathPrev &prevPath(int arrival_index); - void copyArrivals(TagGroup *tag_group, - Arrival *arrivals, - PathPrev *prev_paths); + const Arrival &arrival); + void setMatchPath(Path *match, + size_t path_index, + Tag *tag, + Arrival arrival, + Path *prev_path, + Edge *prev_edge, + TimingArc *prev_arc); + void insertPath(Tag *tag, + Arrival arrival, + Path *prev_path, + Edge *prev_edge, + TimingArc *prev_arc); + void insertPath(const Path &path); + PathIndexMap &pathIndexMap() { return path_index_map_; } + void copyPaths(TagGroup *tag_group, + Path *paths); protected: int tagMatchIndex(); - ArrivalMap *makeArrivalMap(const StaState *sta); + PathIndexMap *makePathIndexMap(const StaState *sta); Vertex *vertex_; - int default_arrival_count_; - ArrivalMap arrival_map_; - ArrivalSeq arrivals_; - PathPrevSeq prev_paths_; + int default_path_count_; + PathIndexMap path_index_map_; + vector paths_; bool has_clk_tag_; - bool has_genclk_src_tag_:1; + bool has_genclk_src_tag_; bool has_filter_tag_; bool has_loop_tag_; + bool has_propagated_clk_; const StaState *sta_; }; void -arrivalMapReport(const ArrivalMap *arrival_map, - const StaState *sta); +pathIndexMapReport(const PathIndexMap *path_index_map, + const StaState *sta); } // namespace diff --git a/search/VisitPathEnds.cc b/search/VisitPathEnds.cc index d7d409d9..561b5fb2 100644 --- a/search/VisitPathEnds.cc +++ b/search/VisitPathEnds.cc @@ -34,7 +34,7 @@ #include "Graph.hh" #include "ClkInfo.hh" #include "Tag.hh" -#include "PathVertex.hh" +#include "Path.hh" #include "PathAnalysisPt.hh" #include "PathEnd.hh" #include "Search.hh" @@ -65,7 +65,7 @@ VisitPathEnds::visitPathEnds(Vertex *vertex, if (!vertex->isBidirectDriver()) { const Pin *pin = vertex->pin(); debugPrint(debug_, "search", 2, "find end slack %s", - vertex->name(sdc_network_)); + vertex->to_string(this).c_str()); visitor->vertexBegin(vertex); bool is_constrained = false; visitClkedPathEnds(pin, vertex, corner, min_max, filtered, visitor, @@ -91,7 +91,7 @@ VisitPathEnds::visitClkedPathEnds(const Pin *pin, bool is_segment_start = search_->isSegmentStart(pin); VertexPathIterator path_iter(vertex, this); while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); + Path *path = path_iter.next(); PathAnalysisPt *path_ap = path->pathAnalysisPt(this); const MinMax *path_min_max = path_ap->pathMinMax(); const RiseFall *end_rf = path->transition(this); @@ -155,13 +155,13 @@ VisitPathEnds::visitCheckEnd(const Pin *pin, && check_role->pathMinMax() == min_max) { TimingArcSet *arc_set = edge->timingArcSet(); for (TimingArc *check_arc : arc_set->arcs()) { - RiseFall *clk_rf = check_arc->fromEdge()->asRiseFall(); + const RiseFall *clk_rf = check_arc->fromEdge()->asRiseFall(); if (check_arc->toEdge()->asRiseFall() == end_rf && clk_rf) { VertexPathIterator tgt_clk_path_iter(tgt_clk_vertex, clk_rf, tgt_clk_path_ap, this); while (tgt_clk_path_iter.hasNext()) { - PathVertex *tgt_clk_path = tgt_clk_path_iter.next(); + Path *tgt_clk_path = tgt_clk_path_iter.next(); ClkInfo *tgt_clk_info = tgt_clk_path->clkInfo(this); const ClockEdge *tgt_clk_edge = tgt_clk_path->clkEdge(this); const Clock *tgt_clk = tgt_clk_path->clock(this); @@ -255,7 +255,7 @@ VisitPathEnds::visitCheckEndUnclked(const Pin *pin, && check_role->pathMinMax() == min_max) { TimingArcSet *arc_set = edge->timingArcSet(); for (TimingArc *check_arc : arc_set->arcs()) { - RiseFall *clk_rf = check_arc->fromEdge()->asRiseFall(); + const RiseFall *clk_rf = check_arc->fromEdge()->asRiseFall(); if (check_arc->toEdge()->asRiseFall() == end_rf && clk_rf && (!filtered @@ -315,10 +315,10 @@ VisitPathEnds::visitOutputDelayEnd(const Pin *pin, if (ref_pin) { Clock *tgt_clk = output_delay->clock(); Vertex *ref_vertex = graph_->pinLoadVertex(ref_pin); - RiseFall *ref_rf = output_delay->refTransition(); + const RiseFall *ref_rf = output_delay->refTransition(); VertexPathIterator ref_path_iter(ref_vertex,ref_rf,path_ap,this); while (ref_path_iter.hasNext()) { - PathVertex *ref_path = ref_path_iter.next(); + Path *ref_path = ref_path_iter.next(); if (ref_path->isClock(this) && (tgt_clk == nullptr || ref_path->clock(this) == tgt_clk)) @@ -343,7 +343,7 @@ VisitPathEnds::visitOutputDelayEnd1(OutputDelay *output_delay, Path *path, const RiseFall *end_rf, const ClockEdge *tgt_clk_edge, - PathVertex *ref_path, + Path *ref_path, const MinMax *min_max, PathEndVisitor *visitor, bool &is_constrained) @@ -406,7 +406,7 @@ VisitPathEnds::visitGatedClkEnd(const Pin *pin, Vertex *clk_vertex = graph_->pinLoadVertex(clk_pin); LogicValue active_value = sdc_->clockGatingActiveValue(clk_pin, pin); - RiseFall *clk_rf = + const RiseFall *clk_rf = // Clock active value specified by set_clock_gating_check // overrides the library cell function active value. gated_clk->gatedClkActiveTrans((active_value == LogicValue::unknown) ? @@ -414,7 +414,7 @@ VisitPathEnds::visitGatedClkEnd(const Pin *pin, min_max); VertexPathIterator clk_path_iter(clk_vertex, clk_rf, clk_path_ap, this); while (clk_path_iter.hasNext()) { - PathVertex *clk_path = clk_path_iter.next(); + Path *clk_path = clk_path_iter.next(); const ClockEdge *clk_edge = clk_path->clkEdge(this); const Clock *clk = clk_edge ? clk_edge->clock() : nullptr; if (clk_path->isClock(this) @@ -425,7 +425,7 @@ VisitPathEnds::visitGatedClkEnd(const Pin *pin, && !path->clkInfo(this)->isGenClkSrcPath() && !sdc_->clkStopPropagation(pin, clk) && clk_vertex->hasDownstreamClkPin()) { - TimingRole *check_role = (min_max == MinMax::max()) + const TimingRole *check_role = (min_max == MinMax::max()) ? TimingRole::gatedClockSetup() : TimingRole::gatedClockHold(); float margin = clockGatingMargin(clk, clk_pin, @@ -536,7 +536,7 @@ VisitPathEnds::visitDataCheckEnd1(DataCheck *check, const PathAnalysisPt *clk_ap, const Pin *from_pin, Vertex *from_vertex, - RiseFall *from_rf, + const RiseFall *from_rf, bool filtered, PathEndVisitor *visitor, bool &is_constrained) @@ -544,7 +544,7 @@ VisitPathEnds::visitDataCheckEnd1(DataCheck *check, bool found_from_path = false; VertexPathIterator tgt_clk_path_iter(from_vertex,from_rf,clk_ap,this); while (tgt_clk_path_iter.hasNext()) { - PathVertex *tgt_clk_path = tgt_clk_path_iter.next(); + Path *tgt_clk_path = tgt_clk_path_iter.next(); const ClockEdge *tgt_clk_edge = tgt_clk_path->clkEdge(this); // Ignore generated clock source paths. if (tgt_clk_edge @@ -584,7 +584,7 @@ VisitPathEnds::visitUnconstrainedPathEnds(const Pin *pin, { VertexPathIterator path_iter(vertex, this); while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); + Path *path = path_iter.next(); PathAnalysisPt *path_ap = path->pathAnalysisPt(this); const MinMax *path_min_max = path_ap->pathMinMax(); if ((corner == nullptr diff --git a/search/VisitPathGroupVertices.cc b/search/VisitPathGroupVertices.cc index 2d4217bc..b20ef395 100644 --- a/search/VisitPathGroupVertices.cc +++ b/search/VisitPathGroupVertices.cc @@ -28,21 +28,20 @@ #include "Graph.hh" #include "Bfs.hh" #include "Search.hh" -#include "PathVertex.hh" +#include "Path.hh" #include "PathEnd.hh" #include "Tag.hh" #include "VisitPathEnds.hh" namespace sta { -typedef Set PathVertexSet; -typedef Map VertexPathSetMap; +typedef Set PathSet; +typedef Map VertexPathSetMap; static void vertexPathSetMapInsertPath(VertexPathSetMap *matching_path_map, Vertex *vertex, Tag *tag, - int arrival_index, const StaState *sta); // Visit each path end for a vertex and add the worst one in each @@ -87,7 +86,7 @@ protected: Vertex *from_vertex, const RiseFall *from_rf, Tag *from_tag, - PathVertex *from_path, + Path *from_path, const Arrival &from_arrival, Edge *edge, TimingArc *arc, @@ -99,8 +98,7 @@ protected: const MinMax *min_max, const PathAnalysisPt *path_ap); void fromMatches(Vertex *from_vertex, - Tag *from_tag, - int from_arrival_index); + Tag *from_tag); private: VertexVisitor *visitor_; @@ -139,10 +137,10 @@ visitPathGroupVertices(PathGroup *path_group, // Cleanup. VertexPathSetMap::Iterator matching_iter(matching_path_map); while (matching_iter.hasNext()) { - PathVertexSet *paths = matching_iter.next(); - PathVertexSet::Iterator path_iter(paths); + PathSet *paths = matching_iter.next(); + PathSet::Iterator path_iter(paths); while (path_iter.hasNext()) { - PathVertex *path = path_iter.next(); + Path *path = path_iter.next(); delete path; } delete paths; @@ -181,14 +179,9 @@ VisitPathGroupEnds::visit(PathEnd *path_end) { PathGroup *group = sta_->search()->pathGroup(path_end); if (group == path_group_) { - PathRef path(path_end->pathRef()); - Vertex *vertex = path.vertex(sta_); - - int arrival_index; - bool arrival_exists; - path.arrivalIndex(arrival_index, arrival_exists); - vertexPathSetMapInsertPath(matching_path_map_, vertex, path.tag(sta_), - arrival_index, sta_); + Path *path = path_end->path(); + Vertex *vertex = path->vertex(sta_); + vertexPathSetMapInsertPath(matching_path_map_, vertex, path->tag(sta_), sta_); vertex_matches_ = true; } } @@ -197,16 +190,15 @@ static void vertexPathSetMapInsertPath(VertexPathSetMap *matching_path_map, Vertex *vertex, Tag *tag, - int arrival_index, const StaState *sta) { - PathVertexSet *matching_paths = matching_path_map->findKey(vertex); + PathSet *matching_paths = matching_path_map->findKey(vertex); if (matching_paths == nullptr) { PathLess path_less(sta); - matching_paths = new PathVertexSet(path_less); + matching_paths = new PathSet(path_less); (*matching_path_map)[vertex] = matching_paths; } - PathVertex *vpath = new PathVertex(vertex, tag, arrival_index); + Path *vpath = new Path(vertex, tag, sta); matching_paths->insert(vpath); } @@ -251,7 +243,7 @@ PathGroupPathVisitor::visit(Vertex *vertex) visitFanoutPaths(vertex); if (vertex_matches_) { debugPrint(debug_, "visit_path_group", 1, "visit %s", - vertex->name(network_)); + vertex->to_string(this).c_str()); visitor_->visit(vertex); bkwd_iter_->enqueueAdjacentVertices(vertex); } @@ -262,7 +254,7 @@ PathGroupPathVisitor::visitFromToPath(const Pin *, Vertex *from_vertex, const RiseFall *, Tag *from_tag, - PathVertex *from_path, + Path *, const Arrival &, Edge *, TimingArc *, @@ -274,35 +266,32 @@ PathGroupPathVisitor::visitFromToPath(const Pin *, const MinMax *, const PathAnalysisPt *path_ap) { - PathVertexSet *matching_paths = matching_path_map_->findKey(to_vertex); + PathSet *matching_paths = matching_path_map_->findKey(to_vertex); if (matching_paths) { - int arrival_index; - bool arrival_exists; - from_path->arrivalIndex(arrival_index, arrival_exists); - PathVertex to_path(to_vertex, to_tag, this); + Path to_path(to_vertex, to_tag, this); if (!to_path.isNull()) { if (matching_paths->hasKey(&to_path)) { debugPrint(debug_, "visit_path_group", 2, "match %s %s -> %s %s", - from_vertex->name(network_), - from_tag->asString(this), - to_vertex->name(network_), - to_tag->asString(this)); - fromMatches(from_vertex, from_tag, arrival_index); + from_vertex->to_string(this).c_str(), + from_tag->to_string(this).c_str(), + to_vertex->to_string(this).c_str(), + to_tag->to_string(this).c_str()); + fromMatches(from_vertex, from_tag); } } else { VertexPathIterator to_iter(to_vertex, to_rf, path_ap, this); while (to_iter.hasNext()) { - PathVertex *to_path = to_iter.next(); + Path *to_path = to_iter.next(); if (tagMatchNoCrpr(to_path->tag(this), to_tag) && matching_paths->hasKey(to_path)) { debugPrint(debug_, "visit_path_group", 2, "match crpr %s %s -> %s %s", - from_vertex->name(network_), - from_tag->asString(this), - to_vertex->name(network_), - to_tag->asString(this)); - fromMatches(from_vertex, from_tag, arrival_index); + from_vertex->to_string(this).c_str(), + from_tag->to_string(this).c_str(), + to_vertex->to_string(this).c_str(), + to_tag->to_string(this).c_str()); + fromMatches(from_vertex, from_tag); } } } @@ -312,12 +301,11 @@ PathGroupPathVisitor::visitFromToPath(const Pin *, void PathGroupPathVisitor::fromMatches(Vertex *from_vertex, - Tag *from_tag, - int from_arrival_index) + Tag *from_tag) { vertex_matches_ = true; vertexPathSetMapInsertPath(matching_path_map_, from_vertex, - from_tag, from_arrival_index, this); + from_tag, this); } } // namespace diff --git a/search/WorstSlack.cc b/search/WorstSlack.cc index f7f798c6..e61fccca 100644 --- a/search/WorstSlack.cc +++ b/search/WorstSlack.cc @@ -254,7 +254,7 @@ WorstSlack::checkQueue(PathAPIndex path_ap_index) && delayLessEqual(search_->wnsSlack(end, path_ap_index), slack_threshold_, this)) report_->reportLine("WorstSlack queue missing %s %s < %s", - end->name(network_), + end->to_string(this).c_str(), delayAsString(search_->wnsSlack(end, path_ap_index), this), delayAsString(slack_threshold_, this)); } @@ -262,7 +262,7 @@ WorstSlack::checkQueue(PathAPIndex path_ap_index) for (Vertex *end : *queue_) { if (!end_set.hasKey(end)) report_->reportLine("WorstSlack queue extra %s %s > %s", - end->name(network_), + end->to_string(this).c_str(), delayAsString(search_->wnsSlack(end, path_ap_index), this), delayAsString(slack_threshold_, this)); } @@ -289,13 +289,13 @@ WorstSlack::updateWorstSlack(Vertex *vertex, if (!delayEqual(slack, slack_init_) && delayLessEqual(slack, slack_threshold_, this)) { debugPrint(debug_, "wns", 3, "insert %s %s", - vertex->name(network_), + vertex->to_string(this).c_str(), delayAsString(slack, this)); queue_->insert(vertex); } else { debugPrint(debug_, "wns", 3, "delete %s %s", - vertex->name(network_), + vertex->to_string(this).c_str(), delayAsString(slack, this)); queue_->erase(vertex); } @@ -308,7 +308,7 @@ WorstSlack::setWorstSlack(Vertex *vertex, Slack slack) { debugPrint(debug_, "wns", 3, "%s %s", - vertex->name(network_), + vertex->to_string(this).c_str(), delayAsString(slack, this)); worst_vertex_ = vertex; worst_slack_ = slack; diff --git a/spice/WritePathSpice.cc b/spice/WritePathSpice.cc index bc4136ca..2a7f7616 100644 --- a/spice/WritePathSpice.cc +++ b/spice/WritePathSpice.cc @@ -45,7 +45,6 @@ #include "Parasitics.hh" #include "PathAnalysisPt.hh" #include "Path.hh" -#include "PathRef.hh" #include "PathExpanded.hh" #include "StaState.hh" #include "search/Sim.hh" @@ -118,11 +117,11 @@ private: int stageGateInputPathIndex(Stage stage); int stageDrvrPathIndex(Stage stage); int stageLoadPathIndex(Stage stage); - const PathRef *stageGateInputPath(Stage stage); - const PathRef *stageDrvrPath(Stage stage); - const PathRef *stageLoadPath(Stage stage); - TimingArc *stageGateArc(Stage stage); - TimingArc *stageWireArc(Stage stage); + const Path *stageGateInputPath(Stage stage); + const Path *stageDrvrPath(Stage stage); + const Path *stageLoadPath(Stage stage); + const TimingArc *stageGateArc(Stage stage); + const TimingArc *stageWireArc(Stage stage); Edge *stageGateEdge(Stage stage); Edge *stageWireEdge(Stage stage); Pin *stageGateInputPin(Stage stage); @@ -139,7 +138,7 @@ private: float findSlew(const Path *path); float findSlew(const Path *path, const RiseFall *rf, - TimingArc *next_arc); + const TimingArc *next_arc); Path *path_; PathExpanded path_expanded_; // Input clock waveform cycles. @@ -223,9 +222,9 @@ WritePathSpice::writeHeader() const Path *start_path = path_expanded_.startPath(); string title = stdstrPrint("Path from %s %s to %s %s", network_->pathName(start_path->pin(this)), - start_path->transition(this)->asString(), + start_path->transition(this)->to_string().c_str(), network_->pathName(path_->pin(this)), - path_->transition(this)->asString()); + path_->transition(this)->to_string().c_str()); float max_time = maxTime(); float time_step = 1e-13; writeHeader(title, max_time, time_step); @@ -246,7 +245,7 @@ float WritePathSpice::maxTime() { Stage input_stage = stageFirst(); - const PathRef *input_path = stageDrvrPath(input_stage); + const Path *input_path = stageDrvrPath(input_stage); if (input_path->isClock(this)) { const Clock *clk = input_path->clock(this); float period = clk->period(); @@ -264,7 +263,7 @@ WritePathSpice::pathMaxTime() { float max_time = 0.0; for (size_t i = 0; i < path_expanded_.size(); i++) { - const PathRef *path = path_expanded_.path(i); + const Path *path = path_expanded_.path(i); const RiseFall *rf = path->transition(this); Vertex *vertex = path->vertex(this); float path_max_slew = railToRailSlew(findSlew(vertex,rf,nullptr), rf); @@ -278,7 +277,7 @@ WritePathSpice::pathMaxTime() path_max_slew = load_slew; } } - float path_max_time = delayAsFloat(path->arrival(this)) + path_max_slew * 2.0; + float path_max_time = delayAsFloat(path->arrival()) + path_max_slew * 2.0; if (path_max_time > max_time) max_time = path_max_time; } @@ -321,7 +320,7 @@ WritePathSpice::writeInputSource() streamPrint(spice_stream_, "**************\n\n"); Stage input_stage = stageFirst(); - const PathRef *input_path = stageDrvrPath(input_stage); + const Path *input_path = stageDrvrPath(input_stage); if (input_path->isClock(this)) writeClkWaveform(); else @@ -333,9 +332,9 @@ void WritePathSpice::writeInputWaveform() { Stage input_stage = stageFirst(); - const PathRef *input_path = stageDrvrPath(input_stage); + const Path *input_path = stageDrvrPath(input_stage); const RiseFall *rf = input_path->transition(this); - TimingArc *next_arc = stageGateArc(input_stage + 1); + const TimingArc *next_arc = stageGateArc(input_stage + 1); float slew0 = findSlew(input_path, rf, next_arc); float threshold = default_library_->inputThreshold(rf); @@ -358,14 +357,14 @@ void WritePathSpice::writeClkWaveform() { Stage input_stage = stageFirst(); - const PathRef *input_path = stageDrvrPath(input_stage); - TimingArc *next_arc = stageGateArc(input_stage + 1); + const Path *input_path = stageDrvrPath(input_stage); + const TimingArc *next_arc = stageGateArc(input_stage + 1); const ClockEdge *clk_edge = input_path->clkEdge(this); const Clock *clk = clk_edge->clock(); float period = clk->period(); float time_offset = clkWaveformTimeOffset(clk); - RiseFall *rf0, *rf1; + const RiseFall *rf0, *rf1; float volt0; if (clk_edge->time() < period) { rf0 = RiseFall::rise(); @@ -403,7 +402,7 @@ WritePathSpice::findSlew(const Path *path) float WritePathSpice::findSlew(const Path *path, const RiseFall *rf, - TimingArc *next_arc) + const TimingArc *next_arc) { Vertex *vertex = path->vertex(this); return findSlew(vertex, rf, next_arc); @@ -419,9 +418,9 @@ WritePathSpice::writeMeasureStmts() streamPrint(spice_stream_, "********************\n\n"); for (Stage stage = stageFirst(); stage <= stageLast(); stage++) { - const PathRef *gate_input_path = stageGateInputPath(stage); - const PathRef *drvr_path = stageDrvrPath(stage); - const PathRef *load_path = stageLoadPath(stage); + const Path *gate_input_path = stageGateInputPath(stage); + const Path *drvr_path = stageDrvrPath(stage); + const Path *load_path = stageLoadPath(stage); if (gate_input_path) { // gate input -> gate output writeMeasureSlewStmt(stage, gate_input_path); @@ -520,7 +519,7 @@ WritePathSpice::writeGateStage(Stage stage) drvr_port->name()); writeSubcktInst(inst); - const PathRef *drvr_path = stageDrvrPath(stage); + const Path *drvr_path = stageDrvrPath(stage); const RiseFall *drvr_rf = drvr_path->transition(this); Edge *gate_edge = stageGateEdge(stage); @@ -550,7 +549,7 @@ WritePathSpice::writeGateStage(Stage stage) void WritePathSpice::writeStageParasitics(Stage stage) { - const PathRef *drvr_path = stageDrvrPath(stage); + const Path *drvr_path = stageDrvrPath(stage); DcalcAnalysisPt *dcalc_ap = drvr_path->dcalcAnalysisPt(this); ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt(); const Pin *drvr_pin = stageDrvrPin(stage); @@ -579,7 +578,7 @@ WritePathSpice::findPathCellNames() { StdStringSet path_cell_names; for (Stage stage = stageFirst(); stage <= stageLast(); stage++) { - TimingArc *arc = stageGateArc(stage); + const TimingArc *arc = stageGateArc(stage); if (arc) { LibertyCell *cell = arc->set()->libertyCell(); if (cell) { @@ -643,64 +642,62 @@ WritePathSpice::stageLoadPathIndex(Stage stage) return stage * 2 - 1; } -const PathRef * +const Path * WritePathSpice::stageGateInputPath(Stage stage) { int path_index = stageGateInputPathIndex(stage); return path_expanded_.path(path_index); } -const PathRef * +const Path * WritePathSpice::stageDrvrPath(Stage stage) { int path_index = stageDrvrPathIndex(stage); return path_expanded_.path(path_index); } -const PathRef * +const Path * WritePathSpice::stageLoadPath(Stage stage) { int path_index = stageLoadPathIndex(stage); return path_expanded_.path(path_index); } -TimingArc * +const TimingArc * WritePathSpice::stageGateArc(Stage stage) { int path_index = stageDrvrPathIndex(stage); if (path_index >= 0) - return path_expanded_.prevArc(path_index); + return path_expanded_.path(path_index)->prevArc(this); else return nullptr; } -TimingArc * +const TimingArc * WritePathSpice::stageWireArc(Stage stage) { int path_index = stageLoadPathIndex(stage); - return path_expanded_.prevArc(path_index); + return path_expanded_.path(path_index)->prevArc(this); } Edge * WritePathSpice::stageGateEdge(Stage stage) { - const PathRef *path = stageDrvrPath(stage); - TimingArc *arc = stageGateArc(stage); - return path->prevEdge(arc, this); + const Path *path = stageDrvrPath(stage); + return path->prevEdge(this); } Edge * WritePathSpice::stageWireEdge(Stage stage) { - const PathRef *path = stageLoadPath(stage); - TimingArc *arc = stageWireArc(stage); - return path->prevEdge(arc, this); + const Path *path = stageLoadPath(stage); + return path->prevEdge(this); } Pin * WritePathSpice::stageGateInputPin(Stage stage) { - const PathRef *path = stageGateInputPath(stage); + const Path *path = stageGateInputPath(stage); return path->pin(this); } @@ -714,7 +711,7 @@ WritePathSpice::stageGateInputPort(Stage stage) Pin * WritePathSpice::stageDrvrPin(Stage stage) { - const PathRef *path = stageDrvrPath(stage); + const Path *path = stageDrvrPath(stage); return path->pin(this); } @@ -728,7 +725,7 @@ WritePathSpice::stageDrvrPort(Stage stage) Pin * WritePathSpice::stageLoadPin(Stage stage) { - const PathRef *path = stageLoadPath(stage); + const Path *path = stageLoadPath(stage); return path->pin(this); } diff --git a/spice/WriteSpice.cc b/spice/WriteSpice.cc index 14de0f34..1be4e187 100644 --- a/spice/WriteSpice.cc +++ b/spice/WriteSpice.cc @@ -39,7 +39,7 @@ #include "Graph.hh" #include "search/Sim.hh" #include "Clock.hh" -#include "PathVertex.hh" +#include "Path.hh" #include "DcalcAnalysisPt.hh" #include "Bdd.hh" @@ -474,7 +474,7 @@ WriteSpice::pgPortVoltage(LibertyPgPort *pg_port) float WriteSpice::findSlew(Vertex *vertex, const RiseFall *rf, - TimingArc *next_arc) + const TimingArc *next_arc) { float slew = delayAsFloat(graph_->slew(vertex, rf, dcalc_ap_->index())); if (slew == 0.0 && next_arc) @@ -486,7 +486,7 @@ WriteSpice::findSlew(Vertex *vertex, // Look up the smallest slew axis value in the timing arc delay table. float -WriteSpice::slewAxisMinValue(TimingArc *arc) +WriteSpice::slewAxisMinValue(const TimingArc *arc) { GateTableModel *gate_model = arc->gateTableModel(dcalc_ap_); if (gate_model) { diff --git a/spice/WriteSpice.hh b/spice/WriteSpice.hh index 373a22fb..0396764c 100644 --- a/spice/WriteSpice.hh +++ b/spice/WriteSpice.hh @@ -135,8 +135,8 @@ protected: const char *spiceTrans(const RiseFall *rf); float findSlew(Vertex *vertex, const RiseFall *rf, - TimingArc *next_arc); - float slewAxisMinValue(TimingArc *arc); + const TimingArc *next_arc); + float slewAxisMinValue(const TimingArc *arc); float clkWaveformTimeOffset(const Clock *clk); void gatePortValues(const Pin *input_pin, diff --git a/spice/WriteSpice.i b/spice/WriteSpice.i index 4078cd19..727bf82b 100644 --- a/spice/WriteSpice.i +++ b/spice/WriteSpice.i @@ -33,7 +33,7 @@ %inline %{ void -write_path_spice_cmd(PathRef *path, +write_path_spice_cmd(Path *path, const char *spice_filename, const char *subckt_filename, const char *lib_subckt_filename, diff --git a/tcl/Property.tcl b/tcl/Property.tcl index 4e08b5dd..db86f055 100644 --- a/tcl/Property.tcl +++ b/tcl/Property.tcl @@ -77,7 +77,7 @@ proc get_object_property { object prop } { return [edge_property $object $prop] } elseif { $object_type == "PathEnd" } { return [path_end_property $object $prop] - } elseif { $object_type == "PathRef" } { + } elseif { $object_type == "Path" } { return [path_ref_property $object $prop] } elseif { $object_type == "TimingArcSet" } { return [timing_arc_set_property $object $prop] diff --git a/tcl/StaTclTypes.i b/tcl/StaTclTypes.i index dd3f1c63..8cda6175 100644 --- a/tcl/StaTclTypes.i +++ b/tcl/StaTclTypes.i @@ -42,7 +42,7 @@ #include "Clock.hh" #include "Corner.hh" #include "Search.hh" -#include "PathRef.hh" +#include "Path.hh" #include "search/Tag.hh" #include "PathEnd.hh" #include "SearchClass.hh" @@ -452,38 +452,40 @@ using namespace sta; Transition *tr = $1; const char *str = ""; if (tr) - str = tr->asString(); + str = tr->to_string().c_str(); Tcl_SetResult(interp, const_cast(str), TCL_STATIC); } %typemap(in) RiseFall* { int length; const char *arg = Tcl_GetStringFromObj($input, &length); - RiseFall *rf = RiseFall::find(arg); + const RiseFall *rf = RiseFall::find(arg); if (rf == nullptr) { tclArgError(interp, 2151, "Unknown rise/fall edge '%s'.", arg); return TCL_ERROR; } - $1 = rf; + // Swig is retarded and drops const on args. + $1 = const_cast(rf); } %typemap(out) RiseFall* { - const RiseFall *tr = $1; + const RiseFall *rf = $1; const char *str = ""; - if (tr) - str = tr->asString(); + if (rf) + str = rf->to_string().c_str(); Tcl_SetResult(interp, const_cast(str), TCL_STATIC); } %typemap(in) RiseFallBoth* { int length; const char *arg = Tcl_GetStringFromObj($input, &length); - RiseFallBoth *tr = RiseFallBoth::find(arg); - if (tr == nullptr) { + const RiseFallBoth *rf = RiseFallBoth::find(arg); + if (rf == nullptr) { tclArgError(interp, 2152, "Unknown transition name '%s'.", arg); return TCL_ERROR; } - $1 = tr; + // Swig is retarded and drops const on args. + $1 = const_cast(rf); } %typemap(out) RiseFallBoth* { @@ -509,9 +511,10 @@ using namespace sta; %typemap(in) TimingRole* { int length; const char *arg = Tcl_GetStringFromObj($input, &length); - TimingRole *role = TimingRole::find(arg); + const TimingRole *role = TimingRole::find(arg); if (role) - $1 = TimingRole::find(arg); + // Swig is retarded and drops const on args. + $1 = const_cast(TimingRole::find(arg)); else { tclArgError(interp, 2154, "Unknown timing role '%s'.", arg); return TCL_ERROR; @@ -519,7 +522,7 @@ using namespace sta; } %typemap(out) TimingRole* { - Tcl_SetResult(interp, const_cast($1->asString()), TCL_STATIC); + Tcl_SetResult(interp, const_cast($1->to_string().c_str()), TCL_STATIC); } %typemap(in) LogicValue { @@ -848,7 +851,8 @@ using namespace sta; %typemap(in) MinMax* { int length; char *arg = Tcl_GetStringFromObj($input, &length); - MinMax *min_max = MinMax::find(arg); + // Swig is retarded and drops const on args. + MinMax *min_max = const_cast(MinMax::find(arg)); if (min_max) $1 = min_max; else { @@ -858,17 +862,18 @@ using namespace sta; } %typemap(out) MinMax* { - Tcl_SetResult(interp, const_cast($1->asString()), TCL_STATIC); + Tcl_SetResult(interp, const_cast($1->to_string().c_str()), TCL_STATIC); } %typemap(out) MinMax* { - Tcl_SetResult(interp, const_cast($1->asString()), TCL_STATIC); + Tcl_SetResult(interp, const_cast($1->to_string().c_str()), TCL_STATIC); } %typemap(in) MinMaxAll* { int length; char *arg = Tcl_GetStringFromObj($input, &length); - MinMaxAll *min_max = MinMaxAll::find(arg); + // Swig is retarded and drops const on args. + MinMaxAll *min_max = const_cast(MinMaxAll::find(arg)); if (min_max) $1 = min_max; else { @@ -883,7 +888,8 @@ using namespace sta; if (stringEqual(arg, "NULL")) $1 = nullptr; else { - MinMaxAll *min_max = MinMaxAll::find(arg); + // Swig is retarded and drops const on args. + MinMaxAll *min_max = const_cast(MinMaxAll::find(arg)); if (min_max) $1 = min_max; else { @@ -898,15 +904,16 @@ using namespace sta; } // SetupHold is typedef'd to MinMax. -%typemap(in) SetupHold* { +%typemap(in) const SetupHold* { int length; char *arg = Tcl_GetStringFromObj($input, &length); + // Swig is retarded and drops const on args. if (stringEqual(arg, "hold") || stringEqual(arg, "min")) - $1 = MinMax::min(); + $1 = const_cast(MinMax::min()); else if (stringEqual(arg, "setup") || stringEqual(arg, "max")) - $1 = MinMax::max(); + $1 = const_cast(MinMax::max()); else { tclArgError(interp, 2162, "%s not setup, hold, min or max.", arg); return TCL_ERROR; @@ -914,18 +921,19 @@ using namespace sta; } // SetupHoldAll is typedef'd to MinMaxAll. -%typemap(in) SetupHoldAll* { +%typemap(in) const SetupHoldAll* { int length; char *arg = Tcl_GetStringFromObj($input, &length); + // Swig is retarded and drops const on args. if (stringEqual(arg, "hold") || stringEqual(arg, "min")) - $1 = SetupHoldAll::min(); + $1 = const_cast(SetupHoldAll::min()); else if (stringEqual(arg, "setup") || stringEqual(arg, "max")) - $1 = SetupHoldAll::max(); + $1 = const_cast(SetupHoldAll::max()); else if (stringEqual(arg, "setup_hold") || stringEqual(arg, "min_max")) - $1 = SetupHoldAll::all(); + $1 = const_cast(SetupHoldAll::all()); else { tclArgError(interp, 2163, "%s not setup, hold, setup_hold, min, max or min_max.", arg); return TCL_ERROR; @@ -933,10 +941,11 @@ using namespace sta; } // EarlyLate is typedef'd to MinMax. -%typemap(in) EarlyLate* { +%typemap(in) const EarlyLate* { int length; char *arg = Tcl_GetStringFromObj($input, &length); - EarlyLate *early_late = EarlyLate::find(arg); + // Swig is retarded and drops const on args. + EarlyLate *early_late = const_cast(EarlyLate::find(arg)); if (early_late) $1 = early_late; else { @@ -946,10 +955,11 @@ using namespace sta; } // EarlyLateAll is typedef'd to MinMaxAll. -%typemap(in) EarlyLateAll* { +%typemap(in) const EarlyLateAll* { int length; char *arg = Tcl_GetStringFromObj($input, &length); - EarlyLateAll *early_late = EarlyLateAll::find(arg); + // Swig is retarded and drops const on args. + EarlyLateAll *early_late = const_cast(EarlyLateAll::find(arg)); if (early_late) $1 = early_late; else { @@ -1138,17 +1148,17 @@ using namespace sta; Tcl_SetObjResult(interp, obj); } -%typemap(out) PathRefSeq* { +%typemap(out) PathSeq* { Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false); Tcl_SetObjResult(interp, obj); Tcl_Obj *list = Tcl_NewListObj(0, nullptr); - PathRefSeq *paths = $1; - PathRefSeq::Iterator path_iter(paths); + PathSeq *paths = $1; + PathSeq::Iterator path_iter(paths); while (path_iter.hasNext()) { - PathRef *path = &path_iter.next(); - PathRef *copy = new PathRef(path); - Tcl_Obj *obj = SWIG_NewInstanceObj(copy, SWIGTYPE_p_PathRef, false); + Path *path = &path_iter.next(); + Path *copy = new Path(path); + Tcl_Obj *obj = SWIG_NewInstanceObj(copy, SWIGTYPE_p_Path, false); Tcl_ListObjAppendElement(interp, list, obj); } Tcl_SetObjResult(interp, list); @@ -1354,11 +1364,10 @@ using namespace sta; Tcl_SetObjResult(interp, list); } break; - case PropertyValue::Type::type_path_refs: { + case PropertyValue::Type::type_paths: { Tcl_Obj *list = Tcl_NewListObj(0, nullptr); - for (PathRef &path : *value.pathRefs()) { - PathRef *copy = new PathRef(path); - Tcl_Obj *obj = SWIG_NewInstanceObj(copy, SWIGTYPE_p_PathRef, false); + for (const Path *path : *value.paths()) { + Tcl_Obj *obj = SWIG_NewInstanceObj(const_cast(path), SWIGTYPE_p_Path, false); Tcl_ListObjAppendElement(interp, list, obj); } Tcl_SetObjResult(interp, list); diff --git a/tcl/TclTypeHelpers.cc b/tcl/TclTypeHelpers.cc index 228ab083..e3cabbb6 100644 --- a/tcl/TclTypeHelpers.cc +++ b/tcl/TclTypeHelpers.cc @@ -161,7 +161,7 @@ tclArcDcalcArg(ArcDcalcArg &gate, obj = Tcl_NewStringObj(from_name, strlen(from_name)); Tcl_ListObjAppendElement(interp, list, obj); - const char *from_edge = arc->fromEdge()->asString(); + const char *from_edge = arc->fromEdge()->to_string().c_str(); obj = Tcl_NewStringObj(from_edge, strlen(from_edge)); Tcl_ListObjAppendElement(interp, list, obj); @@ -169,7 +169,7 @@ tclArcDcalcArg(ArcDcalcArg &gate, obj = Tcl_NewStringObj(to_name, strlen(to_name)); Tcl_ListObjAppendElement(interp, list, obj); - const char *to_edge = arc->toEdge()->asString(); + const char *to_edge = arc->toEdge()->to_string().c_str(); obj = Tcl_NewStringObj(to_edge, strlen(to_edge)); Tcl_ListObjAppendElement(interp, list, obj); diff --git a/tcl/Util.tcl b/tcl/Util.tcl index 3a3919a0..701b6d08 100644 --- a/tcl/Util.tcl +++ b/tcl/Util.tcl @@ -188,28 +188,42 @@ proc define_hidden_cmd_args { cmd arglist } { ################################################################ proc sta_warn { msg_id msg } { - variable sdc_file - variable sdc_line - if { [info exists sdc_file] } { - report_file_warn $msg_id [file tail $sdc_file] $sdc_line $msg + if { [sdc_filename] != "" } { + report_file_warn $msg_id [file tail [sdc_filename]] [sdc_file_line] $msg } else { report_warn $msg_id $msg } } proc sta_error { msg_id msg } { - variable sdc_file - variable sdc_line - if { ! [is_suppressed $msg_id] } { - if { [info exists sdc_file] } { - error "Error: [file tail $sdc_file] line $sdc_line, $msg" + if { [sdc_filename] != "" } { + error "Error: [file tail [sdc_filename]] line [sdc_file_line], $msg" } else { error "Error: $msg" } } } +proc sdc_filename {} { + return [info script] +} + +proc sdc_file_line { } { + variable include_line + for { set fr [info frame] } { $fr >= 0 } { incr fr -1 } { + set type [dict get [info frame $fr] type] + if { $type == "source" } { + return [dict get [info frame $fr] line] + } + if { $type == "proc" \ + && [lindex [dict get [info frame $fr] cmd] 0] == "include_file" } { + return $include_line + } + } + return 1 +} + proc sta_warn_error { msg_id warn_error msg } { if { $warn_error == "warn" } { sta_warn $msg_id $msg @@ -347,6 +361,112 @@ proc check_percent { cmd_arg arg } { } } +################################################################ + +set ::sta_continue_on_error 0 + +define_cmd_args "include" \ + {[-echo] filename [> filename] [>> filename]} + +# Tcl "source" command analog to support -echo and -verbose return values. +proc_redirect include { + parse_key_args "include" args keys {-encoding} flags {-echo -verbose} + if { [llength $args] != 1 } { + cmd_usage_error "include" + } + set echo [info exists flags(-echo)] + set verbose [info exists flags(-verbose)] + set filename [file nativename [lindex $args 0]] + include_file $filename $echo $verbose +} + +proc include_file { filename echo verbose } { + global sta_continue_on_error + variable include_line + + set prev_filename [info script] + if { [info exists include_line] } { + set prev_line $include_line + } + try { + # set filename/line for sta_warn/error + info script $filename + set include_line 1 + if [catch {open $filename r} stream] { + sta_error 340 "cannot open '$filename'." + } else { + if { [file extension $filename] == ".gz" } { + if { [info commands zlib] == "" } { + sta_error 339 "tcl version > 8.6 required for zlib support." + } + zlib push gunzip $stream + } + set cmd "" + set error {} + while {![eof $stream]} { + gets $stream line + if { $line != "" } { + if {$echo} { + report_line $line + } + } + append cmd $line "\n" + if { [string index $line end] != "\\" \ + && [info complete $cmd] } { + set error {} + set error_code [catch {uplevel \#0 $cmd} result] + # cmd consumed + set cmd "" + # Flush results printed outside tcl to stdout/stderr. + fflush + switch $error_code { + 0 { if { $verbose && $result != "" } { report_line $result } } + 1 { set error $result } + 2 { set error {invoked "return" outside of a proc.} } + 3 { set error {invoked "break" outside of a loop.} } + 4 { set error {invoked "continue" outside of a loop.} } + } + if { $error != {} } { + if { $sta_continue_on_error } { + # Only prepend error message with file/line once. + if { [string first "Error" $error] == 0 } { + report_line $error + } else { + report_line "Error: [file tail $filename], $include_line $error" + } + set error {} + } else { + break + } + } + } + incr include_line + } + close $stream + if { $cmd != {} } { + sta_error 341 "incomplete command at end of file." + } + if { $error != {} } { + # Only prepend error message with file/line once. + if { [string first "Error" $error] == 0 } { + error $error + } else { + error "Error: [file tail $filename], $include_line $error" + } + } + } + } finally { + if { $prev_filename != "" } { + info script $prev_filename + } + if { [info exists prev_line] } { + set include_line $prev_line + } else { + unset include_line + } + } +} + # sta namespace end } @@ -362,7 +482,7 @@ proc sta_unknown { args } { if { [llength $args] == 1 && [is_bus_subscript $args] } { return "\[$args\]" } - + # Command name abbreviation support. set ret [catch {set cmds [info commands $name*]} msg] if {[string equal $name "::"]} { @@ -371,7 +491,7 @@ proc sta_unknown { args } { if { $ret != 0 } { return -code $ret -errorcode $errorCode \ "Error in unknown while checking if \"$name\" is a unique command abbreviation: $msg." - } + } if { [llength $cmds] == 1 } { return [uplevel 1 [lreplace $args 0 0 $cmds]] } diff --git a/test/regression.tcl b/test/regression.tcl index b24bf4e1..a6a86f97 100755 --- a/test/regression.tcl +++ b/test/regression.tcl @@ -292,7 +292,7 @@ proc run_test_plain { test cmd_file log_file } { set run_file [test_run_file $test] set run_stream [open $run_file "w"] puts $run_stream "cd [file dirname $cmd_file]" - puts $run_stream "source [file tail $cmd_file]" + puts $run_stream "include [file tail $cmd_file]" if { $report_stats } { set stat_file [file normalize [test_stats_file $test]] puts $run_stream "sta::write_stats $stat_file" @@ -328,7 +328,7 @@ proc run_test_valgrind { test cmd_file log_file } { set vg_cmd_file [test_valgrind_cmd_file $test] set vg_stream [open $vg_cmd_file "w"] puts $vg_stream "cd [file dirname $cmd_file]" - puts $vg_stream "source [file tail $cmd_file]" + puts $vg_stream "include [file tail $cmd_file]" puts $vg_stream "sta::delete_all_memory" close $vg_stream diff --git a/util/MinMax.cc b/util/MinMax.cc index 27b598b8..074030bd 100644 --- a/util/MinMax.cc +++ b/util/MinMax.cc @@ -49,9 +49,9 @@ compareMax(float value1, //////////////////////////////////////////////////////////////// -MinMax MinMax::min_("min", 0, INF, std::numeric_limits::max(), compareMin); -MinMax MinMax::max_("max", 1, -INF, std::numeric_limits::min(), compareMax); -const std::array MinMax::range_{&min_, &max_}; +const MinMax MinMax::min_("min", 0, INF, std::numeric_limits::max(), compareMin); +const MinMax MinMax::max_("max", 1, -INF, std::numeric_limits::min(), compareMax); +const std::array MinMax::range_{&min_, &max_}; const std::array MinMax::range_index_{min_.index(), max_.index()}; MinMax::MinMax(const char *name, @@ -67,7 +67,7 @@ MinMax::MinMax(const char *name, { } -MinMaxAll * +const MinMaxAll * MinMax::asMinMaxAll() const { if (this == &min_) @@ -76,7 +76,7 @@ MinMax::asMinMaxAll() const return MinMaxAll::max(); } -MinMax * +const MinMax * MinMax::opposite() const { if (this == &max_) @@ -85,7 +85,7 @@ MinMax::opposite() const return &max_; } -MinMax * +const MinMax * MinMax::find(const char *min_max) { if (stringEq(min_max, "min") @@ -98,7 +98,7 @@ MinMax::find(const char *min_max) return nullptr; } -MinMax * +const MinMax * MinMax::find(int index) { if (index == min_.index()) @@ -128,14 +128,14 @@ MinMax::minMax(float value1, //////////////////////////////////////////////////////////////// -MinMaxAll MinMaxAll::min_("min", 0, {MinMax::min()}, {MinMax::min()->index()}); -MinMaxAll MinMaxAll::max_("max", 1, {MinMax::max()}, {MinMax::max()->index()}); -MinMaxAll MinMaxAll::all_("all", 2, {MinMax::min(), MinMax::max()}, +const MinMaxAll MinMaxAll::min_("min", 0, {MinMax::min()}, {MinMax::min()->index()}); +const MinMaxAll MinMaxAll::max_("max", 1, {MinMax::max()}, {MinMax::max()->index()}); +const MinMaxAll MinMaxAll::all_("all", 2, {MinMax::min(), MinMax::max()}, {MinMax::min()->index(), MinMax::max()->index()}); MinMaxAll::MinMaxAll(const char *name, int index, - std::vector range, + std::vector range, std::vector range_index) : name_(name), index_(index), @@ -144,7 +144,7 @@ MinMaxAll::MinMaxAll(const char *name, { } -MinMax * +const MinMax * MinMaxAll::asMinMax() const { if (this == &min_) @@ -165,7 +165,7 @@ MinMaxAll::matches(const MinMaxAll *min_max) const return this == &all_ || this == min_max; } -MinMaxAll * +const MinMaxAll * MinMaxAll::find(const char *min_max) { if (stringEq(min_max, "min") diff --git a/util/RiseFallMinMax.cc b/util/RiseFallMinMax.cc index 2a692ff9..abc96eb3 100644 --- a/util/RiseFallMinMax.cc +++ b/util/RiseFallMinMax.cc @@ -237,7 +237,7 @@ RiseFallMinMax::hasValue(const RiseFall *rf, const MinMax *min_max) const void RiseFallMinMax::mergeWith(RiseFallMinMax *rfmm) { - for (MinMax *min_max : MinMax::range()) { + for (const MinMax *min_max : MinMax::range()) { int mm_index = min_max->index(); for (int rf_index : RiseFall::rangeIndex()) { bool exists1 = exists_[rf_index][mm_index]; diff --git a/util/StringUtil.cc b/util/StringUtil.cc index 52de6928..b2d604f3 100644 --- a/util/StringUtil.cc +++ b/util/StringUtil.cc @@ -220,6 +220,14 @@ makeTmpString(size_t length) return tmp_str; } +char * +makeTmpString(string &str) +{ + char *tmp = makeTmpString(str.length() + 1); + strcpy(tmp, str.c_str()); + return tmp; +} + void stringDeleteCheck(const char *str) { diff --git a/util/Transition.cc b/util/Transition.cc index cf327424..5188f9f2 100644 --- a/util/Transition.cc +++ b/util/Transition.cc @@ -28,33 +28,21 @@ namespace sta { using std::max; -RiseFall RiseFall::rise_("rise", "^", 0); -RiseFall RiseFall::fall_("fall", "v", 1); -const std::array RiseFall::range_{&rise_, &fall_}; +const RiseFall RiseFall::rise_("rise", "^", 0); +const RiseFall RiseFall::fall_("fall", "v", 1); +const std::array RiseFall::range_{&rise_, &fall_}; const std::array RiseFall::range_index_{rise_.index(), fall_.index()}; RiseFall::RiseFall(const char *name, - const char *short_name, - int sdf_triple_index) : + const char *short_name, + int sdf_triple_index) : name_(name), - short_name_(stringCopy(short_name)), + short_name_(short_name), sdf_triple_index_(sdf_triple_index) { } -RiseFall::~RiseFall() -{ - stringDelete(short_name_); -} - -void -RiseFall::setShortName(const char *short_name) -{ - stringDelete(short_name_); - short_name_ = stringCopy(short_name); -} - -RiseFall * +const RiseFall * RiseFall::opposite() const { if (this == &rise_) @@ -63,7 +51,7 @@ RiseFall::opposite() const return &rise_; } -RiseFall * +const RiseFall * RiseFall::find(const char *rf_str) { if (stringEq(rf_str, rise_.name()) @@ -76,7 +64,7 @@ RiseFall::find(const char *rf_str) return nullptr; } -RiseFall * +const RiseFall * RiseFall::find(int index) { if (index == rise_.index()) @@ -85,7 +73,7 @@ RiseFall::find(int index) return &fall_; } -RiseFallBoth * +const RiseFallBoth * RiseFall::asRiseFallBoth() { if (this == &rise_) @@ -103,7 +91,7 @@ RiseFall::asRiseFallBoth() const return RiseFallBoth::fall(); } -Transition * +const Transition * RiseFall::asTransition() const { if (this == &rise_) @@ -114,29 +102,29 @@ RiseFall::asTransition() const //////////////////////////////////////////////////////////////// -RiseFallBoth RiseFallBoth::rise_("rise", "^", 0, - RiseFall::rise(), - {RiseFall::rise()}, - {RiseFall::riseIndex()}); -RiseFallBoth RiseFallBoth::fall_("fall", "v", 1, - RiseFall::fall(), - {RiseFall::fall()}, - {RiseFall::fallIndex()}); -RiseFallBoth RiseFallBoth::rise_fall_("rise_fall", "rf", 2, - nullptr, - {RiseFall::rise(), - RiseFall::fall()}, - {RiseFall::riseIndex(), - RiseFall::fallIndex()}); +const RiseFallBoth RiseFallBoth::rise_("rise", "^", 0, + RiseFall::rise(), + {RiseFall::rise()}, + {RiseFall::riseIndex()}); +const RiseFallBoth RiseFallBoth::fall_("fall", "v", 1, + RiseFall::fall(), + {RiseFall::fall()}, + {RiseFall::fallIndex()}); +const RiseFallBoth RiseFallBoth::rise_fall_("rise_fall", "rf", 2, + nullptr, + {RiseFall::rise(), + RiseFall::fall()}, + {RiseFall::riseIndex(), + RiseFall::fallIndex()}); RiseFallBoth::RiseFallBoth(const char *name, const char *short_name, int sdf_triple_index, - RiseFall *as_rise_fall, - std::vector range, + const RiseFall *as_rise_fall, + std::vector range, std::vector range_index) : name_(name), - short_name_(stringCopy(short_name)), + short_name_(short_name), sdf_triple_index_(sdf_triple_index), as_rise_fall_(as_rise_fall), range_(range), @@ -144,12 +132,7 @@ RiseFallBoth::RiseFallBoth(const char *name, { } -RiseFallBoth::~RiseFallBoth() -{ - stringDelete(short_name_); -} - -RiseFallBoth * +const RiseFallBoth * RiseFallBoth::find(const char *tr_str) { if (stringEq(tr_str, rise_.name())) @@ -179,38 +162,31 @@ RiseFallBoth::matches(const Transition *tr) const && tr == Transition::fall()); } -void -RiseFallBoth::setShortName(const char *short_name) -{ - stringDelete(short_name_); - short_name_ = stringCopy(short_name); -} - //////////////////////////////////////////////////////////////// TransitionMap Transition::transition_map_; int Transition::max_index_ = 0; // Sdf triple order defined on Sdf 3.0 spec, pg 3-17. -Transition Transition::rise_{ "^", "01", RiseFall::rise(), 0}; -Transition Transition::fall_ { "v", "10", RiseFall::fall(), 1}; -Transition Transition::tr_0Z_{"0Z", "0Z", RiseFall::rise(), 2}; -Transition Transition::tr_Z1_{"Z1", "Z1", RiseFall::rise(), 3}; -Transition Transition::tr_1Z_{"1Z", "1Z", RiseFall::fall(), 4}; -Transition Transition::tr_Z0_{"Z0", "Z0", RiseFall::fall(), 5}; -Transition Transition::tr_0X_{"0X", "0X", RiseFall::rise(), 6}; -Transition Transition::tr_X1_{"X1", "X1", RiseFall::rise(), 7}; -Transition Transition::tr_1X_{"1X", "1X", RiseFall::fall(), 8}; -Transition Transition::tr_X0_{"X0", "X0", RiseFall::fall(), 9}; -Transition Transition::tr_XZ_{"XZ", "XZ", nullptr, 10}; -Transition Transition::tr_ZX_{"ZX", "ZX", nullptr, 11}; -Transition Transition::rise_fall_{"*", "**", nullptr, -1}; +const Transition Transition::rise_{ "^", "01", RiseFall::rise(), 0}; +const Transition Transition::fall_ { "v", "10", RiseFall::fall(), 1}; +const Transition Transition::tr_0Z_{"0Z", "0Z", RiseFall::rise(), 2}; +const Transition Transition::tr_Z1_{"Z1", "Z1", RiseFall::rise(), 3}; +const Transition Transition::tr_1Z_{"1Z", "1Z", RiseFall::fall(), 4}; +const Transition Transition::tr_Z0_{"Z0", "Z0", RiseFall::fall(), 5}; +const Transition Transition::tr_0X_{"0X", "0X", RiseFall::rise(), 6}; +const Transition Transition::tr_X1_{"X1", "X1", RiseFall::rise(), 7}; +const Transition Transition::tr_1X_{"1X", "1X", RiseFall::fall(), 8}; +const Transition Transition::tr_X0_{"X0", "X0", RiseFall::fall(), 9}; +const Transition Transition::tr_XZ_{"XZ", "XZ", nullptr, 10}; +const Transition Transition::tr_ZX_{"ZX", "ZX", nullptr, 11}; +const Transition Transition::rise_fall_{"*", "**", nullptr, -1}; Transition::Transition(const char *name, const char *init_final, - RiseFall *as_rise_fall, + const RiseFall *as_rise_fall, int sdf_triple_index) : - name_(stringCopy(name)), + name_(name), init_final_(init_final), as_rise_fall_(as_rise_fall), sdf_triple_index_(sdf_triple_index) @@ -220,18 +196,13 @@ Transition::Transition(const char *name, max_index_ = max(sdf_triple_index, max_index_); } -Transition::~Transition() -{ - stringDelete(name_); -} - bool Transition::matches(const Transition *tr) const { return this == riseFall() || tr == this; } -Transition * +const Transition * Transition::find(const char *tr_str) { return transition_map_.findKey(tr_str); @@ -243,11 +214,4 @@ Transition::asRiseFallBoth() const return reinterpret_cast(as_rise_fall_); } -void -Transition::setName(const char *name) -{ - stringDelete(name_); - name_ = stringCopy(name); -} - } // namespace