Fix for pr3368642.v.

The vvp target code generator may not elide a BUFZ if the output of
the BUFZ is connected to a net that is the subject of a procedural
force statement.
This commit is contained in:
Martin Whitaker 2011-08-06 00:10:41 +01:00 committed by Stephen Williams
parent 3e3b83da30
commit 5fc1a9c9e0
6 changed files with 27 additions and 1 deletions

View File

@ -218,6 +218,7 @@ ivl_signal_data_type
ivl_signal_dimensions
ivl_signal_discipline
ivl_signal_file
ivl_signal_forced_net
ivl_signal_integer
ivl_signal_lineno
ivl_signal_local

View File

@ -1781,6 +1781,10 @@ extern int ivl_scope_time_units(ivl_scope_t net);
* A signal that was generated by the compiler as a place holder is
* marked as local.
*
* ivl_signal_forced_net
* Return whether the signal is a net that is the subject of a force
* statement.
*
* ivl_signal_type
* Return the type of the signal, i.e., reg, wire, tri0, etc.
*
@ -1836,6 +1840,7 @@ extern ivl_signal_port_t ivl_signal_port(ivl_signal_t net);
extern int ivl_signal_signed(ivl_signal_t net);
extern int ivl_signal_integer(ivl_signal_t net);
extern int ivl_signal_local(ivl_signal_t net);
extern unsigned ivl_signal_forced_net(ivl_signal_t net);
extern unsigned ivl_signal_npath(ivl_signal_t net);
extern ivl_delaypath_t ivl_signal_path(ivl_signal_t net, unsigned idx);
extern ivl_signal_type_t ivl_signal_type(ivl_signal_t net);

View File

@ -2167,6 +2167,11 @@ extern "C" int ivl_signal_signed(ivl_signal_t net)
return net->signed_;
}
extern "C" unsigned ivl_signal_forced_net(ivl_signal_t net)
{
return net->forced_net_;
}
extern "C" const char* ivl_signal_file(ivl_signal_t net)
{
assert(net);

View File

@ -2405,6 +2405,8 @@ void dll_target::signal(const NetNet*net)
obj->lsb_dist = net->msb() >= net->lsb() ? 1 : -1;
obj->isint_ = false;
obj->local_ = net->local_flag()? 1 : 0;
obj->forced_net_ = (net->type() != NetNet::REG) &&
(net->peek_lref() > 0) ? 1 : 0;
obj->discipline = net->get_discipline();
obj->array_dimensions_ = net->array_dimensions();

View File

@ -682,6 +682,8 @@ struct ivl_signal_s {
unsigned isint_ : 1;
unsigned local_ : 1;
unsigned forced_net_ : 1;
/* For now, support only 0 or 1 array dimensions. */
unsigned array_dimensions_ : 1;
unsigned array_addr_swapped : 1;

View File

@ -296,7 +296,7 @@ static unsigned is_netlist_signal(ivl_net_logic_t net, ivl_nexus_t nex)
*/
int can_elide_bufz(ivl_net_logic_t net, ivl_nexus_ptr_t nptr)
{
ivl_nexus_t in_n;
ivl_nexus_t in_n, out_n;
unsigned idx;
/* These are the drives we expect. */
@ -339,6 +339,17 @@ int can_elide_bufz(ivl_net_logic_t net, ivl_nexus_ptr_t nptr)
if (drive_count != 1)
return 0;
/* If the BUFZ output is connected to a net that is subject
to a force statement, we need to keep the BUFZ to prevent
back-flow of the forced value. */
out_n = ivl_logic_pin(net, 0);
for (idx = 0 ; idx < ivl_nexus_ptrs(out_n) ; idx += 1) {
ivl_nexus_ptr_t out_np = ivl_nexus_ptr(out_n, idx);
ivl_signal_t out_sig = ivl_nexus_ptr_sig(out_np);
if (out_sig && ivl_signal_forced_net(out_sig))
return 0;
}
/* If both the input and output are netlist signal then we cannot
elide a BUFZ since it represents a continuous assignment. */
if (is_netlist_signal(net, ivl_logic_pin(net, 0)) &&