@@ -681,26 +681,127 @@ bool BaseMove::replaceCell(Instance* inst, const LibertyCell* replacement)
681681 const char * replacement_name = replacement->name ();
682682 dbMaster* replacement_master = db_->findMaster (replacement_name);
683683
684- if (replacement_master) {
685- dbInst* dinst = db_network_->staToDb (inst);
686- dbMaster* master = dinst->getMaster ();
687- resizer_->designAreaIncr (-area (master));
688- Cell* replacement_cell1 = db_network_->dbToSta (replacement_master);
689- sta_->replaceCell (inst, replacement_cell1);
690- resizer_->designAreaIncr (area (replacement_master));
691-
692- // Legalize the position of the instance in case it leaves the die
693- if (estimate_parasitics_->getParasiticsSrc ()
694- == est::ParasiticsSrc::global_routing
695- || estimate_parasitics_->getParasiticsSrc ()
696- == est::ParasiticsSrc::detailed_routing) {
697- opendp_->legalCellPos (db_network_->staToDb (inst));
684+ if (!replacement_master) {
685+ return false ;
686+ }
687+
688+ // Check if replacement would cause max_cap violations on input nets
689+ if (!checkMaxCapViolation (inst, replacement)) {
690+ return false ;
691+ }
692+
693+ dbInst* dinst = db_network_->staToDb (inst);
694+ dbMaster* master = dinst->getMaster ();
695+ resizer_->designAreaIncr (-area (master));
696+ Cell* replacement_cell1 = db_network_->dbToSta (replacement_master);
697+ sta_->replaceCell (inst, replacement_cell1);
698+ resizer_->designAreaIncr (area (replacement_master));
699+
700+ // Legalize the position of the instance in case it leaves the die
701+ if (estimate_parasitics_->getParasiticsSrc ()
702+ == est::ParasiticsSrc::global_routing
703+ || estimate_parasitics_->getParasiticsSrc ()
704+ == est::ParasiticsSrc::detailed_routing) {
705+ opendp_->legalCellPos (db_network_->staToDb (inst));
706+ }
707+
708+ return true ;
709+ }
710+
711+ // Check if replacing inst with replacement cell would cause max_cap violation
712+ // on any of the fanin nets.
713+ bool BaseMove::checkMaxCapViolation (Instance* inst,
714+ const LibertyCell* replacement)
715+ {
716+ LibertyCell* current_cell = network_->libertyCell (inst);
717+ if (!current_cell) {
718+ return true ; // Nothing to check, just allow it
719+ }
720+
721+ // Iterate through all input pins of the instance
722+ InstancePinIterator* pin_iter = network_->pinIterator (inst);
723+ while (pin_iter->hasNext ()) {
724+ Pin* pin = pin_iter->next ();
725+
726+ // Only check input pins
727+ if (!network_->direction (pin)->isAnyInput ()) {
728+ continue ;
729+ }
730+ PinSet* drivers = network_->drivers (pin);
731+ if (drivers) {
732+ // Calculate capacitance delta (new - old)
733+ float old_cap = getInputPinCapacitance (pin, current_cell);
734+ float new_cap = getInputPinCapacitance (pin, replacement);
735+ float cap_delta = new_cap - old_cap;
736+ if (cap_delta <= 0.0 ) {
737+ continue ;
738+ }
739+ for (const Pin* drvr_pin : *drivers) {
740+ if (!checkMaxCapOK (drvr_pin, cap_delta)) {
741+ delete pin_iter;
742+ return false ;
743+ }
744+ }
698745 }
746+ }
699747
700- return true ;
748+ delete pin_iter;
749+ return true ;
750+ }
751+
752+ // Get input capacitance for a specific port in a liberty cell
753+ float BaseMove::getInputPinCapacitance (Pin* pin, const LibertyCell* cell)
754+ {
755+ LibertyPort* port = network_->libertyPort (pin);
756+ if (!port) {
757+ return 0.0 ;
701758 }
702- return false ;
759+
760+ // Find corresponding port in the new cell
761+ LibertyPort* cell_port = cell->findLibertyPort (port->name ());
762+ if (!cell_port) {
763+ return 0.0 ;
764+ }
765+
766+ // Get worst capacitance
767+ float cap = 0.0 ;
768+ for (auto rf : RiseFall::range ()) {
769+ float port_cap = cell_port->capacitance (rf, resizer_->max_ );
770+ cap = max (cap, port_cap);
771+ }
772+
773+ return cap;
774+ }
775+
776+ // Check for possible max cap violation with new cap_delta
777+ // If max cap is already violating, accept a solution only if
778+ // it does not worsen the violation
779+ bool BaseMove::checkMaxCapOK (const Pin* drvr_pin, float cap_delta)
780+ {
781+ float cap, max_cap, cap_slack;
782+ const Corner* corner;
783+ const RiseFall* tr;
784+ sta_->checkCapacitance (drvr_pin,
785+ nullptr /* corner */ ,
786+ resizer_->max_ ,
787+ // return values
788+ corner,
789+ tr,
790+ cap,
791+ max_cap,
792+ cap_slack);
793+
794+ if (max_cap > 0.0 && corner) {
795+ float new_cap = cap + cap_delta;
796+ // If it is already violating, accept only if violation is no worse
797+ if (cap_slack < 0.0 ) {
798+ return new_cap <= cap;
799+ }
800+ return new_cap <= max_cap;
801+ }
802+ return true ;
703803}
804+
704805Slack BaseMove::getWorstInputSlack (Instance* inst)
705806{
706807 Slack worst_slack = INF;
0 commit comments