Skip to content

Commit 5f65c48

Browse files
Merge pull request #10179 from The-OpenROAD-Project-staging/secure-odb-access-point-cleanup
Fix access point cleanup on instance removal
2 parents 76065ea + 46ac421 commit 5f65c48

3 files changed

Lines changed: 60 additions & 13 deletions

File tree

src/odb/src/db/dbInst.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,6 +1215,13 @@ bool dbInst::swapMaster(dbMaster* new_master_)
12151215
return false;
12161216
}
12171217

1218+
// Clear preferred APs before the ITerms are remapped to the new master.
1219+
for (const uint32_t iterm_id : inst->iterms_) {
1220+
dbITerm* iterm = (dbITerm*) block->iterm_tbl_->getPtr(iterm_id);
1221+
iterm->clearPrefAccessPoints();
1222+
}
1223+
inst->pin_access_idx_ = -1;
1224+
12181225
// remove reference to inst_hdr
12191226
_dbInstHdr* old_inst_hdr
12201227
= block->inst_hdr_hash_.find(((_dbMaster*) old_master_)->id_);
@@ -1501,16 +1508,7 @@ void dbInst::destroy(dbInst* inst_)
15011508
_dbITerm* _iterm = block->iterm_tbl_->getPtr(id);
15021509
dbITerm* iterm = (dbITerm*) _iterm;
15031510
iterm->disconnect();
1504-
if (inst_->getPinAccessIdx() >= 0) {
1505-
for (const auto& [pin, aps] : iterm->getAccessPoints()) {
1506-
for (auto ap : aps) {
1507-
_dbAccessPoint* _ap = (_dbAccessPoint*) ap;
1508-
auto [first, last] = std::ranges::remove_if(
1509-
_ap->iterms_, [id](const auto& id_in) { return id_in == id; });
1510-
_ap->iterms_.erase(first, last);
1511-
}
1512-
}
1513-
}
1511+
iterm->clearPrefAccessPoints();
15141512

15151513
// Notify when pins are deleted (assumption: pins are destroyed only when
15161514
// the related instance is destroyed)

src/odb/src/db/dbMPin.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "dbMPin.h"
55

6+
#include <cstddef>
67
#include <cstdint>
78
#include <vector>
89

@@ -16,6 +17,7 @@
1617
#include "dbMaster.h"
1718
#include "dbPolygonItr.h"
1819
#include "dbTable.h"
20+
#include "dbVector.h"
1921
#include "odb/db.h"
2022
#include "odb/dbSet.h"
2123
#include "odb/geom.h"
@@ -150,11 +152,13 @@ void dbMPin::clearPinAccess(const int pin_access_idx)
150152
{
151153
_dbMPin* pin = (_dbMPin*) this;
152154
_dbBlock* block = (_dbBlock*) getDb()->getChip()->getBlock();
153-
if (pin->aps_.size() <= pin_access_idx) {
155+
if (pin_access_idx < 0
156+
|| pin->aps_.size() <= static_cast<std::size_t>(pin_access_idx)) {
154157
return;
155158
}
156-
const auto aps = pin->aps_[pin_access_idx];
157-
for (const auto& ap : aps) {
159+
dbVector<dbId<_dbAccessPoint>> aps;
160+
aps.swap(pin->aps_[pin_access_idx]);
161+
for (const dbId<_dbAccessPoint>& ap : aps) {
158162
odb::dbAccessPoint::destroy(
159163
(odb::dbAccessPoint*) block->ap_tbl_->getPtr(ap));
160164
}

src/odb/test/cpp/TestAccessPoint.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <cstdint>
12
#include <filesystem>
23
#include <fstream>
34
#include <ios>
@@ -76,5 +77,49 @@ TEST_F(SimpleDbFixture, test_default)
7677
dbDatabase::destroy(db2);
7778
}
7879

80+
TEST_F(SimpleDbFixture, SwapMasterClearsAndInvalidatesAccessPoints)
81+
{
82+
createSimpleDB();
83+
dbBlock* block = db_->getChip()->getBlock();
84+
dbLib* lib = db_->findLib("lib1");
85+
ASSERT_NE(lib, nullptr);
86+
dbMaster* old_master = db_->findMaster("and2");
87+
ASSERT_NE(old_master, nullptr);
88+
dbMaster* new_master
89+
= createMaster2X1(lib, "and2_x4", 2000, 1000, "a", "b", "o");
90+
ASSERT_NE(new_master, nullptr);
91+
dbMTerm* old_term = old_master->findMTerm("a");
92+
ASSERT_NE(old_term, nullptr);
93+
dbMTerm* new_term = new_master->findMTerm("a");
94+
ASSERT_NE(new_term, nullptr);
95+
96+
// Create APs on both masters so a stale pin-access index would be visible.
97+
dbMPin* old_pin = dbMPin::create(old_term);
98+
ASSERT_NE(old_pin, nullptr);
99+
dbAccessPoint* old_ap = dbAccessPoint::create(block, old_pin, 0);
100+
ASSERT_NE(old_ap, nullptr);
101+
dbMPin* new_pin = dbMPin::create(new_term);
102+
ASSERT_NE(new_pin, nullptr);
103+
dbAccessPoint* new_ap = dbAccessPoint::create(block, new_pin, 0);
104+
ASSERT_NE(new_ap, nullptr);
105+
106+
dbInst* inst = dbInst::create(block, old_master, "i1");
107+
ASSERT_NE(inst, nullptr);
108+
dbITerm* iterm = inst->getITerm(old_term);
109+
ASSERT_NE(iterm, nullptr);
110+
inst->setPinAccessIdx(0);
111+
iterm->setAccessPoint(old_pin, old_ap);
112+
ASSERT_EQ(iterm->getPrefAccessPoints().size(), 1);
113+
ASSERT_EQ(iterm->getAccessPoints().at(old_pin).size(), 1);
114+
115+
ASSERT_TRUE(inst->swapMaster(new_master));
116+
dbITerm* swapped_iterm = inst->findITerm("a");
117+
ASSERT_NE(swapped_iterm, nullptr);
118+
119+
EXPECT_EQ(inst->getPinAccessIdx(), static_cast<uint32_t>(-1));
120+
EXPECT_TRUE(swapped_iterm->getPrefAccessPoints().empty());
121+
EXPECT_TRUE(swapped_iterm->getAccessPoints().empty());
122+
}
123+
79124
} // namespace
80125
} // namespace odb

0 commit comments

Comments
 (0)