diff --git a/src/gui/src/chiplet3DWidget.cpp b/src/gui/src/chiplet3DWidget.cpp index 71daf61c207..c8de4493bb9 100644 --- a/src/gui/src/chiplet3DWidget.cpp +++ b/src/gui/src/chiplet3DWidget.cpp @@ -73,7 +73,7 @@ void Chiplet3DWidget::buildGeometries() return; } const odb::Cuboid global_cuboid = chip_->getCuboid(); - const odb::UnfoldedModel model(logger_, chip_); + const odb::UnfoldedModel* model = chip_->getDb()->getUnfoldedModel(); const odb::dbTransform center_transform = odb::dbTransform(odb::Point3D(-global_cuboid.xCenter(), -global_cuboid.yCenter(), @@ -98,7 +98,7 @@ void Chiplet3DWidget::buildGeometries() } int index = 0; - for (const auto& chip : model.getChips()) { + for (const auto& chip : model->getChips()) { odb::Cuboid draw_cuboid = chip.cuboid; center_transform.apply(draw_cuboid); // Color by Depth (proportional to Z) diff --git a/src/odb/include/odb/db.h b/src/odb/include/odb/db.h index 17997135754..fe47766e549 100644 --- a/src/odb/include/odb/db.h +++ b/src/odb/include/odb/db.h @@ -184,6 +184,8 @@ class dbExtControl; // Custom iterators class dbModuleBusPortModBTermItr; +class UnfoldedModel; + /////////////////////////////////////////////////////////////////////////////// /// /// A box is the element used to represent layout shapes. @@ -7550,6 +7552,9 @@ class dbDatabase : public dbObject /// dbChip* getChip(); + void constructUnfoldedModel(); + + const UnfoldedModel* getUnfoldedModel() const; //////////////////////// /// DEPRECATED //////////////////////// diff --git a/src/odb/src/3dblox/3dblox.cpp b/src/odb/src/3dblox/3dblox.cpp index b81c47472c2..887fbd24101 100644 --- a/src/odb/src/3dblox/3dblox.cpp +++ b/src/odb/src/3dblox/3dblox.cpp @@ -209,8 +209,8 @@ void ThreeDBlox::readDbx(const std::string& dbx_file) void ThreeDBlox::check() { - Checker checker(logger_); - checker.check(db_->getChip()); + Checker checker(logger_, db_); + checker.check(); } namespace { diff --git a/src/odb/src/3dblox/CMakeLists.txt b/src/odb/src/3dblox/CMakeLists.txt index ec0cc33f07b..b6423b687de 100644 --- a/src/odb/src/3dblox/CMakeLists.txt +++ b/src/odb/src/3dblox/CMakeLists.txt @@ -13,7 +13,6 @@ add_library(3dblox dbvWriter.cpp dbxWriter.cpp 3dblox.cpp - unfoldedModel.cpp checker.cpp ) diff --git a/src/odb/src/3dblox/checker.cpp b/src/odb/src/3dblox/checker.cpp index 3c9f6e8e7d8..22067fd2633 100644 --- a/src/odb/src/3dblox/checker.cpp +++ b/src/odb/src/3dblox/checker.cpp @@ -91,14 +91,18 @@ bool isValid(const UnfoldedConnection& conn) } // namespace -Checker::Checker(utl::Logger* logger) : logger_(logger) +Checker::Checker(utl::Logger* logger, dbDatabase* db) : logger_(logger), db_(db) { } -void Checker::check(dbChip* chip) +void Checker::check() { + dbChip* chip = db_->getChip(); + const UnfoldedModel* model = db_->getUnfoldedModel(); + if (model == nullptr || chip == nullptr) { + return; + } auto* top_cat = dbMarkerCategory::createOrReplace(chip, "3DBlox"); - UnfoldedModel model(logger_, chip); checkLogicalConnectivity(top_cat, model); checkFloatingChips(top_cat, model); checkOverlappingChips(top_cat, model); @@ -108,9 +112,9 @@ void Checker::check(dbChip* chip) } void Checker::checkFloatingChips(dbMarkerCategory* top_cat, - const UnfoldedModel& model) + const UnfoldedModel* model) { - const auto& chips = model.getChips(); + const auto& chips = model->getChips(); // Add one more node for "ground" (external world: package, PCB, ...) utl::UnionFind uf(chips.size() + 1); const size_t ground_node = chips.size(); @@ -120,7 +124,7 @@ void Checker::checkFloatingChips(dbMarkerCategory* top_cat, chip_map[&chips[i]] = i; } - for (const auto& conn : model.getConnections()) { + for (const auto& conn : model->getConnections()) { if (isValid(conn)) { // Case 1: Both regions exist - connect the two chips together if (conn.top_region && conn.bottom_region) { @@ -181,9 +185,9 @@ void Checker::checkFloatingChips(dbMarkerCategory* top_cat, } void Checker::checkOverlappingChips(dbMarkerCategory* top_cat, - const UnfoldedModel& model) + const UnfoldedModel* model) { - const auto& chips = model.getChips(); + const auto& chips = model->getChips(); std::vector sorted(chips.size()); std::iota(sorted.begin(), sorted.end(), 0); std::ranges::sort(sorted, [&](int a, int b) { @@ -220,10 +224,10 @@ void Checker::checkOverlappingChips(dbMarkerCategory* top_cat, } void Checker::checkInternalExtUsage(dbMarkerCategory* top_cat, - const UnfoldedModel& model) + const UnfoldedModel* model) { dbMarkerCategory* cat = nullptr; - for (const auto& chip : model.getChips()) { + for (const auto& chip : model->getChips()) { for (const auto& region : chip.regions) { if (region.isInternalExt() && !region.isUsed) { if (!cat) { @@ -246,7 +250,7 @@ void Checker::checkInternalExtUsage(dbMarkerCategory* top_cat, } void Checker::checkConnectionRegions(dbMarkerCategory* top_cat, - const UnfoldedModel& model) + const UnfoldedModel* model) { auto describe = [](const UnfoldedRegion* r, dbMarker* marker) { marker->addSource(r->region_inst); @@ -261,7 +265,7 @@ void Checker::checkConnectionRegions(dbMarkerCategory* top_cat, }; int count = 0; dbMarkerCategory* cat = nullptr; - for (const auto& conn : model.getConnections()) { + for (const auto& conn : model->getConnections()) { if (!isValid(conn)) { if (!cat) { cat = dbMarkerCategory::createOrReplace(top_cat, "Connection regions"); @@ -283,11 +287,11 @@ void Checker::checkConnectionRegions(dbMarkerCategory* top_cat, } void Checker::checkBumpPhysicalAlignment(dbMarkerCategory* top_cat, - const UnfoldedModel& model) + const UnfoldedModel* model) { dbMarkerCategory* cat = nullptr; int violation_count = 0; - for (const auto& chip : model.getChips()) { + for (const auto& chip : model->getChips()) { for (const auto& region : chip.regions) { for (const auto& bump : region.bumps) { const auto& p = bump.global_position; @@ -318,15 +322,15 @@ void Checker::checkBumpPhysicalAlignment(dbMarkerCategory* top_cat, } void Checker::checkNetConnectivity(dbMarkerCategory* top_cat, - const UnfoldedModel& model) + const UnfoldedModel* model) { } void Checker::checkLogicalConnectivity(dbMarkerCategory* top_cat, - const UnfoldedModel& model) + const UnfoldedModel* model) { std::unordered_map bump_net_map; - for (const auto& net : model.getNets()) { + for (const auto& net : model->getNets()) { for (const auto* bump : net.connected_bumps) { bump_net_map[bump] = &net; } @@ -341,7 +345,7 @@ void Checker::checkLogicalConnectivity(dbMarkerCategory* top_cat, }; dbMarkerCategory* cat = nullptr; - for (const auto& conn : model.getConnections()) { + for (const auto& conn : model->getConnections()) { if (!isValid(conn)) { continue; } diff --git a/src/odb/src/3dblox/checker.h b/src/odb/src/3dblox/checker.h index e37de374d27..404a9ec21cf 100644 --- a/src/odb/src/3dblox/checker.h +++ b/src/odb/src/3dblox/checker.h @@ -3,16 +3,17 @@ #pragma once -#include "odb/db.h" -#include "odb/unfoldedModel.h" -#include "utl/Logger.h" +namespace utl { +class Logger; +} namespace sta { class Sta; } namespace odb { -class dbChip; +class dbDatabase; +class UnfoldedModel; class dbMarkerCategory; struct MatingSurfaces @@ -25,26 +26,27 @@ struct MatingSurfaces class Checker { public: - Checker(utl::Logger* logger); + Checker(utl::Logger* logger, dbDatabase* db); ~Checker() = default; - void check(dbChip* chip); + void check(); private: void checkLogicalConnectivity(dbMarkerCategory* top_cat, - const UnfoldedModel& model); + const UnfoldedModel* model); void checkFloatingChips(dbMarkerCategory* top_cat, - const UnfoldedModel& model); + const UnfoldedModel* model); void checkOverlappingChips(dbMarkerCategory* top_cat, - const UnfoldedModel& model); + const UnfoldedModel* model); void checkInternalExtUsage(dbMarkerCategory* top_cat, - const UnfoldedModel& model); + const UnfoldedModel* model); void checkConnectionRegions(dbMarkerCategory* top_cat, - const UnfoldedModel& model); + const UnfoldedModel* model); void checkBumpPhysicalAlignment(dbMarkerCategory* top_cat, - const UnfoldedModel& model); + const UnfoldedModel* model); void checkNetConnectivity(dbMarkerCategory* top_cat, - const UnfoldedModel& model); + const UnfoldedModel* model); utl::Logger* logger_; + dbDatabase* db_; }; } // namespace odb diff --git a/src/odb/src/db/CMakeLists.txt b/src/odb/src/db/CMakeLists.txt index 4eadccb6736..3b9a4f2b6d7 100644 --- a/src/odb/src/db/CMakeLists.txt +++ b/src/odb/src/db/CMakeLists.txt @@ -86,6 +86,7 @@ add_library(db dbGroupGroundNetItr.cpp dbGDSLib.cpp dbSwapMasterSanityChecker.cpp + unfoldedModel.cpp # Generator Code Begin cpp dbAccessPoint.cpp dbBusPort.cpp diff --git a/src/odb/src/db/dbDatabase.cpp b/src/odb/src/db/dbDatabase.cpp index 6b8229cbbfe..bd616c50c78 100644 --- a/src/odb/src/db/dbDatabase.cpp +++ b/src/odb/src/db/dbDatabase.cpp @@ -59,6 +59,7 @@ #include "odb/dbDatabaseObserver.h" #include "odb/dbObject.h" #include "odb/dbStream.h" +#include "odb/unfoldedModel.h" #include "utl/Logger.h" // User Code End Includes namespace odb { @@ -207,6 +208,8 @@ _dbDatabase::_dbDatabase(_dbDatabase* db) chip_bump_inst_itr_ = new dbChipBumpInstItr(chip_bump_inst_tbl_); chip_net_itr_ = new dbChipNetItr(chip_net_tbl_); + + unfolded_model_ = nullptr; // User Code End Constructor } @@ -446,6 +449,7 @@ _dbDatabase::~_dbDatabase() delete chip_conn_itr_; delete chip_bump_inst_itr_; delete chip_net_itr_; + delete unfolded_model_; // User Code End Destructor } @@ -495,6 +499,8 @@ _dbDatabase::_dbDatabase(_dbDatabase* /* unused: db */, int id) chip_bump_inst_itr_ = new dbChipBumpInstItr(chip_bump_inst_tbl_); chip_net_itr_ = new dbChipNetItr(chip_net_tbl_); + + unfolded_model_ = nullptr; } utl::Logger* _dbDatabase::getLogger() const @@ -685,6 +691,19 @@ dbChip* dbDatabase::getChip() return (dbChip*) db->chip_tbl_->getPtr(db->chip_); } +void dbDatabase::constructUnfoldedModel() +{ + _dbDatabase* db = (_dbDatabase*) this; + delete db->unfolded_model_; + db->unfolded_model_ = new UnfoldedModel(db->logger_, getChip()); +} + +const UnfoldedModel* dbDatabase::getUnfoldedModel() const +{ + _dbDatabase* db = (_dbDatabase*) this; + return db->unfolded_model_; +} + dbTech* dbDatabase::getTech() { auto techs = getTechs(); @@ -993,6 +1012,7 @@ void dbDatabase::triggerPostRead3Dbx(dbChip* chip) for (dbDatabaseObserver* observer : db->observers_) { observer->postRead3Dbx(chip); } + constructUnfoldedModel(); } void dbDatabase::triggerPostReadDb() diff --git a/src/odb/src/db/dbDatabase.h b/src/odb/src/db/dbDatabase.h index c6c1480f9cd..dd9e6c818d9 100644 --- a/src/odb/src/db/dbDatabase.h +++ b/src/odb/src/db/dbDatabase.h @@ -282,6 +282,7 @@ class _dbNameCache; class _dbTech; class _dbLib; class _dbGDSLib; +class UnfoldedModel; // User Code End Classes class _dbDatabase : public _dbObject @@ -335,6 +336,8 @@ class _dbDatabase : public _dbObject utl::Logger* logger_; std::set observers_; + UnfoldedModel* unfolded_model_; // non-persistent object + // User Code End Fields }; dbIStream& operator>>(dbIStream& stream, _dbDatabase& obj); diff --git a/src/odb/src/3dblox/unfoldedModel.cpp b/src/odb/src/db/unfoldedModel.cpp similarity index 100% rename from src/odb/src/3dblox/unfoldedModel.cpp rename to src/odb/src/db/unfoldedModel.cpp diff --git a/src/odb/test/check_3dblox.tcl b/src/odb/test/check_3dblox.tcl index aa301d689d2..e7ea5241ada 100644 --- a/src/odb/test/check_3dblox.tcl +++ b/src/odb/test/check_3dblox.tcl @@ -25,6 +25,7 @@ set p [odb::Point3D] $p set $x1 $y1 [expr $z1 + $t1] $inst2 setLoc $p +$db constructUnfoldedModel check_3dblox check "Touching chips not floating" { get_3dblox_marker_count "Floating chips" } 0 @@ -33,6 +34,7 @@ check "Touching chips not floating" { get_3dblox_marker_count "Floating chips" } $p set $x1 $y1 [expr $z1 + $t1 + 10000] $inst2 setLoc $p +$db constructUnfoldedModel check_3dblox check "Vertical gap detected as floating" { get_3dblox_marker_count "Floating chips" } 1 @@ -42,6 +44,7 @@ set inst3 [odb::dbChipInst_create $top_chip $master1 "inst3"] $p set [expr $x1 + 10 * $w1] [expr $y1 + 10 * $h1] $z1 $inst3 setLoc $p +$db constructUnfoldedModel check_3dblox # Should find 2 sets of floating chips (inst1, inst2 and inst3 are all separate from each other) check "Multiple floating sets detected" { get_3dblox_marker_count "Floating chips" } 2 @@ -52,6 +55,7 @@ set p [odb::Point3D] $p set [expr $x1 + $w1 / 4] [expr $y1 + $h1 / 4] [expr $z1 + $t1 / 2] $inst2 setLoc $p +$db constructUnfoldedModel check_3dblox check "Partial overlap detected" { get_3dblox_marker_count "Overlapping chips" } 1 diff --git a/src/odb/test/cpp/Test3DBloxCheckerFixture.h b/src/odb/test/cpp/Test3DBloxCheckerFixture.h index a0a4c141688..783594124b8 100644 --- a/src/odb/test/cpp/Test3DBloxCheckerFixture.h +++ b/src/odb/test/cpp/Test3DBloxCheckerFixture.h @@ -49,6 +49,7 @@ class CheckerFixture : public tst::Fixture void check() { db_->setTopChip(top_chip_); + db_->constructUnfoldedModel(); ThreeDBlox three_dblox(&logger_, db_.get()); three_dblox.check(); } diff --git a/src/odb/test/cpp/Test3DBloxCheckerLogicalConn.cpp b/src/odb/test/cpp/Test3DBloxCheckerLogicalConn.cpp index 26026e9a4e6..c09265be3c8 100644 --- a/src/odb/test/cpp/Test3DBloxCheckerLogicalConn.cpp +++ b/src/odb/test/cpp/Test3DBloxCheckerLogicalConn.cpp @@ -75,6 +75,7 @@ class CheckerLogicalConnFixture : public CheckerFixture void check() { utl::Logger logger; + db_->constructUnfoldedModel(); ThreeDBlox three_dblox(&logger, db_.get()); three_dblox.check(); }