Repository navigation
mpl: keep snapped macros inside the core #11901
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
c1d91a8
267a495
9cbb408
a3bc878
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,7 +40,41 @@ void Snapper::snap(const odb::dbTechLayerDir& target_direction) | |
| : inst_->getOrigin().y(); | ||
|
|
||
| if (layers_data_list.empty()) { | ||
| const int initial_origin = origin; | ||
| alignWithManufacturingGrid(origin); | ||
|
|
||
| if (!isOriginInsideCore(origin, target_direction)) { | ||
| // Grid rounding can move an initially contained macro past the core. | ||
| const odb::Rect& macro_bbox = inst_->getBBox()->getBox(); | ||
| const odb::Rect& core = inst_->getBlock()->getCoreArea(); | ||
| const int manufacturing_grid | ||
| = inst_->getDb()->getTech()->getManufacturingGrid(); | ||
|
joaomai marked this conversation as resolved.
Resolved
|
||
| const int lower_bound | ||
| = initial_origin | ||
| + (target_direction == odb::dbTechLayerDir::VERTICAL | ||
| ? core.xMin() - macro_bbox.xMin() | ||
| : core.yMin() - macro_bbox.yMin()); | ||
| const int upper_bound | ||
| = initial_origin | ||
| + (target_direction == odb::dbTechLayerDir::VERTICAL | ||
| ? core.xMax() - macro_bbox.xMax() | ||
| : core.yMax() - macro_bbox.yMax()); | ||
| const int minimum_origin | ||
| = static_cast<int>(std::ceil( | ||
| lower_bound / static_cast<double>(manufacturing_grid))) | ||
| * manufacturing_grid; | ||
| const int maximum_origin | ||
| = static_cast<int>(std::floor( | ||
| upper_bound / static_cast<double>(manufacturing_grid))) | ||
| * manufacturing_grid; | ||
|
Comment on lines
+62
to
+69
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can avoid floating-point conversions and potential precision/performance overhead by using pure integer arithmetic to compute const int minimum_origin
= (lower_bound >= 0
? (lower_bound + manufacturing_grid - 1) / manufacturing_grid
: lower_bound / manufacturing_grid)
* manufacturing_grid;
const int maximum_origin
= (upper_bound >= 0
? upper_bound / manufacturing_grid
: (upper_bound - manufacturing_grid + 1) / manufacturing_grid)
* manufacturing_grid; |
||
|
|
||
| if (minimum_origin > maximum_origin) { | ||
| setOrigin(initial_origin, target_direction); | ||
| return; | ||
| } | ||
| origin = std::clamp(origin, minimum_origin, maximum_origin); | ||
| } | ||
|
|
||
| setOrigin(origin, target_direction); | ||
| return; | ||
| } | ||
|
|
@@ -61,14 +95,33 @@ void Snapper::snap(const odb::dbTechLayerDir& target_direction) | |
| starting_position_index -= 1; | ||
| } | ||
|
|
||
| snapPinToPosition(lowest_grid_pin, | ||
| lowest_grid_positions[starting_position_index], | ||
| target_direction); | ||
|
|
||
| attemptSnapToExtraPatterns( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function can be renamed to something akin to "snapToGridPatterns" since the extra has no meaning now. |
||
| starting_position_index, layers_data_list, target_direction); | ||
| } | ||
|
|
||
| bool Snapper::isOriginInsideCore( | ||
| const int origin, | ||
| const odb::dbTechLayerDir& target_direction) const | ||
| { | ||
| const odb::Rect& macro_bbox = inst_->getBBox()->getBox(); | ||
| const odb::Rect& core = inst_->getBlock()->getCoreArea(); | ||
| if (core.dx() <= 0 || core.dy() <= 0) { | ||
| return true; | ||
| } | ||
|
|
||
| const int current_origin = target_direction == odb::dbTechLayerDir::VERTICAL | ||
| ? inst_->getOrigin().x() | ||
| : inst_->getOrigin().y(); | ||
| const int displacement = origin - current_origin; | ||
|
|
||
| if (target_direction == odb::dbTechLayerDir::VERTICAL) { | ||
| return macro_bbox.xMin() + displacement >= core.xMin() | ||
| && macro_bbox.xMax() + displacement <= core.xMax(); | ||
| } | ||
| return macro_bbox.yMin() + displacement >= core.yMin() | ||
| && macro_bbox.yMax() + displacement <= core.yMax(); | ||
| } | ||
|
|
||
| void Snapper::setOrigin(const int origin, | ||
| const odb::dbTechLayerDir& target_direction) | ||
| { | ||
|
|
@@ -178,13 +231,19 @@ int Snapper::getPinOffset(odb::dbITerm* pin, | |
| return pin_offset; | ||
| } | ||
|
|
||
| int Snapper::getSnappedOrigin(const int position, const int pin_offset) | ||
| { | ||
| int origin = position - pin_offset; | ||
| alignWithManufacturingGrid(origin); | ||
| return origin; | ||
| } | ||
|
|
||
| void Snapper::snapPinToPosition(odb::dbITerm* pin, | ||
| int position, | ||
| const int position, | ||
| const odb::dbTechLayerDir& direction) | ||
| { | ||
| int origin = position - getPinOffset(pin, direction); | ||
| alignWithManufacturingGrid(origin); | ||
| setOrigin(origin, direction); | ||
| setOrigin(getSnappedOrigin(position, getPinOffset(pin, direction)), | ||
| direction); | ||
| } | ||
|
|
||
| void Snapper::getTrackGridPattern(odb::dbTrackGrid* track_grid, | ||
|
|
@@ -216,33 +275,45 @@ void Snapper::attemptSnapToExtraPatterns( | |
|
|
||
| odb::dbITerm* snap_pin = layers_data_list[0].pins[0]; | ||
| const std::vector<int>& positions = layers_data_list[0].available_positions; | ||
|
|
||
| int best_index = start_index; | ||
| int best_snapped_pins = 0; | ||
|
|
||
| std::vector<int> legal_positions; | ||
| legal_positions.reserve(total_attempts + 1); | ||
| const int pin_offset = getPinOffset(snap_pin, target_direction); | ||
| // Keep the existing nearest-first order, but cull before moving the macro. | ||
| for (int i = 0; i <= total_attempts; i++) { | ||
| int steps = (i % 2 == 1) ? (i + 1) / 2 : -(i / 2); | ||
|
|
||
| int current_index = start_index + steps; | ||
|
|
||
| if (current_index < 0 | ||
| || current_index >= layers_data_list[0].available_positions.size()) { | ||
| continue; | ||
| } | ||
| snapPinToPosition(snap_pin, positions[current_index], target_direction); | ||
| const int position = positions[current_index]; | ||
| if (isOriginInsideCore(getSnappedOrigin(position, pin_offset), | ||
| target_direction)) { | ||
| legal_positions.push_back(position); | ||
| } | ||
| } | ||
|
Comment on lines
+278
to
+294
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The std::vector<int> legal_positions;
legal_positions.reserve(total_attempts + 1);
const int pin_offset = getPinOffset(snap_pin, target_direction);
// Keep the existing nearest-first order, but cull before moving the macro.
for (int i = 0; i <= total_attempts; i++) {
int steps = (i % 2 == 1) ? (i + 1) / 2 : -(i / 2);
int current_index = start_index + steps;
if (current_index < 0
|| current_index >= layers_data_list[0].available_positions.size()) {
continue;
}
const int position = positions[current_index];
int origin = position - pin_offset;
alignWithManufacturingGrid(origin);
if (isOriginInsideCore(origin, target_direction)) {
legal_positions.push_back(position);
}
} |
||
| if (legal_positions.empty()) { | ||
| // Keeping the original location must not bypass mandatory pin-grid rules. | ||
| totalAlignedPins(layers_data_list, target_direction, true); | ||
| return; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Early returning here skips the warning down the function, which is undesirable. |
||
| } | ||
|
|
||
| int best_position = legal_positions.front(); | ||
| int best_snapped_pins = -1; | ||
| for (const int position : legal_positions) { | ||
| snapPinToPosition(snap_pin, position, target_direction); | ||
| int snapped_pins = totalAlignedPins(layers_data_list, target_direction); | ||
|
|
||
| if (snapped_pins > best_snapped_pins) { | ||
| best_snapped_pins = snapped_pins; | ||
| best_index = current_index; | ||
| best_position = position; | ||
| if (best_snapped_pins == total_pins) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| snapPinToPosition(snap_pin, positions[best_index], target_direction); | ||
| snapPinToPosition(snap_pin, best_position, target_direction); | ||
|
|
||
| if (best_snapped_pins != total_pins) { | ||
| totalAlignedPins(layers_data_list, target_direction, true); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't the same be achieved by changing the way
alignWithManufacturingGridrounds the origin value? In the sense that if rounding down fails, rounding up should pass and vice-versa.