Implement release of linked force nodes

When nets are forced by non-constant expressions, the value is linked
to the destination net through a force_link. This patch adds the code
needed to unlink a force/link so that release and new force/links can
work. This fixes pr1735836.

Signed-off-by: Stephen Williams <steve@icarus.com>
This commit is contained in:
Stephen Williams 2007-11-13 19:35:44 -08:00
parent d7a0f48944
commit 9759c19734
1 changed files with 42 additions and 2 deletions

View File

@ -1653,6 +1653,42 @@ bool of_END(vthread_t thr, vvp_code_t)
return false;
}
static void unlink_force(vvp_net_t*net)
{
vvp_fun_signal_base*sig
= reinterpret_cast<vvp_fun_signal_base*>(net->fun);
/* This node must be a signal... */
assert(sig);
/* This signal is being forced. */
assert(sig->force_link);
vvp_net_t*src = sig->force_link;
sig->force_link = 0;
/* We are looking for this pointer. */
vvp_net_ptr_t net_ptr (net, 2);
/* If net is first in the fan-out list, then simply pull it
from the front. */
if (src->out == net_ptr) {
src->out = net->port[2];
net->port[2] = vvp_net_ptr_t();
return;
}
/* Look for the pointer in the fan-out chain */
vvp_net_ptr_t cur_ptr = src->out;
assert(!cur_ptr.nil());
while (cur_ptr.ptr()->port[cur_ptr.port()] != net_ptr) {
cur_ptr = cur_ptr.ptr()->port[cur_ptr.port()];
assert( !cur_ptr.nil() );
}
/* Remove as if from a singly-linked list. */
cur_ptr.ptr()->port[cur_ptr.port()] = net->port[2];
net->port[2] = vvp_net_ptr_t();
}
/*
* the %force/link instruction connects a source node to a
* destination node. The destination node must be a signal, as it is
@ -1674,8 +1710,10 @@ bool of_FORCE_LINK(vthread_t thr, vvp_code_t cp)
if (sig->force_link == src)
return true;
/* FIXME: Don't yet support changing the force. */
assert(sig->force_link == 0);
/* If there is a linked force already, then unlink it. */
if (sig->force_link)
unlink_force(dst);
sig->force_link = src;
/* Link the output of the src to the port[2] (the force
@ -3051,6 +3089,8 @@ bool of_RELEASE_NET(vthread_t thr, vvp_code_t cp)
assert(sig);
/* XXXX Release for %force/link not yet implemented. */
if (sig->force_link)
unlink_force(net);
assert(sig->force_link == 0);
vvp_net_ptr_t ptr (net, 3);