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) {
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype
<< " dynamic array "
<< name_ << " in scope " << scope_path(scope) << endl;
cerr << get_fileline() << ": PWire::elaborate_sig: "
<< "Create signal " << wtype
<< " dynamic array " << name_
<< " in scope " << scope_path(scope) << endl;
}
ivl_assert(*this, packed_dimensions.empty());

View File

@ -224,7 +224,7 @@ void NetPins::set_default_dir(Link::DIR d)
default_dir_ = d;
}
bool NetPins::is_linked(void)
bool NetPins::is_linked(void) const
{
bool linked_flag = 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 set_default_dir(Link::DIR d);
bool is_linked();
bool is_linked() const;
bool pins_are_virtual(void) const;
void devirtualize_pins(void);

View File

@ -915,12 +915,10 @@ bool dll_target::proc_wait(const NetEvWait*net)
break;
}
for (unsigned bit = 0
; bit < pr->pin_count()
; bit += 1) {
for (unsigned bit = 0; bit < pr->pin_count(); bit += 1) {
ivl_nexus_t nex = (ivl_nexus_t)
pr->pin(bit).nexus()->t_cookie();
assert(nex);
ivl_assert(*ev, 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->array_dimensions_ = net->unpacked_dimensions();
assert(obj->array_dimensions_ == net->unpacked_dimensions());
switch (net->port_type()) {
@ -2679,6 +2678,18 @@ void dll_target::signal(const NetNet*net)
obj->nattr = net->attr_cnt();
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
the signal has only one pin, then write the single
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_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 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",
ind, "", word_count);
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
match the signal width. We have IVL_EX_SELECT expressions
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",
ind+2, "", width, ivl_signal_width(sig));
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()
{
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,
vvp_context_t context);
void recv_object(vvp_net_ptr_t port, vvp_object_t bit,
vvp_context_t context);
private:
vthread_t threads_;