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 << " (";
|
o << " (";
|
||||||
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
|
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;
|
o << ")" << endl;
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,9 @@
|
||||||
#define _END_DECL
|
#define _END_DECL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
# define __attribute__(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
_BEGIN_DECL
|
_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_scope_s *ivl_scope_t;
|
||||||
typedef struct ivl_signal_s *ivl_signal_t;
|
typedef struct ivl_signal_s *ivl_signal_t;
|
||||||
typedef struct ivl_switch_s *ivl_switch_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;
|
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.
|
* 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 unsigned ivl_nexus_ptrs(ivl_nexus_t net);
|
||||||
extern ivl_nexus_ptr_t ivl_nexus_ptr(ivl_nexus_t net, unsigned idx);
|
extern ivl_nexus_ptr_t ivl_nexus_ptr(ivl_nexus_t net, unsigned idx);
|
||||||
|
|
||||||
|
|
|
||||||
32
net_link.cc
32
net_link.cc
|
|
@ -33,11 +33,16 @@
|
||||||
void connect(Nexus*l, Link&r)
|
void connect(Nexus*l, Link&r)
|
||||||
{
|
{
|
||||||
assert(l);
|
assert(l);
|
||||||
assert(r.nexus_);
|
|
||||||
|
|
||||||
if (l == r.nexus_)
|
if (l == r.nexus_)
|
||||||
return;
|
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_;
|
Nexus*tmp = r.nexus_;
|
||||||
while (Link*cur = tmp->list_) {
|
while (Link*cur = tmp->list_) {
|
||||||
|
|
@ -56,30 +61,36 @@ void connect(Nexus*l, Link&r)
|
||||||
void connect(Link&l, Link&r)
|
void connect(Link&l, Link&r)
|
||||||
{
|
{
|
||||||
assert(&l != &r);
|
assert(&l != &r);
|
||||||
if (r.is_linked() && !l.is_linked())
|
if (l.nexus_ != 0) {
|
||||||
connect(r.nexus_, l);
|
|
||||||
else
|
|
||||||
connect(l.nexus_, r);
|
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()
|
Link::Link()
|
||||||
: dir_(PASSIVE), drive0_(STRONG), drive1_(STRONG), init_(verinum::Vx),
|
: dir_(PASSIVE), drive0_(STRONG), drive1_(STRONG), init_(verinum::Vx),
|
||||||
next_(0), nexus_(0)
|
next_(0), nexus_(0)
|
||||||
{
|
{
|
||||||
(new Nexus()) -> relink(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Link::~Link()
|
Link::~Link()
|
||||||
{
|
{
|
||||||
assert(nexus_);
|
if (Nexus*tmp = nexus_) {
|
||||||
Nexus*tmp = nexus_;
|
|
||||||
nexus_->unlink(this);
|
nexus_->unlink(this);
|
||||||
if (tmp->list_ == 0)
|
if (tmp->list_ == 0)
|
||||||
delete tmp;
|
delete tmp;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Nexus* Link::nexus()
|
Nexus* Link::nexus()
|
||||||
{
|
{
|
||||||
|
if (nexus_ == 0)
|
||||||
|
(new Nexus()) ->relink(this);
|
||||||
return nexus_;
|
return nexus_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,7 +169,6 @@ void Link::unlink()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nexus_->unlink(this);
|
nexus_->unlink(this);
|
||||||
(new Nexus()) -> relink(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Link::is_equal(const Link&that) const
|
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
|
bool Link::is_linked() const
|
||||||
{
|
{
|
||||||
|
if (nexus_ == 0)
|
||||||
|
return false;
|
||||||
if (next_)
|
if (next_)
|
||||||
return true;
|
return true;
|
||||||
if (nexus_->first_nlink() != this)
|
if (nexus_->first_nlink() != this)
|
||||||
|
|
@ -178,6 +190,8 @@ bool Link::is_linked() const
|
||||||
|
|
||||||
bool Link::is_linked(const Link&that) const
|
bool Link::is_linked(const Link&that) const
|
||||||
{
|
{
|
||||||
|
if (nexus_ == 0)
|
||||||
|
return false;
|
||||||
return nexus_ == that.nexus_;
|
return nexus_ == that.nexus_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -489,6 +503,7 @@ unsigned NexusSet::count() const
|
||||||
|
|
||||||
void NexusSet::add(Nexus*that)
|
void NexusSet::add(Nexus*that)
|
||||||
{
|
{
|
||||||
|
assert(that);
|
||||||
if (nitems_ == 0) {
|
if (nitems_ == 0) {
|
||||||
assert(items_ == 0);
|
assert(items_ == 0);
|
||||||
items_ = (Nexus**)malloc(sizeof(Nexus*));
|
items_ = (Nexus**)malloc(sizeof(Nexus*));
|
||||||
|
|
@ -518,6 +533,7 @@ void NexusSet::add(const NexusSet&that)
|
||||||
|
|
||||||
void NexusSet::rem(Nexus*that)
|
void NexusSet::rem(Nexus*that)
|
||||||
{
|
{
|
||||||
|
assert(that);
|
||||||
if (nitems_ == 0)
|
if (nitems_ == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -290,6 +290,9 @@ class Link {
|
||||||
verinum::V init_ : 2;
|
verinum::V init_ : 2;
|
||||||
|
|
||||||
private:
|
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_;
|
Link *next_;
|
||||||
Nexus*nexus_;
|
Nexus*nexus_;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1354,7 +1354,9 @@ extern "C" const char* ivl_nexus_name(ivl_nexus_t net)
|
||||||
{
|
{
|
||||||
assert(net);
|
assert(net);
|
||||||
if (net->name_ == 0) {
|
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_;
|
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->npins_ = net->pin_count();
|
||||||
obj->pins_ = new ivl_nexus_t[obj->npins_];
|
obj->pins_ = new ivl_nexus_t[obj->npins_];
|
||||||
for (unsigned idx = 0 ; idx < obj->npins_ ; idx += 1) {
|
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
|
/* Skip unconnected input pins. These will take on HiZ
|
||||||
values by the code generators. */
|
values by the code generators. */
|
||||||
if (nex->t_cookie() == 0) {
|
if (! net->pin(idx).is_linked()) {
|
||||||
obj->pins_[idx] = 0;
|
obj->pins_[idx] = 0;
|
||||||
continue;
|
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();
|
obj->pins_[idx] = nex->t_cookie();
|
||||||
nexus_log_add(obj->pins_[idx], obj, idx);
|
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) {
|
for (unsigned idx = 0 ; idx < obj->array_words ; idx += 1) {
|
||||||
|
|
||||||
const Nexus*nex = net->pin(idx).nexus();
|
const Nexus*nex = net->pin(idx).nexus();
|
||||||
ivl_assert(*net, nex);
|
if (nex == 0) {
|
||||||
if (nex->t_cookie()) {
|
// 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) {
|
if (obj->array_words > 1) {
|
||||||
obj->pins[idx] = nex->t_cookie();
|
obj->pins[idx] = nex->t_cookie();
|
||||||
nexus_sig_add(obj->pins[idx], obj, idx);
|
nexus_sig_add(obj->pins[idx], obj, idx);
|
||||||
|
|
@ -2585,7 +2595,6 @@ void dll_target::signal(const NetNet*net)
|
||||||
else
|
else
|
||||||
obj->pin = tmp;
|
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",
|
fprintf(stderr, "internal error: no input to nexus.\n");
|
||||||
ivl_nexus_name(nex));
|
|
||||||
assert(0);
|
assert(0);
|
||||||
return strdup("C<z>");
|
return strdup("C<z>");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue