From 39305aa372bf9f90cfc103caf96dbadc6344eba9 Mon Sep 17 00:00:00 2001 From: dsengupta0628 Date: Mon, 12 Oct 2026 21:51:28 +0000 Subject: [PATCH 1/5] Update OpenSTA and adapt dbNetwork to const Net* API Bump src/sta to the 10/12 upstream OpenSTA update. Upstream OpenSTA changed Network::highestNetAbove and Network::highestConnectedNet to take (and return) const Net*. Update the dbNetwork overrides to match so they still override the base virtuals. Signed-off-by: dsengupta0628 --- src/dbSta/include/db_sta/dbNetwork.hh | 4 ++-- src/dbSta/src/dbNetwork.cc | 4 ++-- src/sta | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/dbSta/include/db_sta/dbNetwork.hh b/src/dbSta/include/db_sta/dbNetwork.hh index ba63f7d9c0b..080973da987 100644 --- a/src/dbSta/include/db_sta/dbNetwork.hh +++ b/src/dbSta/include/db_sta/dbNetwork.hh @@ -383,7 +383,7 @@ class dbNetwork : public ConcreteNetwork bool isGround(const Net* net) const override; NetPinIterator* pinIterator(const Net* net) const override; NetTermIterator* termIterator(const Net* net) const override; - const Net* highestConnectedNet(Net* net) const override; + const Net* highestConnectedNet(const Net* net) const override; // Get the flat net (odb::dbNet) with the Net*. // If the net is a hierarchical net (odb::dbModNet), return nullptr @@ -412,7 +412,7 @@ class dbNetwork : public ConcreteNetwork // This ensures parasitic externality checks in ensureParasiticNode work // correctly: net_ is always a flat net, so the comparison net != net_ // must also operate on flat nets. - Net* highestNetAbove(Net* net) const override; + const Net* highestNetAbove(const Net* net) const override; //////////////////////////////////////////////////////////////// // Edit functions diff --git a/src/dbSta/src/dbNetwork.cc b/src/dbSta/src/dbNetwork.cc index 38120302597..16300bb20a1 100644 --- a/src/dbSta/src/dbNetwork.cc +++ b/src/dbSta/src/dbNetwork.cc @@ -2743,7 +2743,7 @@ void dbNetwork::visitConnectedPins(const Net* net, // - It behaves differently to cope with the issue 9724. // - This redefinition may cause another issue later when // `Network::highestConnectedNet(Net *net)` is used elsewhere. -const Net* dbNetwork::highestConnectedNet(Net* net) const +const Net* dbNetwork::highestConnectedNet(const Net* net) const { const Net* flat = findFlatNet(net); return flat ? flat : net; @@ -5987,7 +5987,7 @@ bool dbNetwork::isPGSupply(dbNet* net) const return net->isSpecial() && net->getSigType().isSupply(); } -Net* dbNetwork::highestNetAbove(Net* net) const +const Net* dbNetwork::highestNetAbove(const Net* net) const { if (net == nullptr) { return nullptr; diff --git a/src/sta b/src/sta index e983e15b2cb..fcabb342256 160000 --- a/src/sta +++ b/src/sta @@ -1 +1 @@ -Subproject commit e983e15b2cb346badf8f23725fd3914d25312c44 +Subproject commit fcabb3422562a27142b8d094108e3d4ee336ae5e From bf9d1c0759717de43885a01bbe7331ec76e2e09a Mon Sep 17 00:00:00 2001 From: dsengupta0628 Date: Tue, 13 Oct 2026 16:05:33 +0000 Subject: [PATCH 2/5] update STA to 10/13 morning latest Signed-off-by: dsengupta0628 --- src/sta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sta b/src/sta index fcabb342256..80fbbb2945f 160000 --- a/src/sta +++ b/src/sta @@ -1 +1 @@ -Subproject commit fcabb3422562a27142b8d094108e3d4ee336ae5e +Subproject commit 80fbbb2945fee2702a84e711a95a0a3bb7050f22 From 4154f47f4e95016b76bd8dae95b137861ffb5769 Mon Sep 17 00:00:00 2001 From: dsengupta0628 Date: Tue, 13 Oct 2026 16:12:23 +0000 Subject: [PATCH 3/5] dbSta: use const Net* for highestNetAbove in unit test Upstream OpenSTA changed Network::highestNetAbove to return const Net*. Signed-off-by: dsengupta0628 --- src/dbSta/test/cpp/TestDbSta.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dbSta/test/cpp/TestDbSta.cc b/src/dbSta/test/cpp/TestDbSta.cc index 81745389bdd..452185c94fe 100644 --- a/src/dbSta/test/cpp/TestDbSta.cc +++ b/src/dbSta/test/cpp/TestDbSta.cc @@ -73,7 +73,7 @@ TEST_F(TestDbSta, TestHierarchyConnectivity) ASSERT_NE(dbnet_out2, nullptr); Net* sta_dbnet_out2 = db_network_->dbToSta(dbnet_out2); ASSERT_NE(sta_dbnet_out2, nullptr); - Net* sta_highest_net = db_network_->highestNetAbove(sta_dbnet_out2); + const Net* sta_highest_net = db_network_->highestNetAbove(sta_dbnet_out2); ASSERT_EQ(sta_highest_net, sta_dbnet_out2); odb::dbModNet* modnet_mod_out = block_->findModNet("sub_inst/mod_out"); @@ -86,7 +86,7 @@ TEST_F(TestDbSta, TestHierarchyConnectivity) ASSERT_NE(sta_modnet_out2, nullptr); // highestNetAbove on a mod net now returns the associated flat dbNet, not the // highest mod net, so that parasitic externality checks work correctly. - Net* sta_highest_modnet_out + const Net* sta_highest_modnet_out = db_network_->highestNetAbove(sta_modnet_mod_out); ASSERT_EQ(sta_highest_modnet_out, sta_dbnet_out2); From a34949f6e19f7453947f2add27e07573b6794d09 Mon Sep 17 00:00:00 2001 From: dsengupta0628 Date: Tue, 13 Oct 2026 17:48:45 +0000 Subject: [PATCH 4/5] est: make parasitic entries before threaded estimation Upstream OpenSTA removed the ConcreteParasitics lock; parasitic map entries must now exist before threads build parasitics. The OpenMP loops in estimateWireParasitics and estimateRoutesInParallel start from new, empty parasitics, so concurrent makeParasiticNetwork calls inserted into the shared maps and crashed (e.g. sky130hd/aes in GPL, jpeg in GRT). Call Parasitics::ensureParasitics() before both loops. Signed-off-by: dsengupta0628 --- src/est/include/est/EstimateParasitics.h | 3 +++ src/est/src/EstimateParasitics.cpp | 21 ++++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/est/include/est/EstimateParasitics.h b/src/est/include/est/EstimateParasitics.h index 8ee29a9895e..e0463fc2275 100644 --- a/src/est/include/est/EstimateParasitics.h +++ b/src/est/include/est/EstimateParasitics.h @@ -197,6 +197,9 @@ class EstimateParasitics : public sta::dbStaState, public ParasiticsService const std::vector>& work, int threads, bool partial); + // Make the parasitic placeholders for every driver and net so threads + // only look up sta::Parasitics entries, which are not locked. + void ensureParasiticsForThreads(); void clearParasitics(); //////////////////////////////////////////////////////////////// diff --git a/src/est/src/EstimateParasitics.cpp b/src/est/src/EstimateParasitics.cpp index bb54db1ef8f..f9f7c47db45 100644 --- a/src/est/src/EstimateParasitics.cpp +++ b/src/est/src/EstimateParasitics.cpp @@ -125,14 +125,15 @@ void EstimateParasitics::estimateRoutesInParallel( threads = std::min(threads, static_cast(work.size())); // Each net is estimated and reduced on its own and stored by net and // driver pin, so the result does not depend on the thread count or the - // order the threads run in. The parasitics store locks its own writes; - // the reduction goes through one arc delay calculator per thread, as - // sta::GraphDelayCalc does for its threads. + // order the threads run in. The parasitics store is not locked, so its + // entries are made before the threads; the reduction goes through one arc + // delay calculator per thread, as sta::GraphDelayCalc does for its threads. std::vector> calcs; calcs.reserve(threads); for (int i = 0; i < threads; ++i) { calcs.emplace_back(sta_->arcDelayCalc()->copy()); } + ensureParasiticsForThreads(); odb::dbTech* tech = block_->getTech(); #pragma omp parallel for num_threads(threads) schedule(dynamic, 64) for (int i = 0; i < static_cast(work.size()); ++i) { @@ -154,6 +155,19 @@ void EstimateParasitics::estimateRoutesInParallel( } } +void EstimateParasitics::ensureParasiticsForThreads() +{ + std::set done; + for (Scene* scene : sta_->scenes()) { + for (const sta::MinMax* min_max : sta::MinMax::range()) { + sta::Parasitics* parasitics = scene->parasitics(min_max); + if (parasitics && done.insert(parasitics).second) { + parasitics->ensureParasitics(); + } + } + } +} + void EstimateParasitics::updateGlobalRouteParasitics(odb::dbNet* db_net, grt::GRoute& route) { @@ -812,6 +826,7 @@ void EstimateParasitics::estimateWireParasitics(sta::SpefWriter* spef_writer) for (int i = 0; i < threads; ++i) { calcs.emplace_back(arc_delay_calc_->copy()); } + ensureParasiticsForThreads(); #pragma omp parallel for num_threads(threads) \ schedule(dynamic, 64) if (threads > 1) for (int i = 0; i < static_cast(work.size()); ++i) { From 2e952a1216ade37926dd05f65d9027e807434933 Mon Sep 17 00:00:00 2001 From: dsengupta0628 Date: Tue, 13 Oct 2026 18:43:08 +0000 Subject: [PATCH 5/5] rsz: expect INF slack for input with no fanout in TestResizer OpenSTA f861c627 ("required init resolves #523") reports INF slack for an input port with no fanout instead of -input_delay, since it is on no timing path. Signed-off-by: dsengupta0628 --- src/rsz/test/cpp/TestResizer.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rsz/test/cpp/TestResizer.cc b/src/rsz/test/cpp/TestResizer.cc index 56d8a763899..2194d4fd7a8 100644 --- a/src/rsz/test/cpp/TestResizer.cc +++ b/src/rsz/test/cpp/TestResizer.cc @@ -308,7 +308,8 @@ TEST_F(TestResizer, ResizeSlacksExcludeNonTimingDrivers) ASSERT_TRUE(unconstrained->hasFanout()); const sta::Slack wns = sta_->worstSlack(max); EXPECT_NEAR(wns, staTime(-0.028), tolerance); - EXPECT_NEAR(sta_->slack(isolated, max), staTime(-0.270), tolerance); + // An input with no fanout is on no timing path (OpenSTA #523). + EXPECT_TRUE(sta::fuzzyInf(sta_->slack(isolated, max))); EXPECT_TRUE(sta::fuzzyInf(sta_->slack(unconstrained, max))); const odb::dbNet* timed_net = db_network_->flatNet(constrained->pin());