aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/verilog
diff options
context:
space:
mode:
Diffstat (limited to 'frontends/verilog')
-rw-r--r--frontends/verilog/preproc.cc8
-rw-r--r--frontends/verilog/verilog_frontend.cc3
-rw-r--r--frontends/verilog/verilog_parser.y172
3 files changed, 119 insertions, 64 deletions
diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc
index ea23139e2..c451c4c20 100644
--- a/frontends/verilog/preproc.cc
+++ b/frontends/verilog/preproc.cc
@@ -321,7 +321,6 @@ struct define_body_t
define_map_t::define_map_t()
{
add("YOSYS", "1");
- add(formal_mode ? "FORMAL" : "SYNTHESIS", "1");
}
// We must define this destructor here (rather than relying on the default), because we need to
@@ -391,13 +390,16 @@ static void input_file(std::istream &f, std::string filename)
// the argument list); false if we finished with ','.
static bool read_argument(std::string &dest)
{
+ skip_spaces();
std::vector<char> openers;
for (;;) {
- skip_spaces();
std::string tok = next_token(true);
if (tok == ")") {
- if (openers.empty())
+ if (openers.empty()) {
+ while (dest.size() && (dest.back() == ' ' || dest.back() == '\t'))
+ dest = dest.substr(0, dest.size() - 1);
return true;
+ }
if (openers.back() != '(')
log_error("Mismatched brackets in macro argument: %c and %c.\n",
openers.back(), tok[0]);
diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc
index 2e9c9b2e2..5319a45ad 100644
--- a/frontends/verilog/verilog_frontend.cc
+++ b/frontends/verilog/verilog_frontend.cc
@@ -446,6 +446,9 @@ struct VerilogFrontend : public Frontend {
}
break;
}
+
+ defines_map.add(formal_mode ? "FORMAL" : "SYNTHESIS", "1");
+
extra_args(f, filename, args, argidx);
log_header(design, "Executing Verilog-2005 frontend: %s\n", filename.c_str());
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index 678ce6c87..7fbd2aa27 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -282,7 +282,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode)
%token TOK_OR_ASSIGN TOK_XOR_ASSIGN TOK_AND_ASSIGN TOK_SUB_ASSIGN
%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
+%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type
%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number
%type <string> type_name
%type <ast> opt_enum_init enum_type struct_type non_wire_data_type
@@ -619,26 +619,19 @@ non_opt_delay:
delay:
non_opt_delay | %empty;
-wire_type:
- {
- astbuf3 = new AstNode(AST_WIRE);
- current_wire_rand = false;
- current_wire_const = false;
- } wire_type_token_list {
- $$ = astbuf3;
- SET_RULE_LOC(@$, @2, @$);
- };
+io_wire_type:
+ { astbuf3 = new AstNode(AST_WIRE); current_wire_rand = false; current_wire_const = false; }
+ wire_type_token_io wire_type_const_rand opt_wire_type_token wire_type_signedness
+ { $$ = astbuf3; SET_RULE_LOC(@$, @2, @$); };
-wire_type_token_list:
- wire_type_token |
- wire_type_token_list wire_type_token |
- wire_type_token_io |
- hierarchical_type_id {
- astbuf3->is_custom_type = true;
- astbuf3->children.push_back(new AstNode(AST_WIRETYPE));
- astbuf3->children.back()->str = *$1;
- delete $1;
- };
+non_io_wire_type:
+ { astbuf3 = new AstNode(AST_WIRE); current_wire_rand = false; current_wire_const = false; }
+ wire_type_const_rand wire_type_token wire_type_signedness
+ { $$ = astbuf3; SET_RULE_LOC(@$, @2, @$); };
+
+wire_type:
+ io_wire_type |
+ non_io_wire_type;
wire_type_token_io:
TOK_INPUT {
@@ -652,8 +645,32 @@ wire_type_token_io:
astbuf3->is_output = true;
};
+wire_type_signedness:
+ TOK_SIGNED { astbuf3->is_signed = true; } |
+ TOK_UNSIGNED { astbuf3->is_signed = false; } |
+ %empty;
+
+wire_type_const_rand:
+ TOK_RAND TOK_CONST {
+ current_wire_rand = true;
+ current_wire_const = true;
+ } |
+ TOK_CONST {
+ current_wire_const = true;
+ } |
+ TOK_RAND {
+ current_wire_rand = true;
+ } |
+ %empty;
+
+opt_wire_type_token:
+ wire_type_token | %empty;
+
wire_type_token:
- TOK_WIRE {
+ hierarchical_type_id {
+ astbuf3->is_custom_type = true;
+ astbuf3->children.push_back(new AstNode(AST_WIRETYPE));
+ astbuf3->children.back()->str = *$1;
} |
TOK_WOR {
astbuf3->is_wor = true;
@@ -661,20 +678,27 @@ wire_type_token:
TOK_WAND {
astbuf3->is_wand = true;
} |
+ // wires
+ TOK_WIRE {
+ } |
+ TOK_WIRE logic_type {
+ } |
+ // regs
TOK_REG {
astbuf3->is_reg = true;
} |
- TOK_LOGIC {
- astbuf3->is_logic = true;
+ TOK_VAR TOK_REG {
+ astbuf3->is_reg = true;
} |
+ // logics
TOK_VAR {
astbuf3->is_logic = true;
} |
- TOK_INTEGER {
- astbuf3->is_reg = true;
- astbuf3->range_left = 31;
- astbuf3->range_right = 0;
- astbuf3->is_signed = true;
+ TOK_VAR logic_type {
+ astbuf3->is_logic = true;
+ } |
+ logic_type {
+ astbuf3->is_logic = true;
} |
TOK_GENVAR {
astbuf3->type = AST_GENVAR;
@@ -682,15 +706,15 @@ wire_type_token:
astbuf3->is_signed = true;
astbuf3->range_left = 31;
astbuf3->range_right = 0;
+ };
+
+logic_type:
+ TOK_LOGIC {
} |
- TOK_SIGNED {
+ TOK_INTEGER {
+ astbuf3->range_left = 31;
+ astbuf3->range_right = 0;
astbuf3->is_signed = true;
- } |
- TOK_RAND {
- current_wire_rand = true;
- } |
- TOK_CONST {
- current_wire_const = true;
};
non_opt_range:
@@ -746,6 +770,7 @@ module_body:
module_body module_body_stmt |
/* the following line makes the generate..endgenrate keywords optional */
module_body gen_stmt |
+ module_body gen_block |
module_body ';' |
%empty;
@@ -884,7 +909,11 @@ task_func_args:
task_func_port:
attr wire_type range {
+ bool prev_was_input = true;
+ bool prev_was_output = false;
if (albuf) {
+ prev_was_input = astbuf1->is_input;
+ prev_was_output = astbuf1->is_output;
delete astbuf1;
if (astbuf2 != NULL)
delete astbuf2;
@@ -893,6 +922,12 @@ task_func_port:
albuf = $1;
astbuf1 = $2;
astbuf2 = checkRange(astbuf1, $3);
+ if (!astbuf1->is_input && !astbuf1->is_output) {
+ if (!sv_mode)
+ frontend_verilog_yyerror("task/function argument direction missing");
+ astbuf1->is_input = prev_was_input;
+ astbuf1->is_output = prev_was_output;
+ }
} wire_name |
{
if (!astbuf1) {
@@ -1456,10 +1491,10 @@ enum_base_type: type_atom type_signing
| %empty { astbuf1->is_reg = true; addRange(astbuf1); }
;
-type_atom: TOK_INTEGER { astbuf1->is_reg = true; addRange(astbuf1); } // 4-state signed
- | TOK_INT { astbuf1->is_reg = true; addRange(astbuf1); } // 2-state signed
- | TOK_SHORTINT { astbuf1->is_reg = true; addRange(astbuf1, 15, 0); } // 2-state signed
- | TOK_BYTE { astbuf1->is_reg = true; addRange(astbuf1, 7, 0); } // 2-state signed
+type_atom: TOK_INTEGER { astbuf1->is_reg = true; astbuf1->is_signed = true; addRange(astbuf1); } // 4-state signed
+ | TOK_INT { astbuf1->is_reg = true; astbuf1->is_signed = true; addRange(astbuf1); } // 2-state signed
+ | TOK_SHORTINT { astbuf1->is_reg = true; astbuf1->is_signed = true; addRange(astbuf1, 15, 0); } // 2-state signed
+ | TOK_BYTE { astbuf1->is_reg = true; astbuf1->is_signed = true; addRange(astbuf1, 7, 0); } // 2-state signed
;
type_vec: TOK_REG { astbuf1->is_reg = true; } // unsigned
@@ -1749,7 +1784,13 @@ wire_name:
}
rewriteAsMemoryNode(node, $2);
}
- if (current_function_or_task == NULL) {
+ if (current_function_or_task) {
+ if (node->is_input || node->is_output)
+ node->port_id = current_function_or_task_port_id++;
+ } else if (ast_stack.back()->type == AST_GENBLOCK) {
+ if (node->is_input || node->is_output)
+ frontend_verilog_yyerror("Cannot declare module port `%s' within a generate block.", $1->c_str());
+ } else {
if (do_not_require_port_stubs && (node->is_input || node->is_output) && port_stubs.count(*$1) == 0) {
port_stubs[*$1] = ++port_counter;
}
@@ -1764,9 +1805,6 @@ wire_name:
if (node->is_input || node->is_output)
frontend_verilog_yyerror("Module port `%s' is not declared in module header.", $1->c_str());
}
- } else {
- if (node->is_input || node->is_output)
- node->port_id = current_function_or_task_port_id++;
}
//FIXME: for some reason, TOK_ID has a location which always points to one column *after* the real last column...
SET_AST_NODE_LOC(node, @1, @1);
@@ -1793,7 +1831,7 @@ type_name: TOK_ID // first time seen
;
typedef_decl:
- TOK_TYPEDEF wire_type range type_name range_or_multirange ';' {
+ TOK_TYPEDEF non_io_wire_type range type_name range_or_multirange ';' {
astbuf1 = $2;
astbuf2 = checkRange(astbuf1, $3);
if (astbuf2)
@@ -2425,6 +2463,16 @@ behavioral_stmt:
exitTypeScope();
if ($4 != NULL && $8 != NULL && *$4 != *$8)
frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $4->c_str()+1, $8->c_str()+1);
+ AstNode *node = ast_stack.back();
+ // In SystemVerilog, unnamed blocks with block item declarations
+ // create an implicit hierarchy scope
+ if (sv_mode && node->str.empty())
+ for (const AstNode* child : node->children)
+ if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER
+ || child->type == AST_LOCALPARAM || child->type == AST_TYPEDEF) {
+ node->str = "$unnamed_block$" + std::to_string(autoidx++);
+ break;
+ }
SET_AST_NODE_LOC(ast_stack.back(), @2, @8);
delete $4;
delete $8;
@@ -2439,6 +2487,7 @@ behavioral_stmt:
ast_stack.back()->children.push_back($7);
} ';' simple_behavioral_stmt ')' {
AstNode *block = new AstNode(AST_BLOCK);
+ block->str = "$for_loop$" + std::to_string(autoidx++);
ast_stack.back()->children.push_back(block);
ast_stack.push_back(block);
} behavioral_stmt {
@@ -2688,6 +2737,7 @@ single_arg:
module_gen_body:
module_gen_body gen_stmt_or_module_body_stmt |
+ module_gen_body gen_block |
%empty;
gen_stmt_or_module_body_stmt:
@@ -2713,12 +2763,7 @@ gen_stmt:
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
ast_stack.back()->children.push_back($3);
- AstNode *block = new AstNode(AST_GENBLOCK);
- ast_stack.back()->children.push_back(block);
- ast_stack.push_back(block);
- } gen_stmt_block {
- ast_stack.pop_back();
- } opt_gen_else {
+ } gen_stmt_block opt_gen_else {
SET_AST_NODE_LOC(ast_stack.back(), @1, @7);
ast_stack.pop_back();
} |
@@ -2731,6 +2776,18 @@ gen_stmt:
SET_AST_NODE_LOC(ast_stack.back(), @1, @7);
ast_stack.pop_back();
} |
+ TOK_MSG_TASKS {
+ AstNode *node = new AstNode(AST_TECALL);
+ node->str = *$1;
+ delete $1;
+ ast_stack.back()->children.push_back(node);
+ ast_stack.push_back(node);
+ } opt_arg_list ';'{
+ SET_AST_NODE_LOC(ast_stack.back(), @1, @3);
+ ast_stack.pop_back();
+ };
+
+gen_block:
TOK_BEGIN {
enterTypeScope();
} opt_label {
@@ -2740,22 +2797,15 @@ gen_stmt:
ast_stack.push_back(node);
} module_gen_body TOK_END opt_label {
exitTypeScope();
+ if ($3 != NULL && $7 != NULL && *$3 != *$7)
+ frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $3->c_str()+1, $7->c_str()+1);
delete $3;
delete $7;
SET_AST_NODE_LOC(ast_stack.back(), @1, @7);
ast_stack.pop_back();
- } |
- TOK_MSG_TASKS {
- AstNode *node = new AstNode(AST_TECALL);
- node->str = *$1;
- delete $1;
- ast_stack.back()->children.push_back(node);
- ast_stack.push_back(node);
- } opt_arg_list ';'{
- SET_AST_NODE_LOC(ast_stack.back(), @1, @3);
- ast_stack.pop_back();
};
+// result is wrapped in a genblock only if necessary
gen_stmt_block:
{
AstNode *node = new AstNode(AST_GENBLOCK);
@@ -2764,7 +2814,7 @@ gen_stmt_block:
} gen_stmt_or_module_body_stmt {
SET_AST_NODE_LOC(ast_stack.back(), @2, @2);
ast_stack.pop_back();
- };
+ } | gen_block;
opt_gen_else:
TOK_ELSE gen_stmt_block | %empty %prec FAKE_THEN;