Skip to content

Commit 7ae18b5

Browse files
authored
Merge pull request #6738 from joaomai/mpl-multi-pattern
MPL: support for multi pattern snapping
2 parents 5d8e6d2 + 3054bea commit 7ae18b5

14 files changed

Lines changed: 390 additions & 194 deletions

src/mpl/src/hier_rtlmp.cpp

Lines changed: 152 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -3220,41 +3220,43 @@ void Snapper::snapMacro()
32203220

32213221
void Snapper::snap(const odb::dbTechLayerDir& target_direction)
32223222
{
3223-
SameDirectionLayersData layers_data
3224-
= computeSameDirectionLayersData(target_direction);
3223+
LayerDataList layers_data_list = computeLayerDataList(target_direction);
32253224

32263225
int origin = target_direction == odb::dbTechLayerDir::VERTICAL
32273226
? inst_->getOrigin().x()
32283227
: inst_->getOrigin().y();
32293228

3230-
if (!layers_data.snap_layer) {
3229+
if (layers_data_list.empty()) {
32313230
// There are no pins to align with the track-grid.
32323231
alignWithManufacturingGrid(origin);
32333232
setOrigin(origin, target_direction);
32343233
return;
32353234
}
32363235

3237-
odb::dbITerm* snap_pin = layers_data.layer_to_pin.at(layers_data.snap_layer);
3238-
const LayerParameters& snap_layer_params
3239-
= layers_data.layer_to_params.at(layers_data.snap_layer);
3236+
const std::vector<int>& lowest_grid_positions
3237+
= layers_data_list[0].available_positions;
3238+
odb::dbITerm* lowest_grid_pin = layers_data_list[0].pins[0];
32403239

3241-
if (!pinsAreAlignedWithTrackGrid(
3242-
snap_pin, snap_layer_params, target_direction)) {
3243-
// The idea here is to first align the origin of the macro with
3244-
// the track-grid taking into account that the grid has a certain
3245-
// offset with regards to (0,0) and, then, compensate the offset
3246-
// of the pins themselves so that the lines of the grid cross
3247-
// their center.
3248-
origin = std::round(origin / static_cast<double>(snap_layer_params.pitch))
3249-
* snap_layer_params.pitch
3250-
+ snap_layer_params.offset - snap_layer_params.pin_offset;
3240+
const int lowest_pin_center_pos
3241+
= origin + getPinOffset(lowest_grid_pin, target_direction);
32513242

3252-
alignWithManufacturingGrid(origin);
3253-
setOrigin(origin, target_direction);
3243+
auto closest_pos = std::lower_bound(lowest_grid_positions.begin(),
3244+
lowest_grid_positions.end(),
3245+
lowest_pin_center_pos);
3246+
3247+
int starting_position_index
3248+
= std::distance(lowest_grid_positions.begin(), closest_pos);
3249+
// If no position is found, use the last available
3250+
if (starting_position_index == lowest_grid_positions.size()) {
3251+
starting_position_index -= 1;
32543252
}
32553253

3256-
attemptSnapToExtraLayers(
3257-
origin, layers_data, snap_layer_params, target_direction);
3254+
snapPinToPosition(lowest_grid_pin,
3255+
lowest_grid_positions[starting_position_index],
3256+
target_direction);
3257+
3258+
attemptSnapToExtraPatterns(
3259+
starting_position_index, layers_data_list, target_direction);
32583260
}
32593261

32603262
void Snapper::setOrigin(const int origin,
@@ -3267,183 +3269,197 @@ void Snapper::setOrigin(const int origin,
32673269
}
32683270
}
32693271

3270-
SameDirectionLayersData Snapper::computeSameDirectionLayersData(
3272+
Snapper::LayerDataList Snapper::computeLayerDataList(
32713273
const odb::dbTechLayerDir& target_direction)
32723274
{
3273-
SameDirectionLayersData data;
3275+
TrackGridToPinListMap track_grid_to_pin_list;
3276+
3277+
odb::dbBlock* block = inst_->getBlock();
32743278

32753279
for (odb::dbITerm* iterm : inst_->getITerms()) {
32763280
if (iterm->getSigType() != odb::dbSigType::SIGNAL) {
32773281
continue;
32783282
}
32793283

32803284
for (odb::dbMPin* mpin : iterm->getMTerm()->getMPins()) {
3281-
for (odb::dbBox* box : mpin->getGeometry()) {
3282-
odb::dbTechLayer* layer = box->getTechLayer();
3283-
if (layer->getDirection() == target_direction) {
3284-
if (data.layer_to_pin.find(layer) != data.layer_to_pin.end()) {
3285-
continue;
3286-
}
3285+
odb::dbTechLayer* layer = getPinLayer(mpin);
32873286

3288-
if (data.layer_to_pin.empty()) {
3289-
data.snap_layer = layer;
3290-
}
3287+
if (layer->getDirection() != target_direction) {
3288+
continue;
3289+
}
32913290

3292-
data.layer_to_pin[layer] = iterm;
3293-
data.layer_to_params[layer]
3294-
= computeLayerParameters(layer, iterm, target_direction);
3295-
}
3291+
odb::dbTrackGrid* track_grid = block->findTrackGrid(layer);
3292+
if (track_grid == nullptr) {
3293+
logger_->error(
3294+
MPL, 39, "No track-grid found for layer {}", layer->getName());
32963295
}
3296+
3297+
track_grid_to_pin_list[track_grid].push_back(iterm);
3298+
}
3299+
}
3300+
3301+
auto compare_pin_center = [&](odb::dbITerm* pin1, odb::dbITerm* pin2) {
3302+
return (target_direction == odb::dbTechLayerDir::VERTICAL
3303+
? pin1->getBBox().xCenter() < pin2->getBBox().xCenter()
3304+
: pin1->getBBox().yCenter() < pin2->getBBox().yCenter());
3305+
};
3306+
3307+
LayerDataList layers_data;
3308+
for (auto& [track_grid, pins] : track_grid_to_pin_list) {
3309+
std::vector<int> positions;
3310+
if (target_direction == odb::dbTechLayerDir::VERTICAL) {
3311+
track_grid->getGridX(positions);
3312+
} else {
3313+
track_grid->getGridY(positions);
32973314
}
3315+
std::sort(pins.begin(), pins.end(), compare_pin_center);
3316+
layers_data.push_back(LayerData{track_grid, positions, pins});
32983317
}
32993318

3300-
return data;
3319+
auto compare_layer_number = [](LayerData data1, LayerData data2) {
3320+
return (data1.track_grid->getTechLayer()->getNumber()
3321+
< data2.track_grid->getTechLayer()->getNumber());
3322+
};
3323+
std::sort(layers_data.begin(), layers_data.end(), compare_layer_number);
3324+
3325+
return layers_data;
33013326
}
33023327

3303-
LayerParameters Snapper::computeLayerParameters(
3304-
odb::dbTechLayer* layer,
3305-
odb::dbITerm* pin,
3306-
const odb::dbTechLayerDir& target_direction)
3328+
odb::dbTechLayer* Snapper::getPinLayer(odb::dbMPin* pin)
33073329
{
3308-
LayerParameters params;
3309-
3310-
odb::dbBlock* block = inst_->getBlock();
3311-
odb::dbTrackGrid* track_grid = block->findTrackGrid(layer);
3330+
return (*pin->getGeometry().begin())->getTechLayer();
3331+
}
33123332

3313-
if (track_grid) {
3314-
getTrackGrid(track_grid, params.offset, params.pitch, target_direction);
3333+
int Snapper::getPinOffset(odb::dbITerm* pin,
3334+
const odb::dbTechLayerDir& direction)
3335+
{
3336+
int pin_width = 0;
3337+
if (direction == odb::dbTechLayerDir::VERTICAL) {
3338+
pin_width = pin->getBBox().dx();
33153339
} else {
3316-
logger_->error(
3317-
MPL, 39, "No track-grid found for layer {}", layer->getName());
3340+
pin_width = pin->getBBox().dy();
33183341
}
33193342

3320-
params.pin_width = getPinWidth(pin, target_direction);
3321-
params.lower_left_to_first_pin
3322-
= getPinToLowerLeftDistance(pin, target_direction);
3323-
3324-
// The distance between the pins and the lower-left corner
3325-
// of the master of a macro instance may not be a multiple
3326-
// of the track-grid, in these cases, we need to compensate
3327-
// a small offset.
3328-
int mterm_offset = 0;
3329-
if (params.pitch != 0) {
3330-
mterm_offset = params.lower_left_to_first_pin
3331-
- std::floor(params.lower_left_to_first_pin / params.pitch)
3332-
* params.pitch;
3343+
int pin_to_origin = 0;
3344+
odb::dbMTerm* mterm = pin->getMTerm();
3345+
if (direction == odb::dbTechLayerDir::VERTICAL) {
3346+
pin_to_origin = mterm->getBBox().xMin();
3347+
} else {
3348+
pin_to_origin = mterm->getBBox().yMin();
33333349
}
3334-
params.pin_offset = params.pin_width / 2 + mterm_offset;
3350+
3351+
int pin_offset = pin_to_origin + (pin_width / 2);
33353352

33363353
const odb::dbOrientType& orientation = inst_->getOrient();
3337-
if (target_direction == odb::dbTechLayerDir::VERTICAL) {
3354+
if (direction == odb::dbTechLayerDir::VERTICAL) {
33383355
if (orientation == odb::dbOrientType::MY
33393356
|| orientation == odb::dbOrientType::R180) {
3340-
params.pin_offset = -params.pin_offset;
3357+
pin_offset = -pin_offset;
33413358
}
3342-
} else if (orientation == odb::dbOrientType::MX
3343-
|| orientation == odb::dbOrientType::R180) {
3344-
params.pin_offset = -params.pin_offset;
3345-
}
3346-
return params;
3347-
}
3348-
3349-
int Snapper::getPinWidth(odb::dbITerm* pin,
3350-
const odb::dbTechLayerDir& target_direction)
3351-
{
3352-
int pin_width = 0;
3353-
if (target_direction == odb::dbTechLayerDir::VERTICAL) {
3354-
pin_width = pin->getBBox().dx();
33553359
} else {
3356-
pin_width = pin->getBBox().dy();
3360+
if (orientation == odb::dbOrientType::MX
3361+
|| orientation == odb::dbOrientType::R180) {
3362+
pin_offset = -pin_offset;
3363+
}
33573364
}
3358-
return pin_width;
3365+
3366+
return pin_offset;
33593367
}
33603368

3361-
void Snapper::getTrackGrid(odb::dbTrackGrid* track_grid,
3362-
int& origin,
3363-
int& step,
3364-
const odb::dbTechLayerDir& target_direction)
3369+
void Snapper::snapPinToPosition(odb::dbITerm* pin,
3370+
int position,
3371+
const odb::dbTechLayerDir& direction)
33653372
{
3366-
// TODO: handle multiple patterns
3367-
int count;
3368-
if (target_direction == odb::dbTechLayerDir::VERTICAL) {
3369-
track_grid->getGridPatternX(0, origin, count, step);
3370-
} else {
3371-
track_grid->getGridPatternY(0, origin, count, step);
3372-
}
3373+
int origin = position - getPinOffset(pin, direction);
3374+
alignWithManufacturingGrid(origin);
3375+
setOrigin(origin, direction);
33733376
}
33743377

3375-
int Snapper::getPinToLowerLeftDistance(
3376-
odb::dbITerm* pin,
3377-
const odb::dbTechLayerDir& target_direction)
3378+
void Snapper::getTrackGridPattern(odb::dbTrackGrid* track_grid,
3379+
int pattern_idx,
3380+
int& origin,
3381+
int& step,
3382+
const odb::dbTechLayerDir& target_direction)
33783383
{
3379-
int pin_to_origin = 0;
3380-
3381-
odb::dbMTerm* mterm = pin->getMTerm();
3384+
int count;
33823385
if (target_direction == odb::dbTechLayerDir::VERTICAL) {
3383-
pin_to_origin = mterm->getBBox().xMin();
3386+
track_grid->getGridPatternX(pattern_idx, origin, count, step);
33843387
} else {
3385-
pin_to_origin = mterm->getBBox().yMin();
3388+
track_grid->getGridPatternY(pattern_idx, origin, count, step);
33863389
}
3387-
3388-
return pin_to_origin;
33893390
}
33903391

3391-
void Snapper::attemptSnapToExtraLayers(
3392-
const int origin,
3393-
const SameDirectionLayersData& layers_data,
3394-
const LayerParameters& snap_layer_params,
3392+
void Snapper::attemptSnapToExtraPatterns(
3393+
const int start_index,
3394+
const LayerDataList& layers_data_list,
33953395
const odb::dbTechLayerDir& target_direction)
33963396
{
3397-
// Calculate LCM from the layers pitches to define the search
3398-
// range
3399-
int lcm = 1;
3400-
for (const auto& [layer, params] : layers_data.layer_to_params) {
3401-
lcm = std::lcm(lcm, params.pitch);
3402-
}
3403-
const int pitch = snap_layer_params.pitch;
3404-
const int total_attempts = lcm / snap_layer_params.pitch;
3397+
const int total_attempts = 100;
3398+
const int total_pins = std::accumulate(layers_data_list.begin(),
3399+
layers_data_list.end(),
3400+
0,
3401+
[](int total, const LayerData& data) {
3402+
return total + data.pins.size();
3403+
});
34053404

3406-
const int total_layers = static_cast<int>(layers_data.layer_to_pin.size());
3405+
odb::dbITerm* snap_pin = layers_data_list[0].pins[0];
3406+
const std::vector<int>& positions = layers_data_list[0].available_positions;
34073407

3408-
int best_origin = origin;
3409-
int best_snapped_layers = 1;
3408+
int best_index = start_index;
3409+
int best_snapped_pins = 0;
34103410

34113411
for (int i = 0; i <= total_attempts; i++) {
34123412
// Alternates steps from positive to negative incrementally
34133413
int steps = (i % 2 == 1) ? (i + 1) / 2 : -(i / 2);
34143414

3415-
setOrigin(origin + (pitch * steps), target_direction);
3416-
int snapped_layers = 0;
3417-
for (const auto& [layer, pin] : layers_data.layer_to_pin) {
3418-
if (pinsAreAlignedWithTrackGrid(
3419-
pin, layers_data.layer_to_params.at(layer), target_direction)) {
3420-
++snapped_layers;
3421-
}
3415+
int current_index = start_index + steps;
3416+
3417+
if (current_index < 0
3418+
|| current_index >= layers_data_list[0].available_positions.size()) {
3419+
continue;
34223420
}
3421+
snapPinToPosition(snap_pin, positions[current_index], target_direction);
34233422

3424-
if (snapped_layers > best_snapped_layers) {
3425-
best_snapped_layers = snapped_layers;
3426-
best_origin = origin + (pitch * steps);
3423+
int snapped_pins = totalPinsAligned(layers_data_list, target_direction);
34273424

3428-
// Stop search if all layers are snapped
3429-
if (total_layers == best_snapped_layers) {
3425+
if (snapped_pins > best_snapped_pins) {
3426+
best_snapped_pins = snapped_pins;
3427+
best_index = current_index;
3428+
if (best_snapped_pins == total_pins) {
34303429
break;
34313430
}
34323431
}
34333432
}
34343433

3435-
setOrigin(best_origin, target_direction);
3434+
snapPinToPosition(snap_pin, positions[best_index], target_direction);
34363435
}
34373436

3438-
bool Snapper::pinsAreAlignedWithTrackGrid(
3439-
odb::dbITerm* pin,
3440-
const LayerParameters& layer_params,
3441-
const odb::dbTechLayerDir& target_direction)
3437+
int Snapper::totalPinsAligned(const LayerDataList& layers_data_list,
3438+
const odb::dbTechLayerDir& direction)
34423439
{
3443-
int pin_center = target_direction == odb::dbTechLayerDir::VERTICAL
3444-
? pin->getBBox().xCenter()
3445-
: pin->getBBox().yCenter();
3446-
return (pin_center - layer_params.offset) % layer_params.pitch == 0;
3440+
int pins_aligned = 0;
3441+
3442+
for (auto& data : layers_data_list) {
3443+
std::vector<int> pin_centers(data.pins.size());
3444+
for (auto& pin : data.pins) {
3445+
pin_centers.push_back(direction == odb::dbTechLayerDir::VERTICAL
3446+
? pin->getBBox().xCenter()
3447+
: pin->getBBox().yCenter());
3448+
}
3449+
3450+
int i = 0, j = 0;
3451+
while (i < pin_centers.size() && j < data.available_positions.size()) {
3452+
if (pin_centers[i] == data.available_positions[j]) {
3453+
pins_aligned++;
3454+
i++;
3455+
} else if (pin_centers[i] < data.available_positions[j]) {
3456+
i++;
3457+
} else {
3458+
j++;
3459+
}
3460+
}
3461+
}
3462+
return pins_aligned;
34473463
}
34483464

34493465
void Snapper::alignWithManufacturingGrid(int& origin)

0 commit comments

Comments
 (0)