diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index fe86626b8..feff2d0aa 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -53,6 +53,8 @@ YOSYS_NAMESPACE_BEGIN namespace VERILOG_FRONTEND { int port_counter; dict port_stubs; + dict port_alias_assigns; + std::vector port_alias_wires; dict *attr_list, default_attr_list; std::stack *> attr_list_stack; dict *albuf; @@ -585,6 +587,8 @@ module: ast_stack.push_back(mod); current_ast_mod = mod; port_stubs.clear(); + port_alias_wires.clear(); + port_alias_assigns.clear(); port_counter = 0; mod->str = *$4; append_attr(mod, $1); @@ -592,6 +596,22 @@ module: if (port_stubs.size() != 0) frontend_verilog_yyerror("Missing details for module port `%s'.", port_stubs.begin()->first.c_str()); + AstNode *mod = ast_stack.back(); + for (auto alias_wire: port_alias_wires) { + AstNode *wire = new AstNode(AST_WIRE); + wire->str = alias_wire; + mod->children.push_back(wire); + } + for (auto alias: port_alias_assigns) { + AstNode *assign = new AstNode(AST_ASSIGN); + AstNode *lhs = new AstNode(AST_IDENTIFIER); + lhs->str = alias.first; + assign->children.push_back(lhs); + AstNode *rhs = new AstNode(AST_IDENTIFIER); + rhs->str = alias.second; + assign->children.push_back(rhs); + mod->children.push_back(assign); + } SET_AST_NODE_LOC(ast_stack.back(), @2, @$); ast_stack.pop_back(); log_assert(ast_stack.size() == 1); @@ -669,6 +689,14 @@ module_arg: } delete $1; } module_arg_opt_assignment | + '.' TOK_ID '(' TOK_ID { + port_alias_assigns[*$4] = *$2; + port_alias_wires.push_back(*$4); + port_stubs[*$2] = ++port_counter; + port_stubs[*$4] = port_counter; + delete $2; + delete $4; + } ')' | TOK_ID { astbuf1 = new AstNode(AST_INTERFACEPORT); astbuf1->children.push_back(new AstNode(AST_INTERFACEPORTTYPE)); @@ -2088,6 +2116,21 @@ wire_name: frontend_verilog_yyerror("Input port `%s' is declared as register.", $1->c_str()); node->port_id = port_stubs[*$1]; port_stubs.erase(*$1); + // handle port aliases + for (auto port : port_stubs) { + if (port.second == node->port_id) { + // this port stub is the alias name, so set it + node->str = port.first.c_str(); + port_stubs.erase(port.first); + // if the node is an output, we have to swap the + // left and right hand side of the alias wire assignment + if (node->is_output) { + auto rhs = port_alias_assigns[*$1]; + port_alias_assigns.erase(*$1); + port_alias_assigns[rhs] = *$1; + } + } + } } else { if (node->is_input || node->is_output) frontend_verilog_yyerror("Module port `%s' is not declared in module header.", $1->c_str());