@@ -1218,6 +1218,8 @@ bool PlacerPadPlacer::padSpreading(
12181218 const double dbus = getBlock ()->getDbUnitsPerMicron ();
12191219 const int site_width = getRow ()->getSpacing ();
12201220
1221+ std::map<int , int > failed_tunnel_positions;
1222+
12211223 int total_move = 0 ;
12221224 int net_move = 0 ;
12231225 debugPrint (getLogger (),
@@ -1310,9 +1312,12 @@ bool PlacerPadPlacer::padSpreading(
13101312 const int check_move
13111313 = std::max (prev_pos, std::min (next_pos, curr_pos + move_by));
13121314 if (move_by != 0 ) {
1313- const int tunnel_move = getTunnelingPosition (
1315+ const auto & [ tunnel_move, tunnel_ideal] = getTunnelingPosition (
13141316 curr, check_move, move_by > 0 , prev_pos, curr_pos, next_pos, itr);
13151317 move_by = tunnel_move - curr_pos;
1318+ if (tunnel_move != tunnel_ideal) {
1319+ failed_tunnel_positions.emplace (i, tunnel_ideal);
1320+ }
13161321 }
13171322
13181323 // Record stats
@@ -1342,6 +1347,70 @@ bool PlacerPadPlacer::padSpreading(
13421347 total_force);
13431348 }
13441349
1350+ // Push instances causing tunneling to fail
1351+ for (const auto & [inst_idx, ideal_pos] : failed_tunnel_positions) {
1352+ const int delta_pos = ideal_pos - positions[insts[inst_idx]]->center ;
1353+ const int push = ((delta_pos < 0 ) ? -1 : 1 )
1354+ * std::ceil ((damper * std::abs (delta_pos)) / site_width)
1355+ * site_width;
1356+ std::vector<odb::dbInst*> push_insts;
1357+ int last_idx = inst_idx;
1358+ int bound_pos;
1359+ if (delta_pos > 0 ) {
1360+ for (int j = inst_idx + 1 ; j < insts.size (); j++) {
1361+ if (positions[insts[j]]->center <= ideal_pos) {
1362+ push_insts.push_back (insts[j]);
1363+ last_idx = j;
1364+ }
1365+ }
1366+ bound_pos = last_idx == insts.size ()
1367+ ? getRowEnd (insts[last_idx])
1368+ : positions[insts[last_idx + 1 ]]->center ;
1369+ } else {
1370+ for (int j = inst_idx - 1 ; j >= 0 ; j--) {
1371+ if (positions[insts[j]]->center >= ideal_pos) {
1372+ push_insts.push_back (insts[j]);
1373+ last_idx = j;
1374+ }
1375+ }
1376+ bound_pos = last_idx == 0 ? getRowStart (insts[last_idx])
1377+ : positions[insts[last_idx - 1 ]]->center ;
1378+ }
1379+ debugPrint (getLogger (),
1380+ utl::PAD,
1381+ " Place" ,
1382+ 2 ,
1383+ " {} / {}: Unable to tunnel to {:.4f}um, stuck at {:.4f}um, push "
1384+ " boundary at {:.4f}um, desired push {:.4f}um applies to: {}" ,
1385+ itr,
1386+ insts[inst_idx]->getName (),
1387+ ideal_pos / dbus,
1388+ positions[insts[inst_idx]]->center / dbus,
1389+ bound_pos / dbus,
1390+ push / dbus,
1391+ instNameList (push_insts));
1392+ // push instances
1393+ for (odb::dbInst* inst : push_insts) {
1394+ const int curr_pos = positions[inst]->center ;
1395+ int desired_pos;
1396+ if (push < 0 ) {
1397+ desired_pos = std::max (bound_pos, curr_pos + push);
1398+ } else {
1399+ desired_pos = std::min (bound_pos, curr_pos + push);
1400+ }
1401+ const int move_to = convertRowIndexToPos (snapToRowSite (
1402+ desired_pos - (positions[inst]->width / 2 )))
1403+ + (positions[inst]->width / 2 );
1404+ positions[inst]->setLocation (move_to - (positions[inst]->width / 2 ));
1405+
1406+ // Record stats
1407+ const int delta_move = move_to - curr_pos;
1408+ net_move += delta_move;
1409+ total_move += std::abs (delta_move);
1410+ }
1411+ has_violations = true ;
1412+ }
1413+
13451414 placeInstances (positions);
13461415 addChartData (itr, estimateWirelengths (), total_move);
13471416 debugPrint (getLogger (),
@@ -1462,25 +1531,26 @@ int PlacerPadPlacer::getRowEnd(odb::dbInst* inst) const
14621531 return PadPlacer::getRowEnd () - (getInstWidths ().at (inst) / 2 );
14631532}
14641533
1465- int PlacerPadPlacer::getTunnelingPosition (odb::dbInst* inst,
1466- int target,
1467- bool move_up,
1468- int low_bound,
1469- int curr_pos,
1470- int high_bound,
1471- int itr) const
1534+ std::pair< int , int > PlacerPadPlacer::getTunnelingPosition (odb::dbInst* inst,
1535+ int target,
1536+ bool move_up,
1537+ int low_bound,
1538+ int curr_pos,
1539+ int high_bound,
1540+ int itr) const
14721541{
14731542 const double dbus = getBlock ()->getDbUnitsPerMicron ();
14741543 placeInstanceSimple (inst, target, true );
1544+ const int ideal = getNearestLegalPosition (inst, target, !move_up, move_up);
14751545 if (move_up) {
14761546 // pad is moving up in the row
1477- int next = getNearestLegalPosition (inst, target, false , true );
1478- if (next != target) {
1479- if (next > high_bound) {
1547+ if (ideal != target) {
1548+ if (ideal > high_bound) {
14801549 // check if high_bound is safe to pin to
14811550 placeInstanceSimple (inst, high_bound, true );
14821551 if (checkInstancePlacement (inst)) {
1483- next = getNearestLegalPosition (inst, target, true , false );
1552+ // inst is obstructed, so move to the nearest edge of the obstruction
1553+ const int next = getNearestLegalPosition (inst, target, true , false );
14841554 if (next <= high_bound) {
14851555 debugPrint (getLogger (),
14861556 utl::PAD,
@@ -1497,7 +1567,7 @@ int PlacerPadPlacer::getTunnelingPosition(odb::dbInst* inst,
14971567 low_bound / dbus,
14981568 curr_pos / dbus,
14991569 high_bound / dbus);
1500- return next;
1570+ return { next, ideal} ;
15011571 }
15021572 debugPrint (getLogger (),
15031573 utl::PAD,
@@ -1509,12 +1579,12 @@ int PlacerPadPlacer::getTunnelingPosition(odb::dbInst* inst,
15091579 itr,
15101580 inst->getName (),
15111581 target / dbus,
1512- next / dbus,
1582+ curr_pos / dbus,
15131583 high_bound / dbus,
15141584 low_bound / dbus,
15151585 curr_pos / dbus,
15161586 high_bound / dbus);
1517- return curr_pos;
1587+ return { curr_pos, ideal}; // stay in the same position
15181588 }
15191589 }
15201590 debugPrint (getLogger (),
@@ -1526,21 +1596,20 @@ int PlacerPadPlacer::getTunnelingPosition(odb::dbInst* inst,
15261596 itr,
15271597 inst->getName (),
15281598 target / dbus,
1529- next / dbus,
1599+ ideal / dbus,
15301600 low_bound / dbus,
15311601 curr_pos / dbus,
15321602 high_bound / dbus);
1533- return next ;
1603+ return {ideal, ideal} ;
15341604 }
15351605 }
15361606 // pad is moving down in the row
1537- int next = getNearestLegalPosition (inst, target, true , false );
1538- if (next != target) {
1539- if (next < low_bound) {
1607+ if (ideal != target) {
1608+ if (ideal < low_bound) {
15401609 // check if low_bound is safe to pin to
15411610 placeInstanceSimple (inst, low_bound, true );
15421611 if (checkInstancePlacement (inst)) {
1543- next = getNearestLegalPosition (inst, target, true , false );
1612+ const int next = getNearestLegalPosition (inst, target, true , false );
15441613 if (next >= low_bound) {
15451614 debugPrint (getLogger (),
15461615 utl::PAD,
@@ -1557,9 +1626,8 @@ int PlacerPadPlacer::getTunnelingPosition(odb::dbInst* inst,
15571626 low_bound / dbus,
15581627 curr_pos / dbus,
15591628 high_bound / dbus);
1560- return next;
1629+ return { next, ideal} ;
15611630 }
1562- next = curr_pos;
15631631 debugPrint (getLogger (),
15641632 utl::PAD,
15651633 " Place" ,
@@ -1570,12 +1638,12 @@ int PlacerPadPlacer::getTunnelingPosition(odb::dbInst* inst,
15701638 itr,
15711639 inst->getName (),
15721640 target / dbus,
1573- next / dbus,
1641+ curr_pos / dbus,
15741642 low_bound / dbus,
15751643 low_bound / dbus,
15761644 curr_pos / dbus,
15771645 high_bound / dbus);
1578- return next ;
1646+ return {curr_pos, ideal} ;
15791647 }
15801648 }
15811649 debugPrint (getLogger (),
@@ -1587,14 +1655,14 @@ int PlacerPadPlacer::getTunnelingPosition(odb::dbInst* inst,
15871655 itr,
15881656 inst->getName (),
15891657 target / dbus,
1590- next / dbus,
1658+ ideal / dbus,
15911659 low_bound / dbus,
15921660 curr_pos / dbus,
15931661 high_bound / dbus);
1594- return next ;
1662+ return {ideal, ideal} ;
15951663 }
15961664
1597- return target;
1665+ return { target, target} ;
15981666}
15991667
16001668void PlacerPadPlacer::debugCheckPlacement () const
@@ -1622,6 +1690,19 @@ void PlacerPadPlacer::debugCheckPlacement() const
16221690 }
16231691}
16241692
1693+ std::string PlacerPadPlacer::instNameList (
1694+ const std::vector<odb::dbInst*>& insts) const
1695+ {
1696+ std::string inst_string;
1697+ for (auto * inst : insts) {
1698+ if (!inst_string.empty ()) {
1699+ inst_string += " , " ;
1700+ }
1701+ inst_string += inst->getName ();
1702+ }
1703+ return inst_string;
1704+ }
1705+
16251706// ////////////////////////
16261707
16271708int PlacerPadPlacer::InstAnchors::overlap (
0 commit comments