diff --git a/parse.y b/parse.y index 950910368..b7f880b8c 100644 --- a/parse.y +++ b/parse.y @@ -352,6 +352,13 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vectorset_statement(tmp); } +static void port_declaration_context_init(void) +{ + port_declaration_context.port_type = NetNet::PINOUT; + port_declaration_context.port_net_type = NetNet::IMPLICIT; + port_declaration_context.data_type = nullptr; +} + Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, NetNet::PortType port_type, NetNet::Type net_type, @@ -705,6 +712,7 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, %type list_of_variable_decl_assignments %type data_type data_type_opt data_type_or_implicit data_type_or_implicit_or_void +%type data_type_or_implicit_no_opt %type simple_type_or_string let_formal_type %type packed_array_data_type %type ps_type_identifier @@ -1337,7 +1345,11 @@ scalar_vector_opt /*IEEE1800-2005: optional support for packed array */ ; data_type_or_implicit /* IEEE1800-2005: A.2.2.1 */ - : data_type_opt + : data_type_or_implicit_no_opt + | { $$ = nullptr; } + +data_type_or_implicit_no_opt + : data_type { $$ = $1; } | signing dimensions_opt { vector_type_t*tmp = new vector_type_t(IVL_VT_LOGIC, $1, $2); @@ -4466,39 +4478,16 @@ list_of_port_declarations tmp->push_back($3); $$ = tmp; } - | list_of_port_declarations ',' IDENTIFIER initializer_opt - { Module::port_t*ptmp; - perm_string name = lex_strings.make($3); - ptmp = pform_module_port_reference(@3, name); - std::vector*tmp = $1; - tmp->push_back(ptmp); + | list_of_port_declarations ',' attribute_list_opt IDENTIFIER dimensions_opt initializer_opt + { std::vector *ports = $1; - if ($4) { - switch (port_declaration_context.port_type) { - case NetNet::PINOUT: - yyerror(@4, "error: Default port value not allowed for inout ports."); - break; - case NetNet::PINPUT: - pform_requires_sv(@4, "Default port value"); - ptmp->default_value = $4; - break; - case NetNet::POUTPUT: - pform_make_var_init(@3, name, $4); - break; - default: - break; - } - } - /* Get the port declaration details, the port type - and what not, from context data stored by the - last port_declaration rule. */ - pform_module_define_port(@3, name, - port_declaration_context.port_type, - port_declaration_context.port_net_type, - port_declaration_context.data_type, - nullptr, nullptr); - delete[]$3; - $$ = tmp; + Module::port_t* port; + port = module_declare_port(@4, $4, port_declaration_context.port_type, + port_declaration_context.port_net_type, + port_declaration_context.data_type, + $5, $6, $3); + ports->push_back(port); + $$ = ports; } | list_of_port_declarations ',' { yyerror(@2, "error: Superfluous comma in port declaration list."); } @@ -4506,9 +4495,21 @@ list_of_port_declarations { yyerror(@2, "error: ';' is an invalid port declaration separator."); } ; + // All of port direction, port kind and data type are optional, but at least + // one has to be specified, so we need multiple rules. port_declaration : attribute_list_opt port_direction net_type_or_var_opt data_type_or_implicit IDENTIFIER dimensions_opt initializer_opt - { $$ = module_declare_port(@2, $5, $2, $3, $4, $6, $7, $1); + { $$ = module_declare_port(@5, $5, $2, $3, $4, $6, $7, $1); + } + | attribute_list_opt net_type_or_var data_type_or_implicit IDENTIFIER dimensions_opt initializer_opt + { pform_requires_sv(@4, "Partial ANSI port declaration"); + $$ = module_declare_port(@4, $4, port_declaration_context.port_type, + $2, $3, $5, $6, $1); + } + | attribute_list_opt data_type_or_implicit_no_opt IDENTIFIER dimensions_opt initializer_opt + { pform_requires_sv(@3, "Partial ANSI port declaration"); + $$ = module_declare_port(@3, $3, port_declaration_context.port_type, + NetNet::IMPLICIT, $2, $4, $5, $1); } | attribute_list_opt port_direction K_wreal IDENTIFIER { real_type_t*real_type = new real_type_t(real_type_t::REAL); @@ -4613,7 +4614,8 @@ cont_assign_list module : attribute_list_opt module_start lifetime_opt IDENTIFIER - { pform_startmodule(@2, $4, $2==K_program, $2==K_interface, $3, $1); } + { pform_startmodule(@2, $4, $2==K_program, $2==K_interface, $3, $1); + port_declaration_context_init(); } module_package_import_list_opt module_parameter_port_list_opt module_port_list_opt