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.
This commit is contained in:
Stephen Williams 2014-05-08 14:00:39 -07:00
parent 109c5d895d
commit 020e280a98
8 changed files with 52 additions and 66 deletions

View File

@ -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;

View File

@ -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<NetEvProbe*>&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<NetEvProbe*>&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_;

View File

@ -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_;

View File

@ -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];
}

View File

@ -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::vector<NetEvent*>events_;
};
ostream& operator << (ostream&out, const NetEvWait&obj);

View File

@ -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);
}
}
}

View File

@ -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)

View File

@ -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);