Merge branch 'master' of github.com:steveicarus/iverilog

This commit is contained in:
Cary R 2020-12-13 23:02:43 -08:00
commit b7b7280794
10 changed files with 227 additions and 13 deletions

View File

@ -2623,6 +2623,27 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
return sys_expr; return sys_expr;
} }
if (method_name == "atoi") {
NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$atoi",
IVL_VT_BOOL, integer_width, 1);
sys_expr->parm(0, new NetESignal(net));
return sys_expr;
}
if (method_name == "atoreal") {
NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$atoreal",
IVL_VT_REAL, 1, 1);
sys_expr->parm(0, new NetESignal(net));
return sys_expr;
}
if (method_name == "atohex") {
NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$atohex",
IVL_VT_BOOL, integer_width, 1);
sys_expr->parm(0, new NetESignal(net));
return sys_expr;
}
if (method_name == "substr") { if (method_name == "substr") {
NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$substr", NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$substr",
IVL_VT_STRING, 1, 3); IVL_VT_STRING, 1, 3);

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

@ -19,6 +19,7 @@
# include "sys_priv.h" # include "sys_priv.h"
# include <assert.h> # include <assert.h>
# include <ctype.h>
# include <math.h> # include <math.h>
# include <stdlib.h> # include <stdlib.h>
# include <string.h> # include <string.h>
@ -78,6 +79,136 @@ static PLI_INT32 len_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
return 0; return 0;
} }
static PLI_INT32 atoi_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv;
vpiHandle arg;
s_vpi_value value;
(void)name; /* Parameter not used */
argv = vpi_iterate(vpiArgument, callh);
assert(argv);
arg = vpi_scan(argv);
assert(arg);
vpi_free_object(argv);
int res = 0;
value.format = vpiStringVal;
vpi_get_value(arg, &value);
const char*bufp = value.value.str;
while (bufp && *bufp) {
if (isdigit(*bufp)) {
res = (res * 10) + (*bufp - '0');
bufp += 1;
} else if (*bufp == '_') {
bufp += 1;
} else {
bufp = 0;
}
}
value.format = vpiIntVal;
value.value.integer = res;
vpi_put_value(callh, &value, 0, vpiNoDelay);
return 0;
}
static PLI_INT32 atoreal_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv;
vpiHandle arg;
s_vpi_value value;
(void)name; /* Parameter not used */
argv = vpi_iterate(vpiArgument, callh);
assert(argv);
arg = vpi_scan(argv);
assert(arg);
vpi_free_object(argv);
double res = 0;
value.format = vpiStringVal;
vpi_get_value(arg, &value);
res = strtod(value.value.str, 0);
value.format = vpiRealVal;
value.value.real = res;
vpi_put_value(callh, &value, 0, vpiNoDelay);
return 0;
}
static PLI_INT32 atohex_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv;
vpiHandle arg;
s_vpi_value value;
(void)name; /* Parameter not used */
argv = vpi_iterate(vpiArgument, callh);
assert(argv);
arg = vpi_scan(argv);
assert(arg);
vpi_free_object(argv);
int res = 0;
value.format = vpiStringVal;
vpi_get_value(arg, &value);
const char*bufp = value.value.str;
while (bufp && *bufp) {
switch (*bufp) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
res = (res * 16) + (*bufp - '0');
bufp += 1;
break;
case 'a': case 'A':
case 'b': case 'B':
case 'c': case 'C':
case 'd': case 'D':
case 'e': case 'E':
case 'f': case 'F':
res = (res * 16) + (toupper(*bufp) - 'A' + 10);
bufp += 1;
break;
case '_':
bufp += 1;
break;
default:
bufp = 0;
break;
}
}
value.format = vpiIntVal;
value.value.integer = res;
vpi_put_value(callh, &value, 0, vpiNoDelay);
return 0;
}
void v2009_string_register(void) void v2009_string_register(void)
{ {
s_vpi_systf_data tf_data; s_vpi_systf_data tf_data;
@ -92,4 +223,34 @@ void v2009_string_register(void)
tf_data.user_data = "$ivl_string_method$len"; tf_data.user_data = "$ivl_string_method$len";
res = vpi_register_systf(&tf_data); res = vpi_register_systf(&tf_data);
vpip_make_systf_system_defined(res); vpip_make_systf_system_defined(res);
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiIntFunc;
tf_data.tfname = "$ivl_string_method$atoi";
tf_data.calltf = atoi_calltf;
tf_data.compiletf = one_string_arg_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$ivl_string_method$atoi";
res = vpi_register_systf(&tf_data);
vpip_make_systf_system_defined(res);
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiRealFunc;
tf_data.tfname = "$ivl_string_method$atoreal";
tf_data.calltf = atoreal_calltf;
tf_data.compiletf = one_string_arg_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$ivl_string_method$atoreal";
res = vpi_register_systf(&tf_data);
vpip_make_systf_system_defined(res);
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiIntFunc;
tf_data.tfname = "$ivl_string_method$atohex";
tf_data.calltf = atohex_calltf;
tf_data.compiletf = one_string_arg_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = "$ivl_string_method$atohex";
res = vpi_register_systf(&tf_data);
vpip_make_systf_system_defined(res);
} }

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_;