odb: decompose non-rectilinear LEF polygons into rectangles (#10256)#10715
odb: decompose non-rectilinear LEF polygons into rectangles (#10256)#10715saurav-fermions wants to merge 2 commits into
Conversation
…ROAD-Project#10256) LEF POLYGON ingestion and the polygon->box->consumer chain were already intact, and rectilinear (Manhattan) polygons decomposed correctly. The real defect was non-rectilinear (45-degree/sloped) polygons: decompose_polygon fed them into Boost.Polygon's polygon_90 machinery, which only models axis-aligned geometry and corrupted sloped shapes (both dropping real metal and filling empty corners). This produced wrong obstruction/pin geometry for octagonal IO pads (e.g. sky130_ef_io__gpiov2_pad), causing the missing-geometry shorts/DRC violations vs KLayout. Fix: keep the exact polygon_90 path for rectilinear polygons (unchanged output), and for non-rectilinear polygons fracture into horizontal trapezoids and staircase each into axis-aligned rectangles, rounding outward so the result fully covers the sloped edges (never leaving gaps/shorts). Add TestGeom unit tests: rectangle, rectilinear L-shape (regression-guard the already-working path), and an octagon coverage test that fails before / passes after. Signed-off-by: Saurav Singh <saurav.singh@fermions.co>
There was a problem hiding this comment.
Code Review
This pull request introduces support for decomposing non-rectilinear (e.g., 45-degree or octagonal) polygons into axis-aligned rectangles by fracturing them into horizontal trapezoids and staircasing them, while preserving the fast, exact path for Manhattan polygons. Unit tests have been added to verify the correctness of the decomposition. The reviewer suggested a performance optimization in staircaseTrapezoid to bypass the unit-by-unit Y loop when a trapezoid is purely rectangular (has no sloped edges).
| y_lo = std::min(y_lo, gtl::y(p)); | ||
| y_hi = std::max(y_hi, gtl::y(p)); | ||
| } | ||
|
|
There was a problem hiding this comment.
For horizontal trapezoids that do not contain any sloped edges (i.e., they are purely rectangular), we can avoid the unit-by-unit Y loop entirely. This is a significant performance optimization because non-rectilinear polygons (like octagons) often decompose into a mix of sloped and purely rectangular trapezoids, and the rectangular parts can be quite tall in DBUs, leading to thousands of unnecessary iterations and floating-point operations.
bool has_sloped_edge = false;
for (int i = 0; i < n; ++i) {
const auto& a = v[i];
const auto& b = v[(i + 1) % n];
if (gtl::x(a) != gtl::x(b) && gtl::y(a) != gtl::y(b)) {
has_sloped_edge = true;
break;
}
}
if (!has_sloped_edge) {
int x_lo = std::numeric_limits<int>::max();
int x_hi = std::numeric_limits<int>::min();
for (const auto& p : v) {
x_lo = std::min(x_lo, gtl::x(p));
x_hi = std::max(x_hi, gtl::x(p));
}
if (x_lo < x_hi && y_lo < y_hi) {
if (!rects.empty() && rects.back().xMin() == x_lo
&& rects.back().xMax() == x_hi && rects.back().yMax() == y_lo) {
rects.back().set_yhi(y_hi);
} else {
rects.emplace_back(x_lo, y_lo, x_hi, y_hi);
}
}
return;
}|
What motivates this PR? |
|
Hi @maliberty — this one's from #10256: sky130's Rectilinear polygons already decompose fine — it's the sloped ones that get mangled. This PR fixes just that case and leaves the rectilinear path untouched; odb tests still pass. Glad to add a regression test for the pad if you'd like. I wasn't totally sure which angle your question was getting at though — if you had something specific in mind (scope, the approach, a particular concern), point me at it and I'll address it directly. For context: we're Fermions (fermions.co) — this came out of a human + AI workflow with our agent SAIGE (benchmarked on NVIDIA CVDP and RTLLM 2.0). |
Non-rectilinear polygons fracture into a mix of sloped and purely rectangular horizontal trapezoids. The rectangular ones (e.g. the straight body of an octagonal pad) can be thousands of DBU tall, and the per-DBU band loop iterated over every row only to coalesce them back into one rectangle. Detect the no-sloped-edge case and emit the rectangle directly. Output is unchanged. Addresses gemini-code-assist review on The-OpenROAD-Project#10715. Signed-off-by: Saurav Singh <saurav.singh@fermions.co>
|
Thanks. Motivation (from above): sky130 octagonal IO pads have 45° polygon geometry that was being drawn wrong vs KLayout, causing DRC violations/shorts — this fixes the sloped case and leaves the rectilinear path untouched. I took the performance suggestion: rectangular sub-trapezoids (the straight body of a pad) now emit a single rectangle instead of iterating per-DBU; output is identical (the existing |
Summary
Non-rectilinear (45°/sloped) LEF polygons (e.g. octagonal IO pads) were corrupted during decomposition; rectilinear polygons were already handled correctly. This decomposes sloped polygons into rectangles, leaving the already-working rectilinear path byte-for-byte identical.
Type of Change
Impact
Sloped LEF polygon geometry is preserved; rectilinear decomposition unchanged.
Verification
ctest -R '^odb\.' -E '\.py'82/82 (tcl+cpp).Related Issues
Fixes #10256
Developed with SAIGE, Fermions' autonomous RTL/EDA debugging agent; root-caused, tested, and signed off by the submitter (@saurav-fermions).