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); } while (0);
#else #else
if (name_tail.index.size() > sig->array_dimensions()) if (name_tail.index.size() > sig->array_dimensions())
tmp = process_select_(des, scope, sig); tmp = process_select_(des, scope, tmp);
#endif #endif
return tmp; return tmp;

View File

@ -53,7 +53,7 @@ void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
assert(ex); assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope); NetExpr*val = ex->elaborate_pexpr(des, scope);
if (val == 0) return;
NetExpr*msb = 0; NetExpr*msb = 0;
NetExpr*lsb = 0; NetExpr*lsb = 0;
bool signed_flag = cur.signed_flag; 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); 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; NetScope::range_t*range_list = 0;
for (Module::range_t*range = cur.range ; range ; range = range->next) { for (Module::range_t*range = cur.range ; range ; range = range->next) {
NetScope::range_t*tmp = new NetScope::range_t; 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; range_list = tmp;
} }
val = scope->set_parameter(name, val, cur.type, msb, lsb, signed_flag, range_list, cur); /* Set the parameter expression to 0 if the evaluation failed. */
assert(val); 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; delete val;
} }
@ -316,17 +324,17 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// here because the parameter receiving the assignment may be // here because the parameter receiving the assignment may be
// in a scope not discovered by this pass. // in a scope not discovered by this pass.
while (! defparms.empty()) { typedef list<Module::named_expr_t>::const_iterator defparms_iter_t;
Module::named_expr_t cur = defparms.front(); for (defparms_iter_t cur = defparms.begin()
defparms.pop_front(); ; cur != defparms.end() ; cur ++) {
PExpr*ex = cur.second; PExpr*ex = cur->second;
assert(ex); assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope); NetExpr*val = ex->elaborate_pexpr(des, scope);
delete ex;
if (val == 0) continue; 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 // 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; container->genvar_tmp_val = genvar;
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1); NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*test = dynamic_cast<NetEConst*>(test_ex); 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()) { while (test->value().as_long()) {
// The actual name of the scope includes the genvar so // 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. // Calculate the step for the loop variable.
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1); NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
NetEConst*step = dynamic_cast<NetEConst*>(step_ex); 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) if (debug_scopes)
cerr << get_fileline() << ": debug: genvar step from " cerr << get_fileline() << ": debug: genvar step from "
<< genvar << " to " << step->value().as_long() << endl; << 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); NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*test = dynamic_cast<NetEConst*> (test_ex); 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 // If the condition evaluates as false, then do not create the
// scope. // 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); NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex); 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. // The name of the scope to generate, whatever that item is.
hname_t use_name (scope_name); hname_t use_name (scope_name);

View File

@ -589,9 +589,17 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
break; break;
default: default:
cerr << get_fileline() << ": internal error: I don't know how " if (ports_) {
<< "to deal with return type of function " cerr << get_fileline() << ": internal error: I don't know "
<< scope->basename() << "." << endl; << "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); svector<NetNet*>ports (ports_? ports_->count() : 0);
@ -1003,8 +1011,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " cerr << get_fileline() << ": debug: Create signal "
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_ << wtype << " ["<<msb<<":"<<lsb<<"] " << name_;
<< " in scope " << scope_path(scope) << endl; 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. */ /* Evaluate the parameter expression, if necessary. */
NetExpr*expr = (*cur).second.expr; NetExpr*expr = (*cur).second.expr;
assert(expr); if (expr == NULL) return; // This is an invalid parameter so return.
eval_expr(expr); 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 second.expr value cannot be relied on. Might as well replace
it now with the expression that we evaluated. */ it now with the expression that we evaluated. */
(*cur).second.expr = expr; (*cur).second.expr = expr;

230
parse.y
View File

@ -351,6 +351,13 @@ number : BASED_NUMBER
based_size = 0; } 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 /* Verilog-2001 supports attribute lists, which can be attached to a
variety of different objects. The syntax inside the (* *) is a variety of different objects. The syntax inside the (* *) is a
comma separated list of names or names with assigned values. */ comma separated list of names or names with assigned values. */
@ -2426,17 +2433,7 @@ parameter_assign_decl
param_active_signed = false; param_active_signed = false;
param_active_type = IVL_VT_LOGIC; param_active_type = IVL_VT_LOGIC;
} }
| K_real | real_or_realtime
{ 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
{ param_active_range = 0; { param_active_range = 0;
param_active_signed = true; param_active_signed = true;
param_active_type = IVL_VT_REAL; param_active_type = IVL_VT_REAL;
@ -2565,17 +2562,7 @@ localparam_assign_decl
param_active_signed = false; param_active_signed = false;
param_active_type = IVL_VT_LOGIC; param_active_type = IVL_VT_LOGIC;
} }
| K_real | real_or_realtime
{ 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
{ param_active_range = 0; { param_active_range = 0;
param_active_signed = true; param_active_signed = true;
param_active_type = IVL_VT_REAL; param_active_type = IVL_VT_REAL;
@ -3734,39 +3721,43 @@ task_item
| task_port_item { $$ = $1; } | task_port_item { $$ = $1; }
; ;
reg_opt
: K_reg
|
;
task_port_item 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 { svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT, = pform_make_task_ports(NetNet::PINPUT,
IVL_VT_NO_TYPE, $2, IVL_VT_NO_TYPE, $3,
$3, $4, $4, $5,
@1.text, @1.first_line); @1.text, @1.first_line);
$$ = tmp; $$ = tmp;
} }
| K_output signed_opt range_opt list_of_identifiers ';' | K_output reg_opt signed_opt range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp { svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT, = pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_LOGIC, $2, IVL_VT_LOGIC, $3,
$3, $4, $4, $5,
@1.text, @1.first_line); @1.text, @1.first_line);
$$ = tmp; $$ = tmp;
} }
| K_inout signed_opt range_opt list_of_identifiers ';' | K_inout reg_opt signed_opt range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp { svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT, = pform_make_task_ports(NetNet::PINOUT,
IVL_VT_LOGIC, $2, IVL_VT_LOGIC, $3,
$3, $4, $4, $5,
@1.text, @1.first_line); @1.text, @1.first_line);
$$ = tmp; $$ = tmp;
} }
/* When the port is an integer, infer a signed vector of the integer /* 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 ';' | K_input K_integer list_of_identifiers ';'
{ svector<PExpr*>*range_stub { svector<PExpr*>*range_stub = new svector<PExpr*>(2);
= new svector<PExpr*>(2);
PExpr*re; PExpr*re;
re = new PENumber(new verinum(integer_width-1, re = new PENumber(new verinum(integer_width-1,
integer_width)); integer_width));
@ -3781,8 +3772,7 @@ task_port_item
$$ = tmp; $$ = tmp;
} }
| K_output K_integer list_of_identifiers ';' | K_output K_integer list_of_identifiers ';'
{ svector<PExpr*>*range_stub { svector<PExpr*>*range_stub = new svector<PExpr*>(2);
= new svector<PExpr*>(2);
PExpr*re; PExpr*re;
re = new PENumber(new verinum(integer_width-1, re = new PENumber(new verinum(integer_width-1,
integer_width)); integer_width));
@ -3797,8 +3787,7 @@ task_port_item
$$ = tmp; $$ = tmp;
} }
| K_inout K_integer list_of_identifiers ';' | K_inout K_integer list_of_identifiers ';'
{ svector<PExpr*>*range_stub { svector<PExpr*>*range_stub = new svector<PExpr*>(2);
= new svector<PExpr*>(2);
PExpr*re; PExpr*re;
re = new PENumber(new verinum(integer_width-1, re = new PENumber(new verinum(integer_width-1,
integer_width)); integer_width));
@ -3813,9 +3802,54 @@ task_port_item
$$ = tmp; $$ = 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 { svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT, = pform_make_task_ports(NetNet::PINPUT,
IVL_VT_REAL, false, IVL_VT_REAL, false,
@ -3823,7 +3857,7 @@ task_port_item
@1.text, @1.first_line); @1.text, @1.first_line);
$$ = tmp; $$ = tmp;
} }
| K_output K_real list_of_identifiers ';' | K_output real_or_realtime list_of_identifiers ';'
{ svector<PWire*>*tmp { svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT, = pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_REAL, true, IVL_VT_REAL, true,
@ -3831,7 +3865,7 @@ task_port_item
@1.text, @1.first_line); @1.text, @1.first_line);
$$ = tmp; $$ = tmp;
} }
| K_inout K_real list_of_identifiers ';' | K_inout real_or_realtime list_of_identifiers ';'
{ svector<PWire*>*tmp { svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT, = pform_make_task_ports(NetNet::PINOUT,
IVL_VT_REAL, true, IVL_VT_REAL, true,
@ -3861,50 +3895,51 @@ task_item_list_opt
task_port_decl 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.port_type = NetNet::PINPUT;
port_declaration_context.var_type = IVL_VT_LOGIC; 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; delete port_declaration_context.range;
port_declaration_context.range = copy_range($3); port_declaration_context.range = copy_range($4);
svector<PWire*>*tmp svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT, = pform_make_task_ports(NetNet::PINPUT,
IVL_VT_LOGIC, $2, IVL_VT_LOGIC, $3,
$3, list_from_identifier($4), $4, list_from_identifier($5),
@1.text, @1.first_line); @1.text, @1.first_line);
$$ = tmp; $$ = 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.port_type = NetNet::POUTPUT;
port_declaration_context.var_type = IVL_VT_LOGIC; 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; delete port_declaration_context.range;
port_declaration_context.range = copy_range($3); port_declaration_context.range = copy_range($4);
svector<PWire*>*tmp svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT, = pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_LOGIC, $2, IVL_VT_LOGIC, $3,
$3, list_from_identifier($4), $4, list_from_identifier($5),
@1.text, @1.first_line); @1.text, @1.first_line);
$$ = tmp; $$ = 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.port_type = NetNet::PINOUT;
port_declaration_context.var_type = IVL_VT_LOGIC; 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; delete port_declaration_context.range;
port_declaration_context.range = copy_range($3); port_declaration_context.range = copy_range($4);
svector<PWire*>*tmp svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT, = pform_make_task_ports(NetNet::PINOUT,
IVL_VT_LOGIC, $2, IVL_VT_LOGIC, $3,
$3, list_from_identifier($4), $4, list_from_identifier($5),
@1.text, @1.first_line); @1.text, @1.first_line);
$$ = tmp; $$ = tmp;
} }
/* Ports can be integer with a width of [31:0]. */
| K_input K_integer IDENTIFIER | K_input K_integer IDENTIFIER
{ svector<PExpr*>*range_stub { svector<PExpr*>*range_stub = new svector<PExpr*>(2);
= new svector<PExpr*>(2);
PExpr*re; PExpr*re;
re = new PENumber(new verinum(integer_width-1, re = new PENumber(new verinum(integer_width-1,
integer_width)); integer_width));
@ -3925,8 +3960,7 @@ task_port_decl
$$ = tmp; $$ = tmp;
} }
| K_output K_integer IDENTIFIER | K_output K_integer IDENTIFIER
{ svector<PExpr*>*range_stub { svector<PExpr*>*range_stub = new svector<PExpr*>(2);
= new svector<PExpr*>(2);
PExpr*re; PExpr*re;
re = new PENumber(new verinum(integer_width-1, re = new PENumber(new verinum(integer_width-1,
integer_width)); integer_width));
@ -3947,8 +3981,7 @@ task_port_decl
$$ = tmp; $$ = tmp;
} }
| K_inout K_integer IDENTIFIER | K_inout K_integer IDENTIFIER
{ svector<PExpr*>*range_stub { svector<PExpr*>*range_stub = new svector<PExpr*>(2);
= new svector<PExpr*>(2);
PExpr*re; PExpr*re;
re = new PENumber(new verinum(integer_width-1, re = new PENumber(new verinum(integer_width-1,
integer_width)); integer_width));
@ -3969,9 +4002,72 @@ task_port_decl
$$ = tmp; $$ = tmp;
} }
/* Ports can be real. */ /* Ports can be time with a width of [63:0] (unsigned). */
| 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;
}
| K_input K_real IDENTIFIER /* Ports can be real or realtime. */
| K_input real_or_realtime IDENTIFIER
{ port_declaration_context.port_type = NetNet::PINPUT; { port_declaration_context.port_type = NetNet::PINPUT;
port_declaration_context.var_type = IVL_VT_REAL; port_declaration_context.var_type = IVL_VT_REAL;
port_declaration_context.sign_flag = false; port_declaration_context.sign_flag = false;
@ -3984,7 +4080,7 @@ task_port_decl
@1.text, @1.first_line); @1.text, @1.first_line);
$$ = tmp; $$ = tmp;
} }
| K_output K_real IDENTIFIER | K_output real_or_realtime IDENTIFIER
{ port_declaration_context.port_type = NetNet::POUTPUT; { port_declaration_context.port_type = NetNet::POUTPUT;
port_declaration_context.var_type = IVL_VT_REAL; port_declaration_context.var_type = IVL_VT_REAL;
port_declaration_context.sign_flag = false; port_declaration_context.sign_flag = false;
@ -3997,7 +4093,7 @@ task_port_decl
@1.text, @1.first_line); @1.text, @1.first_line);
$$ = tmp; $$ = tmp;
} }
| K_inout K_real IDENTIFIER | K_inout real_or_realtime IDENTIFIER
{ port_declaration_context.port_type = NetNet::PINOUT; { port_declaration_context.port_type = NetNet::PINOUT;
port_declaration_context.var_type = IVL_VT_REAL; port_declaration_context.var_type = IVL_VT_REAL;
port_declaration_context.sign_flag = false; 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) 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 nany = ivl_event_nany(obj);
unsigned nneg = ivl_event_nneg(obj); unsigned nneg = ivl_event_nneg(obj);
unsigned npos = ivl_event_npos(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. */ /* Figure out how many probe functors are needed. */
if (nany > 0) if (nany > 0)
cnt += (nany+3) / 4; cnt += (nany+ntmp-1) / ntmp;
if (nneg > 0) if (nneg > 0)
cnt += (nneg+3) / 4; cnt += (nneg+ntmp-1) / ntmp;
if (npos > 0) if (npos > 0)
cnt += (npos+3) / 4; cnt += (npos+ntmp-1) / ntmp;
if (cnt == 0) { if (cnt == 0) {
/* If none are needed, then this is a named event. The /* 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 idx;
unsigned ecnt = 0; unsigned ecnt = 0;
for (idx = 0 ; idx < nany ; idx += 4, ecnt += 1) { for (idx = 0 ; idx < nany ; idx += ntmp, ecnt += 1) {
unsigned sub, top; unsigned sub, top;
fprintf(vvp_out, "E_%p/%u .event edge", obj, ecnt); top = idx + ntmp;
top = idx + 4;
if (nany < top) if (nany < top)
top = nany; top = nany;
for (sub = idx ; sub < top ; sub += 1) { for (sub = idx ; sub < top ; sub += 1) {
ivl_nexus_t nex = ivl_event_any(obj, sub); 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"); 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; unsigned sub, top;
fprintf(vvp_out, "E_%p/%u .event negedge", obj, ecnt); top = idx + ntmp;
top = idx + 4;
if (nneg < top) if (nneg < top)
top = nneg; top = nneg;
for (sub = idx ; sub < top ; sub += 1) { for (sub = idx ; sub < top ; sub += 1) {
ivl_nexus_t nex = ivl_event_neg(obj, sub); 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"); 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; unsigned sub, top;
fprintf(vvp_out, "E_%p/%u .event posedge", obj, ecnt); top = idx + ntmp;
top = idx + 4;
if (npos < top) if (npos < top)
top = npos; top = npos;
for (sub = idx ; sub < top ; sub += 1) { for (sub = idx ; sub < top ; sub += 1) {
ivl_nexus_t nex = ivl_event_pos(obj, sub); 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"); fprintf(vvp_out, ";\n");
} }
@ -981,20 +994,17 @@ static void draw_event_in_scope(ivl_event_t obj)
} else { } else {
unsigned num_input_strings = nany + nneg + npos; unsigned num_input_strings = nany + nneg + npos;
unsigned idx; unsigned idx;
ivl_nexus_t input_nexa[4];
const char*edge = 0; const char*edge = 0;
assert(num_input_strings <= 4); assert(num_input_strings <= ntmp);
if (nany > 0) { if (nany > 0) {
assert((nneg + npos) == 0); assert((nneg + npos) == 0);
assert(nany <= 4);
edge = "edge"; edge = "edge";
for (idx = 0 ; idx < nany ; idx += 1) { for (idx = 0 ; idx < nany ; idx += 1) {
ivl_nexus_t nex = ivl_event_any(obj, idx); 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) { } 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) { for (idx = 0 ; idx < nneg ; idx += 1) {
ivl_nexus_t nex = ivl_event_neg(obj, idx); 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 { } else {
@ -1012,14 +1022,14 @@ static void draw_event_in_scope(ivl_event_t obj)
for (idx = 0 ; idx < npos ; idx += 1) { for (idx = 0 ; idx < npos ; idx += 1) {
ivl_nexus_t nex = ivl_event_pos(obj, idx); 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); fprintf(vvp_out, "E_%p .event %s", obj, edge);
for (idx = 0 ; idx < num_input_strings ; idx += 1) for (idx = 0 ; idx < num_input_strings ; idx += 1) {
fprintf(vvp_out, ", %s", draw_input_from_net(input_nexa[idx])); fprintf(vvp_out, ", %s", tmp[idx]);
}
fprintf(vvp_out, ";\n"); 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> * %load/av <bit>, <array-label>, <wid>
This instruction loads a word from the specified array. The word This instruction loads a word from the specified array. The word
address is in index register 3. The width should match the width of address is in index register 3. Like %load/v below the width does
the array word. 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 <bit>, <array-label>, <wid>
* %load/avp0/s <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); 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. */ /* Check the address once, before we scan the vector. */
thr_check_addr(thr, bit+wid-1); 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 /* Copy the vector bits into the bits4 vector. Do the copy
directly to skip the excess calls to thr_check_addr. */ directly to skip the excess calls to thr_check_addr. */
thr->bits4.set_vec(bit, word); 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; return true;
} }