diff --git a/src/odb/include/odb/db.h b/src/odb/include/odb/db.h index 07a91c7262d..cab202ae7bc 100644 --- a/src/odb/include/odb/db.h +++ b/src/odb/include/odb/db.h @@ -178,6 +178,11 @@ class dbTechLayerTwoWiresForbiddenSpcRule; class dbTechLayerVoltageSpacing; class dbTechLayerWidthTableRule; class dbTechLayerWrongDirSpacingRule; +class dbUnfoldedBumpInst; +class dbUnfoldedChipInst; +class dbUnfoldedConn; +class dbUnfoldedNet; +class dbUnfoldedRegionInst; // Generator Code End ClassDeclarations // Extraction Objects @@ -186,8 +191,6 @@ class dbExtControl; // Custom iterators class dbModuleBusPortModBTermItr; -class UnfoldedModel; - /////////////////////////////////////////////////////////////////////////////// /// /// A box is the element used to represent layout shapes. @@ -7620,6 +7623,16 @@ class dbDatabase : public dbObject dbSet getChipNets() const; + dbSet getUnfoldedChipInsts() const; + + dbSet getUnfoldedRegionInsts() const; + + dbSet getUnfoldedBumpInsts() const; + + dbSet getUnfoldedConns() const; + + dbSet getUnfoldedNets() const; + // User Code Begin dbDatabase void setHierarchy(bool value); @@ -7670,7 +7683,6 @@ class dbDatabase : public dbObject void constructUnfoldedModel(); - UnfoldedModel* getUnfoldedModel() const; //////////////////////// /// DEPRECATED //////////////////////// @@ -7800,6 +7812,12 @@ class dbDatabase : public dbObject /// Translate a database-id back to a pointer. /// static dbDatabase* getDatabase(uint32_t oid); + + /// + /// Find an unfolded chip by its full path name (slash-joined chip-inst + /// names). Returns nullptr if no match. + /// + dbUnfoldedChipInst* findUnfoldedChip(const std::string& path) const; // User Code End dbDatabase }; @@ -11392,6 +11410,96 @@ class dbTechLayerWrongDirSpacingRule : public dbObject // User Code End dbTechLayerWrongDirSpacingRule }; +class dbUnfoldedBumpInst : public dbObject +{ + public: + dbChipBumpInst* getChipBumpInst() const; + + dbUnfoldedRegionInst* getParentRegion() const; + + // User Code Begin dbUnfoldedBumpInst + Point3D getGlobalPosition() const; + // User Code End dbUnfoldedBumpInst +}; + +class dbUnfoldedChipInst : public dbObject +{ + public: + const std::string& getName() const; + + dbTransform getTransform() const; + + // User Code Begin dbUnfoldedChipInst + Cuboid getCuboid() const; + + dbSet getRegions() const; + + /// + /// Return the chip-instance path that uniquely identifies this unfolded + /// chip in the folded hierarchy (top-most chip inst first, leaf last). + /// + std::vector getChipInstPath() const; + + /// + /// Find the unfolded region within this chip whose source region instance + /// matches `source`. Returns nullptr if no match. + /// + dbUnfoldedRegionInst* findRegion(dbChipRegionInst* source) const; + // User Code End dbUnfoldedChipInst +}; + +class dbUnfoldedConn : public dbObject +{ + public: + dbChipConn* getChipConn() const; + + dbUnfoldedRegionInst* getTopRegion() const; + + dbUnfoldedRegionInst* getBottomRegion() const; +}; + +class dbUnfoldedNet : public dbObject +{ + public: + dbChipNet* getChipNet() const; + + // User Code Begin dbUnfoldedNet + std::vector getConnectedBumps() const; + // User Code End dbUnfoldedNet +}; + +class dbUnfoldedRegionInst : public dbObject +{ + public: + enum class EffectiveSide + { + TOP, + BOTTOM, + INTERNAL, + INTERNAL_EXT + }; + + dbChipRegionInst* getChipRegionInst() const; + + dbUnfoldedChipInst* getParentChip() const; + + // User Code Begin dbUnfoldedRegionInst + Cuboid getCuboid() const; + + EffectiveSide getEffectiveSide() const; + void setEffectiveSide(EffectiveSide side); + + bool isTop() const; + bool isBottom() const; + bool isInternal() const; + bool isInternalExt() const; + + int getSurfaceZ() const; + + dbSet getBumps() const; + // User Code End dbUnfoldedRegionInst +}; + // Generator Code End ClassDefinition /// /// dbProperty - Boolean property. diff --git a/src/odb/include/odb/dbCompare.inc b/src/odb/include/odb/dbCompare.inc index c1f48bacd7f..d0c5b339d23 100644 --- a/src/odb/include/odb/dbCompare.inc +++ b/src/odb/include/odb/dbCompare.inc @@ -819,6 +819,46 @@ struct less = delete; }; +template <> +struct less +{ + bool operator()(const odb::dbUnfoldedBumpInst* lhs, + const odb::dbUnfoldedBumpInst* rhs) const + = delete; +}; + +template <> +struct less +{ + bool operator()(const odb::dbUnfoldedChipInst* lhs, + const odb::dbUnfoldedChipInst* rhs) const + = delete; +}; + +template <> +struct less +{ + bool operator()(const odb::dbUnfoldedConn* lhs, + const odb::dbUnfoldedConn* rhs) const + = delete; +}; + +template <> +struct less +{ + bool operator()(const odb::dbUnfoldedNet* lhs, + const odb::dbUnfoldedNet* rhs) const + = delete; +}; + +template <> +struct less +{ + bool operator()(const odb::dbUnfoldedRegionInst* lhs, + const odb::dbUnfoldedRegionInst* rhs) const + = delete; +}; + // Generator Code End Less } // namespace std diff --git a/src/odb/include/odb/dbObject.h b/src/odb/include/odb/dbObject.h index caef7aec287..79929dd504f 100644 --- a/src/odb/include/odb/dbObject.h +++ b/src/odb/include/odb/dbObject.h @@ -127,6 +127,11 @@ enum dbObjectType dbTechLayerVoltageSpacingObj, dbTechLayerWidthTableRuleObj, dbTechLayerWrongDirSpacingRuleObj, + dbUnfoldedBumpInstObj, + dbUnfoldedChipInstObj, + dbUnfoldedConnObj, + dbUnfoldedNetObj, + dbUnfoldedRegionInstObj, // Generator Code End DbObjectType // Lib Objects diff --git a/src/odb/include/odb/unfoldedModel.h b/src/odb/include/odb/unfoldedModel.h deleted file mode 100644 index 37ada4436d6..00000000000 --- a/src/odb/include/odb/unfoldedModel.h +++ /dev/null @@ -1,157 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2023-2026, The OpenROAD Authors - -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "odb/dbTransform.h" -#include "odb/dbTypes.h" -#include "odb/geom.h" -#include "utl/Logger.h" - -namespace odb { -class dbChip; -class dbChipInst; -class dbChipRegion; -class dbChipRegionInst; -class dbChipBumpInst; -class dbChipConn; -class dbChipNet; -class dbInst; -class dbMaster; -class dbAlignmentMarkerRule; - -enum class UnfoldedRegionSide -{ - TOP, - BOTTOM, - INTERNAL, - INTERNAL_EXT -}; - -struct UnfoldedChip; -struct UnfoldedRegion; - -struct UnfoldedAlignmentMarker -{ - UnfoldedChip* parent_chip = nullptr; - dbInst* inst = nullptr; - - Rect getBBox() const; - dbOrientType getOrient() const; - Point getLocation() const; -}; - -struct UnfoldedBump -{ - dbChipBumpInst* bump_inst = nullptr; - UnfoldedRegion* parent_region = nullptr; - Point3D global_position; -}; - -struct UnfoldedRegion -{ - dbChipRegionInst* region_inst = nullptr; - UnfoldedRegionSide effective_side = UnfoldedRegionSide::TOP; - Cuboid cuboid; - UnfoldedChip* parent_chip = nullptr; - std::deque bumps; - bool isUsed = false; - - int getSurfaceZ() const; - bool isTop() const { return effective_side == UnfoldedRegionSide::TOP; } - bool isBottom() const { return effective_side == UnfoldedRegionSide::BOTTOM; } - bool isInternal() const - { - return effective_side == UnfoldedRegionSide::INTERNAL; - } - bool isInternalExt() const - { - return effective_side == UnfoldedRegionSide::INTERNAL_EXT; - } -}; - -struct UnfoldedConnection -{ - dbChipConn* connection = nullptr; - UnfoldedRegion* top_region = nullptr; - UnfoldedRegion* bottom_region = nullptr; -}; - -struct UnfoldedNet -{ - dbChipNet* chip_net = nullptr; - std::vector connected_bumps; -}; - -struct UnfoldedChip -{ - std::string name; - - std::vector chip_inst_path; - Cuboid cuboid; - dbTransform transform; - - std::deque regions; - std::deque alignment_markers; - - std::unordered_map region_map; - std::unordered_map bump_inst_map; - - UnfoldedRegion* findUnfoldedRegion(dbChipRegionInst* region_inst); - UnfoldedBump* findUnfoldedBump(dbChipBumpInst* bump_inst); -}; - -class UnfoldedModel -{ - public: - UnfoldedModel(utl::Logger* logger, dbChip* chip); - - const std::deque& getChips() const { return unfolded_chips_; } - const std::vector& getConnections() const - { - return unfolded_connections_; - } - const std::vector& getNets() const { return unfolded_nets_; } - UnfoldedChip* findUnfoldedChip(const std::string& path); - const std::unordered_map>& - getAlignmentMarkerRuleMap() const - { - return alignment_marker_rule_map_; - } - const std::vector& getAlignmentMarkerRules( - dbMaster* master) const - { - return alignment_marker_rule_map_.at(master); - } - - private: - UnfoldedChip* buildUnfoldedChip(dbChipInst* chip_inst, - std::vector& path, - const dbTransform& parent_xform); - void registerUnfoldedChip(UnfoldedChip* uf_chip); - void unfoldRegions(UnfoldedChip& uf_chip, dbChipInst* inst); - void unfoldBumps(UnfoldedRegion& uf_region, const dbTransform& transform); - void unfoldAlignmentMarkers(UnfoldedChip& uf_chip); - void unfoldConnections(dbChip* chip, - const std::vector& parent_path); - void unfoldNets(dbChip* chip, const std::vector& parent_path); - - UnfoldedChip* findUnfoldedChip(const std::vector& path); - - utl::Logger* logger_; - std::deque unfolded_chips_; - std::vector unfolded_connections_; - std::vector unfolded_nets_; - std::map chip_map_; - std::unordered_map> - alignment_marker_rule_map_; -}; - -} // namespace odb diff --git a/src/odb/src/3dblox/BUILD b/src/odb/src/3dblox/BUILD index a953f593ca2..87c6c3760a3 100644 --- a/src/odb/src/3dblox/BUILD +++ b/src/odb/src/3dblox/BUILD @@ -26,6 +26,7 @@ cc_library( "//src/odb/src/lefout", "//src/sta:opensta_lib", "//src/utl", + "@spdlog", "@yaml-cpp", ], ) diff --git a/src/odb/src/3dblox/checker.cpp b/src/odb/src/3dblox/checker.cpp index 3d8efc06943..982af8e5f31 100644 --- a/src/odb/src/3dblox/checker.cpp +++ b/src/odb/src/3dblox/checker.cpp @@ -5,10 +5,8 @@ #include #include -#include #include #include -#include #include #include #include @@ -23,7 +21,7 @@ #include "odb/dbTypes.h" #include "odb/geom.h" #include "odb/geom_boost.h" // IWYU pragma: keep -#include "odb/unfoldedModel.h" +#include "spdlog/fmt/fmt.h" #include "utl/Logger.h" #include "utl/spatialIndex.h" #include "utl/unionFind.h" @@ -34,74 +32,40 @@ namespace { constexpr int kBumpMarkerHalfSize = 50; -const char* sideToString(UnfoldedRegionSide side) +// Local representation of an alignment-marker instance found while +// scanning an unfolded chip's leaf block. Holds the source dbInst plus +// its parent dbUnfoldedChipInst; bbox and orient are computed by applying +// the chip's world transform. +// +// Lives only inside checkAlignmentMarkers(). When STA-style +// dbUnfoldedInst is introduced, this becomes a filtered view over that +// table. +struct UnfoldedAlignmentMarker { - switch (side) { - case UnfoldedRegionSide::TOP: - return "TOP"; - case UnfoldedRegionSide::BOTTOM: - return "BOTTOM"; - case UnfoldedRegionSide::INTERNAL: - return "INTERNAL"; - case UnfoldedRegionSide::INTERNAL_EXT: - return "INTERNAL_EXT"; - } - return "UNKNOWN"; -} - -MatingSurfaces getMatingSurfaces(const UnfoldedConnection& conn) -{ - auto* r1 = conn.top_region; - auto* r2 = conn.bottom_region; - if (!r1 || !r2) { - return {.valid = false, .top_z = 0, .bot_z = 0}; - } - - // r1 faces down (Bottom side) and r2 faces up (Top side) -> r1 is above r2 - bool r1_down_r2_up = r1->isBottom() && r2->isTop(); - // r1 faces up (Top side) and r2 faces down (Bottom side) -> r2 is above r1 - bool r1_up_r2_down = r1->isTop() && r2->isBottom(); - - if (r1_down_r2_up == r1_up_r2_down) { - return {.valid = false, .top_z = 0, .bot_z = 0}; - } - - auto* top = r1_down_r2_up ? r1 : r2; - auto* bot = r1_down_r2_up ? r2 : r1; - return { - .valid = true, .top_z = top->getSurfaceZ(), .bot_z = bot->getSurfaceZ()}; -} - -bool isValid(const UnfoldedConnection& conn) -{ - if (!conn.top_region || !conn.bottom_region) { - return true; - } - if (!conn.top_region->cuboid.xyIntersects(conn.bottom_region->cuboid)) { - return false; - } - if (conn.top_region->isInternalExt() || conn.bottom_region->isInternalExt()) { - return std::max(conn.top_region->cuboid.zMin(), - conn.bottom_region->cuboid.zMin()) - <= std::min(conn.top_region->cuboid.zMax(), - conn.bottom_region->cuboid.zMax()); + dbUnfoldedChipInst* parent_chip = nullptr; + dbInst* inst = nullptr; + + Rect getBBox() const + { + Rect bbox = inst->getBBox()->getBox(); + parent_chip->getTransform().apply(bbox); + return bbox; } - auto surfaces = getMatingSurfaces(conn); - if (!surfaces.valid) { - return false; - } - if (surfaces.top_z < surfaces.bot_z) { - return false; + dbOrientType getOrient() const + { + dbTransform inst_xform = inst->getTransform(); + dbTransform total = inst_xform; + total.concat(parent_chip->getTransform()); + return total.getOrient(); } - return (surfaces.top_z - surfaces.bot_z) == conn.connection->getThickness(); -} +}; using AlignmentMarkerIndex = utl::SpatialIndex; std::vector collectMarkersInRect( - const std::deque& markers, + const std::vector& markers, const Rect& rect) { std::vector out; @@ -120,20 +84,25 @@ using AlignmentViolationReporter const std::string&)>; void matchMarkersBetweenChips( - const UnfoldedModel* model, + const std::unordered_map>& + rules_by_master, const std::vector& list_a, const std::vector& list_b, - const UnfoldedChip* c_a, - const UnfoldedChip* c_b, + dbUnfoldedChipInst* c_a, + dbUnfoldedChipInst* c_b, std::unordered_set& matched_markers, const AlignmentViolationReporter& report) { AlignmentMarkerIndex index_b(list_b); for (auto& [pa, marker] : list_a) { + auto rules_it = rules_by_master.find(marker->inst->getMaster()); + if (rules_it == rules_by_master.end()) { + continue; + } + const std::vector& rules = rules_it->second; + int max_tolerance = 0; - const std::vector& rules - = model->getAlignmentMarkerRules(marker->inst->getMaster()); for (const auto* rule : rules) { max_tolerance = std::max(max_tolerance, rule->getTolerance()); } @@ -154,28 +123,24 @@ void matchMarkersBetweenChips( if (b_marker->inst->getMaster() != rule->getMasterB()) { continue; } - if (odb::Point::manhattanDistance(a_marker->getBBox().center(), - b_marker->getBBox().center()) + if (Point::manhattanDistance(a_marker->getBBox().center(), + b_marker->getBBox().center()) <= rule->getTolerance()) { counterparts.insert(candidate); - // check the relative orientation if (!rule->getRelativeOrientations().empty()) { dbTransform rel_xform(a_marker->getOrient()); rel_xform.invert(); rel_xform.concat(dbTransform(b_marker->getOrient())); const dbOrientType relative_orient = rel_xform.getOrient(); - const auto& allowed_relative_orients - = rule->getRelativeOrientations(); - if (std::ranges::find(allowed_relative_orients, relative_orient) - == allowed_relative_orients.end()) { - // candidate violates the relative-orientation constraint + const auto& allowed = rule->getRelativeOrientations(); + if (std::ranges::find(allowed, relative_orient) == allowed.end()) { report(a_marker, b_marker, fmt::format( "Alignment marker on {} has mismatched " "relative orientation with counterpart on {} ({})", - b_marker->parent_chip->name, - a_marker->parent_chip->name, + b_marker->parent_chip->getName(), + a_marker->parent_chip->getName(), relative_orient.getString())); } } @@ -190,9 +155,9 @@ void matchMarkersBetweenChips( fmt::format( "Alignment marker on {} has {} counterparts on {} within " "tolerance", - marker->parent_chip->name, + marker->parent_chip->getName(), counterparts.size(), - c_b->name)); + c_b->getName())); } } for (const auto& counterpart : counterparts) { @@ -201,6 +166,71 @@ void matchMarkersBetweenChips( } } } + +const char* sideToString(dbUnfoldedRegionInst::EffectiveSide side) +{ + switch (side) { + case dbUnfoldedRegionInst::EffectiveSide::TOP: + return "TOP"; + case dbUnfoldedRegionInst::EffectiveSide::BOTTOM: + return "BOTTOM"; + case dbUnfoldedRegionInst::EffectiveSide::INTERNAL: + return "INTERNAL"; + case dbUnfoldedRegionInst::EffectiveSide::INTERNAL_EXT: + return "INTERNAL_EXT"; + } + return "UNKNOWN"; +} + +MatingSurfaces getMatingSurfaces(dbUnfoldedConn* conn) +{ + dbUnfoldedRegionInst* r1 = conn->getTopRegion(); + dbUnfoldedRegionInst* r2 = conn->getBottomRegion(); + if (!r1 || !r2) { + return {.valid = false, .top_z = 0, .bot_z = 0}; + } + + // r1 faces down (Bottom side) and r2 faces up (Top side) -> r1 is above r2 + bool r1_down_r2_up = r1->isBottom() && r2->isTop(); + // r1 faces up (Top side) and r2 faces down (Bottom side) -> r2 is above r1 + bool r1_up_r2_down = r1->isTop() && r2->isBottom(); + + if (r1_down_r2_up == r1_up_r2_down) { + return {.valid = false, .top_z = 0, .bot_z = 0}; + } + + auto* top = r1_down_r2_up ? r1 : r2; + auto* bot = r1_down_r2_up ? r2 : r1; + return { + .valid = true, .top_z = top->getSurfaceZ(), .bot_z = bot->getSurfaceZ()}; +} + +bool isValid(dbUnfoldedConn* conn) +{ + auto* r1 = conn->getTopRegion(); + auto* r2 = conn->getBottomRegion(); + if (!r1 || !r2) { + return true; + } + if (!r1->getCuboid().xyIntersects(r2->getCuboid())) { + return false; + } + if (r1->isInternalExt() || r2->isInternalExt()) { + return std::max(r1->getCuboid().zMin(), r2->getCuboid().zMin()) + <= std::min(r1->getCuboid().zMax(), r2->getCuboid().zMax()); + } + + auto surfaces = getMatingSurfaces(conn); + if (!surfaces.valid) { + return false; + } + if (surfaces.top_z < surfaces.bot_z) { + return false; + } + return (surfaces.top_z - surfaces.bot_z) + == conn->getChipConn()->getThickness(); +} + } // namespace Checker::Checker(utl::Logger* logger, dbDatabase* db) : logger_(logger), db_(db) @@ -210,49 +240,51 @@ Checker::Checker(utl::Logger* logger, dbDatabase* db) : logger_(logger), db_(db) void Checker::check() { dbChip* chip = db_->getChip(); - const UnfoldedModel* model = db_->getUnfoldedModel(); - if (model == nullptr || chip == nullptr) { + if (chip == nullptr) { return; } auto* top_cat = dbMarkerCategory::createOrReplace(chip, "3DBlox"); - checkLogicalConnectivity(top_cat, model); - checkFloatingChips(top_cat, model); - checkOverlappingChips(top_cat, model); - checkInternalExtUsage(top_cat, model); - checkConnectionRegions(top_cat, model); - checkBumpPhysicalAlignment(top_cat, model); - checkAlignmentMarkers(top_cat, model); + checkLogicalConnectivity(top_cat); + checkFloatingChips(top_cat); + checkOverlappingChips(top_cat); + checkInternalExtUsage(top_cat); + checkConnectionRegions(top_cat); + checkBumpPhysicalAlignment(top_cat); + checkAlignmentMarkers(top_cat); } -void Checker::checkFloatingChips(dbMarkerCategory* top_cat, - const UnfoldedModel* model) +void Checker::checkFloatingChips(dbMarkerCategory* top_cat) { - const auto& chips = model->getChips(); + std::vector chips; + for (dbUnfoldedChipInst* chip : db_->getUnfoldedChipInsts()) { + chips.push_back(chip); + } // Add one more node for "ground" (external world: package, PCB, ...) utl::UnionFind uf(chips.size() + 1); const size_t ground_node = chips.size(); - std::unordered_map chip_map; + std::unordered_map chip_map; for (size_t i = 0; i < chips.size(); ++i) { - chip_map[&chips[i]] = i; + chip_map[chips[i]] = i; } - for (const auto& conn : model->getConnections()) { + for (dbUnfoldedConn* conn : db_->getUnfoldedConns()) { if (isValid(conn)) { // Case 1: Both regions exist - connect the two chips together - if (conn.top_region && conn.bottom_region) { - auto it1 = chip_map.find(conn.top_region->parent_chip); - auto it2 = chip_map.find(conn.bottom_region->parent_chip); + if (conn->getTopRegion() && conn->getBottomRegion()) { + auto it1 = chip_map.find(conn->getTopRegion()->getParentChip()); + auto it2 = chip_map.find(conn->getBottomRegion()->getParentChip()); if (it1 != chip_map.end() && it2 != chip_map.end()) { uf.unite(it1->second, it2->second); } } // Case 2: Virtual connection (one region is null) - connect chip to // ground - else if (conn.top_region || conn.bottom_region) { - const UnfoldedRegion* region - = conn.top_region ? conn.top_region : conn.bottom_region; - auto it = chip_map.find(region->parent_chip); + else if (conn->getTopRegion() || conn->getBottomRegion()) { + dbUnfoldedRegionInst* region = conn->getTopRegion() + ? conn->getTopRegion() + : conn->getBottomRegion(); + auto it = chip_map.find(region->getParentChip()); if (it != chip_map.end()) { uf.unite(it->second, ground_node); } @@ -260,9 +292,9 @@ void Checker::checkFloatingChips(dbMarkerCategory* top_cat, } } - std::vector> groups(chips.size() + 1); + std::vector> groups(chips.size() + 1); for (size_t i = 0; i < chips.size(); ++i) { - groups[uf.find(i)].push_back(&chips[i]); + groups[uf.find(i)].push_back(chips[i]); } auto ground_leader = uf.find(ground_node); const bool ground_empty = groups[ground_leader].empty(); @@ -292,34 +324,35 @@ void Checker::checkFloatingChips(dbMarkerCategory* top_cat, // null-deref crash. if (auto* marker = dbMarker::create(cat)) { for (auto* chip : group) { - marker->addShape(chip->cuboid); - marker->addSource(chip->chip_inst_path.back()); + marker->addShape(chip->getCuboid()); + marker->addSource(chip->getChipInstPath().back()); } - marker->setComment("Isolated chip set starting with " + group[0]->name); + marker->setComment("Isolated chip set starting with " + + group[0]->getName()); } } } } -void Checker::checkOverlappingChips(dbMarkerCategory* top_cat, - const UnfoldedModel* model) +void Checker::checkOverlappingChips(dbMarkerCategory* top_cat) { - 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) { - return chips[a].cuboid.xMin() < chips[b].cuboid.xMin(); + std::vector chips; + for (dbUnfoldedChipInst* chip : db_->getUnfoldedChipInsts()) { + chips.push_back(chip); + } + std::ranges::sort(chips, [](dbUnfoldedChipInst* a, dbUnfoldedChipInst* b) { + return a->getCuboid().xMin() < b->getCuboid().xMin(); }); - std::vector> overlaps; - for (size_t i = 0; i < sorted.size(); ++i) { - auto* c1 = &chips[sorted[i]]; - for (size_t j = i + 1; j < sorted.size(); ++j) { - auto* c2 = &chips[sorted[j]]; - if (c2->cuboid.xMin() >= c1->cuboid.xMax()) { + std::vector> overlaps; + for (size_t i = 0; i < chips.size(); ++i) { + auto* c1 = chips[i]; + for (size_t j = i + 1; j < chips.size(); ++j) { + auto* c2 = chips[j]; + if (c2->getCuboid().xMin() >= c1->getCuboid().xMax()) { break; } - if (c1->cuboid.overlaps(c2->cuboid)) { + if (c1->getCuboid().overlaps(c2->getCuboid())) { overlaps.emplace_back(c1, c2); } } @@ -330,24 +363,35 @@ void Checker::checkOverlappingChips(dbMarkerCategory* top_cat, logger_->warn(utl::ODB, 156, "Found {} overlapping chips", overlaps.size()); for (const auto& [inst1, inst2] : overlaps) { if (auto* marker = dbMarker::create(cat)) { - auto intersection = inst1->cuboid.intersect(inst2->cuboid); + auto intersection = inst1->getCuboid().intersect(inst2->getCuboid()); marker->addShape(intersection); - marker->addSource(inst1->chip_inst_path.back()); - marker->addSource(inst2->chip_inst_path.back()); - marker->setComment( - fmt::format("Chips {} and {} overlap", inst1->name, inst2->name)); + marker->addSource(inst1->getChipInstPath().back()); + marker->addSource(inst2->getChipInstPath().back()); + marker->setComment(fmt::format( + "Chips {} and {} overlap", inst1->getName(), inst2->getName())); } } } } -void Checker::checkInternalExtUsage(dbMarkerCategory* top_cat, - const UnfoldedModel* model) +void Checker::checkInternalExtUsage(dbMarkerCategory* top_cat) { + // The struct model maintained an isUsed bit on each region; in the + // dbObject model we derive it here on demand by scanning connections. + std::unordered_set used; + for (dbUnfoldedConn* conn : db_->getUnfoldedConns()) { + if (auto* r = conn->getTopRegion(); r && r->isInternalExt()) { + used.insert(r); + } + if (auto* r = conn->getBottomRegion(); r && r->isInternalExt()) { + used.insert(r); + } + } + dbMarkerCategory* cat = nullptr; - for (const auto& chip : model->getChips()) { - for (const auto& region : chip.regions) { - if (region.isInternalExt() && !region.isUsed) { + for (dbUnfoldedChipInst* chip : db_->getUnfoldedChipInsts()) { + for (dbUnfoldedRegionInst* region : chip->getRegions()) { + if (region->isInternalExt() && !used.contains(region)) { if (!cat) { cat = dbMarkerCategory::createOrReplace(top_cat, "Unused internal_ext"); @@ -355,46 +399,45 @@ void Checker::checkInternalExtUsage(dbMarkerCategory* top_cat, logger_->warn(utl::ODB, 464, "Region {} is internal_ext but unused", - region.region_inst->getChipRegion()->getName()); + region->getChipRegionInst()->getChipRegion()->getName()); if (auto* marker = dbMarker::create(cat)) { - marker->addSource(region.region_inst); - marker->addShape(region.cuboid); - marker->setComment( - fmt::format("Unused internal_ext region: {}", - region.region_inst->getChipRegion()->getName())); + marker->addSource(region->getChipRegionInst()); + marker->addShape(region->getCuboid()); + marker->setComment(fmt::format( + "Unused internal_ext region: {}", + region->getChipRegionInst()->getChipRegion()->getName())); } } } } } -void Checker::checkConnectionRegions(dbMarkerCategory* top_cat, - const UnfoldedModel* model) +void Checker::checkConnectionRegions(dbMarkerCategory* top_cat) { - auto describe = [](const UnfoldedRegion* r, dbMarker* marker) { - marker->addSource(r->region_inst); - marker->addShape(Rect(r->cuboid.xMin(), - r->cuboid.yMin(), - r->cuboid.xMax(), - r->cuboid.yMax())); + auto describe = [](dbUnfoldedRegionInst* r, dbMarker* marker) { + const Cuboid cuboid = r->getCuboid(); + marker->addSource(r->getChipRegionInst()); + marker->addShape( + Rect(cuboid.xMin(), cuboid.yMin(), cuboid.xMax(), cuboid.yMax())); return fmt::format("{}/{} (faces {})", - r->parent_chip->name, - r->region_inst->getChipRegion()->getName(), - sideToString(r->effective_side)); + r->getParentChip()->getName(), + r->getChipRegionInst()->getChipRegion()->getName(), + sideToString(r->getEffectiveSide())); }; int count = 0; dbMarkerCategory* cat = nullptr; - for (const auto& conn : model->getConnections()) { + for (dbUnfoldedConn* conn : db_->getUnfoldedConns()) { if (!isValid(conn)) { if (!cat) { cat = dbMarkerCategory::createOrReplace(top_cat, "Connection regions"); } if (auto* marker = dbMarker::create(cat)) { - marker->addSource(conn.connection); - std::string msg = fmt::format("Invalid connection {}: {} to {}", - conn.connection->getName(), - describe(conn.top_region, marker), - describe(conn.bottom_region, marker)); + marker->addSource(conn->getChipConn()); + std::string msg + = fmt::format("Invalid connection {}: {} to {}", + conn->getChipConn()->getName(), + describe(conn->getTopRegion(), marker), + describe(conn->getBottomRegion(), marker)); marker->setComment(msg); logger_->warn(utl::ODB, 207, msg); } @@ -406,16 +449,16 @@ void Checker::checkConnectionRegions(dbMarkerCategory* top_cat, } } -void Checker::checkBumpPhysicalAlignment(dbMarkerCategory* top_cat, - const UnfoldedModel* model) +void Checker::checkBumpPhysicalAlignment(dbMarkerCategory* top_cat) { dbMarkerCategory* cat = nullptr; int violation_count = 0; - for (const auto& chip : model->getChips()) { - for (const auto& region : chip.regions) { - for (const auto& bump : region.bumps) { - const auto& p = bump.global_position; - if (!region.cuboid.getEnclosingRect().intersects({p.x(), p.y()})) { + for (dbUnfoldedChipInst* chip : db_->getUnfoldedChipInsts()) { + for (dbUnfoldedRegionInst* region : chip->getRegions()) { + for (dbUnfoldedBumpInst* bump : region->getBumps()) { + const Point3D p = bump->getGlobalPosition(); + if (!region->getCuboid().getEnclosingRect().intersects( + {p.x(), p.y()})) { violation_count++; if (!cat) { cat = dbMarkerCategory::createOrReplace(top_cat, "Bump Alignment"); @@ -424,14 +467,14 @@ void Checker::checkBumpPhysicalAlignment(dbMarkerCategory* top_cat, // max_markers_ limit; skip the addSource/addShape/setComment // chain to avoid a null-deref crash in that case. if (auto* marker = dbMarker::create(cat)) { - marker->addSource(bump.bump_inst); + marker->addSource(bump->getChipBumpInst()); marker->addShape(Rect(p.x() - kBumpMarkerHalfSize, p.y() - kBumpMarkerHalfSize, p.x() + kBumpMarkerHalfSize, p.y() + kBumpMarkerHalfSize)); - marker->setComment( - fmt::format("Bump is outside its parent region {}", - region.region_inst->getChipRegion()->getName())); + marker->setComment(fmt::format( + "Bump is outside its parent region {}", + region->getChipRegionInst()->getChipRegion()->getName())); } } } @@ -445,14 +488,46 @@ void Checker::checkBumpPhysicalAlignment(dbMarkerCategory* top_cat, } } -void Checker::checkNetConnectivity(dbMarkerCategory* top_cat, - const UnfoldedModel* model) +void Checker::checkNetConnectivity(dbMarkerCategory* top_cat) { } -void Checker::checkAlignmentMarkers(dbMarkerCategory* top_cat, - const UnfoldedModel* model) +void Checker::checkAlignmentMarkers(dbMarkerCategory* top_cat) { + // Build the per-master rule index. Local to this check; alignment-marker + // rules are queried only here, so there's no point persisting it. + std::unordered_map> + rules_by_master; + for (dbAlignmentMarkerRule* rule : db_->getAlignmentMarkerRules()) { + rules_by_master[rule->getMasterA()].push_back(rule); + if (rule->getMasterB() != rule->getMasterA()) { + rules_by_master[rule->getMasterB()].push_back(rule); + } + } + if (rules_by_master.empty()) { + return; + } + + // Materialize the per-chip marker lists by walking each unfolded chip's + // leaf block and filtering by master against the rule index. + std::unordered_map> + markers; + for (dbUnfoldedChipInst* chip : db_->getUnfoldedChipInsts()) { + std::vector path = chip->getChipInstPath(); + if (path.empty()) { + continue; + } + dbBlock* block = path.back()->getMasterChip()->getBlock(); + if (block == nullptr) { + continue; + } + for (dbInst* inst : block->getInsts()) { + if (rules_by_master.contains(inst->getMaster())) { + markers[chip].push_back({.parent_chip = chip, .inst = inst}); + } + } + } + std::unordered_set matched_markers; dbMarkerCategory* cat = nullptr; int violation_count = 0; @@ -463,6 +538,9 @@ void Checker::checkAlignmentMarkers(dbMarkerCategory* top_cat, cat = dbMarkerCategory::createOrReplace(top_cat, "Alignment Markers"); } auto* marker = dbMarker::create(cat); + if (marker == nullptr) { + return; + } // TODO: Add sources correctly marker->addShape(m->getBBox()); if (other) { @@ -472,42 +550,49 @@ void Checker::checkAlignmentMarkers(dbMarkerCategory* top_cat, violation_count++; }; - for (const auto& conn : model->getConnections()) { + for (dbUnfoldedConn* conn : db_->getUnfoldedConns()) { if (!isValid(conn)) { continue; } - const UnfoldedRegion* ra = conn.top_region; - const UnfoldedRegion* rb = conn.bottom_region; + dbUnfoldedRegionInst* ra = conn->getTopRegion(); + dbUnfoldedRegionInst* rb = conn->getBottomRegion(); if (!ra || !rb) { continue; } - const UnfoldedChip* c_a = ra->parent_chip; - const UnfoldedChip* c_b = rb->parent_chip; + dbUnfoldedChipInst* c_a = ra->getParentChip(); + dbUnfoldedChipInst* c_b = rb->getParentChip(); if (c_a == c_b) { continue; } - if (c_a->alignment_markers.empty() && c_b->alignment_markers.empty()) { + auto a_it = markers.find(c_a); + auto b_it = markers.find(c_b); + if (a_it == markers.end() && b_it == markers.end()) { continue; } - const Rect overlap = ra->cuboid.getEnclosingRect().intersect( - rb->cuboid.getEnclosingRect()); - auto list_a = collectMarkersInRect(c_a->alignment_markers, overlap); - auto list_b = collectMarkersInRect(c_b->alignment_markers, overlap); + const Rect overlap = ra->getCuboid().getEnclosingRect().intersect( + rb->getCuboid().getEnclosingRect()); + auto list_a = (a_it != markers.end()) + ? collectMarkersInRect(a_it->second, overlap) + : std::vector{}; + auto list_b = (b_it != markers.end()) + ? collectMarkersInRect(b_it->second, overlap) + : std::vector{}; if (list_a.empty() && list_b.empty()) { continue; } matchMarkersBetweenChips( - model, list_a, list_b, c_a, c_b, matched_markers, report); + rules_by_master, list_a, list_b, c_a, c_b, matched_markers, report); } - for (const auto& chip : model->getChips()) { - for (const auto& marker : chip.alignment_markers) { - if (matched_markers.find(&marker) == matched_markers.end()) { + + for (const auto& [chip, chip_markers] : markers) { + for (const auto& marker : chip_markers) { + if (!matched_markers.contains(&marker)) { report(&marker, nullptr, fmt::format("Alignment marker on {} has no counterpart", - chip.name)); + chip->getName())); } } } @@ -520,75 +605,78 @@ void Checker::checkAlignmentMarkers(dbMarkerCategory* top_cat, } } -void Checker::checkLogicalConnectivity(dbMarkerCategory* top_cat, - const UnfoldedModel* model) +void Checker::checkLogicalConnectivity(dbMarkerCategory* top_cat) { - std::unordered_map bump_net_map; - for (const auto& net : model->getNets()) { - for (const auto* bump : net.connected_bumps) { - bump_net_map[bump] = &net; + std::unordered_map bump_net_map; + for (dbUnfoldedNet* net : db_->getUnfoldedNets()) { + for (dbUnfoldedBumpInst* bump : net->getConnectedBumps()) { + bump_net_map[bump] = net; } } - auto get_net_name = [&](const UnfoldedBump* bump) -> std::string { + auto get_net_name = [&](dbUnfoldedBumpInst* bump) -> std::string { auto it = bump_net_map.find(bump); if (it != bump_net_map.end()) { - return it->second->chip_net->getName(); + return it->second->getChipNet()->getName(); } return "defines no net"; }; dbMarkerCategory* cat = nullptr; - for (const auto& conn : model->getConnections()) { + for (dbUnfoldedConn* conn : db_->getUnfoldedConns()) { if (!isValid(conn)) { continue; } - if (!conn.top_region || !conn.bottom_region) { + dbUnfoldedRegionInst* top_region = conn->getTopRegion(); + dbUnfoldedRegionInst* bot_region = conn->getBottomRegion(); + if (!top_region || !bot_region) { continue; } - std::map bot_bumps; - for (const auto& bump : conn.bottom_region->bumps) { - Point p(bump.global_position.x(), bump.global_position.y()); - bot_bumps[p] = ≎ + std::map bot_bumps; + for (dbUnfoldedBumpInst* bump : bot_region->getBumps()) { + const Point3D pos = bump->getGlobalPosition(); + bot_bumps[Point(pos.x(), pos.y())] = bump; } - for (const auto& top_bump : conn.top_region->bumps) { - Point p(top_bump.global_position.x(), top_bump.global_position.y()); + for (dbUnfoldedBumpInst* top_bump : top_region->getBumps()) { + const Point3D top_pos = top_bump->getGlobalPosition(); + const Point p(top_pos.x(), top_pos.y()); auto it = bot_bumps.find(p); - if (it != bot_bumps.end()) { - const UnfoldedBump* bot_bump = it->second; + if (it == bot_bumps.end()) { + continue; + } + dbUnfoldedBumpInst* bot_bump = it->second; - // Check logical connectivity - auto top_net_it = bump_net_map.find(&top_bump); - auto bot_net_it = bump_net_map.find(bot_bump); + // Check logical connectivity + auto top_net_it = bump_net_map.find(top_bump); + auto bot_net_it = bump_net_map.find(bot_bump); - const UnfoldedNet* top_net - = top_net_it != bump_net_map.end() ? top_net_it->second : nullptr; - const UnfoldedNet* bot_net - = bot_net_it != bump_net_map.end() ? bot_net_it->second : nullptr; + dbUnfoldedNet* top_net + = top_net_it != bump_net_map.end() ? top_net_it->second : nullptr; + dbUnfoldedNet* bot_net + = bot_net_it != bump_net_map.end() ? bot_net_it->second : nullptr; - if (top_net != bot_net) { - if (!cat) { - cat = dbMarkerCategory::createOrReplace(top_cat, - "Logical Connectivity"); - } - if (auto* marker = dbMarker::create(cat)) { - marker->addSource(top_bump.bump_inst); - marker->addSource(bot_bump->bump_inst); - marker->addShape(conn.top_region->cuboid.intersect( - conn.bottom_region->cuboid)); // Mark overlap region - - std::string msg = fmt::format( - "Bumps at ({}, {}) align physically but logical connectivity " - "mismatch: Top bump {} vs Bottom bump {}", - p.x(), - p.y(), - get_net_name(&top_bump), - get_net_name(bot_bump)); - marker->setComment(msg); - logger_->warn(utl::ODB, 208, msg); - } + if (top_net != bot_net) { + if (!cat) { + cat = dbMarkerCategory::createOrReplace(top_cat, + "Logical Connectivity"); + } + if (auto* marker = dbMarker::create(cat)) { + marker->addSource(top_bump->getChipBumpInst()); + marker->addSource(bot_bump->getChipBumpInst()); + marker->addShape(top_region->getCuboid().intersect( + bot_region->getCuboid())); // Mark overlap region + + std::string msg = fmt::format( + "Bumps at ({}, {}) align physically but logical connectivity " + "mismatch: Top bump {} vs Bottom bump {}", + p.x(), + p.y(), + get_net_name(top_bump), + get_net_name(bot_bump)); + marker->setComment(msg); + logger_->warn(utl::ODB, 208, msg); } } } diff --git a/src/odb/src/3dblox/checker.h b/src/odb/src/3dblox/checker.h index 648bb754fe7..ec0bf770a39 100644 --- a/src/odb/src/3dblox/checker.h +++ b/src/odb/src/3dblox/checker.h @@ -13,7 +13,6 @@ class Sta; namespace odb { class dbDatabase; -class UnfoldedModel; class dbMarkerCategory; struct MatingSurfaces @@ -31,22 +30,14 @@ class Checker void check(); private: - void checkLogicalConnectivity(dbMarkerCategory* top_cat, - const UnfoldedModel* model); - void checkFloatingChips(dbMarkerCategory* top_cat, - const UnfoldedModel* model); - void checkOverlappingChips(dbMarkerCategory* top_cat, - const UnfoldedModel* model); - void checkInternalExtUsage(dbMarkerCategory* top_cat, - const UnfoldedModel* model); - void checkConnectionRegions(dbMarkerCategory* top_cat, - const UnfoldedModel* model); - void checkBumpPhysicalAlignment(dbMarkerCategory* top_cat, - const UnfoldedModel* model); - void checkNetConnectivity(dbMarkerCategory* top_cat, - const UnfoldedModel* model); - void checkAlignmentMarkers(dbMarkerCategory* top_cat, - const UnfoldedModel* model); + void checkLogicalConnectivity(dbMarkerCategory* top_cat); + void checkFloatingChips(dbMarkerCategory* top_cat); + void checkOverlappingChips(dbMarkerCategory* top_cat); + void checkInternalExtUsage(dbMarkerCategory* top_cat); + void checkConnectionRegions(dbMarkerCategory* top_cat); + void checkBumpPhysicalAlignment(dbMarkerCategory* top_cat); + void checkNetConnectivity(dbMarkerCategory* top_cat); + void checkAlignmentMarkers(dbMarkerCategory* top_cat); utl::Logger* logger_; dbDatabase* db_; }; diff --git a/src/odb/src/codeGenerator/schema.json b/src/odb/src/codeGenerator/schema.json index cfcf235d673..1a0d7182008 100644 --- a/src/odb/src/codeGenerator/schema.json +++ b/src/odb/src/codeGenerator/schema.json @@ -209,6 +209,24 @@ "orderReversed": "true", "sequential": 0, "includes": ["dbChipNet.h", "dbChip.h"] + }, + { + "name": "dbUnfoldedRegionInstItr", + "parentObject": "dbUnfoldedRegionInst", + "tableName": "unfolded_region_inst_tbl", + "reversible": "true", + "orderReversed": "true", + "sequential": 0, + "includes": ["dbUnfoldedRegionInst.h", "dbUnfoldedChipInst.h"] + }, + { + "name": "dbUnfoldedBumpInstItr", + "parentObject": "dbUnfoldedBumpInst", + "tableName": "unfolded_bump_inst_tbl", + "reversible": "true", + "orderReversed": "true", + "sequential": 0, + "includes": ["dbUnfoldedBumpInst.h", "dbUnfoldedRegionInst.h"] } ], "relations":[ @@ -545,6 +563,41 @@ "schema":"kSchemaChipRegion", "flags": ["no-serial"] }, + { + "parent":"dbDatabase", + "child":"dbUnfoldedChipInst", + "type":"1_n", + "tbl_name":"unfolded_chip_inst_tbl_", + "flags": ["no-serial"] + }, + { + "parent":"dbDatabase", + "child":"dbUnfoldedRegionInst", + "type":"1_n", + "tbl_name":"unfolded_region_inst_tbl_", + "flags": ["no-serial"] + }, + { + "parent":"dbDatabase", + "child":"dbUnfoldedBumpInst", + "type":"1_n", + "tbl_name":"unfolded_bump_inst_tbl_", + "flags": ["no-serial"] + }, + { + "parent":"dbDatabase", + "child":"dbUnfoldedConn", + "type":"1_n", + "tbl_name":"unfolded_conn_tbl_", + "flags": ["no-serial"] + }, + { + "parent":"dbDatabase", + "child":"dbUnfoldedNet", + "type":"1_n", + "tbl_name":"unfolded_net_tbl_", + "flags": ["no-serial"] + }, { "parent":"dbChip", "child":"dbChipPath", diff --git a/src/odb/src/codeGenerator/schema/chip/dbUnfoldedBumpInst.json b/src/odb/src/codeGenerator/schema/chip/dbUnfoldedBumpInst.json new file mode 100644 index 00000000000..1cfcd086d04 --- /dev/null +++ b/src/odb/src/codeGenerator/schema/chip/dbUnfoldedBumpInst.json @@ -0,0 +1,34 @@ +{ + "name": "dbUnfoldedBumpInst", + "type": "dbObject", + "fields": [ + { + "name": "chip_bump_inst_", + "type": "dbId<_dbChipBumpInst>", + "flags": ["no-set"], + "parent": "dbDatabase" + }, + { + "name": "parent_region_", + "type": "dbId<_dbUnfoldedRegionInst>", + "flags": ["no-set"], + "parent": "dbDatabase" + }, + { + "name": "region_next_", + "type": "dbId<_dbUnfoldedBumpInst>", + "flags": ["private"] + } + ], + "h_includes": [ + "odb/dbId.h" + ], + "cpp_includes": [ + "dbChipBumpInst.h", + "dbChipBump.h", + "dbInst.h", + "dbUnfoldedRegionInst.h", + "dbUnfoldedChipInst.h", + "odb/geom.h" + ] +} diff --git a/src/odb/src/codeGenerator/schema/chip/dbUnfoldedChipInst.json b/src/odb/src/codeGenerator/schema/chip/dbUnfoldedChipInst.json new file mode 100644 index 00000000000..f44bc2cd90a --- /dev/null +++ b/src/odb/src/codeGenerator/schema/chip/dbUnfoldedChipInst.json @@ -0,0 +1,37 @@ +{ + "name": "dbUnfoldedChipInst", + "type": "dbObject", + "fields": [ + { + "name": "name_", + "type": "std::string", + "flags": ["no-set"] + }, + { + "name": "chip_inst_path_", + "type": "dbVector>", + "flags": ["private"] + }, + { + "name": "transform_", + "type": "dbTransform", + "flags": ["no-set"] + }, + { + "name": "region_", + "type": "dbId<_dbUnfoldedRegionInst>", + "flags": ["private"] + } + ], + "h_includes": [ + "odb/dbId.h", + "odb/geom.h", + "odb/dbTransform.h", + "dbVector.h" + ], + "cpp_includes": [ + "dbChipInst.h", + "odb/geom.h", + "odb/dbSet.h" + ] +} diff --git a/src/odb/src/codeGenerator/schema/chip/dbUnfoldedConn.json b/src/odb/src/codeGenerator/schema/chip/dbUnfoldedConn.json new file mode 100644 index 00000000000..5b896993e17 --- /dev/null +++ b/src/odb/src/codeGenerator/schema/chip/dbUnfoldedConn.json @@ -0,0 +1,31 @@ +{ + "name": "dbUnfoldedConn", + "type": "dbObject", + "fields": [ + { + "name": "chip_conn_", + "type": "dbId<_dbChipConn>", + "flags": ["no-set"], + "parent": "dbDatabase" + }, + { + "name": "top_region_", + "type": "dbId<_dbUnfoldedRegionInst>", + "flags": ["no-set"], + "parent": "dbDatabase" + }, + { + "name": "bottom_region_", + "type": "dbId<_dbUnfoldedRegionInst>", + "flags": ["no-set"], + "parent": "dbDatabase" + } + ], + "h_includes": [ + "odb/dbId.h" + ], + "cpp_includes": [ + "dbChipConn.h", + "dbUnfoldedRegionInst.h" + ] +} diff --git a/src/odb/src/codeGenerator/schema/chip/dbUnfoldedNet.json b/src/odb/src/codeGenerator/schema/chip/dbUnfoldedNet.json new file mode 100644 index 00000000000..d2dc24d3806 --- /dev/null +++ b/src/odb/src/codeGenerator/schema/chip/dbUnfoldedNet.json @@ -0,0 +1,25 @@ +{ + "name": "dbUnfoldedNet", + "type": "dbObject", + "fields": [ + { + "name": "chip_net_", + "type": "dbId<_dbChipNet>", + "flags": ["no-set"], + "parent": "dbDatabase" + }, + { + "name": "connected_bumps_", + "type": "dbVector>", + "flags": ["private"] + } + ], + "h_includes": [ + "odb/dbId.h", + "dbVector.h" + ], + "cpp_includes": [ + "dbChipNet.h", + "dbUnfoldedBumpInst.h" + ] +} diff --git a/src/odb/src/codeGenerator/schema/chip/dbUnfoldedRegionInst.json b/src/odb/src/codeGenerator/schema/chip/dbUnfoldedRegionInst.json new file mode 100644 index 00000000000..8b558cf7244 --- /dev/null +++ b/src/odb/src/codeGenerator/schema/chip/dbUnfoldedRegionInst.json @@ -0,0 +1,58 @@ +{ + "name": "dbUnfoldedRegionInst", + "type": "dbObject", + "enums": [ + { + "name": "EffectiveSide", + "class": true, + "values": [ + "TOP", + "BOTTOM", + "INTERNAL", + "INTERNAL_EXT" + ], + "public": true + } + ], + "fields": [ + { + "name": "chip_region_inst_", + "type": "dbId<_dbChipRegionInst>", + "flags": ["no-set"], + "parent": "dbDatabase" + }, + { + "name": "effective_side_", + "type": "uint32_t", + "default": 0, + "bits": 2, + "flags": ["private"] + }, + { + "name": "parent_chip_", + "type": "dbId<_dbUnfoldedChipInst>", + "flags": ["no-set"], + "parent": "dbDatabase" + }, + { + "name": "chip_next_", + "type": "dbId<_dbUnfoldedRegionInst>", + "flags": ["private"] + }, + { + "name": "bump_", + "type": "dbId<_dbUnfoldedBumpInst>", + "flags": ["private"] + } + ], + "h_includes": [ + "odb/dbId.h" + ], + "cpp_includes": [ + "dbChipRegionInst.h", + "dbChipRegion.h", + "dbUnfoldedChipInst.h", + "odb/dbSet.h", + "odb/geom.h" + ] +} diff --git a/src/odb/src/db/BUILD b/src/odb/src/db/BUILD index f93058f1217..f81825a5b95 100644 --- a/src/odb/src/db/BUILD +++ b/src/odb/src/db/BUILD @@ -47,7 +47,6 @@ cc_library( "//src/odb:include/odb/isotropy.h", "//src/odb:include/odb/odbDList.h", "//src/odb:include/odb/poly_decomp.h", - "//src/odb:include/odb/unfoldedModel.h", "//src/odb:include/odb/util.h", "//src/odb:include/odb/wOrder.h", ], diff --git a/src/odb/src/db/CMakeLists.txt b/src/odb/src/db/CMakeLists.txt index 95bfac7a8f0..580a4a15c89 100644 --- a/src/odb/src/db/CMakeLists.txt +++ b/src/odb/src/db/CMakeLists.txt @@ -86,7 +86,7 @@ add_library(db dbGroupGroundNetItr.cpp dbGDSLib.cpp dbSwapMasterSanityChecker.cpp - unfoldedModel.cpp + dbUnfoldedBuilder.cpp util.cpp poly_decomp.cpp # Generator Code Begin cpp @@ -160,6 +160,11 @@ add_library(db dbTechLayerVoltageSpacing.cpp dbTechLayerWidthTableRule.cpp dbTechLayerWrongDirSpacingRule.cpp + dbUnfoldedBumpInst.cpp + dbUnfoldedChipInst.cpp + dbUnfoldedConn.cpp + dbUnfoldedNet.cpp + dbUnfoldedRegionInst.cpp dbChipBumpInstItr.cpp dbChipConnItr.cpp dbChipInstItr.cpp @@ -183,6 +188,8 @@ add_library(db dbNetTrackItr.cpp dbRegionGroupItr.cpp dbScanListScanInstItr.cpp + dbUnfoldedBumpInstItr.cpp + dbUnfoldedRegionInstItr.cpp # Generator Code End cpp ) diff --git a/src/odb/src/db/dbDatabase.cpp b/src/odb/src/db/dbDatabase.cpp index baf6a3afce9..7652ae6df51 100644 --- a/src/odb/src/db/dbDatabase.cpp +++ b/src/odb/src/db/dbDatabase.cpp @@ -16,6 +16,11 @@ #include "dbCore.h" #include "dbProperty.h" #include "dbTable.h" +#include "dbUnfoldedBumpInst.h" +#include "dbUnfoldedChipInst.h" +#include "dbUnfoldedConn.h" +#include "dbUnfoldedNet.h" +#include "dbUnfoldedRegionInst.h" #include "odb/db.h" #include "odb/dbSet.h" // User Code Begin Includes @@ -61,11 +66,13 @@ #include "dbTechLayerCutSpacingRule.h" #include "dbTechLayerMinCutRule.h" #include "dbTechLayerSpacingRule.h" +#include "dbUnfoldedBuilder.h" +#include "dbUnfoldedBumpInstItr.h" +#include "dbUnfoldedRegionInstItr.h" #include "odb/dbBlockCallBackObj.h" #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 { @@ -122,6 +129,21 @@ bool _dbDatabase::operator==(const _dbDatabase& rhs) const if (*chip_net_tbl_ != *rhs.chip_net_tbl_) { return false; } + if (*unfolded_chip_inst_tbl_ != *rhs.unfolded_chip_inst_tbl_) { + return false; + } + if (*unfolded_region_inst_tbl_ != *rhs.unfolded_region_inst_tbl_) { + return false; + } + if (*unfolded_bump_inst_tbl_ != *rhs.unfolded_bump_inst_tbl_) { + return false; + } + if (*unfolded_conn_tbl_ != *rhs.unfolded_conn_tbl_) { + return false; + } + if (*unfolded_net_tbl_ != *rhs.unfolded_net_tbl_) { + return false; + } // User Code Begin == // @@ -191,6 +213,28 @@ _dbDatabase::_dbDatabase(_dbDatabase* db) dbChipBumpInstObj); chip_net_tbl_ = new dbTable<_dbChipNet>( this, this, (GetObjTbl_t) &_dbDatabase::getObjectTable, dbChipNetObj); + unfolded_chip_inst_tbl_ = new dbTable<_dbUnfoldedChipInst>( + this, + this, + (GetObjTbl_t) &_dbDatabase::getObjectTable, + dbUnfoldedChipInstObj); + unfolded_region_inst_tbl_ = new dbTable<_dbUnfoldedRegionInst>( + this, + this, + (GetObjTbl_t) &_dbDatabase::getObjectTable, + dbUnfoldedRegionInstObj); + unfolded_bump_inst_tbl_ = new dbTable<_dbUnfoldedBumpInst>( + this, + this, + (GetObjTbl_t) &_dbDatabase::getObjectTable, + dbUnfoldedBumpInstObj); + unfolded_conn_tbl_ + = new dbTable<_dbUnfoldedConn>(this, + this, + (GetObjTbl_t) &_dbDatabase::getObjectTable, + dbUnfoldedConnObj); + unfolded_net_tbl_ = new dbTable<_dbUnfoldedNet>( + this, this, (GetObjTbl_t) &_dbDatabase::getObjectTable, dbUnfoldedNetObj); // User Code Begin Constructor magic1_ = kMagic1; magic2_ = kMagic2; @@ -225,7 +269,9 @@ _dbDatabase::_dbDatabase(_dbDatabase* db) chip_net_itr_ = new dbChipNetItr(chip_net_tbl_); - unfolded_model_ = nullptr; + unfolded_region_itr_ = new dbUnfoldedRegionInstItr(unfolded_region_inst_tbl_); + + unfolded_bump_itr_ = new dbUnfoldedBumpInstItr(unfolded_bump_inst_tbl_); // User Code End Constructor } @@ -456,6 +502,16 @@ dbObjectTable* _dbDatabase::getObjectTable(dbObjectType type) return chip_bump_inst_tbl_; case dbChipNetObj: return chip_net_tbl_; + case dbUnfoldedChipInstObj: + return unfolded_chip_inst_tbl_; + case dbUnfoldedRegionInstObj: + return unfolded_region_inst_tbl_; + case dbUnfoldedBumpInstObj: + return unfolded_bump_inst_tbl_; + case dbUnfoldedConnObj: + return unfolded_conn_tbl_; + case dbUnfoldedNetObj: + return unfolded_net_tbl_; // User Code Begin getObjectTable case dbTechObj: return tech_tbl_; @@ -486,6 +542,14 @@ void _dbDatabase::collectMemInfo(MemInfo& info) chip_conn_tbl_->collectMemInfo(info.children["chip_conn_tbl_"]); chip_bump_inst_tbl_->collectMemInfo(info.children["chip_bump_inst_tbl_"]); chip_net_tbl_->collectMemInfo(info.children["chip_net_tbl_"]); + unfolded_chip_inst_tbl_->collectMemInfo( + info.children["unfolded_chip_inst_tbl_"]); + unfolded_region_inst_tbl_->collectMemInfo( + info.children["unfolded_region_inst_tbl_"]); + unfolded_bump_inst_tbl_->collectMemInfo( + info.children["unfolded_bump_inst_tbl_"]); + unfolded_conn_tbl_->collectMemInfo(info.children["unfolded_conn_tbl_"]); + unfolded_net_tbl_->collectMemInfo(info.children["unfolded_net_tbl_"]); // User Code Begin collectMemInfo tech_tbl_->collectMemInfo(info.children["tech"]); @@ -505,6 +569,11 @@ _dbDatabase::~_dbDatabase() delete chip_conn_tbl_; delete chip_bump_inst_tbl_; delete chip_net_tbl_; + delete unfolded_chip_inst_tbl_; + delete unfolded_region_inst_tbl_; + delete unfolded_bump_inst_tbl_; + delete unfolded_conn_tbl_; + delete unfolded_net_tbl_; // User Code Begin Destructor delete tech_tbl_; delete lib_tbl_; @@ -516,7 +585,8 @@ _dbDatabase::~_dbDatabase() delete chip_conn_itr_; delete chip_bump_inst_itr_; delete chip_net_itr_; - delete unfolded_model_; + delete unfolded_region_itr_; + delete unfolded_bump_itr_; // User Code End Destructor } @@ -567,7 +637,9 @@ _dbDatabase::_dbDatabase(_dbDatabase* /* unused: db */, int id) chip_net_itr_ = new dbChipNetItr(chip_net_tbl_); - unfolded_model_ = nullptr; + unfolded_region_itr_ = new dbUnfoldedRegionInstItr(unfolded_region_inst_tbl_); + + unfolded_bump_itr_ = new dbUnfoldedBumpInstItr(unfolded_bump_inst_tbl_); } utl::Logger* _dbDatabase::getLogger() const @@ -659,6 +731,36 @@ dbSet dbDatabase::getChipNets() const return dbSet(obj, obj->chip_net_tbl_); } +dbSet dbDatabase::getUnfoldedChipInsts() const +{ + _dbDatabase* obj = (_dbDatabase*) this; + return dbSet(obj, obj->unfolded_chip_inst_tbl_); +} + +dbSet dbDatabase::getUnfoldedRegionInsts() const +{ + _dbDatabase* obj = (_dbDatabase*) this; + return dbSet(obj, obj->unfolded_region_inst_tbl_); +} + +dbSet dbDatabase::getUnfoldedBumpInsts() const +{ + _dbDatabase* obj = (_dbDatabase*) this; + return dbSet(obj, obj->unfolded_bump_inst_tbl_); +} + +dbSet dbDatabase::getUnfoldedConns() const +{ + _dbDatabase* obj = (_dbDatabase*) this; + return dbSet(obj, obj->unfolded_conn_tbl_); +} + +dbSet dbDatabase::getUnfoldedNets() const +{ + _dbDatabase* obj = (_dbDatabase*) this; + return dbSet(obj, obj->unfolded_net_tbl_); +} + // User Code Begin dbDatabasePublicMethods void dbDatabase::setTopChip(dbChip* chip) @@ -767,14 +869,18 @@ dbChip* dbDatabase::getChip() void dbDatabase::constructUnfoldedModel() { _dbDatabase* db = (_dbDatabase*) this; - delete db->unfolded_model_; - db->unfolded_model_ = new UnfoldedModel(db->logger_, getChip()); + dbUnfoldedBuilder builder(db); + builder.build(); } -UnfoldedModel* dbDatabase::getUnfoldedModel() const +dbUnfoldedChipInst* dbDatabase::findUnfoldedChip(const std::string& path) const { - _dbDatabase* db = (_dbDatabase*) this; - return db->unfolded_model_; + for (dbUnfoldedChipInst* chip : getUnfoldedChipInsts()) { + if (chip->getName() == path) { + return chip; + } + } + return nullptr; } dbTech* dbDatabase::getTech() diff --git a/src/odb/src/db/dbDatabase.h b/src/odb/src/db/dbDatabase.h index 1bdae44b92d..1b0a4646411 100644 --- a/src/odb/src/db/dbDatabase.h +++ b/src/odb/src/db/dbDatabase.h @@ -290,6 +290,11 @@ class _dbChipRegionInst; class _dbChipConn; class _dbChipBumpInst; class _dbChipNet; +class _dbUnfoldedChipInst; +class _dbUnfoldedRegionInst; +class _dbUnfoldedBumpInst; +class _dbUnfoldedConn; +class _dbUnfoldedNet; // User Code Begin Classes class dbPropertyItr; class dbChipInstItr; @@ -297,11 +302,12 @@ class dbChipRegionInstItr; class dbChipConnItr; class dbChipBumpInstItr; class dbChipNetItr; +class dbUnfoldedRegionInstItr; +class dbUnfoldedBumpInstItr; class _dbNameCache; class _dbTech; class _dbLib; class _dbGDSLib; -class UnfoldedModel; // User Code End Classes class _dbDatabase : public _dbObject @@ -339,6 +345,11 @@ class _dbDatabase : public _dbObject dbTable<_dbChipConn>* chip_conn_tbl_; dbTable<_dbChipBumpInst>* chip_bump_inst_tbl_; dbTable<_dbChipNet>* chip_net_tbl_; + dbTable<_dbUnfoldedChipInst>* unfolded_chip_inst_tbl_; + dbTable<_dbUnfoldedRegionInst>* unfolded_region_inst_tbl_; + dbTable<_dbUnfoldedBumpInst>* unfolded_bump_inst_tbl_; + dbTable<_dbUnfoldedConn>* unfolded_conn_tbl_; + dbTable<_dbUnfoldedNet>* unfolded_net_tbl_; // User Code Begin Fields dbTable<_dbTech, 2>* tech_tbl_; @@ -350,14 +361,16 @@ class _dbDatabase : public _dbObject dbChipRegionInstItr* chip_region_inst_itr_; dbChipConnItr* chip_conn_itr_; dbChipBumpInstItr* chip_bump_inst_itr_; + dbUnfoldedRegionInstItr* unfolded_region_itr_; + dbUnfoldedBumpInstItr* unfolded_bump_itr_; dbChipNetItr* chip_net_itr_; int unique_id_; bool hierarchy_; utl::Logger* logger_; std::set observers_; - UnfoldedModel* unfolded_model_; // non-persistent object - // User Code End Fields + + // User Code End Fields }; dbIStream& operator>>(dbIStream& stream, _dbDatabase& obj); dbOStream& operator<<(dbOStream& stream, const _dbDatabase& obj); diff --git a/src/odb/src/db/dbObject.cpp b/src/odb/src/db/dbObject.cpp index e81abaddd69..31dc9bb4b7b 100644 --- a/src/odb/src/db/dbObject.cpp +++ b/src/odb/src/db/dbObject.cpp @@ -125,6 +125,11 @@ static const char* name_tbl[] = {"dbGDSLib", "dbTechLayerVoltageSpacing", "dbTechLayerWidthTableRule", "dbTechLayerWrongDirSpacingRule", + "dbUnfoldedBumpInst", + "dbUnfoldedChipInst", + "dbUnfoldedConn", + "dbUnfoldedNet", + "dbUnfoldedRegionInst", // Generator Code End ObjectNames // Lib Objects @@ -247,6 +252,11 @@ static const std::unordered_map hash_to_object_type {0x690396A7, dbTechLayerVoltageSpacingObj}, {0x7BF3D392, dbTechLayerWidthTableRuleObj}, {0xF73FA7DF, dbTechLayerWrongDirSpacingRuleObj}, + {0x9DE679DA, dbUnfoldedBumpInstObj}, + {0x18591EB8, dbUnfoldedChipInstObj}, + {0xCF7B84F0, dbUnfoldedConnObj}, + {0xDC63AD55, dbUnfoldedNetObj}, + {0x4C06DD36, dbUnfoldedRegionInstObj}, // Generator Code End HashToObjectType // Lib Objects @@ -370,6 +380,11 @@ static const std::unordered_map object_type_to_hash {dbTechLayerVoltageSpacingObj, 0x690396A7}, {dbTechLayerWidthTableRuleObj, 0x7BF3D392}, {dbTechLayerWrongDirSpacingRuleObj, 0xF73FA7DF}, + {dbUnfoldedBumpInstObj, 0x9DE679DA}, + {dbUnfoldedChipInstObj, 0x18591EB8}, + {dbUnfoldedConnObj, 0xCF7B84F0}, + {dbUnfoldedNetObj, 0xDC63AD55}, + {dbUnfoldedRegionInstObj, 0x4C06DD36}, // Generator Code End ObjectTypeToHash // Lib Objects diff --git a/src/odb/src/db/dbUnfoldedBuilder.cpp b/src/odb/src/db/dbUnfoldedBuilder.cpp new file mode 100644 index 00000000000..8bbaf0acebe --- /dev/null +++ b/src/odb/src/db/dbUnfoldedBuilder.cpp @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2026, The OpenROAD Authors + +#include "dbUnfoldedBuilder.h" + +#include +#include +#include + +#include "dbChip.h" +#include "dbChipBumpInst.h" +#include "dbChipConn.h" +#include "dbChipInst.h" +#include "dbChipNet.h" +#include "dbChipRegion.h" +#include "dbChipRegionInst.h" +#include "dbDatabase.h" +#include "dbTable.h" +#include "dbUnfoldedBumpInst.h" +#include "dbUnfoldedChipInst.h" +#include "dbUnfoldedConn.h" +#include "dbUnfoldedNet.h" +#include "dbUnfoldedRegionInst.h" +#include "odb/db.h" +#include "odb/dbTransform.h" + +namespace odb { + +namespace { + +std::vector concatPath(const std::vector& head, + const std::vector& tail) +{ + if (tail.empty()) { + return head; + } + std::vector full = head; + full.insert(full.end(), tail.begin(), tail.end()); + return full; +} + +std::string getFullPathName(const std::vector& path) +{ + std::string name; + for (auto* p : path) { + if (!name.empty()) { + name += '/'; + } + name += p->getName(); + } + return name; +} + +dbUnfoldedRegionInst::EffectiveSide mirrorSide( + dbUnfoldedRegionInst::EffectiveSide side) +{ + if (side == dbUnfoldedRegionInst::EffectiveSide::TOP) { + return dbUnfoldedRegionInst::EffectiveSide::BOTTOM; + } + if (side == dbUnfoldedRegionInst::EffectiveSide::BOTTOM) { + return dbUnfoldedRegionInst::EffectiveSide::TOP; + } + return side; +} + +} // namespace + +dbUnfoldedBuilder::dbUnfoldedBuilder(_dbDatabase* db) : db_(db) +{ +} + +void dbUnfoldedBuilder::build() +{ + db_->unfolded_chip_inst_tbl_->clear(); + db_->unfolded_region_inst_tbl_->clear(); + db_->unfolded_bump_inst_tbl_->clear(); + db_->unfolded_conn_tbl_->clear(); + db_->unfolded_net_tbl_->clear(); + chip_by_path_.clear(); + region_map_.clear(); + bump_map_.clear(); + + dbChip* chip = ((dbDatabase*) db_)->getChip(); + if (chip == nullptr) { + return; + } + + std::vector path; + for (dbChipInst* inst : chip->getChipInsts()) { + buildUnfoldedChip(inst, path, dbTransform()); + } + unfoldConnections(chip, {}); + unfoldNets(chip, {}); +} + +_dbUnfoldedChipInst* dbUnfoldedBuilder::buildUnfoldedChip( + dbChipInst* inst, + std::vector& path, + const dbTransform& parent_xform) +{ + dbChip* master = inst->getMasterChip(); + path.push_back(inst); + + const dbTransform inst_xform = inst->getTransform(); + dbTransform total = inst_xform; + total.concat(parent_xform); + + if (master->getChipType() == dbChip::ChipType::HIER) { + for (auto* sub : master->getChipInsts()) { + buildUnfoldedChip(sub, path, total); + } + unfoldConnections(master, path); + unfoldNets(master, path); + path.pop_back(); + return nullptr; + } + + _dbUnfoldedChipInst* uf_chip = db_->unfolded_chip_inst_tbl_->create(); + uf_chip->name_ = getFullPathName(path); + uf_chip->chip_inst_path_.reserve(path.size()); + for (auto* p : path) { + uf_chip->chip_inst_path_.push_back(p->getImpl()->getOID()); + } + uf_chip->transform_ = total; + unfoldRegions(uf_chip, inst); + + chip_by_path_[uf_chip->name_] = uf_chip->getOID(); + + path.pop_back(); + return uf_chip; +} + +void dbUnfoldedBuilder::unfoldRegions(_dbUnfoldedChipInst* uf_chip, + dbChipInst* inst) +{ + auto& chip_region_map = region_map_[uf_chip->getOID()]; + for (auto* region_inst : inst->getRegions()) { + auto region = region_inst->getChipRegion(); + + dbUnfoldedRegionInst::EffectiveSide side + = dbUnfoldedRegionInst::EffectiveSide::INTERNAL; + switch (region->getSide()) { + case dbChipRegion::Side::FRONT: + side = dbUnfoldedRegionInst::EffectiveSide::TOP; + break; + case dbChipRegion::Side::BACK: + side = dbUnfoldedRegionInst::EffectiveSide::BOTTOM; + break; + case dbChipRegion::Side::INTERNAL: + side = dbUnfoldedRegionInst::EffectiveSide::INTERNAL; + break; + case dbChipRegion::Side::INTERNAL_EXT: + side = dbUnfoldedRegionInst::EffectiveSide::INTERNAL_EXT; + break; + } + + if (uf_chip->transform_.isMirrorZ()) { + side = mirrorSide(side); + } + + _dbUnfoldedRegionInst* uf_region = db_->unfolded_region_inst_tbl_->create(); + uf_region->chip_region_inst_ = region_inst->getImpl()->getOID(); + uf_region->flags_.effective_side_ = static_cast(side); + uf_region->parent_chip_ = uf_chip->getOID(); + uf_region->chip_next_ = uf_chip->region_; + uf_chip->region_ = uf_region->getOID(); + + chip_region_map[region_inst] = uf_region->getOID(); + unfoldBumps(uf_region, region_inst); + } + // Inserts were head-first; reverse to restore source order. + ((dbUnfoldedChipInst*) uf_chip)->getRegions().reverse(); +} + +void dbUnfoldedBuilder::unfoldBumps(_dbUnfoldedRegionInst* uf_region, + dbChipRegionInst* region_inst) +{ + auto& chip_bump_map = bump_map_[uf_region->parent_chip_]; + for (auto* bump_inst : region_inst->getChipBumpInsts()) { + dbChipBump* bump = bump_inst->getChipBump(); + if (bump->getInst() == nullptr) { + continue; + } + _dbUnfoldedBumpInst* uf_bump = db_->unfolded_bump_inst_tbl_->create(); + uf_bump->chip_bump_inst_ = bump_inst->getImpl()->getOID(); + uf_bump->parent_region_ = uf_region->getOID(); + uf_bump->region_next_ = uf_region->bump_; + uf_region->bump_ = uf_bump->getOID(); + + chip_bump_map[bump_inst] = uf_bump->getOID(); + } + // Inserts were head-first; reverse to restore source order. + ((dbUnfoldedRegionInst*) uf_region)->getBumps().reverse(); +} + +_dbUnfoldedChipInst* dbUnfoldedBuilder::findUnfoldedChip( + const std::vector& path) +{ + auto it = chip_by_path_.find(getFullPathName(path)); + if (it == chip_by_path_.end()) { + return nullptr; + } + return db_->unfolded_chip_inst_tbl_->getPtr(it->second); +} + +void dbUnfoldedBuilder::unfoldConnections( + dbChip* chip, + const std::vector& parent_path) +{ + for (auto* conn : chip->getChipConns()) { + dbId<_dbUnfoldedRegionInst> top_region = 0; + if (_dbUnfoldedChipInst* top_chip + = findUnfoldedChip(concatPath(parent_path, conn->getTopRegionPath()))) { + auto& map = region_map_[top_chip->getOID()]; + auto it = map.find(conn->getTopRegion()); + if (it != map.end()) { + top_region = it->second; + } + } + dbId<_dbUnfoldedRegionInst> bot_region = 0; + if (_dbUnfoldedChipInst* bot_chip = findUnfoldedChip( + concatPath(parent_path, conn->getBottomRegionPath()))) { + auto& map = region_map_[bot_chip->getOID()]; + auto it = map.find(conn->getBottomRegion()); + if (it != map.end()) { + bot_region = it->second; + } + } + if (top_region.isValid() || bot_region.isValid()) { + _dbUnfoldedConn* uf_conn = db_->unfolded_conn_tbl_->create(); + uf_conn->chip_conn_ = conn->getImpl()->getOID(); + uf_conn->top_region_ = top_region; + uf_conn->bottom_region_ = bot_region; + } + } +} + +void dbUnfoldedBuilder::unfoldNets(dbChip* chip, + const std::vector& parent_path) +{ + for (auto* net : chip->getChipNets()) { + _dbUnfoldedNet* uf_net = db_->unfolded_net_tbl_->create(); + uf_net->chip_net_ = net->getImpl()->getOID(); + for (uint32_t i = 0; i < net->getNumBumpInsts(); i++) { + std::vector rel_path; + dbChipBumpInst* b_inst = net->getBumpInst(i, rel_path); + _dbUnfoldedChipInst* uf_chip + = findUnfoldedChip(concatPath(parent_path, rel_path)); + if (uf_chip == nullptr) { + continue; + } + auto& map = bump_map_[uf_chip->getOID()]; + auto it = map.find(b_inst); + if (it != map.end()) { + uf_net->connected_bumps_.push_back(it->second); + } + } + } +} + +} // namespace odb diff --git a/src/odb/src/db/dbUnfoldedBuilder.h b/src/odb/src/db/dbUnfoldedBuilder.h new file mode 100644 index 00000000000..bcaa8cce4fd --- /dev/null +++ b/src/odb/src/db/dbUnfoldedBuilder.h @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2026, The OpenROAD Authors + +#pragma once + +#include +#include +#include +#include + +#include "odb/dbId.h" +#include "odb/dbTransform.h" + +namespace odb { + +class _dbDatabase; +class _dbUnfoldedBumpInst; +class _dbUnfoldedChipInst; +class _dbUnfoldedRegionInst; +class dbChip; +class dbChipBumpInst; +class dbChipInst; +class dbChipRegionInst; + +class dbUnfoldedBuilder +{ + public: + explicit dbUnfoldedBuilder(_dbDatabase* db); + void build(); + + private: + _dbUnfoldedChipInst* buildUnfoldedChip(dbChipInst* inst, + std::vector& path, + const dbTransform& parent_xform); + void unfoldRegions(_dbUnfoldedChipInst* uf_chip, dbChipInst* inst); + void unfoldBumps(_dbUnfoldedRegionInst* uf_region, + dbChipRegionInst* region_inst); + void unfoldConnections(dbChip* chip, + const std::vector& parent_path); + void unfoldNets(dbChip* chip, const std::vector& parent_path); + + _dbUnfoldedChipInst* findUnfoldedChip(const std::vector& path); + + _dbDatabase* db_; + std::unordered_map> chip_by_path_; + std::unordered_map< + uint32_t, + std::unordered_map>> + region_map_; + std::unordered_map< + uint32_t, + std::unordered_map>> + bump_map_; +}; + +} // namespace odb diff --git a/src/odb/src/db/dbUnfoldedBumpInst.cpp b/src/odb/src/db/dbUnfoldedBumpInst.cpp new file mode 100644 index 00000000000..4c61a0468ff --- /dev/null +++ b/src/odb/src/db/dbUnfoldedBumpInst.cpp @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2019-2025, The OpenROAD Authors + +// Generator Code Begin Cpp +#include "dbUnfoldedBumpInst.h" + +#include "dbChipBump.h" +#include "dbChipBumpInst.h" +#include "dbCore.h" +#include "dbDatabase.h" +#include "dbInst.h" +#include "dbTable.h" +#include "dbUnfoldedChipInst.h" +#include "dbUnfoldedRegionInst.h" +#include "odb/db.h" +#include "odb/geom.h" +namespace odb { +template class dbTable<_dbUnfoldedBumpInst>; + +bool _dbUnfoldedBumpInst::operator==(const _dbUnfoldedBumpInst& rhs) const +{ + // NOLINTBEGIN(readability-simplify-boolean-expr) + if (chip_bump_inst_ != rhs.chip_bump_inst_) { + return false; + } + if (parent_region_ != rhs.parent_region_) { + return false; + } + if (region_next_ != rhs.region_next_) { + return false; + } + + return true; + // NOLINTEND(readability-simplify-boolean-expr) +} + +bool _dbUnfoldedBumpInst::operator<(const _dbUnfoldedBumpInst& rhs) const +{ + return true; +} + +_dbUnfoldedBumpInst::_dbUnfoldedBumpInst(_dbDatabase* db) +{ +} + +dbIStream& operator>>(dbIStream& stream, _dbUnfoldedBumpInst& obj) +{ + stream >> obj.chip_bump_inst_; + stream >> obj.parent_region_; + stream >> obj.region_next_; + return stream; +} + +dbOStream& operator<<(dbOStream& stream, const _dbUnfoldedBumpInst& obj) +{ + stream << obj.chip_bump_inst_; + stream << obj.parent_region_; + stream << obj.region_next_; + return stream; +} + +void _dbUnfoldedBumpInst::collectMemInfo(MemInfo& info) +{ + info.cnt++; + info.size += sizeof(*this); +} + +//////////////////////////////////////////////////////////////////// +// +// dbUnfoldedBumpInst - Methods +// +//////////////////////////////////////////////////////////////////// + +dbChipBumpInst* dbUnfoldedBumpInst::getChipBumpInst() const +{ + _dbUnfoldedBumpInst* obj = (_dbUnfoldedBumpInst*) this; + if (obj->chip_bump_inst_ == 0) { + return nullptr; + } + _dbDatabase* par = (_dbDatabase*) obj->getOwner(); + return (dbChipBumpInst*) par->chip_bump_inst_tbl_->getPtr( + obj->chip_bump_inst_); +} + +dbUnfoldedRegionInst* dbUnfoldedBumpInst::getParentRegion() const +{ + _dbUnfoldedBumpInst* obj = (_dbUnfoldedBumpInst*) this; + if (obj->parent_region_ == 0) { + return nullptr; + } + _dbDatabase* par = (_dbDatabase*) obj->getOwner(); + return (dbUnfoldedRegionInst*) par->unfolded_region_inst_tbl_->getPtr( + obj->parent_region_); +} + +// User Code Begin dbUnfoldedBumpInstPublicMethods +Point3D dbUnfoldedBumpInst::getGlobalPosition() const +{ + _dbUnfoldedBumpInst* obj = (_dbUnfoldedBumpInst*) this; + _dbDatabase* db = (_dbDatabase*) obj->getOwner(); + dbChipBumpInst* bump_inst = (dbChipBumpInst*) db->chip_bump_inst_tbl_->getPtr( + obj->chip_bump_inst_); + dbInst* inst = bump_inst->getChipBump()->getInst(); + if (inst == nullptr) { + return Point3D(); + } + Point pt = inst->getBBox()->getBox().center(); + dbUnfoldedRegionInst* region + = (dbUnfoldedRegionInst*) db->unfolded_region_inst_tbl_->getPtr( + obj->parent_region_); + _dbUnfoldedRegionInst* _region = (_dbUnfoldedRegionInst*) region; + _dbUnfoldedChipInst* parent_chip + = db->unfolded_chip_inst_tbl_->getPtr(_region->parent_chip_); + parent_chip->transform_.apply(pt); + return Point3D(pt.x(), pt.y(), region->getSurfaceZ()); +} +// User Code End dbUnfoldedBumpInstPublicMethods +} // namespace odb +// Generator Code End Cpp \ No newline at end of file diff --git a/src/odb/src/db/dbUnfoldedBumpInst.h b/src/odb/src/db/dbUnfoldedBumpInst.h new file mode 100644 index 00000000000..c5a785afe66 --- /dev/null +++ b/src/odb/src/db/dbUnfoldedBumpInst.h @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2019-2025, The OpenROAD Authors + +// Generator Code Begin Header +#pragma once + +#include + +#include "dbCore.h" +#include "odb/dbId.h" + +namespace odb { +class dbIStream; +class dbOStream; +class _dbDatabase; +class _dbChipBumpInst; +class _dbUnfoldedRegionInst; + +class _dbUnfoldedBumpInst : public _dbObject +{ + public: + _dbUnfoldedBumpInst(_dbDatabase*); + + bool operator==(const _dbUnfoldedBumpInst& rhs) const; + bool operator!=(const _dbUnfoldedBumpInst& rhs) const + { + return !operator==(rhs); + } + bool operator<(const _dbUnfoldedBumpInst& rhs) const; + void collectMemInfo(MemInfo& info); + + dbId<_dbChipBumpInst> chip_bump_inst_; + dbId<_dbUnfoldedRegionInst> parent_region_; + dbId<_dbUnfoldedBumpInst> region_next_; +}; +dbIStream& operator>>(dbIStream& stream, _dbUnfoldedBumpInst& obj); +dbOStream& operator<<(dbOStream& stream, const _dbUnfoldedBumpInst& obj); +} // namespace odb +// Generator Code End Header \ No newline at end of file diff --git a/src/odb/src/db/dbUnfoldedBumpInstItr.cpp b/src/odb/src/db/dbUnfoldedBumpInstItr.cpp new file mode 100644 index 00000000000..a17a44fcadb --- /dev/null +++ b/src/odb/src/db/dbUnfoldedBumpInstItr.cpp @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2019-2025, The OpenROAD Authors + +// Generator Code Begin Cpp +#include "dbUnfoldedBumpInstItr.h" + +#include + +#include "dbTable.h" +#include "dbUnfoldedBumpInst.h" +#include "dbUnfoldedRegionInst.h" + +namespace odb { + +//////////////////////////////////////////////////////////////////// +// +// dbUnfoldedBumpInstItr - Methods +// +//////////////////////////////////////////////////////////////////// + +bool dbUnfoldedBumpInstItr::reversible() const +{ + return true; +} + +bool dbUnfoldedBumpInstItr::orderReversed() const +{ + return true; +} + +void dbUnfoldedBumpInstItr::reverse(dbObject* parent) +{ + // User Code Begin reverse + _dbUnfoldedRegionInst* region = (_dbUnfoldedRegionInst*) parent; + uint32_t id = region->bump_; + uint32_t list = 0; + while (id != 0) { + _dbUnfoldedBumpInst* bump = unfolded_bump_inst_tbl_->getPtr(id); + uint32_t n = bump->region_next_; + bump->region_next_ = list; + list = id; + id = n; + } + region->bump_ = list; + // User Code End reverse +} + +uint32_t dbUnfoldedBumpInstItr::sequential() const +{ + return 0; +} + +uint32_t dbUnfoldedBumpInstItr::size(dbObject* parent) const +{ + uint32_t id; + uint32_t cnt = 0; + + for (id = dbUnfoldedBumpInstItr::begin(parent); + id != dbUnfoldedBumpInstItr::end(parent); + id = dbUnfoldedBumpInstItr::next(id)) { + ++cnt; + } + + return cnt; +} + +uint32_t dbUnfoldedBumpInstItr::begin(dbObject* parent) const +{ + // User Code Begin begin + return ((_dbUnfoldedRegionInst*) parent)->bump_; + // User Code End begin +} + +uint32_t dbUnfoldedBumpInstItr::end(dbObject* /* unused: parent */) const +{ + return 0; +} + +uint32_t dbUnfoldedBumpInstItr::next(uint32_t id, ...) const +{ + // User Code Begin next + return unfolded_bump_inst_tbl_->getPtr(id)->region_next_; + // User Code End next +} + +dbObject* dbUnfoldedBumpInstItr::getObject(uint32_t id, ...) +{ + return unfolded_bump_inst_tbl_->getPtr(id); +} +} // namespace odb +// Generator Code End Cpp \ No newline at end of file diff --git a/src/odb/src/db/dbUnfoldedBumpInstItr.h b/src/odb/src/db/dbUnfoldedBumpInstItr.h new file mode 100644 index 00000000000..d9f7ab6df2e --- /dev/null +++ b/src/odb/src/db/dbUnfoldedBumpInstItr.h @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2019-2025, The OpenROAD Authors + +// Generator Code Begin Header +#pragma once + +#include + +#include "dbCore.h" +#include "odb/dbIterator.h" + +namespace odb { +class _dbUnfoldedBumpInst; + +class dbUnfoldedBumpInstItr : public dbIterator +{ + public: + dbUnfoldedBumpInstItr(dbTable<_dbUnfoldedBumpInst>* unfolded_bump_inst_tbl) + { + unfolded_bump_inst_tbl_ = unfolded_bump_inst_tbl; + } + + bool reversible() const override; + bool orderReversed() const override; + void reverse(dbObject* parent) override; + uint32_t sequential() const override; + uint32_t size(dbObject* parent) const override; + uint32_t begin(dbObject* parent) const override; + uint32_t end(dbObject* parent) const override; + uint32_t next(uint32_t id, ...) const override; + dbObject* getObject(uint32_t id, ...) override; + + private: + dbTable<_dbUnfoldedBumpInst>* unfolded_bump_inst_tbl_; +}; + +} // namespace odb +// Generator Code End Header \ No newline at end of file diff --git a/src/odb/src/db/dbUnfoldedChipInst.cpp b/src/odb/src/db/dbUnfoldedChipInst.cpp new file mode 100644 index 00000000000..0ce301f665c --- /dev/null +++ b/src/odb/src/db/dbUnfoldedChipInst.cpp @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2019-2025, The OpenROAD Authors + +// Generator Code Begin Cpp +#include "dbUnfoldedChipInst.h" + +#include + +#include "dbChipInst.h" +#include "dbCore.h" +#include "dbDatabase.h" +#include "dbTable.h" +#include "odb/db.h" +#include "odb/dbSet.h" +#include "odb/geom.h" +// User Code Begin Includes +#include + +#include "dbUnfoldedRegionInstItr.h" // IWYU pragma: keep +// User Code End Includes +namespace odb { +template class dbTable<_dbUnfoldedChipInst>; + +bool _dbUnfoldedChipInst::operator==(const _dbUnfoldedChipInst& rhs) const +{ + // NOLINTBEGIN(readability-simplify-boolean-expr) + if (name_ != rhs.name_) { + return false; + } + if (region_ != rhs.region_) { + return false; + } + + return true; + // NOLINTEND(readability-simplify-boolean-expr) +} + +bool _dbUnfoldedChipInst::operator<(const _dbUnfoldedChipInst& rhs) const +{ + return true; +} + +_dbUnfoldedChipInst::_dbUnfoldedChipInst(_dbDatabase* db) +{ +} + +dbIStream& operator>>(dbIStream& stream, _dbUnfoldedChipInst& obj) +{ + stream >> obj.name_; + stream >> obj.chip_inst_path_; + stream >> obj.transform_; + stream >> obj.region_; + return stream; +} + +dbOStream& operator<<(dbOStream& stream, const _dbUnfoldedChipInst& obj) +{ + stream << obj.name_; + stream << obj.chip_inst_path_; + stream << obj.transform_; + stream << obj.region_; + return stream; +} + +void _dbUnfoldedChipInst::collectMemInfo(MemInfo& info) +{ + info.cnt++; + info.size += sizeof(*this); + + info.children["name"].add(name_); + info.children["chip_inst_path"].add(chip_inst_path_); +} + +//////////////////////////////////////////////////////////////////// +// +// dbUnfoldedChipInst - Methods +// +//////////////////////////////////////////////////////////////////// + +const std::string& dbUnfoldedChipInst::getName() const +{ + _dbUnfoldedChipInst* obj = (_dbUnfoldedChipInst*) this; + return obj->name_; +} + +dbTransform dbUnfoldedChipInst::getTransform() const +{ + _dbUnfoldedChipInst* obj = (_dbUnfoldedChipInst*) this; + return obj->transform_; +} + +// User Code Begin dbUnfoldedChipInstPublicMethods +Cuboid dbUnfoldedChipInst::getCuboid() const +{ + _dbUnfoldedChipInst* obj = (_dbUnfoldedChipInst*) this; + _dbDatabase* db = (_dbDatabase*) obj->getOwner(); + dbChipInst* leaf + = (dbChipInst*) db->chip_inst_tbl_->getPtr(obj->chip_inst_path_.back()); + Cuboid c = leaf->getMasterChip()->getCuboid(); + obj->transform_.apply(c); + return c; +} + +dbSet dbUnfoldedChipInst::getRegions() const +{ + _dbUnfoldedChipInst* obj = (_dbUnfoldedChipInst*) this; + _dbDatabase* db = (_dbDatabase*) obj->getOwner(); + return dbSet(obj, db->unfolded_region_itr_); +} + +dbUnfoldedRegionInst* dbUnfoldedChipInst::findRegion( + dbChipRegionInst* source) const +{ + for (dbUnfoldedRegionInst* region : getRegions()) { + if (region->getChipRegionInst() == source) { + return region; + } + } + return nullptr; +} + +std::vector dbUnfoldedChipInst::getChipInstPath() const +{ + _dbUnfoldedChipInst* obj = (_dbUnfoldedChipInst*) this; + _dbDatabase* db = (_dbDatabase*) obj->getOwner(); + std::vector path; + path.reserve(obj->chip_inst_path_.size()); + for (const auto& id : obj->chip_inst_path_) { + path.push_back((dbChipInst*) db->chip_inst_tbl_->getPtr(id)); + } + return path; +} +// User Code End dbUnfoldedChipInstPublicMethods +} // namespace odb +// Generator Code End Cpp \ No newline at end of file diff --git a/src/odb/src/db/dbUnfoldedChipInst.h b/src/odb/src/db/dbUnfoldedChipInst.h new file mode 100644 index 00000000000..28ae9cb71d4 --- /dev/null +++ b/src/odb/src/db/dbUnfoldedChipInst.h @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2019-2025, The OpenROAD Authors + +// Generator Code Begin Header +#pragma once + +#include +#include + +#include "dbCore.h" +#include "dbVector.h" +#include "odb/dbId.h" +#include "odb/dbTransform.h" +#include "odb/geom.h" + +namespace odb { +class dbIStream; +class dbOStream; +class _dbDatabase; +class _dbChipInst; +class _dbUnfoldedRegionInst; + +class _dbUnfoldedChipInst : public _dbObject +{ + public: + _dbUnfoldedChipInst(_dbDatabase*); + + bool operator==(const _dbUnfoldedChipInst& rhs) const; + bool operator!=(const _dbUnfoldedChipInst& rhs) const + { + return !operator==(rhs); + } + bool operator<(const _dbUnfoldedChipInst& rhs) const; + void collectMemInfo(MemInfo& info); + + std::string name_; + dbVector> chip_inst_path_; + dbTransform transform_; + dbId<_dbUnfoldedRegionInst> region_; +}; +dbIStream& operator>>(dbIStream& stream, _dbUnfoldedChipInst& obj); +dbOStream& operator<<(dbOStream& stream, const _dbUnfoldedChipInst& obj); +} // namespace odb +// Generator Code End Header \ No newline at end of file diff --git a/src/odb/src/db/dbUnfoldedConn.cpp b/src/odb/src/db/dbUnfoldedConn.cpp new file mode 100644 index 00000000000..a6122d23032 --- /dev/null +++ b/src/odb/src/db/dbUnfoldedConn.cpp @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2019-2025, The OpenROAD Authors + +// Generator Code Begin Cpp +#include "dbUnfoldedConn.h" + +#include "dbChipConn.h" +#include "dbCore.h" +#include "dbDatabase.h" +#include "dbTable.h" +#include "dbUnfoldedRegionInst.h" +#include "odb/db.h" +namespace odb { +template class dbTable<_dbUnfoldedConn>; + +bool _dbUnfoldedConn::operator==(const _dbUnfoldedConn& rhs) const +{ + // NOLINTBEGIN(readability-simplify-boolean-expr) + if (chip_conn_ != rhs.chip_conn_) { + return false; + } + if (top_region_ != rhs.top_region_) { + return false; + } + if (bottom_region_ != rhs.bottom_region_) { + return false; + } + + return true; + // NOLINTEND(readability-simplify-boolean-expr) +} + +bool _dbUnfoldedConn::operator<(const _dbUnfoldedConn& rhs) const +{ + return true; +} + +_dbUnfoldedConn::_dbUnfoldedConn(_dbDatabase* db) +{ +} + +dbIStream& operator>>(dbIStream& stream, _dbUnfoldedConn& obj) +{ + stream >> obj.chip_conn_; + stream >> obj.top_region_; + stream >> obj.bottom_region_; + return stream; +} + +dbOStream& operator<<(dbOStream& stream, const _dbUnfoldedConn& obj) +{ + stream << obj.chip_conn_; + stream << obj.top_region_; + stream << obj.bottom_region_; + return stream; +} + +void _dbUnfoldedConn::collectMemInfo(MemInfo& info) +{ + info.cnt++; + info.size += sizeof(*this); +} + +//////////////////////////////////////////////////////////////////// +// +// dbUnfoldedConn - Methods +// +//////////////////////////////////////////////////////////////////// + +dbChipConn* dbUnfoldedConn::getChipConn() const +{ + _dbUnfoldedConn* obj = (_dbUnfoldedConn*) this; + if (obj->chip_conn_ == 0) { + return nullptr; + } + _dbDatabase* par = (_dbDatabase*) obj->getOwner(); + return (dbChipConn*) par->chip_conn_tbl_->getPtr(obj->chip_conn_); +} + +dbUnfoldedRegionInst* dbUnfoldedConn::getTopRegion() const +{ + _dbUnfoldedConn* obj = (_dbUnfoldedConn*) this; + if (obj->top_region_ == 0) { + return nullptr; + } + _dbDatabase* par = (_dbDatabase*) obj->getOwner(); + return (dbUnfoldedRegionInst*) par->unfolded_region_inst_tbl_->getPtr( + obj->top_region_); +} + +dbUnfoldedRegionInst* dbUnfoldedConn::getBottomRegion() const +{ + _dbUnfoldedConn* obj = (_dbUnfoldedConn*) this; + if (obj->bottom_region_ == 0) { + return nullptr; + } + _dbDatabase* par = (_dbDatabase*) obj->getOwner(); + return (dbUnfoldedRegionInst*) par->unfolded_region_inst_tbl_->getPtr( + obj->bottom_region_); +} + +} // namespace odb +// Generator Code End Cpp \ No newline at end of file diff --git a/src/odb/src/db/dbUnfoldedConn.h b/src/odb/src/db/dbUnfoldedConn.h new file mode 100644 index 00000000000..f2b81662483 --- /dev/null +++ b/src/odb/src/db/dbUnfoldedConn.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2019-2025, The OpenROAD Authors + +// Generator Code Begin Header +#pragma once + +#include + +#include "dbCore.h" +#include "odb/dbId.h" + +namespace odb { +class dbIStream; +class dbOStream; +class _dbDatabase; +class _dbChipConn; +class _dbUnfoldedRegionInst; + +class _dbUnfoldedConn : public _dbObject +{ + public: + _dbUnfoldedConn(_dbDatabase*); + + bool operator==(const _dbUnfoldedConn& rhs) const; + bool operator!=(const _dbUnfoldedConn& rhs) const { return !operator==(rhs); } + bool operator<(const _dbUnfoldedConn& rhs) const; + void collectMemInfo(MemInfo& info); + + dbId<_dbChipConn> chip_conn_; + dbId<_dbUnfoldedRegionInst> top_region_; + dbId<_dbUnfoldedRegionInst> bottom_region_; +}; +dbIStream& operator>>(dbIStream& stream, _dbUnfoldedConn& obj); +dbOStream& operator<<(dbOStream& stream, const _dbUnfoldedConn& obj); +} // namespace odb +// Generator Code End Header \ No newline at end of file diff --git a/src/odb/src/db/dbUnfoldedNet.cpp b/src/odb/src/db/dbUnfoldedNet.cpp new file mode 100644 index 00000000000..1023eab211b --- /dev/null +++ b/src/odb/src/db/dbUnfoldedNet.cpp @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2019-2025, The OpenROAD Authors + +// Generator Code Begin Cpp +#include "dbUnfoldedNet.h" + +#include "dbChipNet.h" +#include "dbCore.h" +#include "dbDatabase.h" +#include "dbTable.h" +#include "dbUnfoldedBumpInst.h" +#include "odb/db.h" +namespace odb { +template class dbTable<_dbUnfoldedNet>; + +bool _dbUnfoldedNet::operator==(const _dbUnfoldedNet& rhs) const +{ + // NOLINTBEGIN(readability-simplify-boolean-expr) + if (chip_net_ != rhs.chip_net_) { + return false; + } + + return true; + // NOLINTEND(readability-simplify-boolean-expr) +} + +bool _dbUnfoldedNet::operator<(const _dbUnfoldedNet& rhs) const +{ + return true; +} + +_dbUnfoldedNet::_dbUnfoldedNet(_dbDatabase* db) +{ +} + +dbIStream& operator>>(dbIStream& stream, _dbUnfoldedNet& obj) +{ + stream >> obj.chip_net_; + stream >> obj.connected_bumps_; + return stream; +} + +dbOStream& operator<<(dbOStream& stream, const _dbUnfoldedNet& obj) +{ + stream << obj.chip_net_; + stream << obj.connected_bumps_; + return stream; +} + +void _dbUnfoldedNet::collectMemInfo(MemInfo& info) +{ + info.cnt++; + info.size += sizeof(*this); + + info.children["connected_bumps"].add(connected_bumps_); +} + +//////////////////////////////////////////////////////////////////// +// +// dbUnfoldedNet - Methods +// +//////////////////////////////////////////////////////////////////// + +dbChipNet* dbUnfoldedNet::getChipNet() const +{ + _dbUnfoldedNet* obj = (_dbUnfoldedNet*) this; + if (obj->chip_net_ == 0) { + return nullptr; + } + _dbDatabase* par = (_dbDatabase*) obj->getOwner(); + return (dbChipNet*) par->chip_net_tbl_->getPtr(obj->chip_net_); +} + +// User Code Begin dbUnfoldedNetPublicMethods +std::vector dbUnfoldedNet::getConnectedBumps() const +{ + _dbUnfoldedNet* obj = (_dbUnfoldedNet*) this; + _dbDatabase* db = (_dbDatabase*) obj->getOwner(); + std::vector bumps; + bumps.reserve(obj->connected_bumps_.size()); + for (const auto& id : obj->connected_bumps_) { + bumps.push_back( + (dbUnfoldedBumpInst*) db->unfolded_bump_inst_tbl_->getPtr(id)); + } + return bumps; +} +// User Code End dbUnfoldedNetPublicMethods +} // namespace odb +// Generator Code End Cpp \ No newline at end of file diff --git a/src/odb/src/db/dbUnfoldedNet.h b/src/odb/src/db/dbUnfoldedNet.h new file mode 100644 index 00000000000..74ce08f564f --- /dev/null +++ b/src/odb/src/db/dbUnfoldedNet.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2019-2025, The OpenROAD Authors + +// Generator Code Begin Header +#pragma once + +#include + +#include "dbCore.h" +#include "dbVector.h" +#include "odb/dbId.h" + +namespace odb { +class dbIStream; +class dbOStream; +class _dbDatabase; +class _dbChipNet; +class _dbUnfoldedBumpInst; + +class _dbUnfoldedNet : public _dbObject +{ + public: + _dbUnfoldedNet(_dbDatabase*); + + bool operator==(const _dbUnfoldedNet& rhs) const; + bool operator!=(const _dbUnfoldedNet& rhs) const { return !operator==(rhs); } + bool operator<(const _dbUnfoldedNet& rhs) const; + void collectMemInfo(MemInfo& info); + + dbId<_dbChipNet> chip_net_; + dbVector> connected_bumps_; +}; +dbIStream& operator>>(dbIStream& stream, _dbUnfoldedNet& obj); +dbOStream& operator<<(dbOStream& stream, const _dbUnfoldedNet& obj); +} // namespace odb +// Generator Code End Header \ No newline at end of file diff --git a/src/odb/src/db/dbUnfoldedRegionInst.cpp b/src/odb/src/db/dbUnfoldedRegionInst.cpp new file mode 100644 index 00000000000..ff740fca913 --- /dev/null +++ b/src/odb/src/db/dbUnfoldedRegionInst.cpp @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2019-2025, The OpenROAD Authors + +// Generator Code Begin Cpp +#include "dbUnfoldedRegionInst.h" + +#include +#include + +#include "dbChipRegion.h" +#include "dbChipRegionInst.h" +#include "dbCore.h" +#include "dbDatabase.h" +#include "dbTable.h" +#include "dbUnfoldedChipInst.h" +#include "odb/db.h" +#include "odb/dbSet.h" +#include "odb/geom.h" +// User Code Begin Includes +#include "dbUnfoldedBumpInstItr.h" +// User Code End Includes +namespace odb { +template class dbTable<_dbUnfoldedRegionInst>; + +bool _dbUnfoldedRegionInst::operator==(const _dbUnfoldedRegionInst& rhs) const +{ + // NOLINTBEGIN(readability-simplify-boolean-expr) + if (flags_.effective_side_ != rhs.flags_.effective_side_) { + return false; + } + if (chip_region_inst_ != rhs.chip_region_inst_) { + return false; + } + if (parent_chip_ != rhs.parent_chip_) { + return false; + } + if (chip_next_ != rhs.chip_next_) { + return false; + } + if (bump_ != rhs.bump_) { + return false; + } + + return true; + // NOLINTEND(readability-simplify-boolean-expr) +} + +bool _dbUnfoldedRegionInst::operator<(const _dbUnfoldedRegionInst& rhs) const +{ + return true; +} + +_dbUnfoldedRegionInst::_dbUnfoldedRegionInst(_dbDatabase* db) +{ + flags_ = {}; +} + +dbIStream& operator>>(dbIStream& stream, _dbUnfoldedRegionInst& obj) +{ + uint32_t flags_bit_field; + stream >> flags_bit_field; + static_assert(sizeof(obj.flags_) == sizeof(flags_bit_field)); + std::memcpy(&obj.flags_, &flags_bit_field, sizeof(flags_bit_field)); + stream >> obj.chip_region_inst_; + stream >> obj.parent_chip_; + stream >> obj.chip_next_; + stream >> obj.bump_; + return stream; +} + +dbOStream& operator<<(dbOStream& stream, const _dbUnfoldedRegionInst& obj) +{ + uint32_t flags_bit_field; + static_assert(sizeof(obj.flags_) == sizeof(flags_bit_field)); + std::memcpy(&flags_bit_field, &obj.flags_, sizeof(obj.flags_)); + stream << flags_bit_field; + stream << obj.chip_region_inst_; + stream << obj.parent_chip_; + stream << obj.chip_next_; + stream << obj.bump_; + return stream; +} + +void _dbUnfoldedRegionInst::collectMemInfo(MemInfo& info) +{ + info.cnt++; + info.size += sizeof(*this); +} + +//////////////////////////////////////////////////////////////////// +// +// dbUnfoldedRegionInst - Methods +// +//////////////////////////////////////////////////////////////////// + +dbChipRegionInst* dbUnfoldedRegionInst::getChipRegionInst() const +{ + _dbUnfoldedRegionInst* obj = (_dbUnfoldedRegionInst*) this; + if (obj->chip_region_inst_ == 0) { + return nullptr; + } + _dbDatabase* par = (_dbDatabase*) obj->getOwner(); + return (dbChipRegionInst*) par->chip_region_inst_tbl_->getPtr( + obj->chip_region_inst_); +} + +dbUnfoldedChipInst* dbUnfoldedRegionInst::getParentChip() const +{ + _dbUnfoldedRegionInst* obj = (_dbUnfoldedRegionInst*) this; + if (obj->parent_chip_ == 0) { + return nullptr; + } + _dbDatabase* par = (_dbDatabase*) obj->getOwner(); + return (dbUnfoldedChipInst*) par->unfolded_chip_inst_tbl_->getPtr( + obj->parent_chip_); +} + +// User Code Begin dbUnfoldedRegionInstPublicMethods +Cuboid dbUnfoldedRegionInst::getCuboid() const +{ + _dbUnfoldedRegionInst* obj = (_dbUnfoldedRegionInst*) this; + _dbDatabase* db = (_dbDatabase*) obj->getOwner(); + dbChipRegionInst* reg_inst + = (dbChipRegionInst*) db->chip_region_inst_tbl_->getPtr( + obj->chip_region_inst_); + Cuboid c = reg_inst->getChipRegion()->getCuboid(); + _dbUnfoldedChipInst* parent + = db->unfolded_chip_inst_tbl_->getPtr(obj->parent_chip_); + parent->transform_.apply(c); + return c; +} + +dbUnfoldedRegionInst::EffectiveSide dbUnfoldedRegionInst::getEffectiveSide() + const +{ + _dbUnfoldedRegionInst* obj = (_dbUnfoldedRegionInst*) this; + return static_cast(obj->flags_.effective_side_); +} + +void dbUnfoldedRegionInst::setEffectiveSide(EffectiveSide side) +{ + _dbUnfoldedRegionInst* obj = (_dbUnfoldedRegionInst*) this; + obj->flags_.effective_side_ = static_cast(side); +} + +bool dbUnfoldedRegionInst::isTop() const +{ + return getEffectiveSide() == EffectiveSide::TOP; +} + +bool dbUnfoldedRegionInst::isBottom() const +{ + return getEffectiveSide() == EffectiveSide::BOTTOM; +} + +bool dbUnfoldedRegionInst::isInternal() const +{ + return getEffectiveSide() == EffectiveSide::INTERNAL; +} + +bool dbUnfoldedRegionInst::isInternalExt() const +{ + return getEffectiveSide() == EffectiveSide::INTERNAL_EXT; +} + +int dbUnfoldedRegionInst::getSurfaceZ() const +{ + Cuboid c = getCuboid(); + if (isTop()) { + return c.zMax(); + } + if (isBottom()) { + return c.zMin(); + } + return c.zCenter(); +} + +dbSet dbUnfoldedRegionInst::getBumps() const +{ + _dbUnfoldedRegionInst* obj = (_dbUnfoldedRegionInst*) this; + _dbDatabase* db = (_dbDatabase*) obj->getOwner(); + return dbSet(obj, db->unfolded_bump_itr_); +} +// User Code End dbUnfoldedRegionInstPublicMethods +} // namespace odb +// Generator Code End Cpp \ No newline at end of file diff --git a/src/odb/src/db/dbUnfoldedRegionInst.h b/src/odb/src/db/dbUnfoldedRegionInst.h new file mode 100644 index 00000000000..63fbcb3beb6 --- /dev/null +++ b/src/odb/src/db/dbUnfoldedRegionInst.h @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2019-2025, The OpenROAD Authors + +// Generator Code Begin Header +#pragma once + +#include + +#include "dbCore.h" +#include "odb/dbId.h" + +namespace odb { +class dbIStream; +class dbOStream; +class _dbDatabase; +class _dbChipRegionInst; +class _dbUnfoldedChipInst; +class _dbUnfoldedBumpInst; + +struct dbUnfoldedRegionInstFlags +{ + uint32_t effective_side_ : 2 = 0; + uint32_t spare_bits : 30; +}; + +class _dbUnfoldedRegionInst : public _dbObject +{ + public: + _dbUnfoldedRegionInst(_dbDatabase*); + + bool operator==(const _dbUnfoldedRegionInst& rhs) const; + bool operator!=(const _dbUnfoldedRegionInst& rhs) const + { + return !operator==(rhs); + } + bool operator<(const _dbUnfoldedRegionInst& rhs) const; + void collectMemInfo(MemInfo& info); + + dbUnfoldedRegionInstFlags flags_; + dbId<_dbChipRegionInst> chip_region_inst_; + dbId<_dbUnfoldedChipInst> parent_chip_; + dbId<_dbUnfoldedRegionInst> chip_next_; + dbId<_dbUnfoldedBumpInst> bump_; +}; +dbIStream& operator>>(dbIStream& stream, _dbUnfoldedRegionInst& obj); +dbOStream& operator<<(dbOStream& stream, const _dbUnfoldedRegionInst& obj); +} // namespace odb +// Generator Code End Header \ No newline at end of file diff --git a/src/odb/src/db/dbUnfoldedRegionInstItr.cpp b/src/odb/src/db/dbUnfoldedRegionInstItr.cpp new file mode 100644 index 00000000000..706d810f943 --- /dev/null +++ b/src/odb/src/db/dbUnfoldedRegionInstItr.cpp @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2019-2025, The OpenROAD Authors + +// Generator Code Begin Cpp +#include "dbUnfoldedRegionInstItr.h" + +#include + +#include "dbTable.h" +#include "dbUnfoldedChipInst.h" +#include "dbUnfoldedRegionInst.h" + +namespace odb { + +//////////////////////////////////////////////////////////////////// +// +// dbUnfoldedRegionInstItr - Methods +// +//////////////////////////////////////////////////////////////////// + +bool dbUnfoldedRegionInstItr::reversible() const +{ + return true; +} + +bool dbUnfoldedRegionInstItr::orderReversed() const +{ + return true; +} + +void dbUnfoldedRegionInstItr::reverse(dbObject* parent) +{ + // User Code Begin reverse + _dbUnfoldedChipInst* chip = (_dbUnfoldedChipInst*) parent; + uint32_t id = chip->region_; + uint32_t list = 0; + while (id != 0) { + _dbUnfoldedRegionInst* region = unfolded_region_inst_tbl_->getPtr(id); + uint32_t n = region->chip_next_; + region->chip_next_ = list; + list = id; + id = n; + } + chip->region_ = list; + // User Code End reverse +} + +uint32_t dbUnfoldedRegionInstItr::sequential() const +{ + return 0; +} + +uint32_t dbUnfoldedRegionInstItr::size(dbObject* parent) const +{ + uint32_t id; + uint32_t cnt = 0; + + for (id = dbUnfoldedRegionInstItr::begin(parent); + id != dbUnfoldedRegionInstItr::end(parent); + id = dbUnfoldedRegionInstItr::next(id)) { + ++cnt; + } + + return cnt; +} + +uint32_t dbUnfoldedRegionInstItr::begin(dbObject* parent) const +{ + // User Code Begin begin + return ((_dbUnfoldedChipInst*) parent)->region_; + // User Code End begin +} + +uint32_t dbUnfoldedRegionInstItr::end(dbObject* /* unused: parent */) const +{ + return 0; +} + +uint32_t dbUnfoldedRegionInstItr::next(uint32_t id, ...) const +{ + // User Code Begin next + return unfolded_region_inst_tbl_->getPtr(id)->chip_next_; + // User Code End next +} + +dbObject* dbUnfoldedRegionInstItr::getObject(uint32_t id, ...) +{ + return unfolded_region_inst_tbl_->getPtr(id); +} +} // namespace odb +// Generator Code End Cpp \ No newline at end of file diff --git a/src/odb/src/db/dbUnfoldedRegionInstItr.h b/src/odb/src/db/dbUnfoldedRegionInstItr.h new file mode 100644 index 00000000000..fe089358591 --- /dev/null +++ b/src/odb/src/db/dbUnfoldedRegionInstItr.h @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2019-2025, The OpenROAD Authors + +// Generator Code Begin Header +#pragma once + +#include + +#include "dbCore.h" +#include "odb/dbIterator.h" + +namespace odb { +class _dbUnfoldedRegionInst; + +class dbUnfoldedRegionInstItr : public dbIterator +{ + public: + dbUnfoldedRegionInstItr( + dbTable<_dbUnfoldedRegionInst>* unfolded_region_inst_tbl) + { + unfolded_region_inst_tbl_ = unfolded_region_inst_tbl; + } + + bool reversible() const override; + bool orderReversed() const override; + void reverse(dbObject* parent) override; + uint32_t sequential() const override; + uint32_t size(dbObject* parent) const override; + uint32_t begin(dbObject* parent) const override; + uint32_t end(dbObject* parent) const override; + uint32_t next(uint32_t id, ...) const override; + dbObject* getObject(uint32_t id, ...) override; + + private: + dbTable<_dbUnfoldedRegionInst>* unfolded_region_inst_tbl_; +}; + +} // namespace odb +// Generator Code End Header \ No newline at end of file diff --git a/src/odb/src/db/unfoldedModel.cpp b/src/odb/src/db/unfoldedModel.cpp deleted file mode 100644 index b0db1f0ba87..00000000000 --- a/src/odb/src/db/unfoldedModel.cpp +++ /dev/null @@ -1,310 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2023-2026, The OpenROAD Authors - -#include "odb/unfoldedModel.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "odb/db.h" -#include "odb/dbTransform.h" -#include "odb/dbTypes.h" -#include "odb/geom.h" -#include "utl/Logger.h" - -namespace odb { - -namespace { - -std::vector concatPath(const std::vector& head, - const std::vector& tail) -{ - if (tail.empty()) { - return head; - } - std::vector full = head; - full.insert(full.end(), tail.begin(), tail.end()); - return full; -} - -std::string getFullPathName(const std::vector& path) -{ - std::string name; - for (auto* p : path) { - if (!name.empty()) { - name += '/'; - } - name += p->getName(); - } - return name; -} - -UnfoldedRegionSide mirrorSide(UnfoldedRegionSide side) -{ - if (side == UnfoldedRegionSide::TOP) { - return UnfoldedRegionSide::BOTTOM; - } - if (side == UnfoldedRegionSide::BOTTOM) { - return UnfoldedRegionSide::TOP; - } - return side; -} - -} // namespace - -Rect UnfoldedAlignmentMarker::getBBox() const -{ - Rect bbox = inst->getBBox()->getBox(); - parent_chip->transform.apply(bbox); - return bbox; -} - -dbOrientType UnfoldedAlignmentMarker::getOrient() const -{ - dbTransform inst_xform = inst->getTransform(); - dbTransform total_xform = inst_xform; - total_xform.concat(parent_chip->transform); - return total_xform.getOrient(); -} - -int UnfoldedRegion::getSurfaceZ() const -{ - if (isTop()) { - return cuboid.zMax(); - } - if (isBottom()) { - return cuboid.zMin(); - } - return cuboid.zCenter(); -} - -UnfoldedRegion* UnfoldedChip::findUnfoldedRegion(dbChipRegionInst* inst) -{ - auto it = region_map.find(inst); - return it != region_map.end() ? it->second : nullptr; -} - -UnfoldedBump* UnfoldedChip::findUnfoldedBump(dbChipBumpInst* bump_inst) -{ - auto it = bump_inst_map.find(bump_inst); - return it != bump_inst_map.end() ? it->second : nullptr; -} - -UnfoldedModel::UnfoldedModel(utl::Logger* logger, dbChip* chip) - : logger_(logger) -{ - std::vector path; - for (dbAlignmentMarkerRule* rule : chip->getDb()->getAlignmentMarkerRules()) { - dbMaster* master_a = rule->getMasterA(); - dbMaster* master_b = rule->getMasterB(); - alignment_marker_rule_map_[master_a].push_back(rule); - if (master_b != master_a) { - alignment_marker_rule_map_[master_b].push_back(rule); - } - } - for (dbChipInst* inst : chip->getChipInsts()) { - buildUnfoldedChip(inst, path, dbTransform()); - } - unfoldConnections(chip, {}); - unfoldNets(chip, {}); -} - -UnfoldedChip* UnfoldedModel::buildUnfoldedChip(dbChipInst* inst, - std::vector& path, - const dbTransform& parent_xform) -{ - dbChip* master = inst->getMasterChip(); - path.push_back(inst); - - const dbTransform inst_xform = inst->getTransform(); - dbTransform total = inst_xform; - total.concat(parent_xform); - - if (master->getChipType() == dbChip::ChipType::HIER) { - for (auto* sub : master->getChipInsts()) { - buildUnfoldedChip(sub, path, total); - } - - unfoldConnections(master, path); - unfoldNets(master, path); - path.pop_back(); - return nullptr; - } - - UnfoldedChip uf_chip; - uf_chip.name = getFullPathName(path); - uf_chip.chip_inst_path = path; - uf_chip.transform = total; - uf_chip.cuboid = master->getCuboid(); - - // Transform cuboid to global space - uf_chip.transform.apply(uf_chip.cuboid); - unfoldRegions(uf_chip, inst); - unfoldAlignmentMarkers(uf_chip); - - unfolded_chips_.push_back(std::move(uf_chip)); - UnfoldedChip* created_chip = &unfolded_chips_.back(); - registerUnfoldedChip(created_chip); - - path.pop_back(); - return created_chip; -} - -void UnfoldedModel::registerUnfoldedChip(UnfoldedChip* chip) -{ - chip_map_[chip->name] = chip; - for (auto& region : chip->regions) { - region.parent_chip = chip; - chip->region_map[region.region_inst] = ®ion; - for (auto& bump : region.bumps) { - bump.parent_region = ®ion; - chip->bump_inst_map[bump.bump_inst] = ≎ - } - } - for (auto& marker : chip->alignment_markers) { - marker.parent_chip = chip; - } -} - -void UnfoldedModel::unfoldRegions(UnfoldedChip& uf_chip, dbChipInst* inst) -{ - auto regions = inst->getRegions(); - - for (auto* region_inst : regions) { - auto region = region_inst->getChipRegion(); - - UnfoldedRegionSide side = UnfoldedRegionSide::INTERNAL; - switch (region->getSide()) { - case dbChipRegion::Side::FRONT: - side = UnfoldedRegionSide::TOP; - break; - case dbChipRegion::Side::BACK: - side = UnfoldedRegionSide::BOTTOM; - break; - case dbChipRegion::Side::INTERNAL: - side = UnfoldedRegionSide::INTERNAL; - break; - case dbChipRegion::Side::INTERNAL_EXT: - side = UnfoldedRegionSide::INTERNAL_EXT; - break; - } - - if (uf_chip.transform.isMirrorZ()) { - side = mirrorSide(side); - } - - UnfoldedRegion uf_region; - uf_region.region_inst = region_inst; - uf_region.effective_side = side; - uf_region.cuboid = region->getCuboid(); - - uf_chip.transform.apply(uf_region.cuboid); - uf_chip.regions.push_back(std::move(uf_region)); - unfoldBumps(uf_chip.regions.back(), uf_chip.transform); - } -} - -void UnfoldedModel::unfoldBumps(UnfoldedRegion& uf_region, - const dbTransform& transform) -{ - const int z = uf_region.getSurfaceZ(); - for (auto* bump_inst : uf_region.region_inst->getChipBumpInsts()) { - dbChipBump* bump = bump_inst->getChipBump(); - if (auto* inst = bump->getInst()) { - Point global_xy = inst->getLocation(); - transform.apply(global_xy); - uf_region.bumps.push_back( - {.bump_inst = bump_inst, - .parent_region = nullptr, // set later in registerUnfoldedChip - .global_position = Point3D(global_xy.x(), global_xy.y(), z)}); - } - } -} - -void UnfoldedModel::unfoldAlignmentMarkers(UnfoldedChip& uf_chip) -{ - auto block = uf_chip.chip_inst_path.back()->getMasterChip()->getBlock(); - if (block == nullptr) { - return; - } - for (dbInst* inst : block->getInsts()) { - dbMaster* master = inst->getMaster(); - if (alignment_marker_rule_map_.find(master) - != alignment_marker_rule_map_.end()) { - uf_chip.alignment_markers.push_back( - {.parent_chip = nullptr, .inst = inst}); - } - } -} - -UnfoldedChip* UnfoldedModel::findUnfoldedChip(const std::string& path) -{ - auto it = chip_map_.find(path); - return it != chip_map_.end() ? it->second : nullptr; -} - -UnfoldedChip* UnfoldedModel::findUnfoldedChip( - const std::vector& path) -{ - return findUnfoldedChip(getFullPathName(path)); -} - -void UnfoldedModel::unfoldConnections( - dbChip* chip, - const std::vector& parent_path) -{ - for (auto* conn : chip->getChipConns()) { - UnfoldedChip* top_chip - = findUnfoldedChip(concatPath(parent_path, conn->getTopRegionPath())); - UnfoldedRegion* top_region(nullptr); - if (top_chip) { - top_region = top_chip->findUnfoldedRegion(conn->getTopRegion()); - } - UnfoldedChip* bot_chip = findUnfoldedChip( - concatPath(parent_path, conn->getBottomRegionPath())); - UnfoldedRegion* bot_region(nullptr); - if (bot_chip) { - bot_region = bot_chip->findUnfoldedRegion(conn->getBottomRegion()); - } - if (top_region || bot_region) { - UnfoldedConnection uf_conn{.connection = conn, - .top_region = top_region, - .bottom_region = bot_region}; - if (top_region && top_region->isInternalExt()) { - top_region->isUsed = true; - } - if (bot_region && bot_region->isInternalExt()) { - bot_region->isUsed = true; - } - unfolded_connections_.push_back(uf_conn); - } - } -} - -void UnfoldedModel::unfoldNets(dbChip* chip, - const std::vector& parent_path) -{ - for (auto* net : chip->getChipNets()) { - UnfoldedNet uf_net; - uf_net.chip_net = net; - for (uint32_t i = 0; i < net->getNumBumpInsts(); i++) { - std::vector rel_path; - dbChipBumpInst* b_inst = net->getBumpInst(i, rel_path); - UnfoldedChip* chip = findUnfoldedChip(concatPath(parent_path, rel_path)); - if (chip) { - UnfoldedBump* bump = chip->findUnfoldedBump(b_inst); - if (bump) { - uf_net.connected_bumps.push_back(bump); - } - } - } - unfolded_nets_.push_back(std::move(uf_net)); - } -} - -} // namespace odb