Skip to content

Commit 03ce502

Browse files
committed
odb: test 3dblox checker
Signed-off-by: osamahammad21 <[email protected]>
1 parent c30e3fd commit 03ce502

File tree

7 files changed

+273
-1
lines changed

7 files changed

+273
-1
lines changed

src/odb/src/db/dbMarker.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "dbVector.h"
2424
#include "odb/db.h"
2525
// User Code Begin Includes
26+
#include "dbChip.h"
2627
#include "dbCore.h"
2728
#include "odb/dbBlockCallBackObj.h"
2829
// User Code End Includes
@@ -203,6 +204,13 @@ _dbBlock* _dbMarker::getBlock() const
203204
return category->getBlock();
204205
}
205206

207+
_dbChip* _dbMarker::getChip() const
208+
{
209+
dbMarker* marker = (dbMarker*) this;
210+
_dbMarkerCategory* category = (_dbMarkerCategory*) marker->getCategory();
211+
return category->getChip();
212+
}
213+
206214
void _dbMarker::writeTR(std::ofstream& report) const
207215
{
208216
dbBlock* block = (dbBlock*) getBlock();
@@ -622,6 +630,9 @@ std::string dbMarker::getName() const
622630
case dbObstructionObj:
623631
sources += "obstruction";
624632
break;
633+
case dbChipInstObj:
634+
sources += static_cast<dbChipInst*>(src)->getName();
635+
break;
625636
default:
626637
obj->getLogger()->error(
627638
utl::ODB, 290, "Unsupported object type: {}", src->getTypeName());
@@ -762,6 +773,7 @@ std::set<dbObject*> dbMarker::getSources() const
762773
{
763774
_dbMarker* marker = (_dbMarker*) this;
764775
_dbBlock* block = marker->getBlock();
776+
_dbChip* chip = marker->getChip();
765777

766778
std::set<dbObject*> objs;
767779
if (block) {
@@ -771,6 +783,13 @@ std::set<dbObject*> dbMarker::getSources() const
771783
objs.insert(table->getObject(id));
772784
}
773785
}
786+
} else {
787+
for (const auto& [db_type, id] : marker->sources_) {
788+
dbObjectTable* table = chip->getObjectTable(db_type);
789+
if (table != nullptr && table->validObject(id)) {
790+
objs.insert(table->getObject(id));
791+
}
792+
}
774793
}
775794
return objs;
776795
}

src/odb/src/db/dbMarker.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class _dbTechLayer;
3131
class Line;
3232
class Rect;
3333
class Polygon;
34+
class _dbChip;
3435
// User Code End Classes
3536

3637
struct dbMarkerFlags
@@ -63,6 +64,7 @@ class _dbMarker : public _dbObject
6364
void collectMemInfo(MemInfo& info);
6465
// User Code Begin Methods
6566
_dbBlock* getBlock() const;
67+
_dbChip* getChip() const;
6668

6769
void populatePTree(_dbMarkerCategory::PropertyTree& tree) const;
6870
void fromPTree(const _dbMarkerCategory::PropertyTree& tree);

src/odb/src/db/dbMarkerCategory.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,14 @@ _dbBlock* _dbMarkerCategory::getBlock() const
153153
return (_dbBlock*) chip->getBlock();
154154
}
155155

156+
_dbChip* _dbMarkerCategory::getChip() const
157+
{
158+
dbMarkerCategory* category = (dbMarkerCategory*) this;
159+
_dbMarkerCategory* top_category
160+
= (_dbMarkerCategory*) category->getTopCategory();
161+
return (_dbChip*) top_category->getOwner();
162+
}
163+
156164
bool _dbMarkerCategory::hasMaxMarkerLimit() const
157165
{
158166
return max_markers_ > 0;

src/odb/src/db/dbMarkerCategory.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class _dbMarker;
2525
class _dbMarkerCategory;
2626
// User Code Begin Classes
2727
class _dbBlock;
28+
class _dbChip;
2829
// User Code End Classes
2930

3031
class _dbMarkerCategory : public _dbObject
@@ -48,6 +49,7 @@ class _dbMarkerCategory : public _dbObject
4849
bool hasMaxMarkerLimit() const;
4950

5051
_dbBlock* getBlock() const;
52+
_dbChip* getChip() const;
5153
void populatePTree(PropertyTree& tree) const;
5254
void fromPTree(const PropertyTree& tree);
5355
static void writeJSON(std::ofstream& report,

src/odb/test/cpp/BUILD

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,5 +231,22 @@ cc_test(
231231
"@googletest//:gtest_main",
232232
],
233233
)
234+
cc_test(
235+
name = "Test3DBloxChecker",
236+
srcs = [
237+
"Test3DBloxChecker.cpp",
238+
],
239+
data = [
240+
"//src/odb/test:regression_resources",
241+
],
242+
deps = [
243+
"//src/odb",
244+
"//src/tst",
245+
"//src/tst:nangate45_fixture",
246+
"//src/utl",
247+
"@googletest//:gtest",
248+
"@googletest//:gtest_main",
249+
],
250+
)
234251

235252
# TODO: more to come.

src/odb/test/cpp/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ add_executable(TestMaster TestMaster.cpp)
3636
add_executable(TestGDSIn TestGDSIn.cpp)
3737
add_executable(TestChips TestChips.cpp)
3838
add_executable(Test3DBloxParser Test3DBloxParser.cpp)
39+
add_executable(Test3DBloxChecker Test3DBloxChecker.cpp)
3940
add_executable(TestSwapMaster TestSwapMaster.cpp)
4041

4142
target_link_libraries(OdbGTests ${TEST_LIBS})
@@ -53,6 +54,7 @@ target_link_libraries(TestMaster ${TEST_LIBS})
5354
target_link_libraries(TestGDSIn ${TEST_LIBS})
5455
target_link_libraries(TestChips ${TEST_LIBS})
5556
target_link_libraries(Test3DBloxParser ${TEST_LIBS})
57+
target_link_libraries(Test3DBloxChecker ${TEST_LIBS})
5658
target_link_libraries(TestSwapMaster ${TEST_LIBS})
5759

5860
# Skip the tests from being registered here, since they are called via
@@ -64,7 +66,7 @@ target_link_libraries(TestSwapMaster ${TEST_LIBS})
6466
# directory.
6567
gtest_discover_tests(OdbGTests
6668
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/..
67-
TEST_FILTER "-TestAccessPoint.*,-TestCallBacks.*,-TestGCellGrid.*,-TestGeom.*,-TestGroup.*,-TestGuide.*,-TestJournal.*-TestLef58Properties.*,-TestMaster.*,-TestModule.*,-TestNetTrack.*,-TestChips.*,-Test3DBloxParser.*"
69+
TEST_FILTER "-TestAccessPoint.*,-TestCallBacks.*,-TestGCellGrid.*,-TestGeom.*,-TestGroup.*,-TestGuide.*,-TestJournal.*-TestLef58Properties.*,-TestMaster.*,-TestModule.*,-TestNetTrack.*,-TestChips.*,-Test3DBloxParser.*,-Test3DBloxChecker.*"
6870
)
6971

7072
add_dependencies(build_and_test
@@ -78,6 +80,7 @@ add_dependencies(build_and_test
7880
TestMaster
7981
TestChips
8082
Test3DBloxParser
83+
Test3DBloxChecker
8184
TestSwapMaster
8285
OdbGTests
8386
)
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
#include <iostream>
2+
#include <string>
3+
4+
#include "gtest/gtest.h"
5+
#include "odb/3dblox.h"
6+
#include "odb/db.h"
7+
#include "odb/geom.h"
8+
#include "tst/fixture.h"
9+
10+
namespace odb {
11+
namespace {
12+
13+
class CheckerFixture : public tst::Fixture
14+
{
15+
protected:
16+
CheckerFixture()
17+
{
18+
tech_ = dbTech::create(db_.get(), "tech");
19+
// Create a top chip
20+
top_chip_
21+
= dbChip::create(db_.get(), nullptr, "TopChip", dbChip::ChipType::HIER);
22+
top_chip_->setWidth(10000);
23+
top_chip_->setHeight(10000);
24+
top_chip_->setThickness(1000);
25+
// Create master chips
26+
chip1_ = dbChip::create(db_.get(), tech_, "Chip1", dbChip::ChipType::DIE);
27+
chip1_->setWidth(2000);
28+
chip1_->setHeight(2000);
29+
chip1_->setThickness(500);
30+
31+
chip2_ = dbChip::create(db_.get(), tech_, "Chip2", dbChip::ChipType::DIE);
32+
chip2_->setWidth(1500);
33+
chip2_->setHeight(1500);
34+
chip2_->setThickness(500);
35+
36+
chip3_ = dbChip::create(db_.get(), tech_, "Chip3", dbChip::ChipType::DIE);
37+
chip3_->setWidth(1000);
38+
chip3_->setHeight(1000);
39+
chip3_->setThickness(500);
40+
}
41+
42+
dbTech* tech_;
43+
dbChip* top_chip_;
44+
dbChip* chip1_;
45+
dbChip* chip2_;
46+
dbChip* chip3_;
47+
};
48+
49+
TEST_F(CheckerFixture, test_overlapping_chips)
50+
{
51+
// Create two overlapping chip instances
52+
auto inst1 = dbChipInst::create(top_chip_, chip1_, "inst1");
53+
inst1->setLoc(Point3D(0, 0, 0));
54+
inst1->setOrient(dbOrientType3D(dbOrientType::R0, false));
55+
56+
auto inst2 = dbChipInst::create(top_chip_, chip2_, "inst2");
57+
// Place inst2 overlapping with inst1
58+
inst2->setLoc(Point3D(1000, 1000, 0)); // Overlaps with inst1
59+
inst2->setOrient(dbOrientType3D(dbOrientType::R0, false));
60+
61+
// Run checker
62+
ThreeDBlox three_dblox(&logger_, db_.get());
63+
three_dblox.check();
64+
65+
// Verify markers were created
66+
auto category = top_chip_->findMarkerCategory("3DBlox");
67+
ASSERT_NE(category, nullptr);
68+
69+
auto overlapping_category = category->findMarkerCategory("Overlapping chips");
70+
ASSERT_NE(overlapping_category, nullptr);
71+
72+
auto markers = overlapping_category->getMarkers();
73+
EXPECT_EQ(markers.size(), 1);
74+
75+
if (markers.size() > 0) {
76+
auto marker = *markers.begin();
77+
auto sources = marker->getSources();
78+
EXPECT_EQ(sources.size(), 2);
79+
EXPECT_EQ(marker->getBBox(), odb::Rect(1000, 1000, 2000, 2000));
80+
// Verify both chip instances are in the sources
81+
bool found_inst1 = false;
82+
bool found_inst2 = false;
83+
for (auto src : sources) {
84+
if (src->getObjectType() == dbObjectType::dbChipInstObj) {
85+
auto chip_inst = static_cast<dbChipInst*>(src);
86+
if (chip_inst->getName() == "inst1") {
87+
found_inst1 = true;
88+
}
89+
if (chip_inst->getName() == "inst2") {
90+
found_inst2 = true;
91+
}
92+
}
93+
}
94+
EXPECT_TRUE(found_inst1);
95+
EXPECT_TRUE(found_inst2);
96+
}
97+
}
98+
99+
TEST_F(CheckerFixture, test_floating_chips)
100+
{
101+
// Create three chip instances: two connected, one floating
102+
auto inst1 = dbChipInst::create(top_chip_, chip1_, "inst1");
103+
inst1->setLoc(Point3D(0, 0, 0));
104+
inst1->setOrient(dbOrientType3D(dbOrientType::R0, false));
105+
106+
auto inst2 = dbChipInst::create(top_chip_, chip2_, "inst2");
107+
// Place inst2 touching inst1 (connected)
108+
inst2->setLoc(Point3D(0, 0, 500)); // Stacked on top of inst1
109+
inst2->setOrient(dbOrientType3D(dbOrientType::R0, false));
110+
111+
auto inst3 = dbChipInst::create(top_chip_, chip3_, "inst3");
112+
// Place inst3 far away (floating)
113+
inst3->setLoc(Point3D(5000, 5000, 0));
114+
inst3->setOrient(dbOrientType3D(dbOrientType::R0, false));
115+
116+
// Run checker
117+
ThreeDBlox three_dblox(&logger_, db_.get());
118+
three_dblox.check();
119+
120+
// Verify markers were created
121+
auto category = top_chip_->findMarkerCategory("3DBlox");
122+
ASSERT_NE(category, nullptr);
123+
124+
auto floating_category = category->findMarkerCategory("Floating chips");
125+
ASSERT_NE(floating_category, nullptr);
126+
127+
auto markers = floating_category->getMarkers();
128+
EXPECT_EQ(markers.size(), 1);
129+
130+
if (markers.size() > 0) {
131+
auto marker = *markers.begin();
132+
auto sources = marker->getSources();
133+
EXPECT_EQ(sources.size(), 1);
134+
// Verify the floating chip is inst3
135+
if (sources.size() > 0) {
136+
auto src = *sources.begin();
137+
EXPECT_EQ(src->getObjectType(), dbObjectType::dbChipInstObj);
138+
auto chip_inst = static_cast<dbChipInst*>(src);
139+
EXPECT_EQ(chip_inst->getName(), "inst3");
140+
}
141+
}
142+
}
143+
144+
TEST_F(CheckerFixture, test_no_violations)
145+
{
146+
// Create two non-overlapping, connected chip instances
147+
auto inst1 = dbChipInst::create(top_chip_, chip1_, "inst1");
148+
inst1->setLoc(Point3D(0, 0, 0));
149+
inst1->setOrient(dbOrientType3D(dbOrientType::R0, false));
150+
151+
auto inst2 = dbChipInst::create(top_chip_, chip2_, "inst2");
152+
// Place inst2 touching but not overlapping inst1
153+
inst2->setLoc(Point3D(0, 0, 500)); // Stacked on top
154+
inst2->setOrient(dbOrientType3D(dbOrientType::R0, false));
155+
156+
// Run checker
157+
ThreeDBlox three_dblox(&logger_, db_.get());
158+
three_dblox.check();
159+
160+
// Verify no violation markers were created
161+
auto category = top_chip_->findMarkerCategory("3DBlox");
162+
ASSERT_NE(category, nullptr);
163+
164+
auto overlapping_category = category->findMarkerCategory("Overlapping chips");
165+
if (overlapping_category != nullptr) {
166+
auto markers = overlapping_category->getMarkers();
167+
EXPECT_EQ(markers.size(), 0);
168+
}
169+
170+
auto floating_category = category->findMarkerCategory("Floating chips");
171+
if (floating_category != nullptr) {
172+
auto markers = floating_category->getMarkers();
173+
EXPECT_EQ(markers.size(), 0);
174+
}
175+
}
176+
177+
TEST_F(CheckerFixture, test_multiple_violations)
178+
{
179+
// Create a complex scenario with both overlapping and floating chips
180+
auto inst1 = dbChipInst::create(top_chip_, chip1_, "inst1");
181+
inst1->setLoc(Point3D(0, 0, 0));
182+
inst1->setOrient(dbOrientType3D(dbOrientType::R0, false));
183+
184+
auto inst2 = dbChipInst::create(top_chip_, chip2_, "inst2");
185+
// Overlapping with inst1
186+
inst2->setLoc(Point3D(500, 500, 0));
187+
inst2->setOrient(dbOrientType3D(dbOrientType::R0, false));
188+
189+
auto inst3 = dbChipInst::create(top_chip_, chip3_, "inst3");
190+
// Also overlapping with inst1
191+
inst3->setLoc(Point3D(1000, 1000, 0));
192+
inst3->setOrient(dbOrientType3D(dbOrientType::R0, false));
193+
194+
auto inst4 = dbChipInst::create(top_chip_, chip3_, "inst4");
195+
// Floating chip
196+
inst4->setLoc(Point3D(7000, 7000, 0));
197+
inst4->setOrient(dbOrientType3D(dbOrientType::R0, false));
198+
199+
// Run checker
200+
ThreeDBlox three_dblox(&logger_, db_.get());
201+
three_dblox.check();
202+
203+
// Verify markers were created
204+
auto category = top_chip_->findMarkerCategory("3DBlox");
205+
ASSERT_NE(category, nullptr);
206+
207+
// Check overlapping chips
208+
auto overlapping_category = category->findMarkerCategory("Overlapping chips");
209+
ASSERT_NE(overlapping_category, nullptr);
210+
auto overlapping_markers = overlapping_category->getMarkers();
211+
EXPECT_GT(overlapping_markers.size(), 0);
212+
213+
// Check floating chips
214+
auto floating_category = category->findMarkerCategory("Floating chips");
215+
ASSERT_NE(floating_category, nullptr);
216+
auto floating_markers = floating_category->getMarkers();
217+
EXPECT_EQ(floating_markers.size(), 1);
218+
}
219+
220+
} // namespace
221+
} // namespace odb

0 commit comments

Comments
 (0)