@@ -640,25 +640,106 @@ bool NegotiationLegalizer::initFromDb()
640640 // only check site existence and hard blockages here (both encoded in
641641 // pixel.is_valid). Soft blockages, routing-layer blockages, and
642642 // cell-vs-cell overlap are left to the negotiation loop.
643- // if (!cell.fixed) {
644- if (false ) {
643+ if (!cell.fixed ) {
644+ // if (false) {
645645 odb::dbSite* site = master->getSite ();
646646 // Check that the full cell footprint (width x height) fits on valid
647647 // sites.
648- auto isValidSite = [&](int gx, int gy) -> bool {
649- if (gx < 0 || gx + cell.width > grid_w_ || gy < 0
650- || gy + cell.height > grid_h_) {
648+ auto isValidSite = [&](int pixel_left, int pixel_bottom) -> bool {
649+ const bool past_left = pixel_left < 0 ;
650+ const bool past_bottom = pixel_bottom < 0 ;
651+ const bool past_right = pixel_left + cell.width > grid_w_;
652+ const bool past_top = pixel_bottom + cell.height > grid_h_;
653+ if (past_left || past_right || past_bottom || past_top) {
654+ std::string detail;
655+ if (past_left) {
656+ detail += fmt::format (
657+ " left edge of footprint is at column {} (before grid "
658+ " column 0);" ,
659+ pixel_left);
660+ }
661+ if (past_bottom) {
662+ detail += fmt::format (
663+ " bottom edge of footprint is at row {} (below grid "
664+ " row 0);" ,
665+ pixel_bottom);
666+ }
667+ if (past_right) {
668+ detail += fmt::format (
669+ " right edge of footprint is at column {} (past grid "
670+ " width {});" ,
671+ pixel_left + cell.width ,
672+ grid_w_);
673+ }
674+ if (past_top) {
675+ detail += fmt::format (
676+ " top edge of footprint is at row {} (past grid "
677+ " height {});" ,
678+ pixel_bottom + cell.height ,
679+ grid_h_);
680+ }
681+ debugPrint (logger_,
682+ utl::DPL ,
683+ " negotiation" ,
684+ 1 ,
685+ " Position grid ({}, {}) rejected for instance '{}': "
686+ " cell footprint {}x{} sites does not fit in grid "
687+ " {}x{} sites.{}" ,
688+ pixel_left,
689+ pixel_bottom,
690+ cell.db_inst ->getName (),
691+ cell.width ,
692+ cell.height ,
693+ grid_w_,
694+ grid_h_,
695+ detail);
651696 return false ;
652697 }
653698 // Site type check at the anchor row is representative for all rows.
654699 if (site != nullptr
655- && !dpl_grid->getSiteOrientation (GridX{gx }, GridY{gy }, site)
700+ && !dpl_grid->getSiteOrientation (GridX{pixel_left }, GridY{pixel_bottom }, site)
656701 .has_value ()) {
702+ debugPrint (logger_,
703+ utl::DPL ,
704+ " negotiation" ,
705+ 1 ,
706+ " Position grid ({}, {}) rejected for instance '{}': "
707+ " the row at this Y has no site matching the master's "
708+ " site '{}' (master='{}', class={}). The row is either "
709+ " missing here or uses a different site definition." ,
710+ pixel_left,
711+ pixel_bottom,
712+ cell.db_inst ->getName (),
713+ site->getName (),
714+ master->getName (),
715+ master->getType ().getString ());
657716 return false ;
658717 }
659- for (int dy = 0 ; dy < cell.height ; ++dy) {
660- for (int dx = 0 ; dx < cell.width ; ++dx) {
661- if (!dpl_grid->pixel (GridY{gy + dy}, GridX{gx + dx}).is_valid ) {
718+ for (int row_offset = 0 ; row_offset < cell.height ; ++row_offset) {
719+ for (int col_offset = 0 ; col_offset < cell.width ; ++col_offset) {
720+ const auto & p = dpl_grid->pixel (
721+ GridY{pixel_bottom + row_offset},
722+ GridX{pixel_left + col_offset});
723+ if (!p.is_valid ) {
724+ debugPrint (logger_,
725+ utl::DPL ,
726+ " negotiation" ,
727+ 1 ,
728+ " Position grid ({}, {}) rejected for instance "
729+ " '{}': pixel ({}, {}) inside the {}x{} footprint "
730+ " is marked invalid (hopeless={}, "
731+ " blocked_layers=0x{:x}). This pixel is under a "
732+ " macro, a hard blockage, or not covered by any "
733+ " row." ,
734+ pixel_left,
735+ pixel_bottom,
736+ cell.db_inst ->getName (),
737+ pixel_left + col_offset,
738+ pixel_bottom + row_offset,
739+ cell.width ,
740+ cell.height ,
741+ p.is_hopeless ,
742+ p.blocked_layers );
662743 return false ;
663744 }
664745 }
@@ -714,18 +795,18 @@ bool NegotiationLegalizer::initFromDb()
714795
715796 if (!isValidSite (cell.init_x , cell.init_y )
716797 || !isInRegionOk (cell.init_x , cell.init_y )) {
717- // debugPrint(logger_,
718- // utl::DPL,
719- // "negotiation",
720- // 1,
721- logger_-> report (
722- " Instance {} at ({}, {}) snaps to invalid site at "
723- " ({}, {}). Searching for nearest valid site." ,
724- cell.db_inst ->getName (),
725- db_x,
726- db_y,
727- die_xlo_ + cell.init_x * site_width_,
728- die_ylo_ + dpl_grid->gridYToDbu (GridY{cell.init_y }).v );
798+ debugPrint (logger_,
799+ utl::DPL ,
800+ " negotiation" ,
801+ 1 ,
802+ " Instance '{}' initially at dbu ({}, {}) rounds to "
803+ " an invalid initial position at dbu ({}, {}). Will "
804+ " search for the nearest valid site." ,
805+ cell.db_inst ->getName (),
806+ db_x,
807+ db_y,
808+ die_xlo_ + cell.init_x * site_width_,
809+ die_ylo_ + dpl_grid->gridYToDbu (GridY{cell.init_y }).v );
729810
730811 // Linear scan in the four cardinal directions (same shape as
731812 // Opendp::moveHopeless).
@@ -814,12 +895,18 @@ bool NegotiationLegalizer::initFromDb()
814895 const int init_x_dbu = die_xlo_ + cell.init_x * site_width_;
815896 const int init_y_dbu
816897 = die_ylo_ + dpl_grid->gridYToDbu (GridY{cell.init_y }).v ;
817- logger_->report (
818- " Could not find a valid site for instance {} (init ({}, {}) "
819- " dbu)." ,
820- cell.db_inst ->getName (),
821- init_x_dbu,
822- init_y_dbu);
898+ debugPrint (logger_,
899+ utl::DPL ,
900+ " negotiation" ,
901+ 1 ,
902+ " No valid site found for instance '{}' near its "
903+ " initial position dbu ({}, {}). Linear scan in all "
904+ " four cardinal directions exhausted with no match. "
905+ " Leaving instance at its initial position; "
906+ " negotiation will need to legalize it." ,
907+ cell.db_inst ->getName (),
908+ init_x_dbu,
909+ init_y_dbu);
823910 }
824911 }
825912 }
0 commit comments