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) {
|
||||
|
||||
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());
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
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->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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
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()
|
||||
{
|
||||
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,
|
||||
vvp_context_t context);
|
||||
void recv_object(vvp_net_ptr_t port, vvp_object_t bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
vthread_t threads_;
|
||||
|
|
|
|||
Loading…
Reference in New Issue