Avoid creating Nexus objects until they are really needed.
By not creating Nexus objects until necessary, we avoid creating a lot of spurious objects. In fact, it is true that almost every link that is created and connected to another link will create a spurious Nexus object without this patch.
This commit is contained in:
parent
2353f91693
commit
a2aff77ca2
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
38
net_link.cc
38
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
}
|
||||
|
|
|
|||
23
t-dll.cc
23
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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<z>");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue