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;
}
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") {
NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$substr",
IVL_VT_STRING, 1, 3);

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

@ -19,6 +19,7 @@
# include "sys_priv.h"
# include <assert.h>
# include <ctype.h>
# include <math.h>
# include <stdlib.h>
# include <string.h>
@ -78,6 +79,136 @@ static PLI_INT32 len_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
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)
{
s_vpi_systf_data tf_data;
@ -92,4 +223,34 @@ void v2009_string_register(void)
tf_data.user_data = "$ivl_string_method$len";
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$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()
{
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_;