From e97a1ad610a406fdf4883fc1d6f24c893cd62c26 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 4 Jun 2008 16:10:43 -0700 Subject: [PATCH] Try to eliminate excessive processing recursions. After calculating the A side of a tran[if/vp], the B side is usually fully specified, so make an effort to push the calculated value through. --- vvp/vvp_island.cc | 101 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 77 insertions(+), 24 deletions(-) diff --git a/vvp/vvp_island.cc b/vvp/vvp_island.cc index 09764a7ac..ea0563db4 100644 --- a/vvp/vvp_island.cc +++ b/vvp/vvp_island.cc @@ -484,34 +484,81 @@ static void resolve_values_from_connections(vvp_vector8_t&val, } } +static void push_value_through_branches(const vvp_vector8_t&val, + list&connections) +{ + for (list::iterator idx = connections.begin() + ; idx != connections.end() ; idx ++ ) { + + vvp_island_branch*tmp_ptr = idx->ptr(); + unsigned tmp_ab = idx->port(); + unsigned other_ab = tmp_ab^1; + + // If other side already done, skip + if (tmp_ptr->flags & (1<enabled_flag) + continue; + + vvp_net_t*other_net = other_ab? tmp_ptr->b : tmp_ptr->a; + + if (tmp_ptr->width == 0) { + // Mark this end as done + tmp_ptr->flags |= (1 << other_ab); + vvp_send_vec8(other_net->out, val); + + } if (other_ab == 1) { + // Mark as done + tmp_ptr->flags |= (1 << other_ab); + vvp_vector8_t tmp = val.subvalue(tmp_ptr->offset, tmp_ptr->part); + vvp_send_vec8(other_net->out, tmp); + } else { + // Otherwise, the other side is not fully + // specified, so we can't take this shortcut. + } + } +} + void vvp_island_branch::run_resolution() { // Collect all the branch endpoints that are joined to my A // side. list connections; - collect_node(connections, vvp_branch_ptr_t(this, 0)); + bool processed_a_side = false; + vvp_vector8_t val; - // Mark my A side as done. Do this early to prevent recursing - // back. All the connections that share this port are also - // done. Make sure their flags are set appropriately. - mark_done_flags(connections); + if ((flags & 1) == 0) { + processed_a_side = true; + collect_node(connections, vvp_branch_ptr_t(this, 0)); - vvp_vector8_t val = get_value(a); - mark_visited_flags(connections); // Mark as visited. + // Mark my A side as done. Do this early to prevent recursing + // back. All the connections that share this port are also + // done. Make sure their flags are set appropriately. + mark_done_flags(connections); - // 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. - resolve_values_from_connections(val, connections); + val = get_value(a); + mark_visited_flags(connections); // Mark as visited. - // A side is done. - vvp_send_vec8(a->out, val); + // 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. + resolve_values_from_connections(val, connections); - // Clear the visited flags. This must be done so that other - // branches can read this input value. - clear_visited_flags(connections); + // A side is done. + vvp_send_vec8(a->out, val); + + // Clear the visited flags. This must be done so that other + // branches can read this input value. + clear_visited_flags(connections); + + push_value_through_branches(val, connections); + } // Repeat the above for the B side. + if (flags & 2) + return; connections.clear(); collect_node(connections, vvp_branch_ptr_t(this, 1)); @@ -519,16 +566,22 @@ void vvp_island_branch::run_resolution() // 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; + // value as this. Even if the B side is a part select, the + // simple part select must be correct because the recursive + // resolve_values_from_connections above must of cycled back + // to the B side of myself when resolving the connections. + if (enabled_flag && processed_a_side) { + if (width != 0) + val = val.subvalue(offset, part); + + } else { + + val = get_value(b); + mark_visited_flags(connections); + resolve_values_from_connections(val, connections); + clear_visited_flags(connections); } - val = get_value(b); - mark_visited_flags(connections); - resolve_values_from_connections(val, connections); - clear_visited_flags(connections); vvp_send_vec8(b->out, val); }