@@ -3220,41 +3220,43 @@ void Snapper::snapMacro()
32203220
32213221void 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
32603262void 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
34493465void Snapper::alignWithManufacturingGrid (int & origin)
0 commit comments