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:
parent
f4d22af4bd
commit
e5f68d7c89
|
|
@ -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());
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
13
t-dll.cc
13
t-dll.cc
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
12
vvp/event.cc
12
vvp/event.cc
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue