@@ -5272,157 +5272,157 @@ bool Resizer::isClockCellCandidate(sta::LibertyCell* cell)
52725272void Resizer::inferClockBufferList (const char * lib_name,
52735273 std::vector<std::string>& buffers)
52745274{
5275- sta::Vector<sta::LibertyCell*> selected_buffers;
5276-
5277- // first, look for buffers with "is_clock_cell: true" cell attribute
5278- sta::LibertyLibraryIterator* lib_iter = network_->libertyLibraryIterator ();
5275+ // Lists to store different types of clock buffer candidates based on several
5276+ // criteria.
5277+ sta::Vector<sta::LibertyCell*> clock_cell_attribute_buffers;
5278+ sta::Vector<sta::LibertyCell*> lef_use_clock_buffers;
5279+ sta::Vector<sta::LibertyCell*> clkbuf_pattern_buffers;
5280+ sta::Vector<sta::LibertyCell*> buf_pattern_buffers;
5281+ sta::Vector<sta::LibertyCell*> all_candidate_buffers;
5282+
5283+ // Patterns for matching common clock buffer and general buffer naming
5284+ // conventions.
5285+ sta::PatternMatch patternClkBuf (" .*CLKBUF.*" ,
5286+ /* is_regexp */ true ,
5287+ /* nocase */ true ,
5288+ /* Tcl_interp* */ sta_->tclInterp ());
5289+ sta::PatternMatch patternBuf (" .*BUF.*" ,
5290+ /* is_regexp */ true ,
5291+ /* nocase */ true ,
5292+ /* Tcl_interp* */ nullptr );
5293+
5294+ // 1. Iterate over all liberty libraries to find candidate cells.
5295+ std::unique_ptr<sta::LibertyLibraryIterator> lib_iter (
5296+ network_->libertyLibraryIterator ());
52795297 while (lib_iter->hasNext ()) {
52805298 sta::LibertyLibrary* lib = lib_iter->next ();
5299+ // Filter by library name if provided.
52815300 if (lib_name != nullptr && strcmp (lib->name (), lib_name) != 0 ) {
52825301 continue ;
52835302 }
5303+
5304+ // Collect candidates by checking cell attributes and LEF pin signal types.
52845305 for (sta::LibertyCell* buffer : *lib->buffers ()) {
5285- if (buffer->isClockCell () && isClockCellCandidate (buffer)) {
5286- // "is_clock_cell: true"
5287- selected_buffers.emplace_back (buffer);
5288- debugPrint (logger_,
5289- RSZ,
5290- " inferClockBufferList" ,
5291- 1 ,
5292- " {} has clock cell attribute" ,
5293- buffer->name ());
5306+ if (!isClockCellCandidate (buffer)) {
5307+ continue ;
52945308 }
5295- }
5296- }
5297- delete lib_iter;
5309+ all_candidate_buffers.emplace_back (buffer);
52985310
5299- // second, look for buffers with an input port that has
5300- // LEF USE as "CLOCK"
5301- if (selected_buffers.empty ()) {
5302- sta::LibertyLibraryIterator* lib_iter = network_->libertyLibraryIterator ();
5303- while (lib_iter->hasNext ()) {
5304- sta::LibertyLibrary* lib = lib_iter->next ();
5305- if (lib_name != nullptr && strcmp (lib->name (), lib_name) != 0 ) {
5306- continue ;
5311+ // Priority 1: Check for explicit "is_clock_cell" attribute in liberty.
5312+ if (buffer->isClockCell ()) {
5313+ clock_cell_attribute_buffers.emplace_back (buffer);
53075314 }
5308- for (sta::LibertyCell* buffer : *lib->buffers ()) {
5309- odb::dbMaster* master = db_->findMaster (buffer->name ());
5310- for (odb::dbMTerm* mterm : master->getMTerms ()) {
5311- if (mterm->getIoType () == odb::dbIoType::INPUT
5312- && mterm->getSigType () == odb::dbSigType::CLOCK
5313- && isClockCellCandidate (buffer)) {
5314- // input port with LEF USE as "CLOCK"
5315- selected_buffers.emplace_back (buffer);
5316- debugPrint (logger_,
5317- RSZ,
5318- " inferClockBufferList" ,
5319- 1 ,
5320- " {} has input port {} with LEF USE as CLOCK" ,
5321- buffer->name (),
5322- mterm->getName ());
5323- }
5315+
5316+ // Priority 2: Check for any input pin with LEF signal type set to CLOCK.
5317+ odb::dbMaster* master = db_->findMaster (buffer->name ());
5318+ for (odb::dbMTerm* mterm : master->getMTerms ()) {
5319+ if (mterm->getIoType () == odb::dbIoType::INPUT
5320+ && mterm->getSigType () == odb::dbSigType::CLOCK) {
5321+ lef_use_clock_buffers.emplace_back (buffer);
5322+ break ; // Avoid duplicates for multiple clock pins
53245323 }
53255324 }
53265325 }
5327- delete lib_iter;
5328- }
53295326
5330- // third, look for all buffers with name CLKBUF or clkbuf
5331- if (selected_buffers.empty ()) {
5332- sta::PatternMatch patternClkBuf (" .*CLKBUF.*" ,
5333- /* is_regexp */ true ,
5334- /* nocase */ true ,
5335- /* Tcl_interp* */ sta_->tclInterp ());
5336- sta::LibertyLibraryIterator* lib_iter = network_->libertyLibraryIterator ();
5337- while (lib_iter->hasNext ()) {
5338- sta::LibertyLibrary* lib = lib_iter->next ();
5339- if (lib_name != nullptr && strcmp (lib->name (), lib_name) != 0 ) {
5340- continue ;
5327+ // Priority 3: Collections based on naming pattern matching (CLKBUF).
5328+ for (sta::LibertyCell* buffer :
5329+ lib->findLibertyCellsMatching (&patternClkBuf)) {
5330+ if (buffer->isBuffer () && isClockCellCandidate (buffer)) {
5331+ clkbuf_pattern_buffers.emplace_back (buffer);
53415332 }
5342- for (sta::LibertyCell* buffer :
5343- lib->findLibertyCellsMatching (&patternClkBuf)) {
5344- if (buffer->isBuffer () && isClockCellCandidate (buffer)) {
5345- debugPrint (logger_,
5346- RSZ,
5347- " inferClockBufferList" ,
5348- 1 ,
5349- " {} found by 'CLKBUF' pattern match" ,
5350- buffer->name ());
5351- selected_buffers.emplace_back (buffer);
5352- }
5333+ }
5334+
5335+ // Priority 4: Collections based on naming pattern matching (BUF).
5336+ for (sta::LibertyCell* buffer :
5337+ lib->findLibertyCellsMatching (&patternBuf)) {
5338+ if (buffer->isBuffer () && isClockCellCandidate (buffer)) {
5339+ buf_pattern_buffers.emplace_back (buffer);
53535340 }
53545341 }
5355- delete lib_iter;
53565342 }
53575343
5358- // fourth, look for all buffers with name BUF or buf
5359- if (selected_buffers.empty ()) {
5360- sta::PatternMatch patternBuf (" .*BUF.*" ,
5361- /* is_regexp */ true ,
5362- /* nocase */ true ,
5363- /* Tcl_interp* */ nullptr );
5364- sta::LibertyLibraryIterator* lib_iter = network_->libertyLibraryIterator ();
5365- while (lib_iter->hasNext ()) {
5366- sta::LibertyLibrary* lib = lib_iter->next ();
5367- if (lib_name != nullptr && strcmp (lib->name (), lib_name) != 0 ) {
5368- continue ;
5369- }
5370- for (sta::LibertyCell* buffer :
5371- lib->findLibertyCellsMatching (&patternBuf)) {
5372- if (buffer->isBuffer () && isClockCellCandidate (buffer)) {
5344+ // 2. Select the final list of buffers based on the defined priority.
5345+ // We take the first non-empty set found.
5346+ sta::Vector<sta::LibertyCell*>* selected_ptr = nullptr ;
5347+ if (!clock_cell_attribute_buffers.empty ()) {
5348+ selected_ptr = &clock_cell_attribute_buffers;
5349+ for (sta::LibertyCell* buffer : *selected_ptr) {
5350+ debugPrint (logger_,
5351+ RSZ,
5352+ " inferClockBufferList" ,
5353+ 1 ,
5354+ " {} has clock cell attribute" ,
5355+ buffer->name ());
5356+ }
5357+ } else if (!lef_use_clock_buffers.empty ()) {
5358+ selected_ptr = &lef_use_clock_buffers;
5359+ for (sta::LibertyCell* buffer : *selected_ptr) {
5360+ odb::dbMaster* master = db_->findMaster (buffer->name ());
5361+ for (odb::dbMTerm* mterm : master->getMTerms ()) {
5362+ if (mterm->getIoType () == odb::dbIoType::INPUT
5363+ && mterm->getSigType () == odb::dbSigType::CLOCK) {
53735364 debugPrint (logger_,
53745365 RSZ,
53755366 " inferClockBufferList" ,
53765367 1 ,
5377- " {} found by 'BUF' pattern match" ,
5378- buffer->name ());
5379- selected_buffers.emplace_back (buffer);
5368+ " {} has input port {} with LEF USE as CLOCK" ,
5369+ buffer->name (),
5370+ mterm->getName ());
5371+ break ;
53805372 }
53815373 }
53825374 }
5383- delete lib_iter;
5384- }
5385-
5386- // abandon attributes & name patterns, just look for all buffers
5387- if (selected_buffers.empty ()) {
5375+ } else if (!clkbuf_pattern_buffers.empty ()) {
5376+ selected_ptr = &clkbuf_pattern_buffers;
5377+ for (sta::LibertyCell* buffer : *selected_ptr) {
5378+ debugPrint (logger_,
5379+ RSZ,
5380+ " inferClockBufferList" ,
5381+ 1 ,
5382+ " {} found by 'CLKBUF' pattern match" ,
5383+ buffer->name ());
5384+ }
5385+ } else if (!buf_pattern_buffers.empty ()) {
5386+ selected_ptr = &buf_pattern_buffers;
5387+ for (sta::LibertyCell* buffer : *selected_ptr) {
5388+ debugPrint (logger_,
5389+ RSZ,
5390+ " inferClockBufferList" ,
5391+ 1 ,
5392+ " {} found by 'BUF' pattern match" ,
5393+ buffer->name ());
5394+ }
5395+ } else {
5396+ // Priority 5: Fallback to all buffers that are valid clock cell candidates.
53885397 debugPrint (logger_,
53895398 RSZ,
53905399 " inferClockBufferList" ,
53915400 1 ,
53925401 " No buffers with clock attributes or name patterns found, using "
53935402 " all buffers" );
5394- sta::LibertyLibraryIterator* lib_iter = network_->libertyLibraryIterator ();
5395- while (lib_iter->hasNext ()) {
5396- sta::LibertyLibrary* lib = lib_iter->next ();
5397- if (lib_name != nullptr && strcmp (lib->name (), lib_name) != 0 ) {
5398- continue ;
5399- }
5400- for (sta::LibertyCell* buffer : *lib->buffers ()) {
5401- if (isClockCellCandidate (buffer)) {
5402- selected_buffers.emplace_back (buffer);
5403- }
5404- }
5405- }
5406- delete lib_iter;
5407-
5408- if (selected_buffers.empty ()) {
5403+ selected_ptr = &all_candidate_buffers;
5404+ if (selected_ptr->empty ()) {
54095405 logger_->error (
54105406 RSZ,
54115407 110 ,
54125408 " No clock buffer candidates could be found from any libraries." );
54135409 }
54145410 }
54155411
5416- setClockBuffersList (selected_buffers);
5412+ // 3. Finalize the inferred list: store it in Resizer and populate the output
5413+ // vector of buffer names.
5414+ if (selected_ptr != nullptr ) {
5415+ setClockBuffersList (*selected_ptr);
54175416
5418- for (sta::LibertyCell* buffer : selected_buffers) {
5419- buffers.emplace_back (buffer->name ());
5420- debugPrint (logger_,
5421- RSZ,
5422- " inferClockBufferList" ,
5423- 1 ,
5424- " {} has been inferred as clock buffer" ,
5425- buffer->name ());
5417+ for (sta::LibertyCell* buffer : *selected_ptr) {
5418+ buffers.emplace_back (buffer->name ());
5419+ debugPrint (logger_,
5420+ RSZ,
5421+ " inferClockBufferList" ,
5422+ 1 ,
5423+ " {} has been inferred as clock buffer" ,
5424+ buffer->name ());
5425+ }
54265426 }
54275427}
54285428
0 commit comments