From 020e280a98994ccb30369ef1ba70080e10b9fd2b Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 8 May 2014 14:00:39 -0700 Subject: [PATCH] nodangle functor accounts for NexusSet links In a design, there may be lingering NexusSet objects, or the nodangle may itself use NexusSet objects. This creates links, and this should not confuse the functor. While we are at it, clean up some handling of events structures. --- async.cc | 4 ++-- net_event.cc | 60 ++++++++++++++-------------------------------------- net_link.cc | 22 +++++++++++++------ netlist.cc | 10 ++++++--- netlist.h | 16 ++++++++------ nodangle.cc | 2 +- sync.cc | 2 +- synth2.cc | 2 +- 8 files changed, 52 insertions(+), 66 deletions(-) diff --git a/async.cc b/async.cc index fa5bbaee0..311b1af2c 100644 --- a/async.cc +++ b/async.cc @@ -50,8 +50,8 @@ bool NetEvWait::is_asynchronous() level sensitive, but the nex_async_ method takes care of that test. */ NexusSet*sense = new NexusSet; - for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) { - NexusSet*tmp = event(idx)->nex_async_(); + for (unsigned idx = 0 ; idx < events_.size() ; idx += 1) { + NexusSet*tmp = events_[idx]->nex_async_(); if (tmp == 0) { delete sense; return false; diff --git a/net_event.cc b/net_event.cc index 5ad61063a..9b67b5b99 100644 --- a/net_event.cc +++ b/net_event.cc @@ -20,6 +20,7 @@ # include "config.h" # include "compiler.h" # include "netlist.h" +# include "ivl_assert.h" /* * NOTE: The name_ is perm-allocated by the caller. @@ -316,6 +317,10 @@ void NetEvProbe::find_similar_probes(list&plist) for (Link*lcur = nex->first_nlink(); lcur; lcur = lcur->next_nlink()) { NetPins*obj = lcur->get_obj(); + // Skip NexusSet objects + if (obj == 0) + continue; + if (obj->pin_count() != pin_count()) continue; @@ -340,14 +345,14 @@ void NetEvProbe::find_similar_probes(list&plist) } NetEvWait::NetEvWait(NetProc*pr) -: statement_(pr), nevents_(0), events_(0) +: statement_(pr) { } NetEvWait::~NetEvWait() { - if (events_) { - for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) { + if (! events_.empty()) { + for (unsigned idx = 0 ; idx < events_.size() ; idx += 1) { NetEvent*tgt = events_[idx]; tgt->waitref_ -= 1; @@ -365,7 +370,7 @@ NetEvWait::~NetEvWait() delete tmp; } } - delete[]events_; + events_.clear(); } delete statement_; } @@ -374,29 +379,12 @@ void NetEvWait::add_event(NetEvent*tgt) { /* A wait fork is an empty event. */ if (! tgt) { - assert(nevents_ == 0); - nevents_ = 1; - events_ = new NetEvent*[1]; - events_[0] = 0; + assert(events_.empty()); + events_.push_back(0); return; } - if (nevents_ == 0) { - events_ = new NetEvent*[1]; - - } else { - assert(events_[0]); - NetEvent**tmp = new NetEvent*[nevents_+1]; - for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) { - tmp[idx] = events_[idx]; - assert(tmp[idx] != tgt); - } - delete[]events_; - events_ = tmp; - } - - events_[nevents_] = tgt; - nevents_ += 1; + events_.push_back(tgt); // Remember to tell the NetEvent that there is someone // pointing to it. @@ -411,14 +399,14 @@ void NetEvWait::add_event(NetEvent*tgt) void NetEvWait::replace_event(NetEvent*src, NetEvent*repl) { unsigned idx; - for (idx = 0 ; idx < nevents_ ; idx += 1) { + for (idx = 0 ; idx < events_.size() ; idx += 1) { if (events_[idx] == src) break; } - assert(idx < nevents_); + assert(idx < events_.size()); - /* First, remove me from the list held by the src NetEvent. */ + // First, remove me from the list held by the src NetEvent. assert(src->waitref_ > 0); src->waitref_ -= 1; struct NetEvent::wcell_*tmp = src->wlist_; @@ -435,6 +423,7 @@ void NetEvWait::replace_event(NetEvent*src, NetEvent*repl) delete tmp; } + // Replace the src pointer with the repl pointer. events_[idx] = repl; // Remember to tell the replacement NetEvent that there is @@ -448,23 +437,6 @@ void NetEvWait::replace_event(NetEvent*src, NetEvent*repl) } -unsigned NetEvWait::nevents() const -{ - return nevents_; -} - -const NetEvent* NetEvWait::event(unsigned idx) const -{ - assert(idx < nevents_); - return events_[idx]; -} - -NetEvent* NetEvWait::event(unsigned idx) -{ - assert(idx < nevents_); - return events_[idx]; -} - NetProc* NetEvWait::statement() { return statement_; diff --git a/net_link.cc b/net_link.cc index 74e7f8790..bccb4c065 100644 --- a/net_link.cc +++ b/net_link.cc @@ -90,13 +90,19 @@ void Nexus::connect(Link&r) void connect(Link&l, Link&r) { + Nexus*tmp; assert(&l != &r); - if (l.nexus_ != 0) { - connect(l.nexus_, r); - } else if (r.nexus_ != 0) { - connect(r.nexus_, l); + // If either the l or r link already are part of a Nexus, then + // re-use that nexus. Go through some effort so that we are + // not gratuitously creating Nexus object. + if (l.next_ && (tmp=l.find_nexus_())) { + connect(tmp, r); + } else if (r.next_ && (tmp=r.find_nexus_())) { + connect(tmp, l); } else { - Nexus*tmp = new Nexus(l); + // No existing Nexus (both links are so far unconnected) + // so start one. + tmp = new Nexus(l); tmp->connect(r); } } @@ -224,9 +230,11 @@ bool Link::is_linked() const bool Link::is_linked(const Link&that) const { - if (next_ == 0) + // If this or that link is linked to nothing, then they cannot + // be linked to each other. + if (! this->is_linked()) return false; - if (that.next_ == 0) + if (! that.is_linked()) return false; const Link*cur = next_; diff --git a/netlist.cc b/netlist.cc index bd0070c6c..ebbf29d0f 100644 --- a/netlist.cc +++ b/netlist.cc @@ -180,7 +180,11 @@ NetPins::NetPins(unsigned npins) NetPins::~NetPins() { - delete[] pins_; + if (pins_) { + assert(pins_[0].node_ == this); + assert(pins_[0].pin_zero_); + delete[] pins_; + } } Link& NetPins::pin(unsigned idx) @@ -194,7 +198,7 @@ Link& NetPins::pin(unsigned idx) } assert(idx < npins_); - assert(idx == 0? pins_[0].pin_zero_ : pins_[idx].pin_==idx); + assert(idx == 0? (pins_[0].pin_zero_ && pins_[0].node_==this) : pins_[idx].pin_==idx); return pins_[idx]; } @@ -208,7 +212,7 @@ const Link& NetPins::pin(unsigned idx) const } assert(pins_); assert(idx < npins_); - assert(idx == 0? pins_[0].pin_zero_ : pins_[idx].pin_==idx); + assert(idx == 0? (pins_[0].pin_zero_ && pins_[0].node_==this) : pins_[idx].pin_==idx); return pins_[idx]; } diff --git a/netlist.h b/netlist.h index bb8a2ac73..13b61e0a4 100644 --- a/netlist.h +++ b/netlist.h @@ -153,7 +153,10 @@ class Link { bool is_equal(const Link&that) const; // Return information about the object that this link is - // a part of. + // a part of. Note that the get_obj() method can return NIL if + // this Link is part of a NexusSet. That should be OK, because + // they are collection variables, and not functional parts of + // a design. const NetPins*get_obj() const; NetPins*get_obj(); unsigned get_pin() const; @@ -3200,9 +3203,9 @@ class NetEvWait : public NetProc { void add_event(NetEvent*tgt); void replace_event(NetEvent*orig, NetEvent*repl); - unsigned nevents() const; - const NetEvent*event(unsigned) const; - NetEvent*event(unsigned); + inline unsigned nevents() const { return events_.size(); } + inline const NetEvent*event(unsigned idx) const { return events_[idx]; } + inline NetEvent*event(unsigned idx) { return events_[idx]; } NetProc*statement(); @@ -3236,9 +3239,8 @@ class NetEvWait : public NetProc { private: NetProc*statement_; - - unsigned nevents_; - NetEvent**events_; + // Events that I might wait for. + std::vectorevents_; }; ostream& operator << (ostream&out, const NetEvWait&obj); diff --git a/nodangle.cc b/nodangle.cc index 19336fc23..9c9940f28 100644 --- a/nodangle.cc +++ b/nodangle.cc @@ -117,7 +117,7 @@ void nodangle_f::event(Design*, NetEvent*ev) NetEvent*tmp = *idx; assert(tmp != ev); - tmp ->replace_event(ev); + tmp ->replace_event(ev); } } } diff --git a/sync.cc b/sync.cc index 1b3a62d88..41c210ac2 100644 --- a/sync.cc +++ b/sync.cc @@ -33,7 +33,7 @@ bool NetProc::is_synchronous() bool NetEvWait::is_synchronous() { - for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) { + for (unsigned idx = 0 ; idx < events_.size() ; idx += 1) { NetEvent*ev = events_[idx]; if (ev->nprobe() == 0) diff --git a/synth2.cc b/synth2.cc index 35362d1ee..ad6f9b7ec 100644 --- a/synth2.cc +++ b/synth2.cc @@ -1002,7 +1002,7 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, /* This can't be other than one unless there are named events, which I cannot synthesize. */ - assert(nevents_ == 1); + ivl_assert(*this, events_.size() == 1); NetEvent*ev = events_[0]; assert(ev->nprobe() >= 1);