odb: refactor 3dblox checkOverlappingChips#9469
odb: refactor 3dblox checkOverlappingChips#9469ahmed532 wants to merge 2 commits intoThe-OpenROAD-Project:masterfrom
Conversation
Allow overlapping embedded chips. Use a line sweep algorithm and connection map for better performance. Create more tests. Signed-off-by: Ahmed R. Mohamed <ahmed@precisioninno.com>
There was a problem hiding this comment.
Code Review
This pull request refactors the checkOverlappingChips function to improve performance and support overlapping embedded chips. The changes include using a sweep-line algorithm for faster overlap detection and relaxing the validation for INTERNAL_EXT connections to handle embedded chip scenarios. The code is cleaner and more modern. The addition of comprehensive test cases is a great way to ensure the new logic is correct. Overall, this is a solid improvement, with a suggestion for minor readability and performance enhancement by moving a lambda definition outside a loop.
src/odb/src/3dblox/checker.cpp
Outdated
| { | ||
| auto overlap = chip1->cuboid.intersect(chip2->cuboid); | ||
| Rect overlap_rect( | ||
| overlap.xMin(), overlap.yMin(), overlap.xMax(), overlap.yMax()); | ||
|
|
||
| const auto* c1 = chip1; | ||
| const auto* c2 = chip2; | ||
| if (c1 > c2) { | ||
| std::swap(c1, c2); | ||
| } | ||
|
|
||
| auto it = connection_map.find({c1, c2}); | ||
| if (it == connection_map.end()) { | ||
| return false; | ||
| } | ||
|
|
||
| for (const auto* conn_ptr : it->second) { | ||
| const auto& conn = *conn_ptr; | ||
| // We already know parent chips match c1/c2 due to map validation | ||
| if (!isValid(conn)) { | ||
| continue; | ||
| } | ||
| auto* r1 = conn.top_region; | ||
| auto* r2 = conn.bottom_region; | ||
| auto valid = [&](auto* r) { | ||
| return r->isInternalExt() | ||
| && Rect(r->cuboid.xMin(), | ||
| r->cuboid.yMin(), | ||
| r->cuboid.xMax(), | ||
| r->cuboid.yMax()) | ||
| .contains(overlap_rect); | ||
| }; | ||
| if (valid(r1) || valid(r2)) { | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| } |
There was a problem hiding this comment.
For improved readability and to avoid recreating the lambda in each iteration of the loop, you can define the valid lambda before the loop starts.
{
auto overlap = chip1->cuboid.intersect(chip2->cuboid);
Rect overlap_rect(
overlap.xMin(), overlap.yMin(), overlap.xMax(), overlap.yMax());
const auto* c1 = chip1;
const auto* c2 = chip2;
if (c1 > c2) {
std::swap(c1, c2);
}
auto it = connection_map.find({c1, c2});
if (it == connection_map.end()) {
return false;
}
auto valid = [&](const auto* r) {
return r->isInternalExt()
&& Rect(r->cuboid.xMin(),
r->cuboid.yMin(),
r->cuboid.xMax(),
r->cuboid.yMax())
.contains(overlap_rect);
};
for (const auto* conn_ptr : it->second) {
const auto& conn = *conn_ptr;
// We already know parent chips match c1/c2 due to map validation
if (!isValid(conn)) {
continue;
}
auto* r1 = conn.top_region;
auto* r2 = conn.bottom_region;
if (valid(r1) || valid(r2)) {
return true;
}
}
return false;
}There was a problem hiding this comment.
please define externally in a namespace
|
clang-tidy review says "All clean, LGTM! 👍" |
osamahammad21
left a comment
There was a problem hiding this comment.
I feel that using connections to verify overlap violations is an overkill. It is simply a violation if 2 chiplets overlap at any condition.
src/odb/src/3dblox/checker.cpp
Outdated
| { | ||
| auto overlap = chip1->cuboid.intersect(chip2->cuboid); | ||
| Rect overlap_rect( | ||
| overlap.xMin(), overlap.yMin(), overlap.xMax(), overlap.yMax()); | ||
|
|
||
| const auto* c1 = chip1; | ||
| const auto* c2 = chip2; | ||
| if (c1 > c2) { | ||
| std::swap(c1, c2); | ||
| } | ||
|
|
||
| auto it = connection_map.find({c1, c2}); | ||
| if (it == connection_map.end()) { | ||
| return false; | ||
| } | ||
|
|
||
| for (const auto* conn_ptr : it->second) { | ||
| const auto& conn = *conn_ptr; | ||
| // We already know parent chips match c1/c2 due to map validation | ||
| if (!isValid(conn)) { | ||
| continue; | ||
| } | ||
| auto* r1 = conn.top_region; | ||
| auto* r2 = conn.bottom_region; | ||
| auto valid = [&](auto* r) { | ||
| return r->isInternalExt() | ||
| && Rect(r->cuboid.xMin(), | ||
| r->cuboid.yMin(), | ||
| r->cuboid.xMax(), | ||
| r->cuboid.yMax()) | ||
| .contains(overlap_rect); | ||
| }; | ||
| if (valid(r1) || valid(r2)) { | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| } |
There was a problem hiding this comment.
please define externally in a namespace
src/odb/src/3dblox/checker.cpp
Outdated
| if (valid(r1) || valid(r2)) { | ||
| return true; | ||
| } |
There was a problem hiding this comment.
The spec allows it like in the diagram on page 18 cases 1 and 3. We define the internal_ext region to span the whole chip z (for now) and this check ensure that it's x and y span the whole overlap (embedded chip).
|
The spec allows embedded chiplets connected via internal_ext. That means one chiplet completely inside another -- an overlap. But that is not a violation if the internal_ext region covers the overlap. You can find examples in the tests. |
Signed-off-by: Ahmed R. Mohamed <ahmed@precisioninno.com>
|
clang-tidy review says "All clean, LGTM! 👍" |
refactors the 3DBlox checkOverlappingChips
Significantly improve performance.
Changes:
Validation
Passed all tests in Test3DBloxChecker.
Verified that existing functionality for floating chips and simple overlaps remains correct.
Related to: #9291