From e872310e4b909fa41439bf28a7f0dce30343bca5 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 4 Jun 2008 11:34:26 -0700 Subject: [PATCH] Optimize recursive branch resolution Recursive branch resolution was scanning every branch end, even though many branch ends share ports and need not be repeatedly scanned. Handle marks and flags to cut off recursion where it is not needed so as to save much run time. --- vvp/vvp_island.cc | 106 ++++++++++++++++++++++++++++++---------------- 1 file changed, 69 insertions(+), 37 deletions(-) diff --git a/vvp/vvp_island.cc b/vvp/vvp_island.cc index eea7b7f7f..09764a7ac 100644 --- a/vvp/vvp_island.cc +++ b/vvp/vvp_island.cc @@ -387,6 +387,39 @@ static vvp_vector8_t get_value(vvp_net_t*net) return fun->invalue; } +static void mark_done_flags(list&connections) +{ + for (list::iterator idx = connections.begin() + ; idx != connections.end() ; idx ++ ) { + + vvp_island_branch*tmp_ptr = idx->ptr(); + unsigned tmp_ab = idx->port(); + tmp_ptr->flags |= 1 << tmp_ab; + } +} + +static void mark_visited_flags(list&connections) +{ + for (list::iterator idx = connections.begin() + ; idx != connections.end() ; idx ++ ) { + + vvp_island_branch*tmp_ptr = idx->ptr(); + unsigned tmp_ab = idx->port(); + tmp_ptr->flags |= 4 << tmp_ab; + } +} + +static void clear_visited_flags(list&connections) +{ + for (list::iterator idx = connections.begin() + ; idx != connections.end() ; idx ++ ) { + + vvp_island_branch*tmp_ptr = idx->ptr(); + unsigned tmp_ab = idx->port(); + tmp_ptr->flags &= ~(4 << tmp_ab); + } +} + static vvp_vector8_t get_value_from_branch(vvp_branch_ptr_t cur) { vvp_island_branch*ptr = cur.ptr(); @@ -398,7 +431,7 @@ static vvp_vector8_t get_value_from_branch(vvp_branch_ptr_t cur) return vvp_vector8_t(); // If the branch other side is already visited, return nil. - if (ptr->flags & (1<flags & (4<a : ptr->b; vvp_vector8_t val_other = get_value(net); - // Temporarily mark as visited. - ptr->flags |= 1< connections; collect_node(connections, other); + mark_visited_flags(connections); for (list::iterator idx = connections.begin() ; idx != connections.end() ; idx ++ ) { @@ -424,7 +455,7 @@ static vvp_vector8_t get_value_from_branch(vvp_branch_ptr_t cur) } // Remove visited flag - ptr->flags &= ~(1<&connections) +{ + for (list::iterator idx = connections.begin() + ; idx != connections.end() ; idx ++ ) { + vvp_vector8_t tmp = get_value_from_branch(*idx); + if (val.size() == 0) + val = tmp; + else if (tmp.size() != 0) + val = resolve(val, tmp); + } +} + void vvp_island_branch::run_resolution() { // Collect all the branch endpoints that are joined to my A @@ -448,56 +492,43 @@ void vvp_island_branch::run_resolution() collect_node(connections, vvp_branch_ptr_t(this, 0)); // Mark my A side as done. Do this early to prevent recursing - // back. - flags |= 1; + // back. All the connections that share this port are also + // done. Make sure their flags are set appropriately. + mark_done_flags(connections); - // Prime the resolution with the port value for this node. vvp_vector8_t val = get_value(a); + mark_visited_flags(connections); // Mark as visited. // Now scan the other sides of all the branches connected to // my A side. The get_value_from_branch() will recurse as // necessary to depth-first walk the graph. - for (list::iterator idx = connections.begin() - ; idx != connections.end() ; idx ++ ) { - vvp_vector8_t tmp = get_value_from_branch(*idx); - if (val.size() == 0) - val = tmp; - else if (tmp.size() != 0) - val = resolve(val, tmp); - } + resolve_values_from_connections(val, connections); // A side is done. vvp_send_vec8(a->out, val); - flags &= ~1; + // Clear the visited flags. This must be done so that other + // branches can read this input value. + clear_visited_flags(connections); - // If this is a connected branch without a part select, then - // we know from the start that the other side has the same + // Repeat the above for the B side. + + connections.clear(); + collect_node(connections, vvp_branch_ptr_t(this, 1)); + mark_done_flags(connections); + + // If this is a connected branch without a part select, then + // we know from the start that the B side has the same // value as this. Mark it and finish. if (enabled_flag && width==0) { vvp_send_vec8(b->out, val); return; } - // Repeat the above for the B side. - - connections.clear(); - collect_node(connections, vvp_branch_ptr_t(this, 1)); - - flags |= 2; - val = get_value(b); - - for (list::iterator idx = connections.begin() - ; idx != connections.end() ; idx ++ ) { - vvp_vector8_t tmp = get_value_from_branch(*idx); - if (val.size() == 0) - val = tmp; - else if (tmp.size() != 0) - val = resolve(val, tmp); - } - - flags &= ~2; + mark_visited_flags(connections); + resolve_values_from_connections(val, connections); + clear_visited_flags(connections); vvp_send_vec8(b->out, val); } @@ -526,6 +557,7 @@ void compile_island(char*label, char*type) } island_table->sym_set_value(label, use_island); + island_list.push_back(use_island); free(label); free(type); }