Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl

This commit is contained in:
Nick Gasson 2008-08-10 09:51:20 +01:00
commit 380e3a8121
8 changed files with 285 additions and 137 deletions

View File

@ -2327,7 +2327,7 @@ NetNet* PEIdent::elaborate_net_array_(Design*des, NetScope*scope,
} while (0);
#else
if (name_tail.index.size() > sig->array_dimensions())
tmp = process_select_(des, scope, sig);
tmp = process_select_(des, scope, tmp);
#endif
return tmp;

View File

@ -53,7 +53,7 @@ void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope);
if (val == 0) return;
NetExpr*msb = 0;
NetExpr*lsb = 0;
bool signed_flag = cur.signed_flag;
@ -71,19 +71,6 @@ void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
assert(lsb);
}
if (signed_flag) {
/* If explicitly signed, then say so. */
val->cast_signed(true);
} else if (cur.msb) {
/* If there is a range, then the signedness comes
from the type and not the expression. */
val->cast_signed(signed_flag);
} else {
/* otherwise, let the expression describe
itself. */
signed_flag = val->has_sign();
}
NetScope::range_t*range_list = 0;
for (Module::range_t*range = cur.range ; range ; range = range->next) {
NetScope::range_t*tmp = new NetScope::range_t;
@ -118,8 +105,29 @@ void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
range_list = tmp;
}
val = scope->set_parameter(name, val, cur.type, msb, lsb, signed_flag, range_list, cur);
assert(val);
/* Set the parameter expression to 0 if the evaluation failed. */
if (val == 0) {
val = scope->set_parameter(name, val, cur.type, msb, lsb,
signed_flag, range_list, cur);
delete val;
return;
}
if (signed_flag) {
/* If explicitly signed, then say so. */
val->cast_signed(true);
} else if (cur.msb) {
/* If there is a range, then the signedness comes
from the type and not the expression. */
val->cast_signed(signed_flag);
} else {
/* otherwise, let the expression describe
itself. */
signed_flag = val->has_sign();
}
val = scope->set_parameter(name, val, cur.type, msb, lsb, signed_flag,
range_list, cur);
delete val;
}
@ -316,17 +324,17 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// here because the parameter receiving the assignment may be
// in a scope not discovered by this pass.
while (! defparms.empty()) {
Module::named_expr_t cur = defparms.front();
defparms.pop_front();
typedef list<Module::named_expr_t>::const_iterator defparms_iter_t;
for (defparms_iter_t cur = defparms.begin()
; cur != defparms.end() ; cur ++) {
PExpr*ex = cur.second;
PExpr*ex = cur->second;
assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope);
delete ex;
if (val == 0) continue;
scope->defparams.push_back(make_pair(cur.first, val));
scope->defparams.push_back(make_pair(cur->first, val));
}
// Evaluate the attributes. Evaluate them in the scope of the
@ -475,7 +483,12 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
container->genvar_tmp_val = genvar;
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
assert(test);
if (test == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
<< " conditional expression: " << *loop_test << endl;
des->errors += 1;
return false;
}
while (test->value().as_long()) {
// The actual name of the scope includes the genvar so
@ -522,7 +535,12 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
// Calculate the step for the loop variable.
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
assert(step);
if (step == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
<< " step expression: " << *loop_step << endl;
des->errors += 1;
return false;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: genvar step from "
<< genvar << " to " << step->value().as_long() << endl;
@ -547,7 +565,12 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
{
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
assert(test);
if (test == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
<< " conditional expression: " << *loop_test << endl;
des->errors += 1;
return false;
}
// If the condition evaluates as false, then do not create the
// scope.
@ -589,7 +612,12 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
{
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex);
assert(case_value_co);
if (case_value_co == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar case"
<< " expression: " << *loop_test << endl;
des->errors += 1;
return false;
}
// The name of the scope to generate, whatever that item is.
hname_t use_name (scope_name);

View File

@ -589,9 +589,17 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
break;
default:
cerr << get_fileline() << ": internal error: I don't know how "
<< "to deal with return type of function "
<< scope->basename() << "." << endl;
if (ports_) {
cerr << get_fileline() << ": internal error: I don't know "
<< "how to deal with return type of function "
<< scope->basename() << "." << endl;
} else {
/* If we do not have any ports or a return type this
* is probably a bad function definition. */
cerr << get_fileline() << ": error: Bad definition for "
<< "function " << scope->basename() << "?" << endl;
return;
}
}
svector<NetNet*>ports (ports_? ports_->count() : 0);
@ -1003,8 +1011,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal "
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_
<< " in scope " << scope_path(scope) << endl;
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_;
if (array_dimensions > 0) {
cerr << " [" << array_s0 << ":" << array_e0 << "]" << endl;
}
cerr << " in scope " << scope_path(scope) << endl;
}

View File

@ -357,11 +357,11 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
/* Evaluate the parameter expression, if necessary. */
NetExpr*expr = (*cur).second.expr;
assert(expr);
if (expr == NULL) return; // This is an invalid parameter so return.
eval_expr(expr);
/* The eval_expr may delete any replace the expr pointer, so the
/* The eval_expr may delete and replace the expr pointer, so the
second.expr value cannot be relied on. Might as well replace
it now with the expression that we evaluated. */
(*cur).second.expr = expr;

230
parse.y
View File

@ -351,6 +351,13 @@ number : BASED_NUMBER
based_size = 0; }
;
/* real and realtime are exactly the same so save some code
* with a common matching rule. */
real_or_realtime
: K_real
| K_realtime
;
/* Verilog-2001 supports attribute lists, which can be attached to a
variety of different objects. The syntax inside the (* *) is a
comma separated list of names or names with assigned values. */
@ -2426,17 +2433,7 @@ parameter_assign_decl
param_active_signed = false;
param_active_type = IVL_VT_LOGIC;
}
| K_real
{ param_active_range = 0;
param_active_signed = true;
param_active_type = IVL_VT_REAL;
}
parameter_assign_list
{ param_active_range = 0;
param_active_signed = false;
param_active_type = IVL_VT_LOGIC;
}
| K_realtime
| real_or_realtime
{ param_active_range = 0;
param_active_signed = true;
param_active_type = IVL_VT_REAL;
@ -2565,17 +2562,7 @@ localparam_assign_decl
param_active_signed = false;
param_active_type = IVL_VT_LOGIC;
}
| K_real
{ param_active_range = 0;
param_active_signed = true;
param_active_type = IVL_VT_REAL;
}
localparam_assign_list
{ param_active_range = 0;
param_active_signed = false;
param_active_type = IVL_VT_LOGIC;
}
| K_realtime
| real_or_realtime
{ param_active_range = 0;
param_active_signed = true;
param_active_type = IVL_VT_REAL;
@ -3734,39 +3721,43 @@ task_item
| task_port_item { $$ = $1; }
;
reg_opt
: K_reg
|
;
task_port_item
: K_input signed_opt range_opt list_of_identifiers ';'
: K_input reg_opt signed_opt range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
IVL_VT_NO_TYPE, $2,
$3, $4,
IVL_VT_NO_TYPE, $3,
$4, $5,
@1.text, @1.first_line);
$$ = tmp;
}
| K_output signed_opt range_opt list_of_identifiers ';'
| K_output reg_opt signed_opt range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_LOGIC, $2,
$3, $4,
IVL_VT_LOGIC, $3,
$4, $5,
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout signed_opt range_opt list_of_identifiers ';'
| K_inout reg_opt signed_opt range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT,
IVL_VT_LOGIC, $2,
$3, $4,
IVL_VT_LOGIC, $3,
$4, $5,
@1.text, @1.first_line);
$$ = tmp;
}
/* When the port is an integer, infer a signed vector of the integer
shape. Generate a range to make it work. */
shape. Generate a range ([31:0]) to make it work. */
| K_input K_integer list_of_identifiers ';'
{ svector<PExpr*>*range_stub
= new svector<PExpr*>(2);
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum(integer_width-1,
integer_width));
@ -3781,8 +3772,7 @@ task_port_item
$$ = tmp;
}
| K_output K_integer list_of_identifiers ';'
{ svector<PExpr*>*range_stub
= new svector<PExpr*>(2);
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum(integer_width-1,
integer_width));
@ -3797,8 +3787,7 @@ task_port_item
$$ = tmp;
}
| K_inout K_integer list_of_identifiers ';'
{ svector<PExpr*>*range_stub
= new svector<PExpr*>(2);
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum(integer_width-1,
integer_width));
@ -3813,9 +3802,54 @@ task_port_item
$$ = tmp;
}
/* Ports can be real. */
/* Ports can be time with a width of [63:0] (unsigned). */
| K_input K_real list_of_identifiers ';'
| K_input K_time list_of_identifiers ';'
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum((uint64_t)63, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
IVL_VT_LOGIC, false,
range_stub, $3,
@1.text, @1.first_line);
$$ = tmp;
}
| K_output K_time list_of_identifiers ';'
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum((uint64_t)63, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_LOGIC, false,
range_stub, $3,
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout K_time list_of_identifiers ';'
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum((uint64_t)63, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT,
IVL_VT_LOGIC, false,
range_stub, $3,
@1.text, @1.first_line);
$$ = tmp;
}
/* Ports can be real or realtime. */
| K_input real_or_realtime list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
IVL_VT_REAL, false,
@ -3823,7 +3857,7 @@ task_port_item
@1.text, @1.first_line);
$$ = tmp;
}
| K_output K_real list_of_identifiers ';'
| K_output real_or_realtime list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_REAL, true,
@ -3831,7 +3865,7 @@ task_port_item
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout K_real list_of_identifiers ';'
| K_inout real_or_realtime list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT,
IVL_VT_REAL, true,
@ -3861,50 +3895,51 @@ task_item_list_opt
task_port_decl
: K_input signed_opt range_opt IDENTIFIER
: K_input reg_opt signed_opt range_opt IDENTIFIER
{ port_declaration_context.port_type = NetNet::PINPUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = $2;
port_declaration_context.sign_flag = $3;
delete port_declaration_context.range;
port_declaration_context.range = copy_range($3);
port_declaration_context.range = copy_range($4);
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
IVL_VT_LOGIC, $2,
$3, list_from_identifier($4),
IVL_VT_LOGIC, $3,
$4, list_from_identifier($5),
@1.text, @1.first_line);
$$ = tmp;
}
| K_output signed_opt range_opt IDENTIFIER
| K_output reg_opt signed_opt range_opt IDENTIFIER
{ port_declaration_context.port_type = NetNet::POUTPUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = $2;
port_declaration_context.sign_flag = $3;
delete port_declaration_context.range;
port_declaration_context.range = copy_range($3);
port_declaration_context.range = copy_range($4);
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_LOGIC, $2,
$3, list_from_identifier($4),
IVL_VT_LOGIC, $3,
$4, list_from_identifier($5),
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout signed_opt range_opt IDENTIFIER
| K_inout reg_opt signed_opt range_opt IDENTIFIER
{ port_declaration_context.port_type = NetNet::PINOUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = $2;
port_declaration_context.sign_flag = $3;
delete port_declaration_context.range;
port_declaration_context.range = copy_range($3);
port_declaration_context.range = copy_range($4);
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT,
IVL_VT_LOGIC, $2,
$3, list_from_identifier($4),
IVL_VT_LOGIC, $3,
$4, list_from_identifier($5),
@1.text, @1.first_line);
$$ = tmp;
}
/* Ports can be integer with a width of [31:0]. */
| K_input K_integer IDENTIFIER
{ svector<PExpr*>*range_stub
= new svector<PExpr*>(2);
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum(integer_width-1,
integer_width));
@ -3925,8 +3960,7 @@ task_port_decl
$$ = tmp;
}
| K_output K_integer IDENTIFIER
{ svector<PExpr*>*range_stub
= new svector<PExpr*>(2);
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum(integer_width-1,
integer_width));
@ -3947,8 +3981,7 @@ task_port_decl
$$ = tmp;
}
| K_inout K_integer IDENTIFIER
{ svector<PExpr*>*range_stub
= new svector<PExpr*>(2);
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum(integer_width-1,
integer_width));
@ -3969,9 +4002,72 @@ task_port_decl
$$ = tmp;
}
/* Ports can be real. */
/* Ports can be time with a width of [63:0] (unsigned). */
| K_input K_real IDENTIFIER
| K_input K_time IDENTIFIER
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum((uint64_t)63, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
port_declaration_context.port_type = NetNet::PINPUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = false;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
IVL_VT_LOGIC, false,
range_stub,
list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
| K_output K_time IDENTIFIER
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum((uint64_t)63, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
port_declaration_context.port_type = NetNet::POUTPUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = false;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_LOGIC, false,
range_stub,
list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout K_time IDENTIFIER
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum((uint64_t)63, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
port_declaration_context.port_type = NetNet::PINOUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = false;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT,
IVL_VT_LOGIC, false,
range_stub,
list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
/* Ports can be real or realtime. */
| K_input real_or_realtime IDENTIFIER
{ port_declaration_context.port_type = NetNet::PINPUT;
port_declaration_context.var_type = IVL_VT_REAL;
port_declaration_context.sign_flag = false;
@ -3984,7 +4080,7 @@ task_port_decl
@1.text, @1.first_line);
$$ = tmp;
}
| K_output K_real IDENTIFIER
| K_output real_or_realtime IDENTIFIER
{ port_declaration_context.port_type = NetNet::POUTPUT;
port_declaration_context.var_type = IVL_VT_REAL;
port_declaration_context.sign_flag = false;
@ -3997,7 +4093,7 @@ task_port_decl
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout K_real IDENTIFIER
| K_inout real_or_realtime IDENTIFIER
{ port_declaration_context.port_type = NetNet::PINOUT;
port_declaration_context.var_type = IVL_VT_REAL;
port_declaration_context.sign_flag = false;

View File

@ -895,6 +895,10 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
static void draw_event_in_scope(ivl_event_t obj)
{
char tmp[4][32];
const unsigned ntmp = sizeof(tmp) / sizeof(tmp[0]);
unsigned nany = ivl_event_nany(obj);
unsigned nneg = ivl_event_nneg(obj);
unsigned npos = ivl_event_npos(obj);
@ -903,13 +907,13 @@ static void draw_event_in_scope(ivl_event_t obj)
/* Figure out how many probe functors are needed. */
if (nany > 0)
cnt += (nany+3) / 4;
cnt += (nany+ntmp-1) / ntmp;
if (nneg > 0)
cnt += (nneg+3) / 4;
cnt += (nneg+ntmp-1) / ntmp;
if (npos > 0)
cnt += (npos+3) / 4;
cnt += (npos+ntmp-1) / ntmp;
if (cnt == 0) {
/* If none are needed, then this is a named event. The
@ -923,48 +927,57 @@ static void draw_event_in_scope(ivl_event_t obj)
unsigned idx;
unsigned ecnt = 0;
for (idx = 0 ; idx < nany ; idx += 4, ecnt += 1) {
for (idx = 0 ; idx < nany ; idx += ntmp, ecnt += 1) {
unsigned sub, top;
fprintf(vvp_out, "E_%p/%u .event edge", obj, ecnt);
top = idx + 4;
top = idx + ntmp;
if (nany < top)
top = nany;
for (sub = idx ; sub < top ; sub += 1) {
ivl_nexus_t nex = ivl_event_any(obj, sub);
fprintf(vvp_out, ", %s", draw_input_from_net(nex));
strncpy(tmp[sub-idx], draw_input_from_net(nex), sizeof(tmp[0]));
}
fprintf(vvp_out, "E_%p/%u .event edge", obj, ecnt);
for (sub = idx ; sub < top ; sub += 1)
fprintf(vvp_out, ", %s", tmp[sub-idx]);
fprintf(vvp_out, ";\n");
}
for (idx = 0 ; idx < nneg ; idx += 4, ecnt += 1) {
for (idx = 0 ; idx < nneg ; idx += ntmp, ecnt += 1) {
unsigned sub, top;
fprintf(vvp_out, "E_%p/%u .event negedge", obj, ecnt);
top = idx + 4;
top = idx + ntmp;
if (nneg < top)
top = nneg;
for (sub = idx ; sub < top ; sub += 1) {
ivl_nexus_t nex = ivl_event_neg(obj, sub);
fprintf(vvp_out, ", %s", draw_input_from_net(nex));
strncpy(tmp[sub-idx], draw_input_from_net(nex), sizeof(tmp[0]));
}
fprintf(vvp_out, "E_%p/%u .event negedge", obj, ecnt);
for (sub = idx ; sub < top ; sub += 1)
fprintf(vvp_out, ", %s", tmp[sub-idx]);
fprintf(vvp_out, ";\n");
}
for (idx = 0 ; idx < npos ; idx += 4, ecnt += 1) {
for (idx = 0 ; idx < npos ; idx += ntmp, ecnt += 1) {
unsigned sub, top;
fprintf(vvp_out, "E_%p/%u .event posedge", obj, ecnt);
top = idx + 4;
top = idx + ntmp;
if (npos < top)
top = npos;
for (sub = idx ; sub < top ; sub += 1) {
ivl_nexus_t nex = ivl_event_pos(obj, sub);
fprintf(vvp_out, ", %s", draw_input_from_net(nex));
strncpy(tmp[sub-idx], draw_input_from_net(nex), sizeof(tmp[0]));
}
fprintf(vvp_out, "E_%p/%u .event posedge", obj, ecnt);
for (sub = idx ; sub < top ; sub += 1)
fprintf(vvp_out, ", %s", tmp[sub-idx]);
fprintf(vvp_out, ";\n");
}
@ -981,20 +994,17 @@ static void draw_event_in_scope(ivl_event_t obj)
} else {
unsigned num_input_strings = nany + nneg + npos;
unsigned idx;
ivl_nexus_t input_nexa[4];
const char*edge = 0;
assert(num_input_strings <= 4);
assert(num_input_strings <= ntmp);
if (nany > 0) {
assert((nneg + npos) == 0);
assert(nany <= 4);
edge = "edge";
for (idx = 0 ; idx < nany ; idx += 1) {
ivl_nexus_t nex = ivl_event_any(obj, idx);
input_nexa[idx] = nex;
strncpy(tmp[idx], draw_input_from_net(nex), sizeof(tmp[0]));
}
} else if (nneg > 0) {
@ -1003,7 +1013,7 @@ static void draw_event_in_scope(ivl_event_t obj)
for (idx = 0 ; idx < nneg ; idx += 1) {
ivl_nexus_t nex = ivl_event_neg(obj, idx);
input_nexa[idx] = nex;
strncpy(tmp[idx], draw_input_from_net(nex), sizeof(tmp[0]));
}
} else {
@ -1012,14 +1022,14 @@ static void draw_event_in_scope(ivl_event_t obj)
for (idx = 0 ; idx < npos ; idx += 1) {
ivl_nexus_t nex = ivl_event_pos(obj, idx);
input_nexa[idx] = nex;
strncpy(tmp[idx], draw_input_from_net(nex), sizeof(tmp[0]));
}
}
fprintf(vvp_out, "E_%p .event %s", obj, edge);
for (idx = 0 ; idx < num_input_strings ; idx += 1)
fprintf(vvp_out, ", %s", draw_input_from_net(input_nexa[idx]));
for (idx = 0 ; idx < num_input_strings ; idx += 1) {
fprintf(vvp_out, ", %s", tmp[idx]);
}
fprintf(vvp_out, ";\n");
}
}

View File

@ -414,8 +414,9 @@ ended, then the %join does not block or yield the thread.
* %load/av <bit>, <array-label>, <wid>
This instruction loads a word from the specified array. The word
address is in index register 3. The width should match the width of
the array word.
address is in index register 3. Like %load/v below the width does
not have to match the width of the array word. See the %load/v
description for more information.
* %load/avp0 <bit>, <array-label>, <wid>
* %load/avp0/s <bit>, <array-label>, <wid>

View File

@ -2363,19 +2363,21 @@ bool of_LOAD_AV(vthread_t thr, vvp_code_t cp)
vvp_vector4_t word = array_get_word(cp->array, adr);
if (word.size() != wid) {
fprintf(stderr, "internal error: array width=%u, word.size()=%u, wid=%u\n",
0, word.size(), wid);
assert(word.size() == wid);
}
/* Check the address once, before we scan the vector. */
thr_check_addr(thr, bit+wid-1);
if (word.size() > wid)
word.resize(wid);
/* Copy the vector bits into the bits4 vector. Do the copy
directly to skip the excess calls to thr_check_addr. */
thr->bits4.set_vec(bit, word);
/* If the source is shorter then the desired width, then pad
with BIT4_X values. */
for (unsigned idx = word.size() ; idx < wid ; idx += 1)
thr->bits4.set_bit(bit+idx, BIT4_X);
return true;
}