-
Notifications
You must be signed in to change notification settings - Fork 891
dbSta: move levelizedDrvrVertices() out of OpenSTA fork #10352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
4003e28
44ceff3
5828eb8
a6428e1
a112df7
d6ec358
dbe5123
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,11 +36,14 @@ | |
| #include "odb/dbBlockCallBackObj.h" | ||
| #include "odb/dbObject.h" | ||
| #include "odb/dbTypes.h" | ||
| #include "search/Levelize.hh" | ||
| #include "sta/ArcDelayCalc.hh" | ||
| #include "sta/Clock.hh" | ||
| #include "sta/Delay.hh" | ||
| #include "sta/EquivCells.hh" | ||
| #include "sta/Graph.hh" | ||
| #include "sta/GraphCmp.hh" | ||
| #include "sta/GraphDelayCalc.hh" | ||
| #include "sta/Liberty.hh" | ||
| #include "sta/MinMax.hh" | ||
| #include "sta/Mode.hh" | ||
|
|
@@ -53,6 +56,7 @@ | |
| #include "sta/PortDirection.hh" | ||
| #include "sta/ReportTcl.hh" | ||
| #include "sta/Sdc.hh" | ||
| #include "sta/Search.hh" | ||
| #include "sta/Sta.hh" | ||
| #include "sta/StaMain.hh" | ||
| #include "sta/Transition.hh" | ||
|
|
@@ -288,6 +292,73 @@ void dbSta::makeSdcNetwork() | |
| sdc_network_ = new dbSdcNetwork(network_); | ||
| } | ||
|
|
||
| // Levelize::setObserver takes ownership and deletes the prior observer, | ||
| // so this composite must replicate the StaLevelizeObserver behavior that | ||
| // Sta::makeObservers installs (forwarding to Search and GraphDelayCalc) | ||
| // in addition to invalidating dbSta's cache. | ||
| class DbStaLevelizeObserver : public LevelizeObserver | ||
| { | ||
| public: | ||
| explicit DbStaLevelizeObserver(dbSta* sta) : sta_(sta) {} | ||
| void levelsChangedBefore() override | ||
| { | ||
| sta_->search()->levelsChangedBefore(); | ||
| sta_->graphDelayCalc()->levelsChangedBefore(); | ||
| sta_->invalidateLevelizedDrvrVertices(); | ||
| } | ||
| void levelChangedBefore(Vertex* vertex) override | ||
| { | ||
| sta_->search()->levelChangedBefore(vertex); | ||
| sta_->graphDelayCalc()->levelChangedBefore(vertex); | ||
| sta_->invalidateLevelizedDrvrVertices(); | ||
| } | ||
|
|
||
| private: | ||
| dbSta* sta_; | ||
| }; | ||
|
|
||
| void dbSta::makeObservers() | ||
| { | ||
| Sta::makeObservers(); | ||
| levelize_->setObserver(new DbStaLevelizeObserver(this)); | ||
| } | ||
|
Comment on lines
+320
to
+324
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hard to address without change in OpenSTA
Proper fix would be to add chaining/multi-observer API to Levelize: Then dbSta installs only the cache-invalidation observer; upstream's StaLevelizeObserver stays untouched. No replication, no drift risk. I don't know if I should add this in OpenSTA and push upstream @maliberty @precisionmoon I am trying to see if I can create a regression to catch any such drift
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @povik FYI
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would make more sense for this observer to inherit from the existing observer and then call the parent class function instead of duplicating the contents.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, and agreed in principle but blocked with current implementation: StaLevelizeObserver is file-local in sta/search/Sta.cc, no header, so dbSta can't include or subclass it as-is. Full fix needs OpenSTA changes (move StaLevelizeObserver + LevelizeObserver to public headers, add Sta::setLevelizeObserver). If you agree, I can file a PR in parallaxsw/OpenSTA, or if you add this, I can merge it too.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it makes more sense to add a set function for the levelize observer on the Sta class than to change the include search path to get access to Levelize.hh
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Absolutely agreed! The setter on Sta is much cleaner. Worth noting though LevelizeObserver itself lives in sta/search/Levelize.hh (private include path), and DbStaLevelizeObserver must subclass it. So even with sta::setLevelizeObserver, dbSta still needs OPENSTA_HOME on the include path unless we also promote LevelizeObserver to a public header (sta/include/sta/LevelizeObserver.hh). Would you be okay to add these two changes in upstream? Either I can create a PR or if you add it, I will merge it here. Thanks! |
||
|
|
||
| void dbSta::invalidateLevelizedDrvrVertices() | ||
| { | ||
| if (drvr_vertices_level_valid_) { | ||
| drvr_vertices_level_valid_ = false; | ||
| levelized_drvr_vertices_.clear(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the the clear is pointless.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The clear is required for correctness- without it, the next rebuild's push_back appends to the stale contents, returning a corrupted concatenated list. After dbStaCbk::inDbInstDestroy it would also be dangling Vertex*. Did you mean to move the clear to the rebuild path? That would definitely be cheaper invalidate (flag flip only), but at the cost of holding stale pointers in the private member until the next query. Please clarify. Thanks. |
||
| } | ||
| } | ||
|
|
||
| const VertexSeq& dbSta::levelizedDrvrVertices() | ||
| { | ||
| ensureLevelized(); | ||
| if (!drvr_vertices_level_valid_) { | ||
| Graph* g = graph(); | ||
| // Approx half of vertices are drivers. | ||
| levelized_drvr_vertices_.reserve(g->vertexCount() / 2); | ||
| Network* net = network(); | ||
| VertexIterator vertex_iter(g); | ||
| while (vertex_iter.hasNext()) { | ||
| Vertex* vertex = vertex_iter.next(); | ||
| if (vertex->isDriver(net)) { | ||
| levelized_drvr_vertices_.push_back(vertex); | ||
| } | ||
| } | ||
| VertexNameLess name_less(net); | ||
| std::ranges::sort(levelized_drvr_vertices_, | ||
| [&name_less](const Vertex* a, const Vertex* b) { | ||
| if (a->level() != b->level()) { | ||
| return a->level() < b->level(); | ||
| } | ||
| return name_less(a, b); | ||
| }); | ||
| drvr_vertices_level_valid_ = true; | ||
| } | ||
| return levelized_drvr_vertices_; | ||
| } | ||
|
|
||
|
Comment on lines
+334
to
+361
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The implementation of References
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no actionable item here |
||
| void dbSta::postReadLef(odb::dbTech* tech, odb::dbLib* library) | ||
| { | ||
| if (library) { | ||
|
|
@@ -1100,13 +1171,19 @@ void dbStaCbk::setNetwork(dbNetwork* network) | |
| void dbStaCbk::inDbInstCreate(odb::dbInst* inst) | ||
| { | ||
| sta_->makeInstanceAfter(network_->dbToSta(inst)); | ||
| // New driver vertices may exist; invalidate cached driver-vertex list. | ||
| sta_->invalidateLevelizedDrvrVertices(); | ||
| } | ||
|
|
||
| void dbStaCbk::inDbInstDestroy(odb::dbInst* inst) | ||
| { | ||
| // This is called after the iterms have been destroyed | ||
| // so it side-steps Sta::deleteInstanceAfter. | ||
| sta_->deleteLeafInstanceBefore(network_->dbToSta(inst)); | ||
| // Sta::deleteLeafInstanceBefore calls Levelize::deleteVertexBefore | ||
| // directly (bypassing the LevelizeObserver), so the dbSta cache must be | ||
| // invalidated explicitly here to avoid a dangling Vertex* on next query. | ||
| sta_->invalidateLevelizedDrvrVertices(); | ||
| } | ||
|
|
||
| void dbStaCbk::inDbModuleCreate(odb::dbModule* module) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: no header providing "sta::VertexSeq" is directly included [misc-include-cleaner]
src/dbSta/include/db_sta/dbSta.hh:12: