Handle dynamic queue objects in event context

In the rare cases where DARRAY signals are in the network, handle
them by creating the proper ivl_nexus_t node. This also implements
the receive of vvp_object_t objects bu vvp_fun_anyedge_sa. This
together makes it possible for IVL_VT_DQUEUE objects to be in
wait lists.

This fixes #412
This commit is contained in:
Stephen Williams 2020-12-13 16:42:04 -08:00
parent f4d22af4bd
commit e5f68d7c89
8 changed files with 45 additions and 13 deletions

View File

@ -1245,9 +1245,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
} else if (netdarray) { } else if (netdarray) {
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype cerr << get_fileline() << ": PWire::elaborate_sig: "
<< " dynamic array " << "Create signal " << wtype
<< name_ << " in scope " << scope_path(scope) << endl; << " dynamic array " << name_
<< " in scope " << scope_path(scope) << endl;
} }
ivl_assert(*this, packed_dimensions.empty()); ivl_assert(*this, packed_dimensions.empty());

View File

@ -224,7 +224,7 @@ void NetPins::set_default_dir(Link::DIR d)
default_dir_ = d; default_dir_ = d;
} }
bool NetPins::is_linked(void) bool NetPins::is_linked(void) const
{ {
bool linked_flag = false; bool linked_flag = false;
if (pins_ == NULL) return false; if (pins_ == NULL) return false;

View File

@ -215,7 +215,7 @@ class NetPins : public LineInfo {
void dump_node_pins(ostream&, unsigned, const char**pin_names =0) const; void dump_node_pins(ostream&, unsigned, const char**pin_names =0) const;
void set_default_dir(Link::DIR d); void set_default_dir(Link::DIR d);
bool is_linked(); bool is_linked() const;
bool pins_are_virtual(void) const; bool pins_are_virtual(void) const;
void devirtualize_pins(void); void devirtualize_pins(void);

View File

@ -915,12 +915,10 @@ bool dll_target::proc_wait(const NetEvWait*net)
break; break;
} }
for (unsigned bit = 0 for (unsigned bit = 0; bit < pr->pin_count(); bit += 1) {
; bit < pr->pin_count()
; bit += 1) {
ivl_nexus_t nex = (ivl_nexus_t) ivl_nexus_t nex = (ivl_nexus_t)
pr->pin(bit).nexus()->t_cookie(); pr->pin(bit).nexus()->t_cookie();
assert(nex); ivl_assert(*ev, nex);
ev_tmp->pins[base+bit] = nex; ev_tmp->pins[base+bit] = nex;
} }
} }

View File

@ -2599,7 +2599,6 @@ void dll_target::signal(const NetNet*net)
obj->discipline = net->get_discipline(); obj->discipline = net->get_discipline();
obj->array_dimensions_ = net->unpacked_dimensions(); obj->array_dimensions_ = net->unpacked_dimensions();
assert(obj->array_dimensions_ == net->unpacked_dimensions());
switch (net->port_type()) { switch (net->port_type()) {
@ -2679,6 +2678,18 @@ void dll_target::signal(const NetNet*net)
obj->nattr = net->attr_cnt(); obj->nattr = net->attr_cnt();
obj->attr = fill_in_attributes(net); obj->attr = fill_in_attributes(net);
// Special case: IVL_VT_QUEUE objects don't normally show up in the
// network, but can in certain special cases. In these cases, it is the
// object itself and not the array elements that is in the network. of
// course, only do this if there is at least one link to this signal.
if (obj->net_type->base_type()==IVL_VT_QUEUE && net->is_linked()) {
const Nexus*nex = net->pin(0).nexus();
ivl_nexus_t tmp = nexus_sig_make(obj, 0);
tmp->nexus_ = nex;
tmp->name_ = 0;
nex->t_cookie(tmp);
}
/* Get the nexus objects for all the pins of the signal. If /* Get the nexus objects for all the pins of the signal. If
the signal has only one pin, then write the single the signal has only one pin, then write the single
ivl_nexus_t object into n.pin_. Otherwise, make an array of ivl_nexus_t object into n.pin_. Otherwise, make an array of

View File

@ -326,11 +326,19 @@ static void show_signal_expression(ivl_expr_t net, unsigned ind)
ivl_expr_t word = ivl_expr_oper1(net); ivl_expr_t word = ivl_expr_oper1(net);
ivl_signal_t sig = ivl_expr_signal(net); ivl_signal_t sig = ivl_expr_signal(net);
const char*vt_sig = data_type_string(ivl_signal_data_type(sig)); ivl_variable_type_t data_type = ivl_signal_data_type(sig);
const char*vt_sig = data_type_string(data_type);
unsigned dimensions = ivl_signal_dimensions(sig); unsigned dimensions = ivl_signal_dimensions(sig);
unsigned word_count = ivl_signal_array_count(sig); unsigned word_count = ivl_signal_array_count(sig);
if (dimensions == 0 && word_count != 1) { if (data_type==IVL_VT_QUEUE) {
if (dimensions != 0) {
fprintf(out, "%*sERROR: Queue objects expect dimensions==0, got %u.\n",
ind, "", dimensions);
stub_errors += 1;
}
} else if (dimensions == 0 && word_count != 1) {
fprintf(out, "%*sERROR: Word count = %u for non-array object\n", fprintf(out, "%*sERROR: Word count = %u for non-array object\n",
ind, "", word_count); ind, "", word_count);
stub_errors += 1; stub_errors += 1;
@ -353,7 +361,7 @@ static void show_signal_expression(ivl_expr_t net, unsigned ind)
/* If this is not an array, then the expression with must /* If this is not an array, then the expression with must
match the signal width. We have IVL_EX_SELECT expressions match the signal width. We have IVL_EX_SELECT expressions
for casting signal widths. */ for casting signal widths. */
if (dimensions == 0 && ivl_signal_width(sig) != width) { if (dimensions == 0 && data_type!=IVL_VT_QUEUE && ivl_signal_width(sig) != width) {
fprintf(out, "%*sERROR: Expression width (%u) doesn't match ivl_signal_width(sig)=%u\n", fprintf(out, "%*sERROR: Expression width (%u) doesn't match ivl_signal_width(sig)=%u\n",
ind+2, "", width, ivl_signal_width(sig)); ind+2, "", width, ivl_signal_width(sig));
stub_errors += 1; stub_errors += 1;

View File

@ -627,6 +627,18 @@ void vvp_fun_anyedge_sa::recv_string(vvp_net_ptr_t port, const std::string&bit,
} }
} }
/*
* An anyedge receiving an object should do nothing with it, but should
* trigger waiting threads.
*/
void vvp_fun_anyedge_sa::recv_object(vvp_net_ptr_t port, vvp_object_t bit,
vvp_context_t)
{
run_waiting_threads_(threads_);
vvp_net_t*net = port.ptr();
net->send_vec4(vvp_vector4_t(), 0);
}
vvp_fun_anyedge_aa::vvp_fun_anyedge_aa() vvp_fun_anyedge_aa::vvp_fun_anyedge_aa()
{ {
context_scope_ = vpip_peek_context_scope(); context_scope_ = vpip_peek_context_scope();

View File

@ -264,6 +264,8 @@ class vvp_fun_anyedge_sa : public vvp_fun_anyedge {
void recv_string(vvp_net_ptr_t port, const std::string&bit, void recv_string(vvp_net_ptr_t port, const std::string&bit,
vvp_context_t context); vvp_context_t context);
void recv_object(vvp_net_ptr_t port, vvp_object_t bit,
vvp_context_t context);
private: private:
vthread_t threads_; vthread_t threads_;