diff --git a/net_event.cc b/net_event.cc index 9cda8f557..c0b9a47a7 100644 --- a/net_event.cc +++ b/net_event.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: net_event.cc,v 1.18 2002/06/30 02:21:31 steve Exp $" +#ident "$Id: net_event.cc,v 1.19 2002/07/24 16:24:45 steve Exp $" #endif # include "config.h" @@ -119,140 +119,67 @@ unsigned NetEvent::nwait() const * A "similar" event is one that has an identical non-nil set of * probes. */ -NetEvent* NetEvent::find_similar_event() +void NetEvent::find_similar_event(list&event_list) { if (probes_ == 0) - return 0; + return; - struct table_s { - NetEvent*ev; - bool mark; - } *table; + map event_matches; - //NetEvent**cand; - //bool*cflg; - unsigned max_cand = 0, ncand = 0; + /* 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. */ + listfirst_probes; + probes_->find_similar_probes(first_probes); - NetEvProbe*cur = probes_; - - /* Get an estimate of the number of candidate events there - are. To get it, count the number of probes that are - connected to my first probe. Since there is no more then - one NetEvent per NetEvProbe, this is the maximum number of - similar events possible. - - Once we get that count, allocate the arrays needed to - account for these events. */ - - for (NetNode*idx = cur->next_node() - ; idx && (idx != cur) ; idx = idx->next_node()) { - NetEvProbe*tmp = dynamic_cast(idx); - if (tmp == 0) - continue; - if (tmp->edge() != cur->edge()) - continue; - - max_cand += 1; + for (list::iterator idx = first_probes.begin() + ; idx != first_probes.end() ; idx ++) { + event_matches[ (*idx)->event() ] = 1; } - table = new struct table_s[max_cand]; + /* 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); - - /* First, locate all the candidate events from my first - probe. Look for all the NetEvProbe objects connected to my - probe (that are the same edge) and save the NetEvent that - that probe drives. */ - - for (NetNode*idx = cur->next_node() - ; idx && (idx != cur) ; idx = idx->next_node()) { - NetEvProbe*tmp = dynamic_cast(idx); - if (tmp == 0) - continue; - if (tmp->edge() != cur->edge()) - continue; - - /* Don't include myself in the list of candidates. */ - NetEvent*etmp = tmp->event(); - if (etmp == this) - continue; - - table[ncand++].ev = etmp; - assert(ncand <= max_cand); - } - - - /* All the events in the cand array are now known to connect - through at least one NetEvProbe. Now go through all my - remaining probes and check that each candidate event is - also connected (through a NetEvProbe) to me. - - By the time I finish this scan, only NetEvents that have - equivilent NetEvProbes remain. These are candidates. The - events may have *more* NetEvProbes then me, I'll catch - those later. */ - - for (cur = cur->enext_ ; cur && ncand ; cur = cur->enext_) { - for (unsigned idx = 0 ; idx < ncand ; idx += 1) - table[idx].mark = false; - - /* For this probe, look for other probes connected to it - and find the event connected to it. Mark that event - as connected to this probe. */ - - for (NetNode*idx = cur->next_node() - ; idx && (idx != cur) ; idx = idx->next_node()) { - NetEvProbe*tmp = dynamic_cast(idx); - if (tmp == 0) - continue; - if (tmp->edge() != cur->edge()) - continue; - - for (unsigned srch = 0 ; srch < ncand ; srch += 1) - if (table[srch].ev == tmp->event()) { - table[srch].mark = true; - break; - } + for (list::iterator idx = similar_probes.begin() + ; idx != similar_probes.end() ; idx ++) { + event_matches[ (*idx)->event() ] += 1; } - /* Look for all the candidates that did not connect to - this probe (cflg is false) and eliminate them. */ - - for (unsigned idx = 0 ; idx < ncand ; ) { - if (table[idx].mark) { - idx += 1; - continue; - } - - for (unsigned tmp = idx ; (tmp+1) < ncand ; tmp += 1) - table[tmp] = table[tmp+1]; - - ncand -= 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 ++) { - /* Scan the remaining candidates for a similar - NetEvent. Eliminate NetEvent objects that have more - NetEvProbe objects then I, because those have a proper - superset of my probes and were not eliminated by the - previous scan. + NetEvent*tmp = (*idx).first; - As soon as we find a similar event, we're done. */ + if (tmp == this) + continue; - for (unsigned idx = 0 ; idx < ncand ; idx += 1) { - if (table[idx].ev->nprobe() == nprobe()) { - NetEvent*res = table[idx].ev; - delete[]table; - return res; - } + if ((*idx).second != probe_count) + continue; + + unsigned tcnt = 0; + for (NetEvProbe*cur = tmp->probes_ ; cur ; cur = cur->enext_) + tcnt += 1; + + if (tcnt == probe_count) + event_list .push_back(tmp); } - - /* Oops, fell off the list without finding a result. return nil. */ - delete[]table; - return 0; } + void NetEvent::replace_event(NetEvent*that) { while (wlist_) { @@ -355,6 +282,42 @@ const NetEvent* NetEvProbe::event() const return event_; } +/* + * A similar NetEvProbe is one that is connected to all the same nexa + * that this probe is connected to, and also is the same edge + * type. Don't count myself as a similar probe. + */ +void NetEvProbe::find_similar_probes(list&plist) +{ + Nexus*nex = pin(0).nexus(); + + for (Link*lcur = nex->first_nlink(); lcur; lcur = lcur->next_nlink()) { + NetObj*obj = lcur->get_obj(); + if (obj->pin_count() != pin_count()) + continue; + + NetEvProbe*tmp = dynamic_cast(obj); + if (tmp == 0) + continue; + + if (tmp == this) + continue; + + if (edge() != tmp->edge()) + continue; + + bool ok_flag = true; + for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) + if (pin(idx).nexus() != tmp->pin(idx).nexus()) { + ok_flag = false; + break; + } + + if (ok_flag == true) + plist .push_back(tmp); + } +} + NetEvWait::NetEvWait(NetProc*pr) : statement_(pr), nevents_(0), events_(0) { @@ -479,6 +442,11 @@ NetProc* NetEvWait::statement() /* * $Log: net_event.cc,v $ + * Revision 1.19 2002/07/24 16:24:45 steve + * Rewrite find_similar_event to support doing + * all event matching and replacement in one + * shot, saving time in the scans. + * * Revision 1.18 2002/06/30 02:21:31 steve * Add structure for asynchronous logic synthesis. * diff --git a/netlist.cc b/netlist.cc index ac023d9f9..a01343e04 100644 --- a/netlist.cc +++ b/netlist.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: netlist.cc,v 1.193 2002/07/02 03:02:57 steve Exp $" +#ident "$Id: netlist.cc,v 1.194 2002/07/24 16:24:45 steve Exp $" #endif # include "config.h" @@ -233,36 +233,6 @@ NetNode::~NetNode() design_->del_node(this); } -NetNode* NetNode::next_node() -{ - Link*pin0 = pin(0).next_nlink(); - if (pin0 == 0) - pin0 = pin(0).nexus()->first_nlink(); - - while (pin0 != &pin(0)) { - NetNode*cur = dynamic_cast(pin0->get_obj()); - if (cur == 0) - goto continue_label; - if (cur->pin_count() != pin_count()) - goto continue_label; - - { bool flag = true; - for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) - flag = flag && pin(idx).is_linked(cur->pin(idx)); - - if (flag == true) - return cur; - } - - continue_label: - pin0 = pin0->next_nlink(); - if (pin0 == 0) - pin0 = pin(0).nexus()->first_nlink(); - } - - return 0; -} - NetNet::NetNet(NetScope*s, const string&n, Type t, unsigned npins) : NetObj(s, n, npins), sig_next_(0), sig_prev_(0), type_(t), port_type_(NOT_A_PORT), signed_(false), msb_(npins-1), lsb_(0), @@ -2371,6 +2341,11 @@ const NetProc*NetTaskDef::proc() const /* * $Log: netlist.cc,v $ + * Revision 1.194 2002/07/24 16:24:45 steve + * Rewrite find_similar_event to support doing + * all event matching and replacement in one + * shot, saving time in the scans. + * * Revision 1.193 2002/07/02 03:02:57 steve * Change the signal to a net when assignments go away. * diff --git a/netlist.h b/netlist.h index 16087c33f..038bcdbae 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: netlist.h,v 1.252 2002/07/07 22:32:15 steve Exp $" +#ident "$Id: netlist.h,v 1.253 2002/07/24 16:24:45 steve Exp $" #endif /* @@ -314,10 +314,6 @@ class NetNode : public NetObj { virtual ~NetNode(); - // This method locates the next node that has all its pins - // connected to the same of my own pins. - NetNode*next_node(); - virtual bool emit_node(struct target_t*) const; virtual void dump_node(ostream&, unsigned) const; @@ -1639,7 +1635,7 @@ class NetEvent : public LineInfo { // Locate the first event that matches my behavior and // monitors the same signals. - NetEvent* find_similar_event(); + void find_similar_event(list&); // This method replaces pointers to me with pointers to // that. It is typically used to replace similar events @@ -1748,6 +1744,8 @@ class NetEvProbe : public NetNode { NetEvent* event(); const NetEvent* event() const; + void find_similar_probes(list&); + virtual bool emit_node(struct target_t*) const; virtual void dump_node(ostream&, unsigned ind) const; @@ -3002,6 +3000,11 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.253 2002/07/24 16:24:45 steve + * Rewrite find_similar_event to support doing + * all event matching and replacement in one + * shot, saving time in the scans. + * * Revision 1.252 2002/07/07 22:32:15 steve * Asynchronous synthesis of case statements. * diff --git a/nodangle.cc b/nodangle.cc index d162233f0..c88e9dc21 100644 --- a/nodangle.cc +++ b/nodangle.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: nodangle.cc,v 1.15 2002/05/26 01:39:02 steve Exp $" +#ident "$Id: nodangle.cc,v 1.16 2002/07/24 16:24:45 steve Exp $" #endif # include "config.h" @@ -30,6 +30,7 @@ */ # include "functor.h" # include "netlist.h" +# include "compiler.h" class nodangle_f : public functor_t { public: @@ -37,22 +38,32 @@ class nodangle_f : public functor_t { void signal(Design*des, NetNet*sig); unsigned count_; + unsigned stotal, etotal; }; void nodangle_f::event(Design*des, NetEvent*ev) { - if (NetEvent*match = ev->find_similar_event()) { - assert(match != ev); - ev->replace_event(match); + /* If there are no references to this event, then go right + ahead and delete in. There is no use looking further at + it. */ + if ((ev->nwait() + ev->ntrig()) == 0) { + delete ev; + etotal += 1; + return; } - if (ev->nwait() != 0) - return; + /* Try to find all the events that are similar to me, and + replace their references with references to me. */ + list match; + ev->find_similar_event(match); + for (list::iterator idx = match.begin() + ; idx != match.end() ; idx ++) { - if (ev->ntrig() != 0) - return; + NetEvent*tmp = *idx; + assert(tmp != ev); + tmp ->replace_event(ev); + } - delete ev; } void nodangle_f::signal(Design*des, NetNet*sig) @@ -74,12 +85,16 @@ void nodangle_f::signal(Design*des, NetNet*sig) /* Check to see if the signal is completely unconnected. If all the bits are unlinked, then delete it. */ - unsigned unlinked = 0; + bool linked_flag = false; for (unsigned idx = 0 ; idx < sig->pin_count() ; idx += 1) - if (! sig->pin(idx).is_linked()) unlinked += 1; + if (sig->pin(idx).is_linked()) { + linked_flag = true; + break; + } - if (unlinked == sig->pin_count()) { + if (! linked_flag) { delete sig; + stotal += 1; return; } @@ -110,6 +125,9 @@ void nodangle_f::signal(Design*des, NetNet*sig) significant_flags += 1; break; } + + if (significant_flags <= idx) + break; } /* If every pin is connected to another significant signal, @@ -117,21 +135,40 @@ void nodangle_f::signal(Design*des, NetNet*sig) if (significant_flags == sig->pin_count()) { count_ += 1; delete sig; + stotal += 1; } } void nodangle(Design*des) { nodangle_f fun; + unsigned count_iterations = 0; + fun.stotal = 0; + fun.etotal = 0; do { fun.count_ = 0; des->functor(&fun); + count_iterations += 1; + + if (verbose_flag) { + cout << " ... " << count_iterations << " iterations" + << " deleted " << fun.stotal << " dangling signals" + << " and " << fun.etotal << " events." + << " (count=" << fun.count_ << ")" << endl; + } + } while (fun.count_ > 0); + } /* * $Log: nodangle.cc,v $ + * Revision 1.16 2002/07/24 16:24:45 steve + * Rewrite find_similar_event to support doing + * all event matching and replacement in one + * shot, saving time in the scans. + * * Revision 1.15 2002/05/26 01:39:02 steve * Carry Verilog 2001 attributes with processes, * all the way through to the ivl_target API.