Slightly improve performance of collapsing NetEvent objects

The NetEvent::find_similar_event method should limit its impact
on the netlist (and Nexus objects) by reducing the candidate event
list as it goes, instead of collecting data and testing later.
This commit is contained in:
Stephen Williams 2009-12-11 17:03:05 -08:00
parent 4622f304d5
commit 38cce38e04
1 changed files with 32 additions and 21 deletions

View File

@ -128,7 +128,7 @@ void NetEvent::find_similar_event(list<NetEvent*>&event_list)
if (probes_ == 0) if (probes_ == 0)
return; return;
map<NetEvent*,unsigned> event_matches; set<NetEvent*> candidate_events;
/* First, get a list of all the NetEvProbes that are connected /* First, get a list of all the NetEvProbes that are connected
to my first probe. Then use that to create a set of to my first probe. Then use that to create a set of
@ -139,34 +139,50 @@ void NetEvent::find_similar_event(list<NetEvent*>&event_list)
for (list<NetEvProbe*>::iterator idx = first_probes.begin() for (list<NetEvProbe*>::iterator idx = first_probes.begin()
; idx != first_probes.end() ; idx ++) { ; idx != first_probes.end() ; idx ++) {
event_matches[ (*idx)->event() ] = 1;
candidate_events.insert( (*idx)->event() );
} }
/* Now scan the remaining probes, in each case ticking the if (candidate_events.empty())
candidate event. The events that really are similar to this return;
one will turn up in every probe list. */
/* Now scan the remaining probes, in each case checking that
the probe event is a candidate event. After each iteration,
events that don't have a similar probe will be removed from
the candidate_events set. If the candidate_events set
becomes empty, then give up. */
unsigned probe_count = 1; unsigned probe_count = 1;
for (NetEvProbe*cur = probes_->enext_ ; cur ; cur = cur->enext_) { for (NetEvProbe*cur = probes_->enext_ ; cur; cur = cur->enext_) {
list<NetEvProbe*>similar_probes; list<NetEvProbe*>similar_probes;
cur->find_similar_probes(similar_probes); cur->find_similar_probes(similar_probes);
set<NetEvent*> candidate_tmp;
for (list<NetEvProbe*>::iterator idx = similar_probes.begin() for (list<NetEvProbe*>::iterator idx = similar_probes.begin()
; idx != similar_probes.end() ; idx ++) { ; idx != similar_probes.end() ; idx ++) {
event_matches[ (*idx)->event() ] += 1;
NetEvent*tmp = (*idx)->event();
if (candidate_events.find(tmp) != candidate_events.end())
candidate_tmp .insert(tmp);
} }
// None of the candidate events match this probe? Give up!
if (candidate_tmp.empty())
return;
candidate_events = candidate_tmp;
probe_count += 1; probe_count += 1;
} }
/* Now scan the candidate events. Those events that are /* Scan the surviving candidate events. We know that they all
connected to all my probes (match_count[x] == probe_count) have probes that match the current event's probes. Check
are possible. If those events have the same number of for remaining compatibility details and save the survivors
events, then jackpot. */ in the event_list that the caller passed. */
for (map<NetEvent*,unsigned>::iterator idx = event_matches.begin() for (set<NetEvent*>::iterator idx = candidate_events.begin()
; idx != event_matches.end() ; idx ++) { ; idx != candidate_events.end() ; idx ++) {
NetEvent*tmp = (*idx).first; NetEvent*tmp = *idx;
// This shouldn't be possible?
if (tmp == this) if (tmp == this)
continue; continue;
@ -176,9 +192,6 @@ void NetEvent::find_similar_event(list<NetEvent*>&event_list)
if (scope()->is_auto() && (tmp->scope() != scope())) if (scope()->is_auto() && (tmp->scope() != scope()))
continue; continue;
if ((*idx).second != probe_count)
continue;
unsigned tcnt = 0; unsigned tcnt = 0;
for (NetEvProbe*cur = tmp->probes_ ; cur ; cur = cur->enext_) for (NetEvProbe*cur = tmp->probes_ ; cur ; cur = cur->enext_)
tcnt += 1; tcnt += 1;
@ -316,11 +329,9 @@ void NetEvProbe::find_similar_probes(list<NetEvProbe*>&plist)
continue; continue;
bool ok_flag = true; bool ok_flag = true;
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) for (unsigned idx = 1 ; ok_flag && idx < pin_count() ; idx += 1)
if (pin(idx).nexus() != tmp->pin(idx).nexus()) { if (! pin(idx).is_linked(tmp->pin(idx)))
ok_flag = false; ok_flag = false;
break;
}
if (ok_flag == true) if (ok_flag == true)
plist .push_back(tmp); plist .push_back(tmp);