Support SystemVerilog types for non-ansi task port declarations
Tasks and functions support two types of port declarations. Either ANSI style, in parenthesis after the task name, or non-ANSI style, as declaration statements in the task body. In the current implementation SystemVerilog types are only accept for ANSI style port declarations, while non-ANSI style only accept Verilog types (reg, integer, time, real). Add support for SystemVerilog data types for non-ansi style ports. This also makes the parsing rules simpler since we can use `data_type` to match all data types and don't need a explicit rule for each supported data type. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
parent
cc0a8c8dd2
commit
c631ff2483
55
parse.y
55
parse.y
|
|
@ -590,7 +590,7 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
|
|||
%type <number> number pos_neg_number
|
||||
%type <flag> signing unsigned_signed_opt signed_unsigned_opt
|
||||
%type <flag> import_export
|
||||
%type <flag> K_genvar_opt K_reg_opt K_static_opt K_virtual_opt
|
||||
%type <flag> K_genvar_opt K_static_opt K_virtual_opt
|
||||
%type <flag> udp_reg_opt edge_operator
|
||||
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
||||
%type <letter> udp_input_sym udp_output_sym
|
||||
|
|
@ -2104,13 +2104,6 @@ random_qualifier /* IEEE1800-2005 A.1.8 */
|
|||
| K_randc { $$ = property_qualifier_t::make_randc(); }
|
||||
;
|
||||
|
||||
/* real and realtime are exactly the same so save some code
|
||||
* with a common matching rule. */
|
||||
real_or_realtime
|
||||
: K_real
|
||||
| K_realtime
|
||||
;
|
||||
|
||||
signing /* IEEE1800-2005: A.2.2.1 */
|
||||
: K_signed { $$ = true; }
|
||||
| K_unsigned { $$ = false; }
|
||||
|
|
@ -2353,50 +2346,9 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
|||
|
||||
|
||||
tf_port_declaration /* IEEE1800-2005: A.2.7 */
|
||||
: port_direction K_reg_opt unsigned_signed_opt dimensions_opt list_of_identifiers ';'
|
||||
{ std::vector<pform_tf_port_t>*tmp = pform_make_task_ports(@1, $1,
|
||||
$2 ? IVL_VT_LOGIC :
|
||||
IVL_VT_NO_TYPE,
|
||||
$3, $4, $5);
|
||||
$$ = tmp;
|
||||
: port_direction data_type_or_implicit list_of_identifiers ';'
|
||||
{ $$ = pform_make_task_ports(@1, $1, $2, $3, true);
|
||||
}
|
||||
|
||||
/* When the port is an integer, infer a signed vector of the integer
|
||||
shape. Generate a range ([31:0]) to make it work. */
|
||||
|
||||
| port_direction K_integer list_of_identifiers ';'
|
||||
{ std::list<pform_range_t>*range_stub = make_range_from_width(integer_width);
|
||||
vector<pform_tf_port_t>*tmp = pform_make_task_ports(@1, $1, IVL_VT_LOGIC, true,
|
||||
range_stub, $3, true);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/* Ports can be time with a width of [63:0] (unsigned). */
|
||||
|
||||
| port_direction K_time list_of_identifiers ';'
|
||||
{ std::list<pform_range_t>*range_stub = make_range_from_width(64);
|
||||
vector<pform_tf_port_t>*tmp = pform_make_task_ports(@1, $1, IVL_VT_LOGIC, false,
|
||||
range_stub, $3);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/* Ports can be real or realtime. */
|
||||
|
||||
| port_direction real_or_realtime list_of_identifiers ';'
|
||||
{ std::vector<pform_tf_port_t>*tmp = pform_make_task_ports(@1, $1, IVL_VT_REAL, true,
|
||||
0, $3);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
|
||||
/* Ports can be string. */
|
||||
|
||||
| port_direction K_string list_of_identifiers ';'
|
||||
{ std::vector<pform_tf_port_t>*tmp = pform_make_task_ports(@1, $1, IVL_VT_STRING, true,
|
||||
0, $3);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
|
||||
|
|
@ -7244,6 +7196,5 @@ unique_priority
|
|||
collect those rules here. */
|
||||
|
||||
K_genvar_opt : K_genvar { $$ = true; } | { $$ = false; } ;
|
||||
K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ;
|
||||
K_static_opt : K_static { $$ = true; } | { $$ = false; } ;
|
||||
K_virtual_opt : K_virtual { $$ = true; } | { $$ = false; } ;
|
||||
|
|
|
|||
23
pform.cc
23
pform.cc
|
|
@ -2923,13 +2923,13 @@ void pform_makewire(const struct vlltype&li,
|
|||
* constraints as those of tasks, so this works fine. Functions have
|
||||
* no output or inout ports.
|
||||
*/
|
||||
vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t vtype,
|
||||
bool signed_flag,
|
||||
list<pform_range_t>*range,
|
||||
list<perm_string>*names,
|
||||
bool isint)
|
||||
static vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t vtype,
|
||||
bool signed_flag,
|
||||
list<pform_range_t>*range,
|
||||
list<perm_string>*names,
|
||||
bool isint = false)
|
||||
{
|
||||
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
|
||||
assert(names);
|
||||
|
|
@ -2999,7 +2999,8 @@ static vector<pform_tf_port_t>*do_make_task_ports(const struct vlltype&loc,
|
|||
vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
||||
NetNet::PortType pt,
|
||||
data_type_t*vtype,
|
||||
list<perm_string>*names)
|
||||
list<perm_string>*names,
|
||||
bool allow_implicit)
|
||||
{
|
||||
vector<pform_tf_port_t>*ret = NULL;
|
||||
std::list<pform_range_t>*unpacked_dims = NULL;
|
||||
|
|
@ -3017,7 +3018,11 @@ vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
|||
}
|
||||
|
||||
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (vtype)) {
|
||||
ret = pform_make_task_ports(loc, pt, vec_type->base_type,
|
||||
ivl_variable_type_t base_type = vec_type->base_type;
|
||||
if (allow_implicit && vec_type->implicit_flag)
|
||||
base_type = IVL_VT_NO_TYPE;
|
||||
|
||||
ret = pform_make_task_ports(loc, pt, base_type,
|
||||
vec_type->signed_flag,
|
||||
copy_range(vec_type->pdims.get()),
|
||||
names, vec_type->integer_flag);
|
||||
|
|
|
|||
13
pform.h
13
pform.h
|
|
@ -492,20 +492,11 @@ extern void pform_make_pgassign_list(std::list<PExpr*>*alist,
|
|||
struct str_pair_t str,
|
||||
const char* fn, unsigned lineno);
|
||||
|
||||
/* Given a port type and a list of names, make a list of wires that
|
||||
can be used as task port information. */
|
||||
extern std::vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t vtype,
|
||||
bool signed_flag,
|
||||
std::list<pform_range_t>*range,
|
||||
std::list<perm_string>*names,
|
||||
bool isint = false);
|
||||
|
||||
extern std::vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
||||
NetNet::PortType pt,
|
||||
data_type_t*vtype,
|
||||
std::list<perm_string>*names);
|
||||
std::list<perm_string>*names,
|
||||
bool allow_implicit = false);
|
||||
|
||||
/*
|
||||
* The parser uses this function to convert a unary
|
||||
|
|
|
|||
Loading…
Reference in New Issue