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:
parent
3e3b83da30
commit
5fc1a9c9e0
1
ivl.def
1
ivl.def
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
2
t-dll.cc
2
t-dll.cc
|
|
@ -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();
|
||||
|
|
|
|||
2
t-dll.h
2
t-dll.h
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)) &&
|
||||
|
|
|
|||
Loading…
Reference in New Issue