diff --git a/elab_net.cc b/elab_net.cc index 71670b1043..c116c0ec76 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -2393,8 +2393,6 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope, connect(ps->pin(0), osig->pin(0)); connect(ps->pin(1), nets[idx]->pin(0)); - join_island(ps); - ivl_assert(*this, wid <= width); width -= wid; } @@ -2801,7 +2799,6 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, des->add_node(sub); connect(sub->pin(0), sig->pin(0)); connect(sub->pin(1), subsig->pin(0)); - join_island(sub); } else { NetPartSelect*sub = new NetPartSelect(sig, lidx, subnet_wid, diff --git a/elaborate.cc b/elaborate.cc index 049b47fdff..eb93811bd9 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -863,14 +863,6 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const des->errors += 1; } - } - - // If these new nodes can belong to an island, then run tests - // to joind islands now. - if (dynamic_cast (cur[0])) { - for (unsigned idx = 0 ; idx < count ; idx += 1) { - join_island(cur[idx]); - } } // "cur" is an array of pointers, and we don't need it any more. @@ -910,7 +902,6 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope, node->set_line(*this); des->add_node(node); - join_island(node); return tmp; } diff --git a/main.cc b/main.cc index 640fcf4d3a..26b237e248 100644 --- a/main.cc +++ b/main.cc @@ -825,6 +825,11 @@ int main(int argc, char*argv[]) func(des); } + if (verbose_flag) { + cout << "CALCULATING ISLANDS" << endl; + } + des->join_islands(); + if (net_path) { if (verbose_flag) cerr<<" dumping netlist to " <node_next_; + do { + join_island(cur); + cur = cur->node_next_; + } while (cur != nodes_->node_next_); +} diff --git a/net_tran.cc b/net_tran.cc index e8088784fb..e31771d7db 100644 --- a/net_tran.cc +++ b/net_tran.cc @@ -82,42 +82,79 @@ unsigned NetTran::part_offset() const void join_island(NetObj*obj) { IslandBranch*branch = dynamic_cast (obj); + + // If this is not even a branch, then stop now. if (branch == 0) return; - ivl_assert(*obj, branch->island == 0); - struct ivl_island_s*use_island = 0; + // If this is a branch, but already given to an island, then + // stop. + if (branch->island) + return; + + list uncommitted_neighbors; + // Look for neighboring objects that might already be in + // islands. If we find something, then join that island. for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1) { Nexus*nex = obj->pin(idx).nexus(); for (Link*cur = nex->first_nlink() ; cur ; cur = cur->next_nlink()) { unsigned pin; NetObj*tmp; cur->cur_link(tmp, pin); + + // Skip self. if (tmp == obj) continue; + // If tmb is not a branch, then skip it. IslandBranch*tmp_branch = dynamic_cast (tmp); if (tmp_branch == 0) continue; - ivl_assert(*tmp, tmp_branch->island); - ivl_assert(*obj, use_island==0 || use_island==tmp_branch->island); - use_island = tmp_branch->island; + // If that is an uncommitted branch, then save + // it. When I finally choose an island for self, + // these branches will be scanned so tha they join + // this island as well. + if (tmp_branch->island == 0) { + uncommitted_neighbors.push_back(tmp); + continue; + } + + ivl_assert(*obj, branch->island==0 || branch->island==tmp_branch->island); + + // We found an existing island to join. Join it + // now. Keep scanning in order to find more neighbors. + if (branch->island == 0) { + if (debug_elaborate) + cerr << obj->get_fileline() << ": debug: " + << "Join brach to existing island." << endl; + branch->island = tmp_branch->island; + + } else if (branch->island != tmp_branch->island) { + cerr << obj->get_fileline() << ": internal error: " + << "Oops, Found 2 neighboring islands." << endl; + ivl_assert(*obj, 0); + } } } - if (use_island == 0) { - use_island = new ivl_island_s; - use_island->discipline = 0; + // If after all that we did not find an idland to join, then + // start the island not and join it. + if (branch->island == 0) { + branch->island = new ivl_island_s; + branch->island->discipline = 0; if (debug_elaborate) cerr << obj->get_fileline() << ": debug: " << "Create new island for this branch" << endl; - } else { - if (debug_elaborate) - cerr << obj->get_fileline() << ": debug: " - << "Join this brach to existing island." << endl; } - branch->island = use_island; + // Now scan all the uncommitted neighbors I found. Calling + // join_island() on them will cause them to notice me in the + // process, and thus they will join my island. This process + // will recurse until all the connected branches join this island. + for (list::iterator cur = uncommitted_neighbors.begin() + ; cur != uncommitted_neighbors.end() ; cur ++ ) { + join_island(*cur); + } } diff --git a/netlist.h b/netlist.h index d3dce71dda..beafc577a8 100644 --- a/netlist.h +++ b/netlist.h @@ -3638,6 +3638,7 @@ class Design { // Iterate over the design... void dump(ostream&) const; void functor(struct functor_t*); + void join_islands(void); int emit(struct target_t*) const; // This is incremented by elaboration when an error is