From db09f2fa7eb059427f7ff4b6fe057bca3d68c8d4 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Tue, 3 Jun 2008 20:21:39 -0700 Subject: [PATCH] More cost effective and reliable island joining algorithm. Rather then join islands while branches are initially created, save the island creating for the end. This way, the process is actually recursive and greedy, reliably collecting branches into islands without conflict. --- elab_net.cc | 3 --- elaborate.cc | 9 -------- main.cc | 5 ++++ net_design.cc | 11 +++++++++ net_tran.cc | 63 ++++++++++++++++++++++++++++++++++++++++----------- netlist.h | 1 + 6 files changed, 67 insertions(+), 25 deletions(-) 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