aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/verilog/verilog_parser.y
diff options
context:
space:
mode:
Diffstat (limited to 'frontends/verilog/verilog_parser.y')
-rw-r--r--frontends/verilog/verilog_parser.y124
1 files changed, 86 insertions, 38 deletions
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index 621b6cc18..e7c3578c7 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
@@ -36,7 +36,7 @@
%{
#include <list>
#include <string.h>
-#include "verilog_frontend.h"
+#include "frontends/verilog/verilog_frontend.h"
#include "kernel/log.h"
USING_YOSYS_NAMESPACE
@@ -57,7 +57,7 @@ namespace VERILOG_FRONTEND {
std::vector<char> case_type_stack;
bool do_not_require_port_stubs;
bool default_nettype_wire;
- bool sv_mode;
+ bool sv_mode, formal_mode;
std::istream *lexin;
}
YOSYS_NAMESPACE_END
@@ -102,6 +102,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)
%token <string> TOK_STRING TOK_ID TOK_CONST TOK_REALVAL TOK_PRIMITIVE
%token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
+%token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP
%token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG
%token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL
%token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR TOK_WHILE TOK_REPEAT
@@ -111,7 +112,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)
%token TOK_GENERATE TOK_ENDGENERATE TOK_GENVAR TOK_REAL
%token TOK_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE
%token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED
-%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_PROPERTY
+%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_ASSUME TOK_PROPERTY
%type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
@@ -139,6 +140,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)
%%
input: {
+ ast_stack.clear();
ast_stack.push_back(current_ast);
} design {
ast_stack.pop_back();
@@ -152,6 +154,9 @@ design:
module design |
defattr design |
task_func_decl design |
+ param_decl design |
+ localparam_decl design |
+ package design |
/* empty */;
attr:
@@ -209,6 +214,14 @@ hierarchical_id:
TOK_ID {
$$ = $1;
} |
+ hierarchical_id TOK_PACKAGESEP TOK_ID {
+ if ($3->substr(0, 1) == "\\")
+ *$1 += "::" + $3->substr(1);
+ else
+ *$1 += "::" + *$3;
+ delete $3;
+ $$ = $1;
+ } |
hierarchical_id '.' TOK_ID {
if ($3->substr(0, 1) == "\\")
*$1 += "." + $3->substr(1);
@@ -243,11 +256,10 @@ module_para_opt:
'#' '(' { astbuf1 = nullptr; } module_para_list { if (astbuf1) delete astbuf1; } ')' | /* empty */;
module_para_list:
- single_module_para |
- single_module_para ',' module_para_list |
- /* empty */;
+ single_module_para | module_para_list ',' single_module_para;
single_module_para:
+ /* empty */ |
TOK_PARAMETER {
if (astbuf1) delete astbuf1;
astbuf1 = new AstNode(AST_PARAMETER);
@@ -299,7 +311,7 @@ module_arg:
node->children.push_back($3);
if (!node->is_input && !node->is_output)
frontend_verilog_yyerror("Module port `%s' is neither input nor output.", $4->c_str());
- if (node->is_reg && node->is_input && !node->is_output)
+ if (node->is_reg && node->is_input && !node->is_output && !sv_mode)
frontend_verilog_yyerror("Input port `%s' is declared as register.", $4->c_str());
ast_stack.back()->children.push_back(node);
append_attr(node, $1);
@@ -309,10 +321,36 @@ module_arg:
do_not_require_port_stubs = true;
};
+package:
+ attr TOK_PACKAGE TOK_ID {
+ AstNode *mod = new AstNode(AST_PACKAGE);
+ ast_stack.back()->children.push_back(mod);
+ ast_stack.push_back(mod);
+ current_ast_mod = mod;
+ mod->str = *$3;
+ append_attr(mod, $1);
+ } ';' package_body TOK_ENDPACKAGE {
+ ast_stack.pop_back();
+ current_ast_mod = NULL;
+ };
+
+package_body:
+ package_body package_body_stmt |;
+
+package_body_stmt:
+ localparam_decl;
+
+non_opt_delay:
+ '#' '(' expr ')' { delete $3; } |
+ '#' '(' expr ':' expr ':' expr ')' { delete $3; delete $5; delete $7; };
+
+delay:
+ non_opt_delay | /* empty */;
+
wire_type:
{
astbuf3 = new AstNode(AST_WIRE);
- } wire_type_token_list {
+ } wire_type_token_list delay {
$$ = astbuf3;
};
@@ -700,6 +738,8 @@ wire_name_and_opt_assign:
wire_name:
TOK_ID range_or_multirange {
+ if (astbuf1 == nullptr)
+ frontend_verilog_yyerror("Syntax error.");
AstNode *node = astbuf1->clone();
node->str = *$1;
append_attr_clone(node, albuf);
@@ -724,7 +764,7 @@ wire_name:
if (port_stubs.count(*$1) != 0) {
if (!node->is_input && !node->is_output)
frontend_verilog_yyerror("Module port `%s' is neither input nor output.", $1->c_str());
- if (node->is_reg && node->is_input && !node->is_output)
+ if (node->is_reg && node->is_input && !node->is_output && !sv_mode)
frontend_verilog_yyerror("Input port `%s' is declared as register.", $1->c_str());
node->port_id = port_stubs[*$1];
port_stubs.erase(*$1);
@@ -741,13 +781,13 @@ wire_name:
};
assign_stmt:
- TOK_ASSIGN assign_expr_list ';';
+ TOK_ASSIGN delay assign_expr_list ';';
assign_expr_list:
assign_expr | assign_expr_list ',' assign_expr;
assign_expr:
- expr '=' expr {
+ lvalue '=' expr {
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, $1, $3));
};
@@ -761,7 +801,7 @@ cell_stmt:
} cell_parameter_list_opt cell_list ';' {
delete astbuf1;
} |
- attr tok_prim_wrapper {
+ attr tok_prim_wrapper delay {
astbuf1 = new AstNode(AST_PRIMITIVE);
astbuf1->str = *$2;
append_attr(astbuf1, $1);
@@ -813,10 +853,10 @@ cell_parameter_list_opt:
'#' '(' cell_parameter_list ')' | /* empty */;
cell_parameter_list:
- /* empty */ | cell_parameter |
- cell_parameter ',' cell_parameter_list;
+ cell_parameter | cell_parameter_list ',' cell_parameter;
cell_parameter:
+ /* empty */ |
expr {
AstNode *node = new AstNode(AST_PARASET);
astbuf1->children.push_back(node);
@@ -831,14 +871,10 @@ cell_parameter:
};
cell_port_list:
- /* empty */ | cell_port |
- cell_port ',' cell_port_list |
- /* empty */ ',' {
- AstNode *node = new AstNode(AST_ARGUMENT);
- astbuf2->children.push_back(node);
- } cell_port_list;
+ cell_port | cell_port_list ',' cell_port;
cell_port:
+ /* empty */ |
expr {
AstNode *node = new AstNode(AST_ARGUMENT);
astbuf2->children.push_back(node);
@@ -926,27 +962,34 @@ opt_label:
assert:
TOK_ASSERT '(' expr ')' ';' {
ast_stack.back()->children.push_back(new AstNode(AST_ASSERT, $3));
+ } |
+ TOK_ASSUME '(' expr ')' ';' {
+ ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $3));
};
assert_property:
TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' {
ast_stack.back()->children.push_back(new AstNode(AST_ASSERT, $4));
+ } |
+ TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' {
+ ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4));
};
simple_behavioral_stmt:
- lvalue '=' expr {
- AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, $3);
+ lvalue '=' delay expr {
+ AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, $4);
ast_stack.back()->children.push_back(node);
} |
- lvalue OP_LE expr {
- AstNode *node = new AstNode(AST_ASSIGN_LE, $1, $3);
+ lvalue OP_LE delay expr {
+ AstNode *node = new AstNode(AST_ASSIGN_LE, $1, $4);
ast_stack.back()->children.push_back(node);
};
// this production creates the obligatory if-else shift/reduce conflict
behavioral_stmt:
- defattr | assert | wire_decl |
- simple_behavioral_stmt ';' |
+ defattr | assert | wire_decl | param_decl | localparam_decl |
+ non_opt_delay behavioral_stmt |
+ simple_behavioral_stmt ';' | ';' |
hierarchical_id attr {
AstNode *node = new AstNode(AST_TCALL);
node->str = *$1;
@@ -1039,13 +1082,13 @@ behavioral_stmt:
};
case_type:
- TOK_CASE {
+ TOK_CASE {
case_type_stack.push_back(0);
} |
- TOK_CASEX {
+ TOK_CASEX {
case_type_stack.push_back('x');
} |
- TOK_CASEZ {
+ TOK_CASEZ {
case_type_stack.push_back('z');
};
@@ -1060,10 +1103,6 @@ opt_synopsys_attr:
} |
/* empty */;
-behavioral_stmt_opt:
- behavioral_stmt |
- ';' ;
-
behavioral_stmt_list:
behavioral_stmt_list behavioral_stmt |
/* empty */;
@@ -1084,7 +1123,9 @@ case_body:
case_item:
{
- AstNode *node = new AstNode(AST_COND);
+ AstNode *node = new AstNode(
+ case_type_stack.size() && case_type_stack.back() == 'x' ? AST_CONDX :
+ case_type_stack.size() && case_type_stack.back() == 'z' ? AST_CONDZ : AST_COND);
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
} case_select {
@@ -1092,7 +1133,7 @@ case_item:
ast_stack.back()->children.push_back(block);
ast_stack.push_back(block);
case_type_stack.push_back(0);
- } behavioral_stmt_opt {
+ } behavioral_stmt {
case_type_stack.pop_back();
ast_stack.pop_back();
ast_stack.pop_back();
@@ -1104,7 +1145,9 @@ gen_case_body:
gen_case_item:
{
- AstNode *node = new AstNode(AST_COND);
+ AstNode *node = new AstNode(
+ case_type_stack.size() && case_type_stack.back() == 'x' ? AST_CONDX :
+ case_type_stack.size() && case_type_stack.back() == 'z' ? AST_CONDZ : AST_COND);
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
} case_select {
@@ -1330,6 +1373,11 @@ basic_expr:
'(' expr ')' {
$$ = $2;
} |
+ '(' expr ':' expr ':' expr ')' {
+ delete $2;
+ $$ = $4;
+ delete $6;
+ } |
'{' concat_list '}' {
$$ = $2;
} |