diff --git a/design_dump.cc b/design_dump.cc index c4065ec60..e6c3ae769 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -215,7 +215,10 @@ void NetNet::dump_net(ostream&o, unsigned ind) const o << " ("; for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1) - o << pin(idx-1).nexus()->get_init(); + if (const Nexus*tmp = pin(idx-1).nexus()) + o << tmp->get_init(); + else + o << "."; o << ")" << endl; for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) { diff --git a/ivl_target.h b/ivl_target.h index 5e11a5f8e..37772ec23 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -29,6 +29,9 @@ #define _END_DECL #endif +#ifndef __GNUC__ +# define __attribute__(x) +#endif _BEGIN_DECL @@ -173,7 +176,7 @@ typedef struct ivl_process_s *ivl_process_t; typedef struct ivl_scope_s *ivl_scope_t; typedef struct ivl_signal_s *ivl_signal_t; typedef struct ivl_switch_s *ivl_switch_t; -typedef struct ivl_memory_s *ivl_memory_t; /* DEPRECATED */ +typedef struct ivl_memory_s *ivl_memory_t; //XXXX __attribute__((deprecated)); typedef struct ivl_statement_s*ivl_statement_t; /* @@ -1414,7 +1417,7 @@ extern ivl_signal_t ivl_lval_sig(ivl_lval_t net); * width. The compiler will insure this is so. */ -extern const char* ivl_nexus_name(ivl_nexus_t net); +extern const char* ivl_nexus_name(ivl_nexus_t net) __attribute__((deprecated)); extern unsigned ivl_nexus_ptrs(ivl_nexus_t net); extern ivl_nexus_ptr_t ivl_nexus_ptr(ivl_nexus_t net, unsigned idx); diff --git a/net_link.cc b/net_link.cc index 76b65d43f..ec9a53049 100644 --- a/net_link.cc +++ b/net_link.cc @@ -33,11 +33,16 @@ void connect(Nexus*l, Link&r) { assert(l); - assert(r.nexus_); if (l == r.nexus_) return; + // Special case: The "r" link is connected to nothing. The + // connect becomes trivially easy. + if (r.nexus_ == 0) { + l->relink(&r); + return; + } Nexus*tmp = r.nexus_; while (Link*cur = tmp->list_) { @@ -56,30 +61,36 @@ void connect(Nexus*l, Link&r) void connect(Link&l, Link&r) { assert(&l != &r); - if (r.is_linked() && !l.is_linked()) - connect(r.nexus_, l); - else + if (l.nexus_ != 0) { connect(l.nexus_, r); + } else if (r.nexus_ != 0) { + connect(r.nexus_, l); + } else { + Nexus*tmp = new Nexus; + connect(tmp, l); + connect(tmp, r); + } } Link::Link() : dir_(PASSIVE), drive0_(STRONG), drive1_(STRONG), init_(verinum::Vx), next_(0), nexus_(0) { - (new Nexus()) -> relink(this); } Link::~Link() { - assert(nexus_); - Nexus*tmp = nexus_; - nexus_->unlink(this); - if (tmp->list_ == 0) - delete tmp; + if (Nexus*tmp = nexus_) { + nexus_->unlink(this); + if (tmp->list_ == 0) + delete tmp; + } } Nexus* Link::nexus() { + if (nexus_ == 0) + (new Nexus()) ->relink(this); return nexus_; } @@ -158,7 +169,6 @@ void Link::unlink() return; nexus_->unlink(this); - (new Nexus()) -> relink(this); } bool Link::is_equal(const Link&that) const @@ -168,6 +178,8 @@ bool Link::is_equal(const Link&that) const bool Link::is_linked() const { + if (nexus_ == 0) + return false; if (next_) return true; if (nexus_->first_nlink() != this) @@ -178,6 +190,8 @@ bool Link::is_linked() const bool Link::is_linked(const Link&that) const { + if (nexus_ == 0) + return false; return nexus_ == that.nexus_; } @@ -489,6 +503,7 @@ unsigned NexusSet::count() const void NexusSet::add(Nexus*that) { + assert(that); if (nitems_ == 0) { assert(items_ == 0); items_ = (Nexus**)malloc(sizeof(Nexus*)); @@ -518,6 +533,7 @@ void NexusSet::add(const NexusSet&that) void NexusSet::rem(Nexus*that) { + assert(that); if (nitems_ == 0) return; diff --git a/netlist.h b/netlist.h index 4256f35f2..37ef42b0a 100644 --- a/netlist.h +++ b/netlist.h @@ -290,6 +290,9 @@ class Link { verinum::V init_ : 2; private: + // The Nexus uses these to maintain a single linked list of + // Link objects. If this link is not connected to anything, + // then these pointers are nil. Link *next_; Nexus*nexus_; diff --git a/t-dll-api.cc b/t-dll-api.cc index 207203f4b..10b51e8ee 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -1354,7 +1354,9 @@ extern "C" const char* ivl_nexus_name(ivl_nexus_t net) { assert(net); if (net->name_ == 0) { - net->name_ = api_strings.add(net->nexus_->name()); + char tmp[2 * sizeof(net) + 5]; + snprintf(tmp, sizeof tmp, "n%p", net); + net->name_ = api_strings.add(tmp); } return net->name_; } diff --git a/t-dll.cc b/t-dll.cc index c72eb939f..c9fda2b64 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -1429,16 +1429,15 @@ void dll_target::udp(const NetUDP*net) obj->npins_ = net->pin_count(); obj->pins_ = new ivl_nexus_t[obj->npins_]; for (unsigned idx = 0 ; idx < obj->npins_ ; idx += 1) { - const Nexus*nex = net->pin(idx).nexus(); - /* Skip unconnected input pins. These will take on HiZ values by the code generators. */ - if (nex->t_cookie() == 0) { + if (! net->pin(idx).is_linked()) { obj->pins_[idx] = 0; continue; } - assert(nex->t_cookie()); + const Nexus*nex = net->pin(idx).nexus(); + ivl_assert(*net, nex && nex->t_cookie()); obj->pins_[idx] = nex->t_cookie(); nexus_log_add(obj->pins_[idx], obj, idx); } @@ -2566,8 +2565,19 @@ void dll_target::signal(const NetNet*net) for (unsigned idx = 0 ; idx < obj->array_words ; idx += 1) { const Nexus*nex = net->pin(idx).nexus(); - ivl_assert(*net, nex); - if (nex->t_cookie()) { + if (nex == 0) { + // Special case: This pin is connected to + // nothing. This can happen, for example, if the + // variable is only used in behavioral + // code. Create a stub nexus. + ivl_nexus_t tmp = nexus_sig_make(obj, idx); + tmp->nexus_ = nex; + tmp->name_ = 0; + if (obj->array_words > 1) + obj->pins[idx] = tmp; + else + obj->pin = tmp; + } else if (nex->t_cookie()) { if (obj->array_words > 1) { obj->pins[idx] = nex->t_cookie(); nexus_sig_add(obj->pins[idx], obj, idx); @@ -2585,7 +2595,6 @@ void dll_target::signal(const NetNet*net) else obj->pin = tmp; } - ivl_assert(*net, net->pin(idx).nexus()->t_cookie()); } } diff --git a/tgt-vvp/draw_net_input.c b/tgt-vvp/draw_net_input.c index 83f06db03..46e00a4ac 100644 --- a/tgt-vvp/draw_net_input.c +++ b/tgt-vvp/draw_net_input.c @@ -466,8 +466,7 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) } - fprintf(stderr, "internal error: no input to nexus %s\n", - ivl_nexus_name(nex)); + fprintf(stderr, "internal error: no input to nexus.\n"); assert(0); return strdup("C"); }