@@ -316,23 +316,81 @@ class DbInstanceNetIterator : public InstanceNetIterator
316316 dbSet<dbNet>::iterator end_;
317317 dbSet<dbModNet>::iterator mod_net_iter_;
318318 dbSet<dbModNet>::iterator mod_net_end_;
319+ std::vector<dbNet*> flat_nets_vec_;
320+ size_t flat_net_idx_ = 0 ;
319321};
320322
321323DbInstanceNetIterator::DbInstanceNetIterator (const Instance* instance,
322324 const dbNetwork* network)
323325 : network_(network)
324326{
325327 if (network_->hasHierarchy ()) {
326- dbInst* db_inst;
327- dbModInst* mod_inst;
328- network_->staToDb (instance, db_inst, mod_inst);
329- if (mod_inst) {
330- dbModule* master = mod_inst->getMaster ();
331- dbSet<dbModNet> nets = master->getModNets ();
332- mod_net_iter_ = nets.begin ();
333- mod_net_end_ = nets.end ();
328+ //
329+ // In hierarchical flow, the net iterator collects both hierarchical
330+ // nets (dbModNets) and unique flat nets (dbNets) within the
331+ // instance's module scope.
332+ // Flat nets can be retrieved by traversing instance ITerms and BTerms.
333+ // Avoids the duplication b/w flat and hierarchical nets.
334+ //
335+
336+ // Get the module of the instance
337+ dbModule* module = nullptr ;
338+ if (instance == network->topInstance ()) {
339+ module = network->block ()->getTopModule ();
340+ } else {
341+ dbInst* db_inst;
342+ dbModInst* mod_inst;
343+ network_->staToDb (instance, db_inst, mod_inst);
344+ if (mod_inst) {
345+ module = mod_inst->getMaster ();
346+ }
347+ }
348+
349+ if (module ) {
350+ // Get dbModNets
351+ dbSet<dbModNet> mod_nets = module ->getModNets ();
352+ mod_net_iter_ = mod_nets.begin ();
353+ mod_net_end_ = mod_nets.end ();
354+
355+ // Keep track of flat nets that are already represented by a mod_net
356+ // to avoid returning both.
357+ std::set<dbNet*> handled_flat_nets;
358+ for (dbModNet* mod_net : mod_nets) {
359+ dbNet* flat_net = network_->findRelatedDbNet (mod_net);
360+ if (flat_net) {
361+ handled_flat_nets.insert (flat_net);
362+ }
363+ }
364+
365+ // Collect dbNets from children dbInsts' pins that are not already
366+ // handled.
367+ std::set<dbNet*> flat_nets_set;
368+ for (dbInst* child_inst : module ->getInsts ()) {
369+ for (dbITerm* iterm : child_inst->getITerms ()) {
370+ dbNet* flat_net = iterm->getNet ();
371+ if (flat_net
372+ && handled_flat_nets.find (flat_net) == handled_flat_nets.end ()) {
373+ flat_nets_set.insert (flat_net);
374+ }
375+ }
376+ }
377+
378+ // For top instance, also check top-level ports (BTerms)
379+ if (instance == network->topInstance ()) {
380+ for (dbBTerm* bterm : network->block ()->getBTerms ()) {
381+ dbNet* flat_net = bterm->getNet ();
382+ if (flat_net
383+ && handled_flat_nets.find (flat_net) == handled_flat_nets.end ()) {
384+ flat_nets_set.insert (flat_net);
385+ }
386+ }
387+ }
388+ flat_nets_vec_.assign (flat_nets_set.begin (), flat_nets_set.end ());
334389 }
335390 } else {
391+ //
392+ // In flat flow, the net iterator collects all nets from top block
393+ //
336394 if (instance == network->topInstance ()) {
337395 dbSet<dbNet> nets = network->block ()->getNets ();
338396 iter_ = nets.begin ();
@@ -344,17 +402,27 @@ DbInstanceNetIterator::DbInstanceNetIterator(const Instance* instance,
344402bool DbInstanceNetIterator::hasNext ()
345403{
346404 if (network_->hasHierarchy ()) {
347- return mod_net_iter_ != mod_net_end_;
405+ if (mod_net_iter_ != mod_net_end_) {
406+ return true ;
407+ }
408+ return flat_net_idx_ < flat_nets_vec_.size ();
348409 }
349410 return iter_ != end_;
350411}
351412
352413Net* DbInstanceNetIterator::next ()
353414{
354415 if (network_->hasHierarchy ()) {
355- dbModNet* net = *mod_net_iter_;
356- mod_net_iter_++;
357- return network_->dbToSta (net);
416+ if (mod_net_iter_ != mod_net_end_) {
417+ dbModNet* net = *mod_net_iter_;
418+ mod_net_iter_++;
419+ return network_->dbToSta (net);
420+ }
421+ if (flat_net_idx_ < flat_nets_vec_.size ()) {
422+ dbNet* net = flat_nets_vec_[flat_net_idx_++];
423+ return network_->dbToSta (net);
424+ }
425+ return nullptr ;
358426 }
359427 dbNet* net = *iter_;
360428 iter_++;
@@ -3226,10 +3294,12 @@ bool dbNetwork::hasMembers(const Port* port) const
32263294 dbBTerm* bterm = nullptr ;
32273295 dbModBTerm* modbterm = nullptr ;
32283296 staToDb (port, bterm, mterm, modbterm);
3229- if (modbterm && modbterm-> isBusPort () ) {
3230- return true ;
3297+ if (modbterm) {
3298+ return modbterm-> isBusPort () ;
32313299 }
3232- return false ;
3300+
3301+ // If port is a bus port of leaf liberty instance, modbterm is null.
3302+ // In the case, cport->hasMembers() should be checked.
32333303 }
32343304 const ConcretePort* cport = reinterpret_cast <const ConcretePort*>(port);
32353305 return cport->hasMembers ();
0 commit comments