User defined functions can have ANSI-style ports
Update the rules for parsing user function definitions to allow Verilog-2001 ANSI style port declarations. In the process, also unify with the user task port declaration so that the types don't diverge. The rules are the same for both, with the extra constraint that function ports must all be input. This latter rule is checked later, during elaboration, so that the task/function pform code can be shared, and better error messages can be generated.
This commit is contained in:
parent
54918cf5b9
commit
bdab7698d2
20
elab_sig.cc
20
elab_sig.cc
|
|
@ -593,6 +593,8 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
perm_string pname = (*ports_)[idx]->basename();
|
||||
|
||||
NetNet*tmp = scope->find_signal(pname);
|
||||
ports[idx] = 0;
|
||||
|
||||
if (tmp == 0) {
|
||||
cerr << get_fileline() << ": internal error: function "
|
||||
<< scope_path(scope) << " is missing port "
|
||||
|
|
@ -600,9 +602,27 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
scope->dump(cerr);
|
||||
cerr << get_fileline() << ": Continuing..." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tmp->port_type() == NetNet::NOT_A_PORT) {
|
||||
cerr << get_fileline() << ": internal error: function "
|
||||
<< scope_path(scope) << " port " << pname
|
||||
<< " is a port but is not a port?" << endl;
|
||||
des->errors += 1;
|
||||
scope->dump(cerr);
|
||||
continue;
|
||||
}
|
||||
|
||||
ports[idx] = tmp;
|
||||
if (tmp->port_type() != NetNet::PINPUT) {
|
||||
cerr << tmp->get_fileline() << ": error: function "
|
||||
<< scope_path(scope) << " port " << pname
|
||||
<< " is not an input port." << endl;
|
||||
cerr << tmp->get_fileline() << ": : Function arguments "
|
||||
<< "must be input ports." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
101
parse.y
101
parse.y
|
|
@ -1097,76 +1097,9 @@ expr_primary
|
|||
}
|
||||
;
|
||||
|
||||
/* A function_item is either a block item (i.e. a reg or integer
|
||||
declaration) or an input declaration. There are no output or
|
||||
inout ports. */
|
||||
function_item
|
||||
: K_input signed_opt range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT,
|
||||
IVL_VT_NO_TYPE, $2,
|
||||
$3, $4,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_output signed_opt range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT,
|
||||
IVL_VT_NO_TYPE, $2,
|
||||
$3, $4,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
yyerror(@1, "Functions may not have output ports.");
|
||||
}
|
||||
| K_inout signed_opt range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT,
|
||||
IVL_VT_NO_TYPE, $2,
|
||||
$3, $4,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
yyerror(@1, "Functions may not have inout ports.");
|
||||
}
|
||||
|
||||
/* When the port is an integer, infer a signed vector of the integer
|
||||
shape. Generate a range to make it work. */
|
||||
|
||||
| K_input K_integer list_of_identifiers ';'
|
||||
{ svector<PExpr*>*range_stub
|
||||
= new svector<PExpr*>(2);
|
||||
PExpr*re;
|
||||
re = new PENumber(new verinum(integer_width-1,
|
||||
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, true,
|
||||
range_stub, $3,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/* Ports can be real. */
|
||||
|
||||
| K_input K_real list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT,
|
||||
IVL_VT_REAL, false,
|
||||
0, $3,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
| block_item_decl
|
||||
{ $$ = 0; }
|
||||
;
|
||||
|
||||
/* A function_item_list only lists the input/output/inout
|
||||
declarations. The integer and reg declarations are handled in
|
||||
place, so are not listed. The list builder needs to account for
|
||||
the possibility that the various parts may be NULL. */
|
||||
/* A function_item_list borrows the task_port_item run to match
|
||||
declarations of ports. We check later to make sure there are no
|
||||
output or inout ports actually used. */
|
||||
function_item_list
|
||||
: function_item
|
||||
{ $$ = $1; }
|
||||
|
|
@ -1184,6 +1117,13 @@ function_item_list
|
|||
}
|
||||
;
|
||||
|
||||
function_item
|
||||
: task_port_item
|
||||
{ $$ = $1; }
|
||||
| block_item_decl
|
||||
{ $$ = 0; }
|
||||
;
|
||||
|
||||
/* A gate_instance is a module instantiation or a built in part
|
||||
type. In any case, the gate has a set of connections to ports. */
|
||||
gate_instance
|
||||
|
|
@ -1865,7 +1805,7 @@ module_item
|
|||
FILE_NAME(current_task, @1);
|
||||
}
|
||||
'(' task_port_decl_list ')' ';'
|
||||
task_item_list_opt
|
||||
block_item_decls_opt
|
||||
statement_or_null
|
||||
K_endtask
|
||||
{ current_task->set_ports($5);
|
||||
|
|
@ -1895,6 +1835,23 @@ module_item
|
|||
delete[]$3;
|
||||
}
|
||||
|
||||
| K_function function_range_or_type_opt IDENTIFIER
|
||||
{ assert(current_function == 0);
|
||||
current_function = pform_push_function_scope($3);
|
||||
FILE_NAME(current_function, @1);
|
||||
}
|
||||
'(' task_port_decl_list ')' ';'
|
||||
block_item_decls_opt
|
||||
statement
|
||||
K_endfunction
|
||||
{ current_function->set_ports($6);
|
||||
current_function->set_statement($10);
|
||||
current_function->set_return($2);
|
||||
pform_pop_scope();
|
||||
current_function = 0;
|
||||
delete[]$3;
|
||||
}
|
||||
|
||||
/* A generate region can contain further module items. Actually, it
|
||||
is supposed to be limited to certain kinds of module items, but
|
||||
the semantic tests will check that for us. */
|
||||
|
|
@ -3312,7 +3269,7 @@ task_port_item
|
|||
: K_input signed_opt range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT,
|
||||
IVL_VT_LOGIC, $2,
|
||||
IVL_VT_NO_TYPE, $2,
|
||||
$3, $4,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
|
|
|
|||
Loading…
Reference in New Issue