From 46b45daea879f633e6de0160f1cc2962f77550ca Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 18 Aug 2010 20:52:43 -0700 Subject: [PATCH] Fix broken search for similar events. The search for similar events, used to elide duplicates, was easily confounded by duplicate pins connected to a probe. This caused the similarity count to get messed up, and bad things happened. Change the method to use set comparisons instead. --- design_dump.cc | 10 ++--- net_event.cc | 104 ++++++++++++++++++++++++++----------------------- 2 files changed, 60 insertions(+), 54 deletions(-) diff --git a/design_dump.cc b/design_dump.cc index 9dd843210..5ddc167e7 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -941,7 +941,7 @@ void NetEvProbe::dump_node(ostream&o, unsigned ind) const o << "negedge "; break; } - o << setw(ind) << "" << "-> " << event_->name() << "; " << endl; + o << setw(ind) << "" << "-> " << scope_path(event_->scope()) << "." << event_->name() << "; " << endl; dump_node_pins(o, ind+4); dump_obj_attr(o, ind+4); } @@ -957,10 +957,10 @@ void NetEvWait::dump(ostream&o, unsigned ind) const o << setw(ind) <<"" << "@("; if (nevents() > 0) - o << event(0)->name(); + o << scope_path(event(0)->scope()) << "." << event(0)->name(); for (unsigned idx = 1 ; idx < nevents() ; idx += 1) - o << " or " << event(idx)->name(); + o << " or " << scope_path(event(idx)->scope()) << "." << event(idx)->name(); o << ") // " << get_fileline() << endl; @@ -981,10 +981,10 @@ void NetEvWait::dump_inline(ostream&o) const o << "@("; if (nevents() > 0) - o << event(0)->name(); + o << scope_path(event(0)->scope()) << "." << event(0)->name(); for (unsigned idx = 1 ; idx < nevents() ; idx += 1) - o << " or " << event(idx)->name(); + o << " or " << scope_path(event(idx)->scope())<<"."<name(); o << ") "; } diff --git a/net_event.cc b/net_event.cc index da496ae7e..dcb6b7b75 100644 --- a/net_event.cc +++ b/net_event.cc @@ -20,6 +20,9 @@ # include "config.h" # include "compiler.h" # include "netlist.h" +# include + +using namespace std; /* * NOTE: The name_ is perm-allocated by the caller. @@ -119,6 +122,49 @@ unsigned NetEvent::nexpr() const return exprref_; } +static bool probes_are_similar(NetEvProbe*a, NetEvProbe*b) +{ + set aset; + for (unsigned idx = 0 ; idx < a->pin_count() ; idx += 1) + aset .insert( a->pin(idx).nexus() ); + + set bset; + for (unsigned idx = 0 ; idx < b->pin_count() ; idx += 1) + bset .insert( b->pin(idx).nexus() ); + + return aset == bset; +} + +static bool events_are_similar(NetEvent*a, NetEvent*b) +{ + if (a->nprobe() != b->nprobe()) + return false; + + vector amatched (a->nprobe()); + vector bmatched (b->nprobe()); + for (unsigned adx = 0 ; adx < a->nprobe() ; adx += 1) { + NetEvProbe*ap = a->probe(adx); + for (unsigned bdx = 0 ; bdx < b->nprobe() ; bdx += 1) { + if (bmatched[bdx]) continue; + + NetEvProbe*bp = b->probe(bdx); + if (! probes_are_similar(ap, bp)) continue; + + amatched[adx] = true; + bmatched[bdx] = true; + break; + } + } + + for (unsigned idx = 0 ; idx < amatched.size() ; idx += 1) + if (amatched[idx] == false) return false; + + for (unsigned idx = 0 ; idx < bmatched.size() ; idx += 1) + if (bmatched[idx] == false) return false; + + return true; +} + /* * A "similar" event is one that has an identical non-nil set of * probes. @@ -128,63 +174,23 @@ void NetEvent::find_similar_event(list&event_list) if (probes_ == 0) return; - map event_matches; - - /* First, get a list of all the NetEvProbes that are connected - to my first probe. Then use that to create a set of - candidate events. These candidate events are a superset of - the similar events, so I will be culling this list later. */ + set event_candidates; listfirst_probes; probes_->find_similar_probes(first_probes); for (list::iterator idx = first_probes.begin() - ; idx != first_probes.end() ; idx ++) { - event_matches[ (*idx)->event() ] = 1; + ; idx != first_probes.end() ; idx ++) { + event_candidates .insert( (*idx)->event() ); } - /* Now scan the remaining probes, in each case ticking the - candidate event. The events that really are similar to this - one will turn up in every probe list. */ - unsigned probe_count = 1; - for (NetEvProbe*cur = probes_->enext_ ; cur ; cur = cur->enext_) { - listsimilar_probes; - cur->find_similar_probes(similar_probes); - - for (list::iterator idx = similar_probes.begin() - ; idx != similar_probes.end() ; idx ++) { - event_matches[ (*idx)->event() ] += 1; - } - - probe_count += 1; - } - - /* Now scan the candidate events. Those events that are - connected to all my probes (match_count[x] == probe_count) - are possible. If those events have the same number of - events, then jackpot. */ - for (map::iterator idx = event_matches.begin() - ; idx != event_matches.end() ; idx ++) { - - NetEvent*tmp = (*idx).first; - - if (tmp == this) + for (set::iterator idx = event_candidates.begin() + ; idx != event_candidates.end() ; idx ++) { + if (this == *idx) continue; - - /* For automatic tasks, the VVP runtime holds state for events - in the automatically allocated context. This means we can't - merge similar events in different automatic tasks. */ - if (scope()->is_auto() && (tmp->scope() != scope())) - continue; - - if ((*idx).second != probe_count) + if (scope()->is_auto() && (scope() != (*idx)->scope())) continue; - - unsigned tcnt = 0; - for (NetEvProbe*cur = tmp->probes_ ; cur ; cur = cur->enext_) - tcnt += 1; - - if (tcnt == probe_count) - event_list .push_back(tmp); + if (events_are_similar(this, *idx)) + event_list.push_back(*idx); } }