Tasks functions with atom2 arguments.
Parse 2-value atoms as arguments to functions and tasks.
This commit is contained in:
parent
e03ff763fb
commit
af6fd66648
4
PTask.h
4
PTask.h
|
|
@ -37,7 +37,9 @@ enum PTaskFuncEnum {
|
|||
PTF_INTEGER,
|
||||
PTF_REAL,
|
||||
PTF_REALTIME,
|
||||
PTF_TIME
|
||||
PTF_TIME,
|
||||
PTF_ATOM2,
|
||||
PTF_ATOM2_S
|
||||
};
|
||||
|
||||
struct PTaskFuncArg {
|
||||
|
|
|
|||
59
elab_sig.cc
59
elab_sig.cc
|
|
@ -69,6 +69,15 @@ static bool get_const_argument(NetExpr*exp, verinum&res)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool get_const_argument(NetExpr*exp, long&res)
|
||||
{
|
||||
verinum tmp;
|
||||
bool rc = get_const_argument(exp, tmp);
|
||||
if (rc == false) return false;
|
||||
res = tmp.as_long();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Statement::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
}
|
||||
|
|
@ -472,18 +481,14 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
need_constant_expr = false;
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(me)) {
|
||||
mnum = tmp->value().as_long();
|
||||
} else {
|
||||
if ( ! get_const_argument(me, mnum) ) {
|
||||
cerr << me->get_fileline() << ": error: "
|
||||
"Unable to evaluate constant expression "
|
||||
<< *me << "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(le)) {
|
||||
lnum = tmp->value().as_long();
|
||||
} else {
|
||||
if ( ! get_const_argument(le, lnum) ) {
|
||||
cerr << le->get_fileline() << ": error: "
|
||||
"Unable to evaluate constant expression "
|
||||
<< *le << "." << endl;
|
||||
|
|
@ -534,6 +539,48 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
ret_sig->data_type(IVL_VT_REAL);
|
||||
break;
|
||||
|
||||
case PTF_ATOM2:
|
||||
case PTF_ATOM2_S:
|
||||
ivl_assert(*this, return_type_.range != 0);
|
||||
probe_expr_width(des, scope, (*return_type_.range)[0]);
|
||||
probe_expr_width(des, scope, (*return_type_.range)[1]);
|
||||
long use_wid;
|
||||
{
|
||||
need_constant_expr = true;
|
||||
NetExpr*me = elab_and_eval(des, scope,
|
||||
(*return_type_.range)[0], -1);
|
||||
assert(me);
|
||||
NetExpr*le = elab_and_eval(des, scope,
|
||||
(*return_type_.range)[1], -1);
|
||||
assert(le);
|
||||
need_constant_expr = false;
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if ( ! get_const_argument(me, mnum) ) {
|
||||
cerr << me->get_fileline() << ": error: "
|
||||
"Unable to evaluate constant expression "
|
||||
<< *me << "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if ( ! get_const_argument(le, lnum) ) {
|
||||
cerr << le->get_fileline() << ": error: "
|
||||
"Unable to evaluate constant expression "
|
||||
<< *le << "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
use_wid = mnum - lnum + 1;
|
||||
}
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG, use_wid);
|
||||
ret_sig->set_line(*this);
|
||||
ret_sig->set_signed(return_type_.type == PTF_ATOM2_S? true : false);
|
||||
ret_sig->set_isint(true);
|
||||
ret_sig->set_scalar(false);
|
||||
ret_sig->port_type(NetNet::POUTPUT);
|
||||
ret_sig->data_type(IVL_VT_BOOL);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (ports_) {
|
||||
cerr << get_fileline() << ": internal error: I don't know "
|
||||
|
|
|
|||
219
parse.y
219
parse.y
|
|
@ -106,6 +106,16 @@ static list<pair<perm_string,PExpr*> >* make_port_list(list<pair<perm_string,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
static svector<PExpr*>* make_range_from_width(uint64_t wid)
|
||||
{
|
||||
svector<PExpr*>*range = new svector<PExpr*>(2);
|
||||
|
||||
(*range)[0] = new PENumber(new verinum(wid-1, integer_width));
|
||||
(*range)[1] = new PENumber(new verinum((uint64_t)0, integer_width));
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
static list<perm_string>* list_from_identifier(char*id)
|
||||
{
|
||||
list<perm_string>*tmp = new list<perm_string>;
|
||||
|
|
@ -167,6 +177,7 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
|
|||
bool flag;
|
||||
|
||||
char letter;
|
||||
int int_val;
|
||||
|
||||
/* text items are C strings allocated by the lexor using
|
||||
strdup. They can be put into lists with the texts type. */
|
||||
|
|
@ -394,6 +405,8 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
|
|||
%type <specpath> specify_simple_path specify_simple_path_decl
|
||||
%type <specpath> specify_edge_path specify_edge_path_decl
|
||||
|
||||
%type <int_val> atom2_type
|
||||
|
||||
%token K_TAND
|
||||
%right '?' ':'
|
||||
%left K_LOR
|
||||
|
|
@ -531,23 +544,8 @@ block_item_decl
|
|||
if ($1) delete $1;
|
||||
}
|
||||
|
||||
| attribute_list_opt K_byte signed_unsigned_opt register_variable_list ';'
|
||||
{ pform_set_integer_2atom(8, $3, $4);
|
||||
if ($1) delete $1;
|
||||
}
|
||||
|
||||
| attribute_list_opt K_shortint signed_unsigned_opt register_variable_list ';'
|
||||
{ pform_set_integer_2atom(16, $3, $4);
|
||||
if ($1) delete $1;
|
||||
}
|
||||
|
||||
| attribute_list_opt K_int signed_unsigned_opt register_variable_list ';'
|
||||
{ pform_set_integer_2atom(32, $3, $4);
|
||||
if ($1) delete $1;
|
||||
}
|
||||
|
||||
| attribute_list_opt K_longint signed_unsigned_opt register_variable_list ';'
|
||||
{ pform_set_integer_2atom(64, $3, $4);
|
||||
| attribute_list_opt atom2_type signed_unsigned_opt register_variable_list ';'
|
||||
{ pform_set_integer_2atom($2, $3, $4);
|
||||
if ($1) delete $1;
|
||||
}
|
||||
|
||||
|
|
@ -2024,6 +2022,17 @@ signed_unsigned_opt
|
|||
| { $$ = true; }
|
||||
;
|
||||
|
||||
/*
|
||||
* In some places we can take any of the 4 2-value atom-type
|
||||
* names. All the context needs to know if that type is its width.
|
||||
*/
|
||||
atom2_type
|
||||
: K_byte { $$ = 8; }
|
||||
| K_shortint { $$ = 16; }
|
||||
| K_int { $$ = 32; }
|
||||
| K_longint { $$ = 64; }
|
||||
;
|
||||
|
||||
/* An lpvalue is the expression that can go on the left side of a
|
||||
procedural assignment. This rule handles only procedural
|
||||
assignments. It is more limited then the general expr_primary
|
||||
|
|
@ -2680,10 +2689,11 @@ net_decl_assigns
|
|||
;
|
||||
|
||||
primitive_type
|
||||
: K_logic { $$ = IVL_VT_LOGIC; }
|
||||
| K_bool { $$ = IVL_VT_BOOL; }
|
||||
| K_real { $$ = IVL_VT_REAL; }
|
||||
;
|
||||
: K_logic { $$ = IVL_VT_LOGIC; }
|
||||
| K_bool { $$ = IVL_VT_BOOL; /* Icarus Verilog xtypes */}
|
||||
| K_bit { $$ = IVL_VT_BOOL; /* IEEE1800 / IEEE1364-2009 */}
|
||||
| K_real { $$ = IVL_VT_REAL; }
|
||||
;
|
||||
|
||||
primitive_type_opt : primitive_type { $$ = $1; } | { $$ = IVL_VT_NO_TYPE; } ;
|
||||
|
||||
|
|
@ -3236,14 +3246,17 @@ dimensions
|
|||
|
||||
/* This is used to express the return type of a function. */
|
||||
function_range_or_type_opt
|
||||
: range { $$.range = $1; $$.type = PTF_REG; }
|
||||
| K_signed range { $$.range = $2; $$.type = PTF_REG_S; }
|
||||
| K_integer { $$.range = 0; $$.type = PTF_INTEGER; }
|
||||
| K_real { $$.range = 0; $$.type = PTF_REAL; }
|
||||
| K_realtime { $$.range = 0; $$.type = PTF_REALTIME; }
|
||||
| K_time { $$.range = 0; $$.type = PTF_TIME; }
|
||||
| { $$.range = 0; $$.type = PTF_REG; }
|
||||
;
|
||||
: range { $$.range = $1; $$.type = PTF_REG; }
|
||||
| K_signed range { $$.range = $2; $$.type = PTF_REG_S; }
|
||||
| K_integer { $$.range = 0; $$.type = PTF_INTEGER; }
|
||||
| K_real { $$.range = 0; $$.type = PTF_REAL; }
|
||||
| K_realtime { $$.range = 0; $$.type = PTF_REALTIME; }
|
||||
| K_time { $$.range = 0; $$.type = PTF_TIME; }
|
||||
| atom2_type { $$.range = make_range_from_width($1); $$.type = PTF_ATOM2_S; }
|
||||
| atom2_type K_signed { $$.range = make_range_from_width($1); $$.type = PTF_ATOM2_S; }
|
||||
| atom2_type K_unsigned { $$.range = make_range_from_width($1); $$.type = PTF_ATOM2; }
|
||||
| { $$.range = 0; $$.type = PTF_REG; }
|
||||
;
|
||||
|
||||
/* The register_variable rule is matched only when I am parsing
|
||||
variables in a "reg" definition. I therefore know that I am
|
||||
|
|
@ -4356,66 +4369,48 @@ task_port_decl
|
|||
|
||||
/* 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_time IDENTIFIER
|
||||
{ svector<PExpr*>*range_stub = make_range_from_width(64);
|
||||
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 = make_range_from_width(64);
|
||||
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 = make_range_from_width(64);
|
||||
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. */
|
||||
|
||||
|
|
@ -4458,7 +4453,51 @@ task_port_decl
|
|||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
/* Ports can be 2-value atom types. */
|
||||
|
||||
| K_input atom2_type signed_unsigned_opt IDENTIFIER
|
||||
{ svector<PExpr*>*range_stub = make_range_from_width($2);
|
||||
port_declaration_context.port_type = NetNet::PINPUT;
|
||||
port_declaration_context.var_type = IVL_VT_BOOL;
|
||||
port_declaration_context.sign_flag = $3;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range(range_stub);
|
||||
svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINPUT,
|
||||
IVL_VT_BOOL, $3,
|
||||
range_stub, list_from_identifier($4),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
| K_output atom2_type signed_unsigned_opt IDENTIFIER
|
||||
{ svector<PExpr*>*range_stub = make_range_from_width($2);
|
||||
port_declaration_context.port_type = NetNet::POUTPUT;
|
||||
port_declaration_context.var_type = IVL_VT_BOOL;
|
||||
port_declaration_context.sign_flag = $3;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range(range_stub);
|
||||
svector<PWire*>*tmp = pform_make_task_ports(NetNet::POUTPUT,
|
||||
IVL_VT_BOOL, $3,
|
||||
range_stub, list_from_identifier($4),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
| K_inout atom2_type signed_unsigned_opt IDENTIFIER
|
||||
{ svector<PExpr*>*range_stub = make_range_from_width($2);
|
||||
port_declaration_context.port_type = NetNet::PINOUT;
|
||||
port_declaration_context.var_type = IVL_VT_BOOL;
|
||||
port_declaration_context.sign_flag = $3;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range(range_stub);
|
||||
svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINOUT,
|
||||
IVL_VT_BOOL, $3,
|
||||
range_stub, list_from_identifier($4),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
task_port_decl_list
|
||||
: task_port_decl_list ',' task_port_decl
|
||||
|
|
|
|||
|
|
@ -55,6 +55,12 @@ static void function_argument_real(ivl_signal_t port, ivl_expr_t expr)
|
|||
clr_word(res);
|
||||
}
|
||||
|
||||
static void function_argument_bool(ivl_signal_t port, ivl_expr_t expr)
|
||||
{
|
||||
/* For now, treat bit2 variables as bit4 variables. */
|
||||
function_argument_logic(port, expr);
|
||||
}
|
||||
|
||||
static void draw_function_argument(ivl_signal_t port, ivl_expr_t expr)
|
||||
{
|
||||
ivl_variable_type_t dtype = ivl_signal_data_type(port);
|
||||
|
|
@ -65,6 +71,9 @@ static void draw_function_argument(ivl_signal_t port, ivl_expr_t expr)
|
|||
case IVL_VT_REAL:
|
||||
function_argument_real(port, expr);
|
||||
break;
|
||||
case IVL_VT_BOOL:
|
||||
function_argument_bool(port, expr);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "XXXX function argument %s type=%d?!\n",
|
||||
ivl_signal_basename(port), dtype);
|
||||
|
|
|
|||
Loading…
Reference in New Issue