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/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); 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) { 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()); diff --git a/src/sta b/src/sta index e983e15b2cb..80fbbb2945f 160000 --- a/src/sta +++ b/src/sta @@ -1 +1 @@ -Subproject commit e983e15b2cb346badf8f23725fd3914d25312c44 +Subproject commit 80fbbb2945fee2702a84e711a95a0a3bb7050f22