From 2b9c75f8e372f6886e073743d1df11bcd1c58281 Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Fri, 9 Mar 2018 10:35:33 +0200 Subject: This PR should be the base for discussion, do not merge it yet! It correctly detects reg/wire mix and incorrect use on blocking,nonblocking assignments within blocks and assign statements. What it DOES'T do: Detect registers connected to output ports of instances. Where it FAILS: memorty nonblocking assignments causes spurious (I assume??) errors on yosys-generated "_ADDR", "_DATA", "EN" signals. You can test it with tests/simple/reg_wire_error.v (look inside for the comments to enable/disable specific lines) --- frontends/ast/ast.cc | 7 ++++++- frontends/ast/ast.h | 2 +- frontends/ast/simplify.cc | 10 ++++++++++ frontends/verilog/verilog_lexer.l | 2 +- frontends/verilog/verilog_parser.y | 6 +++++- 5 files changed, 23 insertions(+), 4 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 037a9f3ee..25267775a 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -191,6 +191,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch is_input = false; is_output = false; is_reg = false; + is_logic = false; is_signed = false; is_string = false; range_valid = false; @@ -285,7 +286,9 @@ void AstNode::dumpAst(FILE *f, std::string indent) const fprintf(f, " input"); if (is_output) fprintf(f, " output"); - if (is_reg) + if (is_logic) + fprintf(f, " logic"); + if (is_reg) // this is an AST dump, not Verilog - if we see "logic reg" that's fine. fprintf(f, " reg"); if (is_signed) fprintf(f, " signed"); @@ -652,6 +655,8 @@ bool AstNode::operator==(const AstNode &other) const return false; if (is_output != other.is_output) return false; + if (is_logic != other.is_logic) + return false; if (is_reg != other.is_reg) return false; if (is_signed != other.is_signed) diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index d1e2c78d1..9b7124934 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -168,7 +168,7 @@ namespace AST // node content - most of it is unused in most node types std::string str; std::vector bits; - bool is_input, is_output, is_reg, is_signed, is_string, range_valid, range_swapped; + bool is_input, is_output, is_reg, is_logic, is_signed, is_string, range_valid, range_swapped; int port_id, range_left, range_right; uint32_t integer; double realvalue; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index a16fdfeeb..c9c5e5263 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -327,6 +327,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (node->type == AST_WIRE) { if (this_wire_scope.count(node->str) > 0) { AstNode *first_node = this_wire_scope[node->str]; + if (first_node->is_input && node->is_reg) + goto wires_are_incompatible; if (!node->is_input && !node->is_output && node->is_reg && node->children.size() == 0) goto wires_are_compatible; if (first_node->children.size() == 0 && node->children.size() == 1 && node->children[0]->type == AST_RANGE) { @@ -361,6 +363,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, first_node->is_output = true; if (node->is_reg) first_node->is_reg = true; + if (node->is_logic) + first_node->is_logic = true; if (node->is_signed) first_node->is_signed = true; for (auto &it : node->attributes) { @@ -440,6 +444,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, children[1]->detectSignWidth(width_hint, sign_hint); width_hint = max(width_hint, backup_width_hint); child_0_is_self_determined = true; + if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && children[0]->id2ast->is_logic) + children[0]->id2ast->is_reg = true; // if logic type is used in a block asignment + if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && !children[0]->id2ast->is_reg) + log_warning("wire '%s' is assigned in a block at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); + if (type == AST_ASSIGN && children[0]->id2ast->is_reg) + log_error("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); break; case AST_PARAMETER: diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index d6d00c371..8aa123e1e 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -189,7 +189,7 @@ YOSYS_NAMESPACE_END "const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); } "checker" { if (formal_mode) return TOK_CHECKER; SV_KEYWORD(TOK_CHECKER); } "endchecker" { if (formal_mode) return TOK_ENDCHECKER; SV_KEYWORD(TOK_ENDCHECKER); } -"logic" { SV_KEYWORD(TOK_REG); } +"logic" { SV_KEYWORD(TOK_LOGIC); } "bit" { SV_KEYWORD(TOK_REG); } "eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index ba2fc036e..722febf13 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -105,7 +105,7 @@ static void free_attr(std::map *al) %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_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG TOK_LOGIC %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 %token TOK_DPI_FUNCTION TOK_POSEDGE TOK_NEGEDGE TOK_OR TOK_AUTOMATIC @@ -394,6 +394,9 @@ wire_type_token: TOK_REG { astbuf3->is_reg = true; } | + TOK_LOGIC { + astbuf3->is_logic = true; + } | TOK_INTEGER { astbuf3->is_reg = true; astbuf3->range_left = 31; @@ -827,6 +830,7 @@ wire_name: node->port_id = current_function_or_task_port_id++; } ast_stack.back()->children.push_back(node); + delete $1; }; -- cgit v1.2.3 From 73d426bc879087ca522ca595a8ba921b647fae27 Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Tue, 5 Jun 2018 17:44:24 +0300 Subject: Modified errors into warnings No longer false warnings for memories and assertions --- frontends/ast/ast.cc | 1 + frontends/ast/ast.h | 2 +- frontends/ast/simplify.cc | 44 ++++++++++++++++++++++++++++++++------ frontends/verilog/verilog_parser.y | 1 + 4 files changed, 41 insertions(+), 7 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 25267775a..b8f25e53e 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -194,6 +194,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch is_logic = false; is_signed = false; is_string = false; + was_checked = false; range_valid = false; range_swapped = false; port_id = 0; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 9b7124934..8a640b1cc 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -168,7 +168,7 @@ namespace AST // node content - most of it is unused in most node types std::string str; std::vector bits; - bool is_input, is_output, is_reg, is_logic, is_signed, is_string, range_valid, range_swapped; + bool is_input, is_output, is_reg, is_logic, is_signed, is_string, range_valid, range_swapped, was_checked; int port_id, range_left, range_right; uint32_t integer; double realvalue; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index c9c5e5263..a9608369c 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -444,12 +444,16 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, children[1]->detectSignWidth(width_hint, sign_hint); width_hint = max(width_hint, backup_width_hint); child_0_is_self_determined = true; - if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && children[0]->id2ast->is_logic) - children[0]->id2ast->is_reg = true; // if logic type is used in a block asignment - if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && !children[0]->id2ast->is_reg) - log_warning("wire '%s' is assigned in a block at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); - if (type == AST_ASSIGN && children[0]->id2ast->is_reg) - log_error("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); + // test only once, before optimizations and memory mappings but after assignment LHS was mapped to an identifier + if (children[0]->id2ast && !children[0]->was_checked) { + if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && children[0]->id2ast->is_logic) + children[0]->id2ast->is_reg = true; // if logic type is used in a block asignment + if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && !children[0]->id2ast->is_reg) + log_warning("wire '%s' is assigned in a block at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); + if (type == AST_ASSIGN && children[0]->id2ast->is_reg) + log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); + children[0]->was_checked = true; + } break; case AST_PARAMETER: @@ -959,6 +963,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, AstNode *assign = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), data); assign->children[0]->str = wire_id; + assign->children[0]->was_checked = true; if (current_block) { @@ -1425,16 +1430,19 @@ skip_dynamic_range_lvalue_expansion:; AstNode *wire_check = new AstNode(AST_WIRE); wire_check->str = id_check; + wire_check->was_checked = true; current_ast_mod->children.push_back(wire_check); current_scope[wire_check->str] = wire_check; while (wire_check->simplify(true, false, false, 1, -1, false, false)) { } AstNode *wire_en = new AstNode(AST_WIRE); wire_en->str = id_en; + wire_en->was_checked = true; current_ast_mod->children.push_back(wire_en); if (current_always_clocked) { current_ast_mod->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), AstNode::mkconst_int(0, false, 1))))); current_ast_mod->children.back()->children[0]->children[0]->children[0]->str = id_en; + current_ast_mod->children.back()->children[0]->children[0]->children[0]->was_checked = true; } current_scope[wire_en->str] = wire_en; while (wire_en->simplify(true, false, false, 1, -1, false, false)) { } @@ -1444,9 +1452,11 @@ skip_dynamic_range_lvalue_expansion:; AstNode *assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bit, false)); assign_check->children[0]->str = id_check; + assign_check->children[0]->was_checked = true; AstNode *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, 1)); assign_en->children[0]->str = id_en; + assign_en->children[0]->was_checked = true; AstNode *default_signals = new AstNode(AST_BLOCK); default_signals->children.push_back(assign_check); @@ -1455,6 +1465,7 @@ skip_dynamic_range_lvalue_expansion:; assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_REDUCE_BOOL, children[0]->clone())); assign_check->children[0]->str = id_check; + assign_check->children[0]->was_checked = true; if (current_always == nullptr || current_always->type != AST_INITIAL) { assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(1, false, 1)); @@ -1463,6 +1474,7 @@ skip_dynamic_range_lvalue_expansion:; assign_en->children[1]->str = "\\$initstate"; } assign_en->children[0]->str = id_en; + assign_en->children[0]->was_checked = true; newNode = new AstNode(AST_BLOCK); newNode->children.push_back(assign_check); @@ -1571,12 +1583,14 @@ skip_dynamic_range_lvalue_expansion:; AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true))); wire_addr->str = id_addr; + wire_addr->was_checked = true; current_ast_mod->children.push_back(wire_addr); current_scope[wire_addr->str] = wire_addr; while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { } AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); wire_data->str = id_data; + wire_data->was_checked = true; wire_data->is_signed = mem_signed; current_ast_mod->children.push_back(wire_data); current_scope[wire_data->str] = wire_data; @@ -1586,6 +1600,7 @@ skip_dynamic_range_lvalue_expansion:; if (current_always->type != AST_INITIAL) { wire_en = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); wire_en->str = id_en; + wire_en->was_checked = true; current_ast_mod->children.push_back(wire_en); current_scope[wire_en->str] = wire_en; while (wire_en->simplify(true, false, false, 1, -1, false, false)) { } @@ -1601,14 +1616,17 @@ skip_dynamic_range_lvalue_expansion:; AstNode *assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_addr, false)); assign_addr->children[0]->str = id_addr; + assign_addr->children[0]->was_checked = true; AstNode *assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_data, false)); assign_data->children[0]->str = id_data; + assign_data->children[0]->was_checked = true; AstNode *assign_en = nullptr; if (current_always->type != AST_INITIAL) { assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width)); assign_en->children[0]->str = id_en; + assign_en->children[0]->was_checked = true; } AstNode *default_signals = new AstNode(AST_BLOCK); @@ -1620,6 +1638,7 @@ skip_dynamic_range_lvalue_expansion:; assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone()); assign_addr->children[0]->str = id_addr; + assign_addr->children[0]->was_checked = true; if (children[0]->children.size() == 2) { @@ -1634,12 +1653,14 @@ skip_dynamic_range_lvalue_expansion:; assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_CONCAT, mkconst_bits(padding_x, false), children[1]->clone())); assign_data->children[0]->str = id_data; + assign_data->children[0]->was_checked = true; if (current_always->type != AST_INITIAL) { for (int i = 0; i < mem_width; i++) set_bits_en[i] = offset <= i && i < offset+width ? RTLIL::State::S1 : RTLIL::State::S0; assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false)); assign_en->children[0]->str = id_en; + assign_en->children[0]->was_checked = true; } } else @@ -1661,6 +1682,7 @@ skip_dynamic_range_lvalue_expansion:; assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_SHIFT_LEFT, children[1]->clone(), offset_ast->clone())); assign_data->children[0]->str = id_data; + assign_data->children[0]->was_checked = true; if (current_always->type != AST_INITIAL) { for (int i = 0; i < mem_width; i++) @@ -1668,6 +1690,7 @@ skip_dynamic_range_lvalue_expansion:; assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_SHIFT_LEFT, mkconst_bits(set_bits_en, false), offset_ast->clone())); assign_en->children[0]->str = id_en; + assign_en->children[0]->was_checked = true; } delete left_at_zero_ast; @@ -1679,10 +1702,12 @@ skip_dynamic_range_lvalue_expansion:; { assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[1]->clone()); assign_data->children[0]->str = id_data; + assign_data->children[0]->was_checked = true; if (current_always->type != AST_INITIAL) { assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false)); assign_en->children[0]->str = id_en; + assign_en->children[0]->was_checked = true; } } @@ -3018,6 +3043,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true))); wire_addr->str = id_addr; wire_addr->is_reg = true; + wire_addr->was_checked = true; wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(1, false); mod->children.push_back(wire_addr); while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { } @@ -3025,6 +3051,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); wire_data->str = id_data; wire_data->is_reg = true; + wire_data->was_checked = true; wire_data->is_signed = mem_signed; wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false); mod->children.push_back(wire_data); @@ -3093,6 +3120,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true))); wire_addr->str = id_addr; wire_addr->is_reg = true; + wire_addr->was_checked = true; if (block) wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(1, false); mod->children.push_back(wire_addr); @@ -3101,6 +3129,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true))); wire_data->str = id_data; wire_data->is_reg = true; + wire_data->was_checked = true; wire_data->is_signed = mem_signed; if (block) wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false); @@ -3109,6 +3138,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *assign_addr = new AstNode(block ? AST_ASSIGN_EQ : AST_ASSIGN, new AstNode(AST_IDENTIFIER), children[0]->children[0]->clone()); assign_addr->children[0]->str = id_addr; + assign_addr->children[0]->was_checked = true; AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER)); case_node->children[0]->str = id_addr; @@ -3119,6 +3149,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *cond_node = new AstNode(AST_COND, AstNode::mkconst_int(i, false, addr_bits), new AstNode(AST_BLOCK)); AstNode *assign_reg = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), new AstNode(AST_IDENTIFIER)); assign_reg->children[0]->str = id_data; + assign_reg->children[0]->was_checked = true; assign_reg->children[1]->str = stringf("%s[%d]", str.c_str(), i); cond_node->children[1]->children.push_back(assign_reg); case_node->children.push_back(cond_node); @@ -3131,6 +3162,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *cond_node = new AstNode(AST_COND, new AstNode(AST_DEFAULT), new AstNode(AST_BLOCK)); AstNode *assign_reg = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), AstNode::mkconst_bits(x_bits, false)); assign_reg->children[0]->str = id_data; + assign_reg->children[0]->was_checked = true; cond_node->children[1]->children.push_back(assign_reg); case_node->children.push_back(cond_node); diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 722febf13..dfdeabbdb 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -548,6 +548,7 @@ task_func_decl: AstNode *outreg = new AstNode(AST_WIRE); outreg->str = *$6; outreg->is_signed = $4; + outreg->is_reg = true; if ($5 != NULL) { outreg->children.push_back($5); outreg->is_signed = $4 || $5->is_signed; -- cgit v1.2.3 From 8b7580b0a152ec937abb1510abf5f2d7cd3b7acb Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Wed, 6 Jun 2018 22:27:25 +0300 Subject: Detect illegal port declaration, e.g input/output/inout keyword must be the first. --- frontends/verilog/verilog_parser.y | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index e803d8072..72a501d11 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -376,9 +376,10 @@ wire_type: }; wire_type_token_list: - wire_type_token | wire_type_token_list wire_type_token; + wire_type_token | wire_type_token_list wire_type_token | + wire_type_token_io ; -wire_type_token: +wire_type_token_io: TOK_INPUT { astbuf3->is_input = true; } | @@ -388,7 +389,9 @@ wire_type_token: TOK_INOUT { astbuf3->is_input = true; astbuf3->is_output = true; - } | + }; + +wire_type_token: TOK_WIRE { } | TOK_REG { -- cgit v1.2.3 From 848c3c5c889945f64ddefc8fe45342a4338dc769 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 22 Jun 2018 20:40:22 +0200 Subject: Add YOSYS_NOVERIFIC env variable for temporarily disabling verific Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 62 ++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 22 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 3c6566f62..fb27810dd 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1669,6 +1669,16 @@ YOSYS_NAMESPACE_END PRIVATE_NAMESPACE_BEGIN +bool check_noverific_env() +{ + const char *e = getenv("YOSYS_NOVERIFIC"); + if (e == nullptr) + return false; + if (atoi(e) == 0) + return false; + return true; +} + struct VerificPass : public Pass { VerificPass() : Pass("verific", "load Verilog and VHDL designs using Verific") { } virtual void help() @@ -1759,6 +1769,9 @@ struct VerificPass : public Pass { #ifdef YOSYS_ENABLE_VERIFIC virtual void execute(std::vector args, RTLIL::Design *design) { + if (check_noverific_env()) + log_cmd_error("This version of Yosys is built without Verific support.\n"); + log_header(design, "Executing VERIFIC (loading SystemVerilog and VHDL designs using Verific).\n"); Message::SetConsoleOutput(0); @@ -2135,44 +2148,50 @@ struct ReadPass : public Pass { if (args.size() < 3) log_cmd_error("Missing file name parameter.\n"); - if (args[1] == "-vlog95" || args[1] == "-vlog2k") { #ifdef YOSYS_ENABLE_VERIFIC - args[0] = "verific"; + bool use_verific = !check_noverific_env(); #else - args[0] = "read_verilog"; - args.erase(args.begin()+1, args.begin()+2); + bool use_verific = false; #endif + + if (args[1] == "-vlog95" || args[1] == "-vlog2k") { + if (use_verific) { + args[0] = "verific"; + } else { + args[0] = "read_verilog"; + args.erase(args.begin()+1, args.begin()+2); + } Pass::call(design, args); return; } if (args[1] == "-sv2005" || args[1] == "-sv2009" || args[1] == "-sv2012" || args[1] == "-sv") { -#ifdef YOSYS_ENABLE_VERIFIC - args[0] = "verific"; -#else - args[0] = "read_verilog"; - args[1] = "-sv"; -#endif + if (use_verific) { + args[0] = "verific"; + } else { + args[0] = "read_verilog"; + args[1] = "-sv"; + } Pass::call(design, args); return; } if (args[1] == "-vhdl87" || args[1] == "-vhdl93" || args[1] == "-vhdl2k" || args[1] == "-vhdl2008" || args[1] == "-vhdl") { -#ifdef YOSYS_ENABLE_VERIFIC - args[0] = "verific"; -#else - log_cmd_error("This version of Yosys is built without Verific support.\n"); -#endif - Pass::call(design, args); + if (use_verific) { + args[0] = "verific"; + Pass::call(design, args); + } else { + log_cmd_error("This version of Yosys is built without Verific support.\n"); + } return; } if (args[1] == "-define") { -#ifdef YOSYS_ENABLE_VERIFIC - args[0] = "verific"; - args[1] = "-vlog-define"; - Pass::call(design, args); -#endif + if (use_verific) { + args[0] = "verific"; + args[1] = "-vlog-define"; + Pass::call(design, args); + } args[0] = "verilog_defines"; args.erase(args.begin()+1, args.begin()+2); for (int i = 1; i < GetSize(args); i++) @@ -2186,4 +2205,3 @@ struct ReadPass : public Pass { } ReadPass; PRIVATE_NAMESPACE_END - -- cgit v1.2.3 From fe2ee833e154691ef61cc72833b86e02266039a2 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 28 Jun 2018 16:57:03 +0200 Subject: Fix handling of signed memories Signed-off-by: Clifford Wolf --- frontends/ast/genrtlil.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'frontends') diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 40cbbc2a3..d9f0039af 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -1300,6 +1300,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(0); cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0); + if (!sign_hint) + is_signed = false; + return RTLIL::SigSpec(wire); } -- cgit v1.2.3 From 07e616900c2d6ddf021644f9687954d92ac8109a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 28 Jun 2018 23:43:38 +0200 Subject: Add "read -undef" Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index fb27810dd..4fa74df3d 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1715,6 +1715,11 @@ struct VerificPass : public Pass { log("Add Verilog defines. (The macros SYNTHESIS and VERIFIC are defined implicitly.)\n"); log("\n"); log("\n"); + log(" verific -vlog-undef ..\n"); + log("\n"); + log("Remove Verilog defines previously set with -vlog-define.\n"); + log("\n"); + log("\n"); log(" verific -import [options] ..\n"); log("\n"); log("Elaborate the design for the specified top modules, import to Yosys and\n"); @@ -1828,6 +1833,14 @@ struct VerificPass : public Pass { goto check_error; } + if (GetSize(args) > argidx && args[argidx] == "-vlog-undef") { + for (argidx++; argidx < GetSize(args); argidx++) { + string name = args[argidx]; + veri_file::UndefineMacro(name.c_str()); + } + goto check_error; + } + if (GetSize(args) > argidx && (args[argidx] == "-vlog95" || args[argidx] == "-vlog2k" || args[argidx] == "-sv2005" || args[argidx] == "-sv2009" || args[argidx] == "-sv2012" || args[argidx] == "-sv")) { @@ -2139,6 +2152,11 @@ struct ReadPass : public Pass { log("\n"); log("Set global Verilog/SystemVerilog defines.\n"); log("\n"); + log("\n"); + log(" read -undef ..\n"); + log("\n"); + log("Unset global Verilog/SystemVerilog defines.\n"); + log("\n"); } virtual void execute(std::vector args, RTLIL::Design *design) { @@ -2200,6 +2218,20 @@ struct ReadPass : public Pass { return; } + if (args[1] == "-undef") { + if (use_verific) { + args[0] = "verific"; + args[1] = "-vlog-undef"; + Pass::call(design, args); + } + args[0] = "verilog_defines"; + args.erase(args.begin()+1, args.begin()+2); + for (int i = 1; i < GetSize(args); i++) + args[i] = "-U" + args[i]; + Pass::call(design, args); + return; + } + log_cmd_error("Missing or unsupported mode parameter.\n"); } } ReadPass; -- cgit v1.2.3 From afedb2d03ee07738025ae77d73d280044c29ec2f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 28 Jun 2018 23:58:15 +0200 Subject: Add "read -sv -D" support Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 4fa74df3d..c9a071f70 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1693,6 +1693,9 @@ struct VerificPass : public Pass { log("Files passed to different calls to this command are treated as belonging to\n"); log("different compilation units.\n"); log("\n"); + log("Additional -D[=] options may be added after the option indicating\n"); + log("the language version (and before file names) to set additional verilog defines.\n"); + log("\n"); log("\n"); log(" verific {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} ..\n"); log("\n"); @@ -1860,8 +1863,25 @@ struct VerificPass : public Pass { else log_abort(); - for (argidx++; argidx < GetSize(args); argidx++) - file_names.Insert(args[argidx].c_str()); + for (argidx++; argidx < GetSize(args) && GetSize(args[argidx]) >= 2 && args[argidx].substr(0, 2) == "-D"; argidx++) { + std::string name = args[argidx].substr(2); + if (args[argidx] == "-D") { + if (++argidx >= GetSize(args)) + break; + name = args[argidx]; + } + size_t equal = name.find('='); + if (equal != std::string::npos) { + string value = name.substr(equal+1); + name = name.substr(0, equal); + veri_file::DefineMacro(name.c_str(), value.c_str()); + } else { + veri_file::DefineMacro(name.c_str()); + } + } + + while (argidx < GetSize(args)) + file_names.Insert(args[argidx++].c_str()); if (!veri_file::AnalyzeMultipleFiles(&file_names, verilog_mode, "work", veri_file::MFCU)) log_cmd_error("Reading Verilog/SystemVerilog sources failed.\n"); @@ -2142,6 +2162,9 @@ struct ReadPass : public Pass { log("Load the specified Verilog/SystemVerilog files. (Full SystemVerilog support\n"); log("is only available via Verific.)\n"); log("\n"); + log("Additional -D[=] options may be added after the option indicating\n"); + log("the language version (and before file names) to set additional verilog defines.\n"); + log("\n"); log("\n"); log(" read {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} ..\n"); log("\n"); -- cgit v1.2.3 From ebf0f003d3e8d219b396d4c6a3943e1ce54d2879 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 29 Jun 2018 10:02:27 +0200 Subject: Add "verific -formal" and "read -formal" Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index c9a071f70..62a8028b8 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1695,8 +1695,13 @@ struct VerificPass : public Pass { log("\n"); log("Additional -D[=] options may be added after the option indicating\n"); log("the language version (and before file names) to set additional verilog defines.\n"); + log("The macros SYNTHESIS and VERIFIC are defined implicitly.\n"); log("\n"); log("\n"); + log(" verific -formal ..\n"); + log("\n"); + log("Like -sv, but define FORMAL instead of SYNTHESIS.\n"); + log("\n"); log(" verific {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} ..\n"); log("\n"); log("Load the specified VHDL files into Verific.\n"); @@ -1715,7 +1720,7 @@ struct VerificPass : public Pass { log("\n"); log(" verific -vlog-define [=]..\n"); log("\n"); - log("Add Verilog defines. (The macros SYNTHESIS and VERIFIC are defined implicitly.)\n"); + log("Add Verilog defines.\n"); log("\n"); log("\n"); log(" verific -vlog-undef ..\n"); @@ -1790,8 +1795,6 @@ struct VerificPass : public Pass { RuntimeFlags::SetVar("veri_extract_dualport_rams", 0); RuntimeFlags::SetVar("veri_extract_multiport_rams", 1); RuntimeFlags::SetVar("db_infer_wide_operators", 1); - veri_file::DefineCmdLineMacro("VERIFIC"); - veri_file::DefineCmdLineMacro("SYNTHESIS"); verific_verbose = 0; @@ -1845,7 +1848,7 @@ struct VerificPass : public Pass { } if (GetSize(args) > argidx && (args[argidx] == "-vlog95" || args[argidx] == "-vlog2k" || args[argidx] == "-sv2005" || - args[argidx] == "-sv2009" || args[argidx] == "-sv2012" || args[argidx] == "-sv")) + args[argidx] == "-sv2009" || args[argidx] == "-sv2012" || args[argidx] == "-sv" || args[argidx] == "-formal")) { Array file_names; unsigned verilog_mode; @@ -1858,11 +1861,14 @@ struct VerificPass : public Pass { verilog_mode = veri_file::SYSTEM_VERILOG_2005; else if (args[argidx] == "-sv2009") verilog_mode = veri_file::SYSTEM_VERILOG_2009; - else if (args[argidx] == "-sv2012" || args[argidx] == "-sv") + else if (args[argidx] == "-sv2012" || args[argidx] == "-sv" || args[argidx] == "-formal") verilog_mode = veri_file::SYSTEM_VERILOG; else log_abort(); + veri_file::DefineMacro("VERIFIC"); + veri_file::DefineMacro(args[argidx] == "-formal" ? "FORMAL" : "SYNTHESIS"); + for (argidx++; argidx < GetSize(args) && GetSize(args[argidx]) >= 2 && args[argidx].substr(0, 2) == "-D"; argidx++) { std::string name = args[argidx].substr(2); if (args[argidx] == "-D") { @@ -2157,7 +2163,7 @@ struct ReadPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" read {-vlog95|-vlog2k|-sv2005|-sv2009|-sv2012|-sv} ..\n"); + log(" read {-vlog95|-vlog2k|-sv2005|-sv2009|-sv2012|-sv|-formal} ..\n"); log("\n"); log("Load the specified Verilog/SystemVerilog files. (Full SystemVerilog support\n"); log("is only available via Verific.)\n"); @@ -2206,11 +2212,13 @@ struct ReadPass : public Pass { return; } - if (args[1] == "-sv2005" || args[1] == "-sv2009" || args[1] == "-sv2012" || args[1] == "-sv") { + if (args[1] == "-sv2005" || args[1] == "-sv2009" || args[1] == "-sv2012" || args[1] == "-sv" || args[1] == "-formal") { if (use_verific) { args[0] = "verific"; } else { args[0] = "read_verilog"; + if (args[1] == "-formal") + args.insert(args.begin()+1, std::string()); args[1] = "-sv"; } Pass::call(design, args); -- cgit v1.2.3 From 0404cf61d5f230de70bc6e6e6bf907bf7b112e0d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 29 Jun 2018 19:21:04 +0200 Subject: Add verific support for eventually properties Signed-off-by: Clifford Wolf --- frontends/verific/verificsva.cc | 110 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 105 insertions(+), 5 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verificsva.cc b/frontends/verific/verificsva.cc index 4e440b4ca..9312fd6e6 100644 --- a/frontends/verific/verificsva.cc +++ b/frontends/verific/verificsva.cc @@ -980,7 +980,6 @@ struct VerificSvaImporter bool mode_assume = false; bool mode_cover = false; bool mode_trigger = false; - bool eventually = false; Instance *net_to_ast_driver(Net *n) { @@ -1487,6 +1486,69 @@ struct VerificSvaImporter fsm.getFirstAcceptReject(accept_p, reject_p); } + bool eventually_property(Net *&net, SigBit &trig) + { + if (clocking.cond_net != nullptr) + trig = importer->net_map_at(clocking.cond_net); + else + trig = State::S1; + + Instance *inst = net_to_ast_driver(net); + + if (inst->Type() == PRIM_SVA_S_EVENTUALLY || inst->Type() == PRIM_SVA_EVENTUALLY) + { + if (mode_cover || mode_trigger) + parser_error(inst); + + net = inst->GetInput(); + clocking.cond_net = nullptr; + + return true; + } + + if (inst->Type() == PRIM_SVA_OVERLAPPED_IMPLICATION || + inst->Type() == PRIM_SVA_NON_OVERLAPPED_IMPLICATION) + { + Net *antecedent_net = inst->GetInput1(); + Net *consequent_net = inst->GetInput2(); + + Instance *consequent_inst = net_to_ast_driver(consequent_net); + + if (consequent_inst->Type() != PRIM_SVA_S_EVENTUALLY && consequent_inst->Type() != PRIM_SVA_EVENTUALLY) { + return false; + } + + if (mode_cover || mode_trigger) + parser_error(consequent_inst); + + int node; + + log_dump(trig); + SvaFsm antecedent_fsm(clocking, trig); + node = parse_sequence(antecedent_fsm, antecedent_fsm.createStartNode(), antecedent_net); + if (inst->Type() == PRIM_SVA_NON_OVERLAPPED_IMPLICATION) { + int next_node = antecedent_fsm.createNode(); + antecedent_fsm.createEdge(node, next_node); + node = next_node; + } + antecedent_fsm.createLink(node, antecedent_fsm.acceptNode); + + trig = antecedent_fsm.getAccept(); + net = consequent_inst->GetInput(); + clocking.cond_net = nullptr; + + if (verific_verbose) { + log(" Eventually Antecedent FSM:\n"); + antecedent_fsm.dump(); + log_dump(trig); + } + + return true; + } + + return false; + } + void parse_property(Net *net, SigBit *accept_p, SigBit *reject_p) { Instance *inst = net_to_ast_driver(net); @@ -1620,10 +1682,48 @@ struct VerificSvaImporter } else { - if (mode_assert || mode_assume) { - parse_property(clocking.body_net, nullptr, &reject_bit); - } else { - parse_property(clocking.body_net, &accept_bit, nullptr); + Net *net = clocking.body_net; + SigBit trig; + + if (eventually_property(net, trig)) + { + SigBit sig_a, sig_en = trig; + parse_property(net, &sig_a, nullptr); + + log_dump(trig, sig_a, sig_en); + + // add final FF stage + + SigBit sig_a_q, sig_en_q; + + if (clocking.body_net == nullptr) { + sig_a_q = sig_a; + sig_en_q = sig_en; + } else { + sig_a_q = module->addWire(NEW_ID); + sig_en_q = module->addWire(NEW_ID); + clocking.addDff(NEW_ID, sig_a, sig_a_q, State::S0); + clocking.addDff(NEW_ID, sig_en, sig_en_q, State::S0); + } + + // generate fair/live cell + + RTLIL::Cell *c = nullptr; + + if (mode_assert) c = module->addLive(root_name, sig_a_q, sig_en_q); + if (mode_assume) c = module->addFair(root_name, sig_a_q, sig_en_q); + + importer->import_attributes(c->attributes, root); + + return; + } + else + { + if (mode_assert || mode_assume) { + parse_property(net, nullptr, &reject_bit); + } else { + parse_property(net, &accept_bit, nullptr); + } } } -- cgit v1.2.3 From 8b92ddb9d2635c30636b17ff3d24bc09a44b8551 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 29 Jun 2018 19:24:58 +0200 Subject: Fix verific eventually handling Signed-off-by: Clifford Wolf --- frontends/verific/verificsva.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verificsva.cc b/frontends/verific/verificsva.cc index 9312fd6e6..8e985c3a6 100644 --- a/frontends/verific/verificsva.cc +++ b/frontends/verific/verificsva.cc @@ -1488,13 +1488,16 @@ struct VerificSvaImporter bool eventually_property(Net *&net, SigBit &trig) { + Instance *inst = net_to_ast_driver(net); + + if (inst == nullptr) + return false; + if (clocking.cond_net != nullptr) trig = importer->net_map_at(clocking.cond_net); else trig = State::S1; - Instance *inst = net_to_ast_driver(net); - if (inst->Type() == PRIM_SVA_S_EVENTUALLY || inst->Type() == PRIM_SVA_EVENTUALLY) { if (mode_cover || mode_trigger) @@ -1523,7 +1526,6 @@ struct VerificSvaImporter int node; - log_dump(trig); SvaFsm antecedent_fsm(clocking, trig); node = parse_sequence(antecedent_fsm, antecedent_fsm.createStartNode(), antecedent_net); if (inst->Type() == PRIM_SVA_NON_OVERLAPPED_IMPLICATION) { @@ -1540,7 +1542,6 @@ struct VerificSvaImporter if (verific_verbose) { log(" Eventually Antecedent FSM:\n"); antecedent_fsm.dump(); - log_dump(trig); } return true; @@ -1690,8 +1691,6 @@ struct VerificSvaImporter SigBit sig_a, sig_en = trig; parse_property(net, &sig_a, nullptr); - log_dump(trig, sig_a, sig_en); - // add final FF stage SigBit sig_a_q, sig_en_q; -- cgit v1.2.3 From f39b897545c0f9b4d02c77cc7b6cd2a3bfc6082f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 16 Jul 2018 15:32:26 +0200 Subject: Add "read -incdir" Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 62a8028b8..ab752b96d 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -2186,6 +2186,11 @@ struct ReadPass : public Pass { log("\n"); log("Unset global Verilog/SystemVerilog defines.\n"); log("\n"); + log("\n"); + log(" read -incdir \n"); + log("\n"); + log("Add directory to global Verilog/SystemVerilog include directories.\n"); + log("\n"); } virtual void execute(std::vector args, RTLIL::Design *design) { @@ -2263,6 +2268,20 @@ struct ReadPass : public Pass { return; } + if (args[1] == "-incdir") { + if (use_verific) { + args[0] = "verific"; + args[1] = "-vlog-incdir"; + Pass::call(design, args); + } + args[0] = "verilog_defaults"; + args[1] = "-add"; + for (int i = 1; i < GetSize(args); i++) + args[i] = "-I" + args[i]; + Pass::call(design, args); + return; + } + log_cmd_error("Missing or unsupported mode parameter.\n"); } } ReadPass; -- cgit v1.2.3 From f897af626dc8f84c79dc9274a5a5fa868018480f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 16 Jul 2018 16:48:09 +0200 Subject: Fix "read -incdir" Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index ab752b96d..54b682082 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -2276,7 +2276,7 @@ struct ReadPass : public Pass { } args[0] = "verilog_defaults"; args[1] = "-add"; - for (int i = 1; i < GetSize(args); i++) + for (int i = 2; i < GetSize(args); i++) args[i] = "-I" + args[i]; Pass::call(design, args); return; -- cgit v1.2.3 From 5041ed2f7df1e932eed6bc4ad38fb0f0973700af Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 16 Jul 2018 18:46:06 +0200 Subject: Fix verific -vlog-incdir and -vlog-libdir handling Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 54b682082..8937cdde8 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -65,6 +65,8 @@ int verific_verbose; bool verific_import_pending; string verific_error_msg; +vector verific_incdirs, verific_libdirs; + void msg_func(msg_type_t msg_type, const char *message_id, linefile_type linefile, const char *msg, va_list args) { string message_prefix = stringf("VERIFIC-%s [%s] ", @@ -1658,6 +1660,8 @@ void verific_import(Design *design, std::string top) veri_file::Reset(); vhdl_file::Reset(); Libset::Reset(); + verific_incdirs.clear(); + verific_libdirs.clear(); verific_import_pending = false; if (!verific_error_msg.empty()) @@ -1814,13 +1818,13 @@ struct VerificPass : public Pass { if (GetSize(args) > argidx && args[argidx] == "-vlog-incdir") { for (argidx++; argidx < GetSize(args); argidx++) - veri_file::AddIncludeDir(args[argidx].c_str()); + verific_incdirs.push_back(args[argidx]); goto check_error; } if (GetSize(args) > argidx && args[argidx] == "-vlog-libdir") { for (argidx++; argidx < GetSize(args); argidx++) - veri_file::AddYDir(args[argidx].c_str()); + verific_libdirs.push_back(args[argidx]); goto check_error; } @@ -1886,6 +1890,11 @@ struct VerificPass : public Pass { } } + for (auto &dir : verific_incdirs) + veri_file::AddIncludeDir(dir.c_str()); + for (auto &dir : verific_libdirs) + veri_file::AddYDir(dir.c_str()); + while (argidx < GetSize(args)) file_names.Insert(args[argidx++].c_str()); @@ -2139,6 +2148,8 @@ struct VerificPass : public Pass { veri_file::Reset(); vhdl_file::Reset(); Libset::Reset(); + verific_incdirs.clear(); + verific_libdirs.clear(); verific_import_pending = false; goto check_error; } -- cgit v1.2.3 From 65234d4b24edd1ec8ec5d41df2d56d76fa41dcc5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 17 Jul 2018 12:43:30 +0200 Subject: Fix handling of eventually properties in verific importer Signed-off-by: Clifford Wolf --- frontends/verific/verificsva.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verificsva.cc b/frontends/verific/verificsva.cc index 8e985c3a6..85b842186 100644 --- a/frontends/verific/verificsva.cc +++ b/frontends/verific/verificsva.cc @@ -1517,9 +1517,11 @@ struct VerificSvaImporter Instance *consequent_inst = net_to_ast_driver(consequent_net); - if (consequent_inst->Type() != PRIM_SVA_S_EVENTUALLY && consequent_inst->Type() != PRIM_SVA_EVENTUALLY) { + if (consequent_inst == nullptr) + return false; + + if (consequent_inst->Type() != PRIM_SVA_S_EVENTUALLY && consequent_inst->Type() != PRIM_SVA_EVENTUALLY) return false; - } if (mode_cover || mode_trigger) parser_error(consequent_inst); -- cgit v1.2.3 From 1a60126a3468c525ac31de930dfb139b70512a34 Mon Sep 17 00:00:00 2001 From: Henner Zeller Date: Thu, 19 Jul 2018 09:40:20 -0700 Subject: Provide source-location logging. o Provide log_file_warning() and log_file_error() that prefix the log message with :: to be easily picked up by IDEs that need to step through errors. o Simplify some duplicate logging code in kernel/log.cc o Use the new log functions in genrtlil. --- frontends/ast/genrtlil.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index d9f0039af..b8208fa80 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -958,9 +958,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); wire->name = str; if (flag_autowire) - log_warning("Identifier `%s' is implicitly declared at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_file_warning(filename, linenum, "Identifier `%s' is implicitly declared.\n", str.c_str()); else - log_error("Identifier `%s' is implicitly declared at %s:%d and `default_nettype is set to none.\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str()); } else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM) { if (id2ast->children[0]->type != AST_CONSTANT) @@ -1563,4 +1563,3 @@ RTLIL::SigSpec AstNode::genWidthRTLIL(int width, const dict Date: Fri, 20 Jul 2018 08:11:20 -0700 Subject: Use log_file_warning(), log_file_error() functions. Wherever we can report a source-level location. --- frontends/ast/genrtlil.cc | 32 ++++----- frontends/ast/simplify.cc | 121 +++++++++++++++++----------------- frontends/verilog/verilog_frontend.cc | 8 +-- 3 files changed, 79 insertions(+), 82 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index b8208fa80..e611ddcb1 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -238,7 +238,7 @@ struct AST_INTERNAL::ProcessGenerator if (found_anyedge_syncs) { if (found_global_syncs) - log_error("Found non-synthesizable event list at %s:%d!\n", always->filename.c_str(), always->linenum); + log_file_error(always->filename, always->linenum, "Found non-synthesizable event list!\n"); log("Note: Assuming pure combinatorial block at %s:%d in\n", always->filename.c_str(), always->linenum); log("compliance with IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002. Recommending\n"); log("use of @* instead of @(...) for better match of synthesis and simulation.\n"); @@ -253,12 +253,12 @@ struct AST_INTERNAL::ProcessGenerator continue; found_clocked_sync = true; if (found_global_syncs || found_anyedge_syncs) - log_error("Found non-synthesizable event list at %s:%d!\n", always->filename.c_str(), always->linenum); + log_file_error(always->filename, always->linenum, "Found non-synthesizable event list!\n"); RTLIL::SyncRule *syncrule = new RTLIL::SyncRule; syncrule->type = child->type == AST_POSEDGE ? RTLIL::STp : RTLIL::STn; syncrule->signal = child->children[0]->genRTLIL(); if (GetSize(syncrule->signal) != 1) - log_error("Found posedge/negedge event on a signal that is not 1 bit wide at %s:%d!\n", always->filename.c_str(), always->linenum); + log_file_error(always->filename, always->linenum, "Found posedge/negedge event on a signal that is not 1 bit wide!\n"); addChunkActions(syncrule->actions, subst_lvalue_from, subst_lvalue_to, true); proc->syncs.push_back(syncrule); } @@ -549,12 +549,12 @@ struct AST_INTERNAL::ProcessGenerator break; case AST_WIRE: - log_error("Found wire declaration in block without label at at %s:%d!\n", ast->filename.c_str(), ast->linenum); + log_file_error(ast->filename, ast->linenum, "Found wire declaration in block without label!\n"); break; case AST_PARAMETER: case AST_LOCALPARAM: - log_error("Found parameter declaration in block without label at at %s:%d!\n", ast->filename.c_str(), ast->linenum); + log_file_error(ast->filename, ast->linenum, "Found parameter declaration in block without label!\n"); break; case AST_NONE: @@ -602,7 +602,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun if (id_ast == NULL && current_scope.count(str)) id_ast = current_scope.at(str); if (!id_ast) - log_error("Failed to resolve identifier %s for width detection at %s:%d!\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to resolve identifier %s for width detection!\n", str.c_str()); if (id_ast->type == AST_PARAMETER || id_ast->type == AST_LOCALPARAM) { if (id_ast->children.size() > 1 && id_ast->children[1]->range_valid) { this_width = id_ast->children[1]->range_left - id_ast->children[1]->range_right + 1; @@ -612,7 +612,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun if (id_ast->children[0]->type == AST_CONSTANT) this_width = id_ast->children[0]->bits.size(); else - log_error("Failed to detect width for parameter %s at %s:%d!\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to detect width for parameter %s!\n", str.c_str()); if (children.size() != 0) range = children[0]; } else if (id_ast->type == AST_WIRE || id_ast->type == AST_AUTOWIRE) { @@ -624,7 +624,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun // log("---\n"); // id_ast->dumpAst(NULL, "decl> "); // dumpAst(NULL, "ref> "); - log_error("Failed to detect width of signal access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to detect width of signal access `%s'!\n", str.c_str()); } } else { this_width = id_ast->range_left - id_ast->range_right + 1; @@ -635,10 +635,10 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun this_width = 32; } else if (id_ast->type == AST_MEMORY) { if (!id_ast->children[0]->range_valid) - log_error("Failed to detect width of memory access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", str.c_str()); this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1; } else - log_error("Failed to detect width for identifier %s at %s:%d!\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to detect width for identifier %s!\n", str.c_str()); if (range) { if (range->children.size() == 1) this_width = 1; @@ -665,7 +665,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun case AST_TO_BITS: while (children[0]->simplify(true, false, false, 1, -1, false, false) == true) { } if (children[0]->type != AST_CONSTANT) - log_error("Left operand of tobits expression is not constant at %s:%d!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Left operand of tobits expression is not constant!\n"); children[1]->detectSignWidthWorker(sub_width_hint, sign_hint); width_hint = max(width_hint, children[0]->bitsAsConst().as_int()); break; @@ -693,7 +693,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun case AST_REPLICATE: while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { } if (children[0]->type != AST_CONSTANT) - log_error("Left operand of replicate expression is not constant at %s:%d!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Left operand of replicate expression is not constant!\n"); children[1]->detectSignWidthWorker(sub_width_hint, sub_sign_hint); width_hint = max(width_hint, children[0]->bitsAsConst().as_int() * sub_width_hint); sign_hint = false; @@ -767,7 +767,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun if (!id2ast->is_signed) sign_hint = false; if (!id2ast->children[0]->range_valid) - log_error("Failed to detect width of memory access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", str.c_str()); this_width = id2ast->children[0]->range_left - id2ast->children[0]->range_right + 1; width_hint = max(width_hint, this_width); break; @@ -1083,7 +1083,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) RTLIL::SigSpec left = children[0]->genRTLIL(); RTLIL::SigSpec right = children[1]->genRTLIL(); if (!left.is_fully_const()) - log_error("Left operand of replicate expression is not constant at %s:%d!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Left operand of replicate expression is not constant!\n"); int count = left.as_int(); RTLIL::SigSpec sig; for (int i = 0; i < count; i++) @@ -1322,7 +1322,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) int num_words = 1; if (type == AST_MEMINIT) { if (children[2]->type != AST_CONSTANT) - log_error("Memory init with non-constant word count at %s:%d!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Memory init with non-constant word count!\n"); num_words = int(children[2]->asInt(false)); cell->parameters["\\WORDS"] = RTLIL::Const(num_words); } @@ -1514,7 +1514,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (attributes.count("\\reg")) { auto &attr = attributes.at("\\reg"); if (attr->type != AST_CONSTANT) - log_error("Attribute `reg' with non-constant value at %s:%d!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Attribute `reg' with non-constant value!\n"); cell->attributes["\\reg"] = attr->asAttrConst(); } diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index a16fdfeeb..81bd3cd7e 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -177,13 +177,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list if ((type == AST_FCALL || type == AST_TCALL) && (str == "$strobe" || str == "$monitor" || str == "$time" || str == "$dumpfile" || str == "$dumpvars" || str == "$dumpon" || str == "$dumpoff" || str == "$dumpall")) { - log_warning("Ignoring call to system %s %s at %s:%d.\n", type == AST_FCALL ? "function" : "task", str.c_str(), filename.c_str(), linenum); + log_file_warning(filename, linenum, "Ignoring call to system %s %s.\n", type == AST_FCALL ? "function" : "task", str.c_str()); delete_children(); str = std::string(); } if ((type == AST_TCALL) && (str == "$display" || str == "$write") && (!current_always || current_always->type != AST_INITIAL)) { - log_warning("System task `%s' outside initial block is unsupported at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_file_warning(filename, linenum, "System task `%s' outside initial block is unsupported.\n", str.c_str()); delete_children(); str = std::string(); } @@ -202,7 +202,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, AstNode *node_string = children[0]; while (node_string->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (node_string->type != AST_CONSTANT) - log_error("Failed to evaluate system task `%s' with non-constant 1st argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to evaluate system task `%s' with non-constant 1st argument.\n", str.c_str()); std::string sformat = node_string->bitsAsConst().decode_string(); // Other arguments are placeholders. Process the string as we go through it @@ -215,7 +215,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, { // If there's no next character, that's a problem if (i+1 >= sformat.length()) - log_error("System task `%s' called with `%%' at end of string at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "System task `%s' called with `%%' at end of string.\n", str.c_str()); char cformat = sformat[++i]; @@ -245,7 +245,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, node_arg = children[next_arg++]; while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (node_arg->type != AST_CONSTANT) - log_error("Failed to evaluate system task `%s' with non-constant argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to evaluate system task `%s' with non-constant argument.\n", str.c_str()); break; case 'm': @@ -253,7 +253,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, break; default: - log_error("System task `%s' called with invalid/unsupported format specifier at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "System task `%s' called with invalid/unsupported format specifier.\n", str.c_str()); break; } @@ -374,7 +374,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, continue; wires_are_incompatible: if (stage > 1) - log_error("Incompatible re-declaration of wire %s at %s:%d.\n", node->str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Incompatible re-declaration of wire %s.\n", node->str.c_str()); continue; } this_wire_scope[node->str] = node; @@ -402,7 +402,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_ALWAYS || type == AST_INITIAL) { if (current_always != nullptr) - log_error("Invalid nesting of always blocks and/or initializations at %s:%d.\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Invalid nesting of always blocks and/or initializations.\n"); current_always = this; current_always_clocked = false; @@ -451,7 +451,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, true) == true) did_something = true; if (!children[1]->range_valid) - log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Non-constant width range on parameter decl.\n"); width_hint = max(width_hint, children[1]->range_left - children[1]->range_right + 1); } break; @@ -695,7 +695,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_DEFPARAM && !children.empty()) { if (children[0]->type != AST_IDENTIFIER) - log_error("Module name in defparam at %s:%d contains non-constant expressions!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Module name in defparam contains non-constant expressions!\n"); string modname, paramname = children[0]->str; @@ -712,7 +712,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } if (pos == std::string::npos) - log_error("Can't find object for defparam `%s` at %s:%d!\n", RTLIL::unescape_id(paramname).c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname).c_str()); paramname = "\\" + paramname.substr(pos+1); @@ -732,7 +732,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_PREFIX) { if (children[0]->type != AST_CONSTANT) { // dumpAst(NULL, "> "); - log_error("Index in generate block prefix syntax at %s:%d is not constant!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Index in generate block prefix syntax is not constant!\n"); } if (children[1]->type == AST_PREFIX) children[1]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param); @@ -748,9 +748,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // evaluate TO_BITS nodes if (type == AST_TO_BITS) { if (children[0]->type != AST_CONSTANT) - log_error("Left operand of to_bits expression is not constant at %s:%d!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Left operand of to_bits expression is not constant!\n"); if (children[1]->type != AST_CONSTANT) - log_error("Right operand of to_bits expression is not constant at %s:%d!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Right operand of to_bits expression is not constant!\n"); RTLIL::Const new_value = children[1]->bitsAsConst(children[0]->bitsAsConst().as_int(), children[1]->is_signed); newNode = mkconst_bits(new_value.bits, children[1]->is_signed); goto apply_newNode; @@ -814,7 +814,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, multirange_dimensions.clear(); for (auto range : children[1]->children) { if (!range->range_valid) - log_error("Non-constant range on memory decl at %s:%d.\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Non-constant range on memory decl.\n"); multirange_dimensions.push_back(min(range->range_left, range->range_right)); multirange_dimensions.push_back(max(range->range_left, range->range_right) - min(range->range_left, range->range_right) + 1); total_size *= multirange_dimensions.back(); @@ -832,7 +832,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, for (int i = 0; 2*i < GetSize(id2ast->multirange_dimensions); i++) { if (GetSize(children[0]->children) < i) - log_error("Insufficient number of array indices for %s at %s:%d.\n", log_id(str), filename.c_str(), linenum); + log_file_error(filename, linenum, "Insufficient number of array indices for %s.\n", log_id(str)); AstNode *new_index_expr = children[0]->children[i]->children.at(0)->clone(); @@ -861,7 +861,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_PARAMETER || type == AST_LOCALPARAM) { if (children.size() > 1 && children[1]->type == AST_RANGE) { if (!children[1]->range_valid) - log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Non-constant width range on parameter decl.\n"); int width = std::abs(children[1]->range_left - children[1]->range_right) + 1; if (children[0]->type == AST_REALVALUE) { RTLIL::Const constvalue = children[0]->realAsConst(width); @@ -924,7 +924,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_IDENTIFIER && children.size() == 2 && children[0]->type == AST_RANGE && children[1]->type == AST_RANGE && !in_lvalue) { if (id2ast == NULL || id2ast->type != AST_MEMORY || children[0]->children.size() != 1) - log_error("Invalid bit-select on memory access at %s:%d!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Invalid bit-select on memory access!\n"); int mem_width, mem_size, addr_bits; id2ast->meminfo(mem_width, mem_size, addr_bits); @@ -973,10 +973,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } if (type == AST_WHILE) - log_error("While loops are only allowed in constant functions at %s:%d!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "While loops are only allowed in constant functions!\n"); if (type == AST_REPEAT) - log_error("Repeat loops are only allowed in constant functions at %s:%d!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Repeat loops are only allowed in constant functions!\n"); // unroll for loops and generate-for blocks if ((type == AST_GENFOR || type == AST_FOR) && children.size() != 0) @@ -991,31 +991,31 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, body_ast = body_ast->children.at(0); if (init_ast->type != AST_ASSIGN_EQ) - log_error("Unsupported 1st expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Unsupported 1st expression of generate for-loop!\n"); if (next_ast->type != AST_ASSIGN_EQ) - log_error("Unsupported 3rd expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Unsupported 3rd expression of generate for-loop!\n"); if (type == AST_GENFOR) { if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_GENVAR) - log_error("Left hand side of 1st expression of generate for-loop at %s:%d is not a gen var!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Left hand side of 1st expression of generate for-loop is not a gen var!\n"); if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_GENVAR) - log_error("Left hand side of 3rd expression of generate for-loop at %s:%d is not a gen var!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Left hand side of 3rd expression of generate for-loop is not a gen var!\n"); } else { if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_WIRE) - log_error("Left hand side of 1st expression of generate for-loop at %s:%d is not a register!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Left hand side of 1st expression of generate for-loop is not a register!\n"); if (next_ast->children[0]->id2ast == NULL || next_ast->children[0]->id2ast->type != AST_WIRE) - log_error("Left hand side of 3rd expression of generate for-loop at %s:%d is not a register!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Left hand side of 3rd expression of generate for-loop is not a register!\n"); } if (init_ast->children[0]->id2ast != next_ast->children[0]->id2ast) - log_error("Incompatible left-hand sides in 1st and 3rd expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Incompatible left-hand sides in 1st and 3rd expression of generate for-loop!\n"); // eval 1st expression AstNode *varbuf = init_ast->children[1]->clone(); while (varbuf->simplify(true, false, false, stage, 32, true, false)) { } if (varbuf->type != AST_CONSTANT) - log_error("Right hand side of 1st expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Right hand side of 1st expression of generate for-loop is not constant!\n"); varbuf = new AstNode(AST_LOCALPARAM, varbuf); varbuf->str = init_ast->children[0]->str; @@ -1037,7 +1037,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (buf->type != AST_CONSTANT) - log_error("2nd expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "2nd expression of generate for-loop is not constant!\n"); if (buf->integer == 0) { delete buf; @@ -1078,7 +1078,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, while (buf->simplify(true, false, false, stage, 32, true, false)) { } if (buf->type != AST_CONSTANT) - log_error("Right hand side of 3rd expression of generate for-loop at %s:%d is not constant!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Right hand side of 3rd expression of generate for-loop is not constant!\n"); delete varbuf->children[0]; varbuf->children[0] = buf; @@ -1144,7 +1144,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (buf->type != AST_CONSTANT) { // for (auto f : log_files) // dumpAst(f, "verilog-ast> "); - log_error("Condition for generate if at %s:%d is not constant!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Condition for generate if is not constant!\n"); } if (buf->asBool() != 0) { delete buf; @@ -1185,7 +1185,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (buf->type != AST_CONSTANT) { // for (auto f : log_files) // dumpAst(f, "verilog-ast> "); - log_error("Condition for generate case at %s:%d is not constant!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Condition for generate case is not constant!\n"); } bool ref_signed = buf->is_signed; @@ -1219,7 +1219,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (buf->type != AST_CONSTANT) { // for (auto f : log_files) // dumpAst(f, "verilog-ast> "); - log_error("Expression in generate case at %s:%d is not constant!\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Expression in generate case is not constant!\n"); } bool is_selected = RTLIL::const_eq(ref_value, buf->bitsAsConst(), ref_signed && buf->is_signed, ref_signed && buf->is_signed, 1).as_bool(); @@ -1260,7 +1260,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_CELLARRAY) { if (!children.at(0)->range_valid) - log_error("Non-constant array range on cell array at %s:%d.\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Non-constant array range on cell array.\n"); newNode = new AstNode(AST_GENBLOCK); int num = max(children.at(0)->range_left, children.at(0)->range_right) - min(children.at(0)->range_left, children.at(0)->range_right) + 1; @@ -1271,7 +1271,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, newNode->children.push_back(new_cell); new_cell->str += stringf("[%d]", idx); if (new_cell->type == AST_PRIMITIVE) { - log_error("Cell arrays of primitives are currently not supported at %s:%d.\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Cell arrays of primitives are currently not supported.\n"); } else { log_assert(new_cell->children.at(0)->type == AST_CELLTYPE); new_cell->children.at(0)->str = stringf("$array:%d:%d:%s", i, num, new_cell->children.at(0)->str.c_str()); @@ -1645,7 +1645,7 @@ skip_dynamic_range_lvalue_expansion:; while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) - log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1; assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), @@ -1749,7 +1749,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *buf = children[1]->clone(); while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (buf->type != AST_CONSTANT) - log_error("Failed to evaluate system function `%s' with non-constant value at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str()); num_steps = buf->asInt(true); delete buf; @@ -1846,7 +1846,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *buf = children[0]->clone(); while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (buf->type != AST_CONSTANT) - log_error("Failed to evaluate system function `%s' with non-constant value at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str()); RTLIL::Const arg_value = buf->bitsAsConst(); if (arg_value.as_bool()) @@ -1893,7 +1893,7 @@ skip_dynamic_range_lvalue_expansion:; if (id_ast == NULL && current_scope.count(buf->str)) id_ast = current_scope.at(buf->str); if (!id_ast) - log_error("Failed to resolve identifier %s for width detection at %s:%d!\n", buf->str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to resolve identifier %s for width detection!\n", buf->str.c_str()); if (id_ast->type == AST_MEMORY) { // We got here only if the argument is a memory // Otherwise $size() and $bits() return the expression width @@ -1901,15 +1901,15 @@ skip_dynamic_range_lvalue_expansion:; if (str == "\\$bits") { if (mem_range->type == AST_RANGE) { if (!mem_range->range_valid) - log_error("Failed to detect width of memory access `%s' at %s:%d!\n", buf->str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", buf->str.c_str()); mem_depth = mem_range->range_left - mem_range->range_right + 1; } else - log_error("Unknown memory depth AST type in `%s' at %s:%d!\n", buf->str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str()); } else { // $size() if (mem_range->type == AST_RANGE) { if (!mem_range->range_valid) - log_error("Failed to detect width of memory access `%s' at %s:%d!\n", buf->str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", buf->str.c_str()); int dims; if (id_ast->multirange_dimensions.empty()) dims = 1; @@ -1920,9 +1920,9 @@ skip_dynamic_range_lvalue_expansion:; else if (dim <= dims) { width_hint = id_ast->multirange_dimensions[2*dim-1]; } else if ((dim > dims+1) || (dim < 0)) - log_error("Dimension %d out of range in `%s', as it only has dimensions 1..%d at %s:%d!\n", dim, buf->str.c_str(), dims+1, filename.c_str(), linenum); + log_file_error(filename, linenum, "Dimension %d out of range in `%s', as it only has dimensions 1..%d!\n", dim, buf->str.c_str(), dims+1); } else - log_error("Unknown memory depth AST type in `%s' at %s:%d!\n", buf->str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Unknown memory depth AST type in `%s'!\n", buf->str.c_str()); } } } @@ -2018,14 +2018,14 @@ skip_dynamic_range_lvalue_expansion:; for (int i = 2; i < GetSize(dpi_decl->children); i++) { if (i-2 >= GetSize(children)) - log_error("Insufficient number of arguments in DPI function call at %s:%d.\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Insufficient number of arguments in DPI function call.\n"); argtypes.push_back(RTLIL::unescape_id(dpi_decl->children.at(i)->str)); args.push_back(children.at(i-2)->clone()); while (args.back()->simplify(true, false, false, stage, -1, false, true)) { } if (args.back()->type != AST_CONSTANT && args.back()->type != AST_REALVALUE) - log_error("Failed to evaluate DPI function with non-constant argument at %s:%d.\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to evaluate DPI function with non-constant argument.\n"); } newNode = dpi_call(rtype, fname, argtypes, args); @@ -2037,7 +2037,7 @@ skip_dynamic_range_lvalue_expansion:; } if (current_scope.count(str) == 0 || current_scope[str]->type != AST_FUNCTION) - log_error("Can't resolve function name `%s' at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Can't resolve function name `%s'.\n", str.c_str()); } if (type == AST_TCALL) @@ -2045,9 +2045,9 @@ skip_dynamic_range_lvalue_expansion:; if (str == "$finish" || str == "$stop") { if (!current_always || current_always->type != AST_INITIAL) - log_error("System task `%s' outside initial block is unsupported at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "System task `%s' outside initial block is unsupported.\n", str.c_str()); - log_error("System task `%s' executed at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "System task `%s' executed.\n", str.c_str()); } if (str == "\\$readmemh" || str == "\\$readmemb") @@ -2059,12 +2059,12 @@ skip_dynamic_range_lvalue_expansion:; AstNode *node_filename = children[0]->clone(); while (node_filename->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (node_filename->type != AST_CONSTANT) - log_error("Failed to evaluate system function `%s' with non-constant 1st argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant 1st argument.\n", str.c_str()); AstNode *node_memory = children[1]->clone(); while (node_memory->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (node_memory->type != AST_IDENTIFIER || node_memory->id2ast == nullptr || node_memory->id2ast->type != AST_MEMORY) - log_error("Failed to evaluate system function `%s' with non-memory 2nd argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-memory 2nd argument.\n", str.c_str()); int start_addr = -1, finish_addr = -1; @@ -2072,7 +2072,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *node_addr = children[2]->clone(); while (node_addr->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (node_addr->type != AST_CONSTANT) - log_error("Failed to evaluate system function `%s' with non-constant 3rd argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant 3rd argument.\n", str.c_str()); start_addr = int(node_addr->asInt(false)); } @@ -2080,7 +2080,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *node_addr = children[3]->clone(); while (node_addr->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (node_addr->type != AST_CONSTANT) - log_error("Failed to evaluate system function `%s' with non-constant 4th argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant 4th argument.\n", str.c_str()); finish_addr = int(node_addr->asInt(false)); } @@ -2106,7 +2106,7 @@ skip_dynamic_range_lvalue_expansion:; } if (current_scope.count(str) == 0 || current_scope[str]->type != AST_TASK) - log_error("Can't resolve task name `%s' at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Can't resolve task name `%s'.\n", str.c_str()); } AstNode *decl = current_scope[str]; @@ -2134,9 +2134,9 @@ skip_dynamic_range_lvalue_expansion:; } if (in_param) - log_error("Non-constant function call in constant expression at %s:%d.\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Non-constant function call in constant expression.\n"); if (require_const_eval) - log_error("Function %s can only be called with constant arguments at %s:%d.\n", str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Function %s can only be called with constant arguments.\n", str.c_str()); } size_t arg_count = 0; @@ -2253,7 +2253,7 @@ skip_dynamic_range_lvalue_expansion:; goto tcall_incompatible_wires; } else { tcall_incompatible_wires: - log_error("Incompatible re-declaration of wire %s at %s:%d.\n", child->str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Incompatible re-declaration of wire %s.\n", child->str.c_str()); } } } @@ -2641,7 +2641,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m yosys_input_files.insert(mem_filename); if (f.fail()) - log_error("Can not open file `%s` for %s at %s:%d.\n", mem_filename.c_str(), str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Can not open file `%s` for %s.\n", mem_filename.c_str(), str.c_str()); log_assert(GetSize(memory->children) == 2 && memory->children[1]->type == AST_RANGE && memory->children[1]->range_valid); int range_left = memory->children[1]->range_left, range_right = memory->children[1]->range_right; @@ -2687,7 +2687,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m char *endptr; cursor = strtol(nptr, &endptr, 16); if (!*nptr || *endptr) - log_error("Can not parse address `%s` for %s at %s:%d.\n", nptr, str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Can not parse address `%s` for %s.\n", nptr, str.c_str()); continue; } @@ -2943,7 +2943,7 @@ bool AstNode::mem2reg_check(pool &mem2reg_set) return false; if (children.empty() || children[0]->type != AST_RANGE || GetSize(children[0]->children) != 1) - log_error("Invalid array access at %s:%d.\n", filename.c_str(), linenum); + log_file_error(filename, linenum, "Invalid array access.\n"); return true; } @@ -3446,4 +3446,3 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) } YOSYS_NAMESPACE_END - diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 505c94619..be925fea2 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -42,7 +42,7 @@ static std::list> verilog_defaults_stack; static void error_on_dpi_function(AST::AstNode *node) { if (node->type == AST::AST_DPI_FUNCTION) - log_error("Found DPI function %s at %s:%d.\n", node->str.c_str(), node->filename.c_str(), node->linenum); + log_file_error(node->filename, node->linenum, "Found DPI function %s.\n", node->str.c_str()); for (auto child : node->children) error_on_dpi_function(child); } @@ -519,13 +519,11 @@ void frontend_verilog_yyerror(char const *fmt, ...) va_list ap; char buffer[1024]; char *p = buffer; - p += snprintf(p, buffer + sizeof(buffer) - p, "Parser error in line %s:%d: ", - YOSYS_NAMESPACE_PREFIX AST::current_filename.c_str(), frontend_verilog_yyget_lineno()); va_start(ap, fmt); p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap); va_end(ap); p += snprintf(p, buffer + sizeof(buffer) - p, "\n"); - YOSYS_NAMESPACE_PREFIX log_error("%s", buffer); + YOSYS_NAMESPACE_PREFIX log_file_error(YOSYS_NAMESPACE_PREFIX AST::current_filename, frontend_verilog_yyget_lineno(), + "%s", buffer); exit(1); } - -- cgit v1.2.3 From 68b5d0c3b11588946982939c00fd6febe198e13f Mon Sep 17 00:00:00 2001 From: Henner Zeller Date: Fri, 20 Jul 2018 09:37:44 -0700 Subject: Convert more log_error() to log_file_error() where possible. Mostly statements that span over multiple lines and haven't been caught with the previous conversion. --- frontends/ast/ast.cc | 13 ++-- frontends/ast/genrtlil.cc | 140 ++++++++++++++++++++--------------------- frontends/ast/simplify.cc | 107 ++++++++++++++++--------------- frontends/verilog/const2ast.cc | 8 +-- 4 files changed, 131 insertions(+), 137 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 999202b47..54ce6a05d 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -171,8 +171,8 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id) AstNode *attr = attributes.at(id); if (attr->type != AST_CONSTANT) - log_error("Attribute `%s' with non-constant value at %s:%d!\n", - id.c_str(), attr->filename.c_str(), attr->linenum); + log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n", + id.c_str()); return attr->integer != 0; } @@ -955,8 +955,8 @@ static AstModule* process_module(AstNode *ast, bool defer) for (auto &attr : ast->attributes) { if (attr.second->type != AST_CONSTANT) - log_error("Attribute `%s' with non-constant value at %s:%d!\n", - attr.first.c_str(), ast->filename.c_str(), ast->linenum); + log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", + attr.first.c_str()); current_module->attributes[attr.first] = attr.second->asAttrConst(); } for (size_t i = 0; i < ast->children.size(); i++) { @@ -1044,8 +1044,8 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump if (design->has((*it)->str)) { RTLIL::Module *existing_mod = design->module((*it)->str); if (!nooverwrite && !overwrite && !existing_mod->get_bool_attribute("\\blackbox")) { - log_error("Re-definition of module `%s' at %s:%d!\n", - (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum); + log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n", + (*it)->str.c_str()); } else if (nooverwrite) { log("Ignoring re-definition of module `%s' at %s:%d.\n", (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum); @@ -1197,4 +1197,3 @@ void AST::use_internal_line_num() } YOSYS_NAMESPACE_END - diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index e611ddcb1..0f7e910f3 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -55,8 +55,8 @@ static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_wi if (gen_attributes) for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_error("Attribute `%s' with non-constant value at %s:%d!\n", - attr.first.c_str(), that->filename.c_str(), that->linenum); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", + attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -89,8 +89,8 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s if (that != NULL) for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_error("Attribute `%s' with non-constant value at %s:%d!\n", - attr.first.c_str(), that->filename.c_str(), that->linenum); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", + attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -117,8 +117,8 @@ static RTLIL::SigSpec binop2rtlil(AstNode *that, std::string type, int result_wi for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_error("Attribute `%s' with non-constant value at %s:%d!\n", - attr.first.c_str(), that->filename.c_str(), that->linenum); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", + attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -152,8 +152,8 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_error("Attribute `%s' with non-constant value at %s:%d!\n", - attr.first.c_str(), that->filename.c_str(), that->linenum); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", + attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -207,8 +207,8 @@ struct AST_INTERNAL::ProcessGenerator proc->name = stringf("$proc$%s:%d$%d", always->filename.c_str(), always->linenum, autoidx++); for (auto &attr : always->attributes) { if (attr.second->type != AST_CONSTANT) - log_error("Attribute `%s' with non-constant value at %s:%d!\n", - attr.first.c_str(), always->filename.c_str(), always->linenum); + log_file_error(always->filename, always->linenum, "Attribute `%s' with non-constant value!\n", + attr.first.c_str()); proc->attributes[attr.first] = attr.second->asAttrConst(); } current_module->processes[proc->name] = proc; @@ -480,8 +480,8 @@ struct AST_INTERNAL::ProcessGenerator for (auto &attr : ast->attributes) { if (attr.second->type != AST_CONSTANT) - log_error("Attribute `%s' with non-constant value at %s:%d!\n", - attr.first.c_str(), ast->filename.c_str(), ast->linenum); + log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", + attr.first.c_str()); sw->attributes[attr.first] = attr.second->asAttrConst(); } @@ -648,8 +648,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) - log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n", - str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", + str.c_str()); this_width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1; delete left_at_zero_ast; delete right_at_zero_ast; @@ -777,8 +777,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun if (GetSize(children) == 1) { while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { } if (children[0]->type != AST_CONSTANT) - log_error("System function %s called with non-const argument at %s:%d!\n", - RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "System function %s called with non-const argument!\n", + RTLIL::unescape_id(str).c_str()); width_hint = max(width_hint, int(children[0]->asInt(true))); } break; @@ -799,8 +799,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun default: for (auto f : log_files) current_ast->dumpAst(f, "verilog-ast> "); - log_error("Don't know how to detect sign and width for %s node at %s:%d!\n", - type2str(type).c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n", + type2str(type).c_str()); } if (*found_real) @@ -863,11 +863,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // create an RTLIL::Wire for an AST_WIRE node case AST_WIRE: { if (current_module->wires_.count(str) != 0) - log_error("Re-definition of signal `%s' at %s:%d!\n", - str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Re-definition of signal `%s'!\n", + str.c_str()); if (!range_valid) - log_error("Signal `%s' with non-constant width at %s:%d!\n", - str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n", + str.c_str()); log_assert(range_left >= range_right || (range_left == -1 && range_right == 0)); @@ -881,8 +881,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_error("Attribute `%s' with non-constant value at %s:%d!\n", - attr.first.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", + attr.first.c_str()); wire->attributes[attr.first] = attr.second->asAttrConst(); } } @@ -891,16 +891,16 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // create an RTLIL::Memory for an AST_MEMORY node case AST_MEMORY: { if (current_module->memories.count(str) != 0) - log_error("Re-definition of memory `%s' at %s:%d!\n", - str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Re-definition of memory `%s'!\n", + str.c_str()); log_assert(children.size() >= 2); log_assert(children[0]->type == AST_RANGE); log_assert(children[1]->type == AST_RANGE); if (!children[0]->range_valid || !children[1]->range_valid) - log_error("Memory `%s' with non-constant width or size at %s:%d!\n", - str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Memory `%s' with non-constant width or size!\n", + str.c_str()); RTLIL::Memory *memory = new RTLIL::Memory; memory->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); @@ -917,8 +917,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_error("Attribute `%s' with non-constant value at %s:%d!\n", - attr.first.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", + attr.first.c_str()); memory->attributes[attr.first] = attr.second->asAttrConst(); } } @@ -937,8 +937,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_REALVALUE: { RTLIL::SigSpec sig = realAsConst(width_hint); - log_warning("converting real value %e to binary %s at %s:%d.\n", - realvalue, log_signal(sig), filename.c_str(), linenum); + log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", + realvalue, log_signal(sig)); return sig; } @@ -964,19 +964,19 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM) { if (id2ast->children[0]->type != AST_CONSTANT) - log_error("Parameter %s does not evaluate to constant value at %s:%d!\n", - str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n", + str.c_str()); chunk = RTLIL::Const(id2ast->children[0]->bits); goto use_const_chunk; } else if (!id2ast || (id2ast->type != AST_WIRE && id2ast->type != AST_AUTOWIRE && id2ast->type != AST_MEMORY) || current_module->wires_.count(str) == 0) - log_error("Identifier `%s' doesn't map to any signal at %s:%d!\n", - str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n", + str.c_str()); if (id2ast->type == AST_MEMORY) - log_error("Identifier `%s' does map to an unexpanded memory at %s:%d!\n", - str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n", + str.c_str()); wire = current_module->wires_[str]; chunk.wire = wire; @@ -994,8 +994,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) - log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n", - str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", + str.c_str()); int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1; AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ? children[0]->children[1]->clone() : children[0]->children[0]->clone()); @@ -1023,11 +1023,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) chunk.offset = (id2ast->range_left - id2ast->range_right + 1) - (chunk.offset + chunk.width); if (chunk.offset >= source_width || chunk.offset + chunk.width < 0) { if (chunk.width == 1) - log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting result bit to undef.\n", - str.c_str(), filename.c_str(), linenum); + log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting result bit to undef.\n", + str.c_str()); else - log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting all %d result bits to undef.\n", - str.c_str(), filename.c_str(), linenum, chunk.width); + log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting all %d result bits to undef.\n", + str.c_str(), chunk.width); chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width); } else { if (chunk.width + chunk.offset > source_width) { @@ -1040,11 +1040,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) chunk.offset += add_undef_bits_lsb; } if (add_undef_bits_lsb) - log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d LSB bits to undef.\n", - str.c_str(), filename.c_str(), linenum, add_undef_bits_lsb); + log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d LSB bits to undef.\n", + str.c_str(), add_undef_bits_lsb); if (add_undef_bits_msb) - log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d MSB bits to undef.\n", - str.c_str(), filename.c_str(), linenum, add_undef_bits_msb); + log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d MSB bits to undef.\n", + str.c_str(), add_undef_bits_msb); } } } @@ -1379,8 +1379,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_error("Attribute `%s' with non-constant value at %s:%d!\n", - attr.first.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", + attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -1401,10 +1401,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) new_left.append(left[i]); new_right.append(right[i]); } - log_warning("Ignoring assignment to constant bits at %s:%d:\n" - " old assignment: %s = %s\n new assignment: %s = %s.\n", - filename.c_str(), linenum, log_signal(left), log_signal(right), - log_signal(new_left), log_signal(new_right)); + log_file_warning(filename, linenum, "Ignoring assignment to constant bits:\n" + " old assignment: %s = %s\n new assignment: %s = %s.\n", + log_signal(left), log_signal(right), + log_signal(new_left), log_signal(new_right)); left = new_left; right = new_right; } @@ -1418,8 +1418,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) int port_counter = 0, para_counter = 0; if (current_module->count_id(str) != 0) - log_error("Re-definition of cell `%s' at %s:%d!\n", - str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Re-definition of cell `%s'!\n", str.c_str()); RTLIL::Cell *cell = current_module->addCell(str, ""); cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); @@ -1435,16 +1434,15 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (child->type == AST_PARASET) { IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str; if (child->children[0]->type == AST_REALVALUE) { - log_warning("Replacing floating point parameter %s.%s = %f with string at %s:%d.\n", - log_id(cell), log_id(paraname), child->children[0]->realvalue, - filename.c_str(), linenum); + log_file_warning(filename, linenum, "Replacing floating point parameter %s.%s = %f with string.\n", + log_id(cell), log_id(paraname), child->children[0]->realvalue); auto strnode = AstNode::mkconst_str(stringf("%f", child->children[0]->realvalue)); strnode->cloneInto(child->children[0]); delete strnode; } if (child->children[0]->type != AST_CONSTANT) - log_error("Parameter %s.%s with non-constant value at %s:%d!\n", - log_id(cell), log_id(paraname), filename.c_str(), linenum); + log_file_error(filename, linenum, "Parameter %s.%s with non-constant value!\n", + log_id(cell), log_id(paraname)); cell->parameters[paraname] = child->children[0]->asParaConst(); continue; } @@ -1465,8 +1463,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_error("Attribute `%s' with non-constant value at %s:%d!\n", - attr.first.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", + attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } } @@ -1493,19 +1491,19 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) int width = width_hint; if (GetSize(children) > 1) - log_error("System function %s got %d arguments, expected 1 or 0 at %s:%d.\n", - RTLIL::unescape_id(str).c_str(), GetSize(children), filename.c_str(), linenum); + log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 0.\n", + RTLIL::unescape_id(str).c_str(), GetSize(children)); if (GetSize(children) == 1) { if (children[0]->type != AST_CONSTANT) - log_error("System function %s called with non-const argument at %s:%d!\n", - RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "System function %s called with non-const argument!\n", + RTLIL::unescape_id(str).c_str()); width = children[0]->asInt(true); } if (width <= 0) - log_error("Failed to detect width of %s at %s:%d!\n", - RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to detect width of %s!\n", + RTLIL::unescape_id(str).c_str()); Cell *cell = current_module->addCell(myid, str.substr(1)); cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); @@ -1532,8 +1530,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (auto f : log_files) current_ast->dumpAst(f, "verilog-ast> "); type_name = type2str(type); - log_error("Don't know how to generate RTLIL code for %s node at %s:%d!\n", - type_name.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n", + type_name.c_str()); } return RTLIL::SigSpec(); diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 81bd3cd7e..be53e8527 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -195,8 +195,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, { int nargs = GetSize(children); if (nargs < 1) - log_error("System task `%s' got %d arguments, expected >= 1 at %s:%d.\n", - str.c_str(), int(children.size()), filename.c_str(), linenum); + log_file_error(filename, linenum, "System task `%s' got %d arguments, expected >= 1.\n", + str.c_str(), int(children.size())); // First argument is the format string AstNode *node_string = children[0]; @@ -239,8 +239,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, case 'x': case 'X': if (next_arg >= GetSize(children)) - log_error("Missing argument for %%%c format specifier in system task `%s' at %s:%d.\n", - cformat, str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Missing argument for %%%c format specifier in system task `%s'.\n", + cformat, str.c_str()); node_arg = children[next_arg++]; while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } @@ -717,8 +717,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, paramname = "\\" + paramname.substr(pos+1); if (current_scope.at(modname)->type != AST_CELL) - log_error("Defparam argument `%s . %s` does not match a cell at %s:%d!\n", - RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Defparam argument `%s . %s` does not match a cell!\n", + RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str()); AstNode *paraset = new AstNode(AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : NULL); paraset->str = paramname; @@ -865,8 +865,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width = std::abs(children[1]->range_left - children[1]->range_right) + 1; if (children[0]->type == AST_REALVALUE) { RTLIL::Const constvalue = children[0]->realAsConst(width); - log_warning("converting real value %e to binary %s at %s:%d.\n", - children[0]->realvalue, log_signal(constvalue), filename.c_str(), linenum); + log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", + children[0]->realvalue, log_signal(constvalue)); delete children[0]; children[0] = mkconst_bits(constvalue.bits, sign_hint); did_something = true; @@ -1095,8 +1095,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, { for (size_t i = 0; i < children.size(); i++) if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM) - log_error("Local declaration in unnamed block at %s:%d is an unsupported SystemVerilog feature!\n", - children[i]->filename.c_str(), children[i]->linenum); + log_file_error(children[i]->filename, children[i]->linenum, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n"); } // transform block with name @@ -1285,8 +1284,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_PRIMITIVE) { if (children.size() < 2) - log_error("Insufficient number of arguments for primitive `%s' at %s:%d!\n", - str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n", + str.c_str()); std::vector children_list; for (auto child : children) { @@ -1301,8 +1300,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1") { if (children_list.size() != 3) - log_error("Invalid number of arguments for primitive `%s' at %s:%d!\n", - str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n", + str.c_str()); std::vector z_const(1, RTLIL::State::Sz); @@ -1387,8 +1386,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, while (left_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { } while (right_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) - log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n", - str.c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", + str.c_str()); result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; } did_something = true; @@ -1737,12 +1736,12 @@ skip_dynamic_range_lvalue_expansion:; int num_steps = 1; if (GetSize(children) != 1 && GetSize(children) != 2) - log_error("System function %s got %d arguments, expected 1 or 2 at %s:%d.\n", - RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum); + log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n", + RTLIL::unescape_id(str).c_str(), int(children.size())); if (!current_always_clocked) - log_error("System function %s is only allowed in clocked blocks at %s:%d.\n", - RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n", + RTLIL::unescape_id(str).c_str()); if (GetSize(children) == 2) { @@ -1805,12 +1804,12 @@ skip_dynamic_range_lvalue_expansion:; if (str == "\\$stable" || str == "\\$rose" || str == "\\$fell") { if (GetSize(children) != 1) - log_error("System function %s got %d arguments, expected 1 at %s:%d.\n", - RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum); + log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", + RTLIL::unescape_id(str).c_str(), int(children.size())); if (!current_always_clocked) - log_error("System function %s is only allowed in clocked blocks at %s:%d.\n", - RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n", + RTLIL::unescape_id(str).c_str()); AstNode *present = children.at(0)->clone(); AstNode *past = clone(); @@ -1840,8 +1839,8 @@ skip_dynamic_range_lvalue_expansion:; if (str == "\\$clog2") { if (children.size() != 1) - log_error("System function %s got %d arguments, expected 1 at %s:%d.\n", - RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum); + log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", + RTLIL::unescape_id(str).c_str(), int(children.size())); AstNode *buf = children[0]->clone(); while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } @@ -1865,12 +1864,12 @@ skip_dynamic_range_lvalue_expansion:; if (str == "\\$size" || str == "\\$bits") { if (str == "\\$bits" && children.size() != 1) - log_error("System function %s got %d arguments, expected 1 at %s:%d.\n", - RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum); + log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", + RTLIL::unescape_id(str).c_str(), int(children.size())); if (str == "\\$size" && children.size() != 1 && children.size() != 2) - log_error("System function %s got %d arguments, expected 1 or 2 at %s:%d.\n", - RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum); + log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n", + RTLIL::unescape_id(str).c_str(), int(children.size())); int dim = 1; if (str == "\\$size" && children.size() == 2) { @@ -1943,19 +1942,19 @@ skip_dynamic_range_lvalue_expansion:; if (func_with_two_arguments) { if (children.size() != 2) - log_error("System function %s got %d arguments, expected 2 at %s:%d.\n", - RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum); + log_file_error(filename, linenum, "System function %s got %d arguments, expected 2.\n", + RTLIL::unescape_id(str).c_str(), int(children.size())); } else { if (children.size() != 1) - log_error("System function %s got %d arguments, expected 1 at %s:%d.\n", - RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum); + log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", + RTLIL::unescape_id(str).c_str(), int(children.size())); } if (children.size() >= 1) { while (children[0]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (!children[0]->isConst()) - log_error("Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n", - RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n", + RTLIL::unescape_id(str).c_str()); int child_width_hint = width_hint; bool child_sign_hint = sign_hint; children[0]->detectSignWidth(child_width_hint, child_sign_hint); @@ -1965,8 +1964,8 @@ skip_dynamic_range_lvalue_expansion:; if (children.size() >= 2) { while (children[1]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (!children[1]->isConst()) - log_error("Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n", - RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum); + log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n", + RTLIL::unescape_id(str).c_str()); int child_width_hint = width_hint; bool child_sign_hint = sign_hint; children[1]->detectSignWidth(child_width_hint, child_sign_hint); @@ -2053,8 +2052,8 @@ skip_dynamic_range_lvalue_expansion:; if (str == "\\$readmemh" || str == "\\$readmemb") { if (GetSize(children) < 2 || GetSize(children) > 4) - log_error("System function %s got %d arguments, expected 2-4 at %s:%d.\n", - RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum); + log_file_error(filename, linenum, "System function %s got %d arguments, expected 2-4.\n", + RTLIL::unescape_id(str).c_str(), int(children.size())); AstNode *node_filename = children[0]->clone(); while (node_filename->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } @@ -3291,16 +3290,16 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) continue; if (stmt->children.at(1)->type != AST_CONSTANT) - log_error("Non-constant expression in constant function at %s:%d (called from %s:%d). X\n", - stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum); + log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function (called from %s:%d). X\n", + fcall->filename.c_str(), fcall->linenum); if (stmt->children.at(0)->type != AST_IDENTIFIER) - log_error("Unsupported composite left hand side in constant function at %s:%d (called from %s:%d).\n", - stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum); + log_file_error(stmt->filename, stmt->linenum, "Unsupported composite left hand side in constant function (called from %s:%d).\n", + fcall->filename.c_str(), fcall->linenum); if (!variables.count(stmt->children.at(0)->str)) - log_error("Assignment to non-local variable in constant function at %s:%d (called from %s:%d).\n", - stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum); + log_file_error(stmt->filename, stmt->linenum, "Assignment to non-local variable in constant function (called from %s:%d).\n", + fcall->filename.c_str(), fcall->linenum); if (stmt->children.at(0)->children.empty()) { variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.bits.size()); @@ -3339,8 +3338,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) while (cond->simplify(true, false, false, 1, -1, false, true)) { } if (cond->type != AST_CONSTANT) - log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n", - stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum); + log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function (called from %s:%d).\n", + fcall->filename.c_str(), fcall->linenum); if (cond->asBool()) { block->children.insert(block->children.begin(), stmt->children.at(1)->clone()); @@ -3360,8 +3359,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) while (num->simplify(true, false, false, 1, -1, false, true)) { } if (num->type != AST_CONSTANT) - log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n", - stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum); + log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function (called from %s:%d).\n", + fcall->filename.c_str(), fcall->linenum); block->children.erase(block->children.begin()); for (int i = 0; i < num->bitsAsConst().as_int(); i++) @@ -3398,8 +3397,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) while (cond->simplify(true, false, false, 1, -1, false, true)) { } if (cond->type != AST_CONSTANT) - log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n", - stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum); + log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function (called from %s:%d).\n", + fcall->filename.c_str(), fcall->linenum); found_match = cond->asBool(); delete cond; @@ -3428,8 +3427,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) continue; } - log_error("Unsupported language construct in constant function at %s:%d (called from %s:%d).\n", - stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum); + log_file_error(stmt->filename, stmt->linenum, "Unsupported language construct in constant function (called from %s:%d).\n", + fcall->filename.c_str(), fcall->linenum); log_abort(); } diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc index 4a58357bf..7848c626d 100644 --- a/frontends/verilog/const2ast.cc +++ b/frontends/verilog/const2ast.cc @@ -49,8 +49,7 @@ static int my_decimal_div_by_two(std::vector &digits) int carry = 0; for (size_t i = 0; i < digits.size(); i++) { if (digits[i] >= 10) - log_error("Invalid use of [a-fxz?] in decimal constant at %s:%d.\n", - current_filename.c_str(), get_line_num()); + log_file_error(current_filename, get_line_num(), "Invalid use of [a-fxz?] in decimal constant.\n"); digits[i] += carry * 10; carry = digits[i] % 2; digits[i] /= 2; @@ -105,8 +104,8 @@ static void my_strtobin(std::vector &data, const char *str, int le int bits_per_digit = my_ilog2(base-1); for (auto it = digits.rbegin(), e = digits.rend(); it != e; it++) { if (*it > (base-1) && *it < 0xf0) - log_error("Digit larger than %d used in in base-%d constant at %s:%d.\n", - base-1, base, current_filename.c_str(), get_line_num()); + log_file_error(current_filename, get_line_num(), "Digit larger than %d used in in base-%d constant.\n", + base-1, base); for (int i = 0; i < bits_per_digit; i++) { int bitmask = 1 << i; if (*it == 0xf0) @@ -238,4 +237,3 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn } YOSYS_NAMESPACE_END - -- cgit v1.2.3 From 3101b9b8c979f0a4239ccd823932a490b60d128c Mon Sep 17 00:00:00 2001 From: Henner Zeller Date: Fri, 20 Jul 2018 18:52:52 -0700 Subject: Fix remaining log_file_error(); emit dependent file references in new line. There are some places that reference dependent file locations ("this function was called from ..."). These are now in a separate line for ease of jumping to it with the editor (behaves similarly to compilers that emit dependent messages). --- frontends/ast/simplify.cc | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index be53e8527..75dc60c68 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -3201,13 +3201,13 @@ void AstNode::replace_variables(std::map &varia int offset = variables.at(str).offset, width = variables.at(str).val.bits.size(); if (!children.empty()) { if (children.size() != 1 || children.at(0)->type != AST_RANGE) - log_error("Memory access in constant function is not supported in %s:%d (called from %s:%d).\n", - filename.c_str(), linenum, fcall->filename.c_str(), fcall->linenum); + log_file_error(filename, linenum, "Memory access in constant function is not supported\n%s:%d: ...called from here.\n", + fcall->filename.c_str(), fcall->linenum); children.at(0)->replace_variables(variables, fcall); while (simplify(true, false, false, 1, -1, false, true)) { } if (!children.at(0)->range_valid) - log_error("Non-constant range in %s:%d (called from %s:%d).\n", - filename.c_str(), linenum, fcall->filename.c_str(), fcall->linenum); + log_file_error(filename, linenum, "Non-constant range\n%s:%d: ... called from here.\n", + fcall->filename.c_str(), fcall->linenum); offset = min(children.at(0)->range_left, children.at(0)->range_right); width = min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width); } @@ -3246,8 +3246,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) { while (child->simplify(true, false, false, 1, -1, false, true)) { } if (!child->range_valid) - log_error("Can't determine size of variable %s in %s:%d (called from %s:%d).\n", - child->str.c_str(), child->filename.c_str(), child->linenum, fcall->filename.c_str(), fcall->linenum); + log_file_error(child->filename, child->linenum, "Can't determine size of variable %s\n%s:%d: ... called from here.\n", + child->str.c_str(), fcall->filename.c_str(), fcall->linenum); variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1); variables[child->str].offset = min(child->range_left, child->range_right); variables[child->str].is_signed = child->is_signed; @@ -3290,15 +3290,15 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) continue; if (stmt->children.at(1)->type != AST_CONSTANT) - log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function (called from %s:%d). X\n", + log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here. X\n", fcall->filename.c_str(), fcall->linenum); if (stmt->children.at(0)->type != AST_IDENTIFIER) - log_file_error(stmt->filename, stmt->linenum, "Unsupported composite left hand side in constant function (called from %s:%d).\n", + log_file_error(stmt->filename, stmt->linenum, "Unsupported composite left hand side in constant function\n%s:%d: ... called from here.\n", fcall->filename.c_str(), fcall->linenum); if (!variables.count(stmt->children.at(0)->str)) - log_file_error(stmt->filename, stmt->linenum, "Assignment to non-local variable in constant function (called from %s:%d).\n", + log_file_error(stmt->filename, stmt->linenum, "Assignment to non-local variable in constant function\n%s:%d: ... called from here.\n", fcall->filename.c_str(), fcall->linenum); if (stmt->children.at(0)->children.empty()) { @@ -3306,8 +3306,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) } else { AstNode *range = stmt->children.at(0)->children.at(0); if (!range->range_valid) - log_error("Non-constant range in %s:%d (called from %s:%d).\n", - range->filename.c_str(), range->linenum, fcall->filename.c_str(), fcall->linenum); + log_file_error(range->filename, range->linenum, "Non-constant range\n%s:%d: ... called from here.\n", + fcall->filename.c_str(), fcall->linenum); int offset = min(range->range_left, range->range_right); int width = std::abs(range->range_left - range->range_right) + 1; varinfo_t &v = variables[stmt->children.at(0)->str]; @@ -3338,7 +3338,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) while (cond->simplify(true, false, false, 1, -1, false, true)) { } if (cond->type != AST_CONSTANT) - log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function (called from %s:%d).\n", + log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", fcall->filename.c_str(), fcall->linenum); if (cond->asBool()) { @@ -3359,7 +3359,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) while (num->simplify(true, false, false, 1, -1, false, true)) { } if (num->type != AST_CONSTANT) - log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function (called from %s:%d).\n", + log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", fcall->filename.c_str(), fcall->linenum); block->children.erase(block->children.begin()); @@ -3397,7 +3397,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) while (cond->simplify(true, false, false, 1, -1, false, true)) { } if (cond->type != AST_CONSTANT) - log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function (called from %s:%d).\n", + log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", fcall->filename.c_str(), fcall->linenum); found_match = cond->asBool(); @@ -3427,7 +3427,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) continue; } - log_file_error(stmt->filename, stmt->linenum, "Unsupported language construct in constant function (called from %s:%d).\n", + log_file_error(stmt->filename, stmt->linenum, "Unsupported language construct in constant function\n%s:%d: ... called from here.\n", fcall->filename.c_str(), fcall->linenum); log_abort(); } -- cgit v1.2.3 From 3aa4484a3cd9a2e82fddd499cde575eaf8c565cc Mon Sep 17 00:00:00 2001 From: Henner Zeller Date: Fri, 20 Jul 2018 23:41:18 -0700 Subject: Consistent use of 'override' for virtual methods in derived classes. o Not all derived methods were marked 'override', but it is a great feature of C++11 that we should make use of. o While at it: touched header files got a -*- c++ -*- for emacs to provide support for that language. o use YS_OVERRIDE for all override keywords (though we should probably use the plain keyword going forward now that C++11 is established) --- frontends/ast/ast.h | 8 ++++---- frontends/blif/blifparse.cc | 4 ++-- frontends/ilang/ilang_frontend.cc | 4 ++-- frontends/json/jsonparse.cc | 4 ++-- frontends/liberty/liberty.cc | 4 ++-- frontends/verific/verific.cc | 10 +++++----- frontends/verilog/verilog_frontend.cc | 12 ++++++------ 7 files changed, 23 insertions(+), 23 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 756629aca..ed784e831 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -1,4 +1,4 @@ -/* +/* -*- c++ -*- * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf @@ -282,9 +282,9 @@ namespace AST struct AstModule : RTLIL::Module { AstNode *ast; bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire; - virtual ~AstModule(); - virtual RTLIL::IdString derive(RTLIL::Design *design, dict parameters, bool mayfail); - virtual RTLIL::Module *clone() const; + ~AstModule() YS_OVERRIDE; + RTLIL::IdString derive(RTLIL::Design *design, dict parameters, bool mayfail) YS_OVERRIDE; + RTLIL::Module *clone() const YS_OVERRIDE; }; // this must be set by the language frontend before parsing the sources diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc index e6bb99954..85ac4ff21 100644 --- a/frontends/blif/blifparse.cc +++ b/frontends/blif/blifparse.cc @@ -550,7 +550,7 @@ error: struct BlifFrontend : public Frontend { BlifFrontend() : Frontend("blif", "read BLIF file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -566,7 +566,7 @@ struct BlifFrontend : public Frontend { log(" multi-bit port 'name'.\n"); log("\n"); } - virtual void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool sop_mode = false; bool wideports = false; diff --git a/frontends/ilang/ilang_frontend.cc b/frontends/ilang/ilang_frontend.cc index ed6789987..d8783ac1d 100644 --- a/frontends/ilang/ilang_frontend.cc +++ b/frontends/ilang/ilang_frontend.cc @@ -35,7 +35,7 @@ YOSYS_NAMESPACE_BEGIN struct IlangFrontend : public Frontend { IlangFrontend() : Frontend("ilang", "read modules from ilang file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -45,7 +45,7 @@ struct IlangFrontend : public Frontend { log("representation of a design in yosys's internal format.)\n"); log("\n"); } - virtual void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing ILANG frontend.\n"); extra_args(f, filename, args, 1); diff --git a/frontends/json/jsonparse.cc b/frontends/json/jsonparse.cc index 629578c61..82361ea9b 100644 --- a/frontends/json/jsonparse.cc +++ b/frontends/json/jsonparse.cc @@ -494,7 +494,7 @@ void json_import(Design *design, string &modname, JsonNode *node) struct JsonFrontend : public Frontend { JsonFrontend() : Frontend("json", "read JSON file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -504,7 +504,7 @@ struct JsonFrontend : public Frontend { log("for a description of the file format.\n"); log("\n"); } - virtual void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing JSON frontend.\n"); diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index b9e53a4be..0a5bd84de 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -452,7 +452,7 @@ void parse_type_map(std::map> &type_map, struct LibertyFrontend : public Frontend { LibertyFrontend() : Frontend("liberty", "read cells from liberty file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -485,7 +485,7 @@ struct LibertyFrontend : public Frontend { log(" set the specified attribute (to the value 1) on all loaded modules\n"); log("\n"); } - virtual void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool flag_lib = false; bool flag_nooverwrite = false; diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 8937cdde8..09bb253f5 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1685,7 +1685,7 @@ bool check_noverific_env() struct VerificPass : public Pass { VerificPass() : Pass("verific", "load Verilog and VHDL designs using Verific") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1784,7 +1784,7 @@ struct VerificPass : public Pass { log("\n"); } #ifdef YOSYS_ENABLE_VERIFIC - virtual void execute(std::vector args, RTLIL::Design *design) + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { if (check_noverific_env()) log_cmd_error("This version of Yosys is built without Verific support.\n"); @@ -2162,7 +2162,7 @@ struct VerificPass : public Pass { } #else /* YOSYS_ENABLE_VERIFIC */ - virtual void execute(std::vector, RTLIL::Design *) { + void execute(std::vector, RTLIL::Design *) YS_OVERRIDE { log_cmd_error("This version of Yosys is built without Verific support.\n"); } #endif @@ -2170,7 +2170,7 @@ struct VerificPass : public Pass { struct ReadPass : public Pass { ReadPass() : Pass("read", "load HDL designs") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -2203,7 +2203,7 @@ struct ReadPass : public Pass { log("Add directory to global Verilog/SystemVerilog include directories.\n"); log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { if (args.size() < 2) log_cmd_error("Missing mode parameter.\n"); diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index be925fea2..911e36112 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -49,7 +49,7 @@ static void error_on_dpi_function(AST::AstNode *node) struct VerilogFrontend : public Frontend { VerilogFrontend() : Frontend("verilog", "read modules from Verilog file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -180,7 +180,7 @@ struct VerilogFrontend : public Frontend { log("supported by the Yosys Verilog front-end.\n"); log("\n"); } - virtual void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool flag_dump_ast1 = false; bool flag_dump_ast2 = false; @@ -395,7 +395,7 @@ struct VerilogFrontend : public Frontend { struct VerilogDefaults : public Pass { VerilogDefaults() : Pass("verilog_defaults", "set default options for read_verilog") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -416,7 +416,7 @@ struct VerilogDefaults : public Pass { log("not imply -clear.\n"); log("\n"); } - virtual void execute(std::vector args, RTLIL::Design*) + void execute(std::vector args, RTLIL::Design*) YS_OVERRIDE { if (args.size() < 2) cmd_error(args, 1, "Missing argument."); @@ -453,7 +453,7 @@ struct VerilogDefaults : public Pass { struct VerilogDefines : public Pass { VerilogDefines() : Pass("verilog_defines", "define and undefine verilog defines") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -469,7 +469,7 @@ struct VerilogDefines : public Pass { log(" undefine the preprocessor symbol 'name'\n"); log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { -- cgit v1.2.3 From e275692e84c935d0cdf42c2a4adf7ac949a88132 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 22 Jul 2018 18:44:05 +0200 Subject: Verific: Produce errors for instantiating unknown module Because if the unknown module is connected to any constants, Verific will actually break all constants in the same module, even if they have nothing to do structurally with that instance of an unknown module. Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 8937cdde8..b8dd72b98 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1800,6 +1800,9 @@ struct VerificPass : public Pass { RuntimeFlags::SetVar("veri_extract_multiport_rams", 1); RuntimeFlags::SetVar("db_infer_wide_operators", 1); + // WARNING: instantiating unknown module 'XYZ' (VERI-1063) + Message::SetMessageType("VERI-1063", VERIFIC_ERROR); + verific_verbose = 0; const char *release_str = Message::ReleaseString(); -- cgit v1.2.3 From f42d6a9c93f8bd456bf5e857dc67f19e3b10ab25 Mon Sep 17 00:00:00 2001 From: litghost <537074+litghost@users.noreply.github.com> Date: Thu, 2 Aug 2018 14:33:39 -0700 Subject: Add BLIF parsing support for .conn and .cname --- frontends/blif/blifparse.cc | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'frontends') diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc index e6bb99954..e2be61da8 100644 --- a/frontends/blif/blifparse.cc +++ b/frontends/blif/blifparse.cc @@ -83,6 +83,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo RTLIL::Module *module = nullptr; RTLIL::Const *lutptr = NULL; RTLIL::Cell *sopcell = NULL; + RTLIL::Cell *lastcell = nullptr; RTLIL::State lut_default_state = RTLIL::State::Sx; int blif_maxnum = 0, sopmode = -1; @@ -159,6 +160,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo if (module != nullptr) goto error; module = new RTLIL::Module; + lastcell = nullptr; module->name = RTLIL::escape_id(strtok(NULL, " \t\r\n")); obj_attributes = &module->attributes; obj_parameters = nullptr; @@ -232,6 +234,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo } module = nullptr; + lastcell = nullptr; obj_attributes = nullptr; obj_parameters = nullptr; continue; @@ -264,6 +267,22 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo continue; } + if (!strcmp(cmd, ".cname")) + { + char *p = strtok(NULL, " \t\r\n"); + if (p == NULL) + goto error; + + if(lastcell == nullptr || module == nullptr) + { + log_error("No primative object to attach .cname %s.\n", p); + goto error; + } + + module->rename(lastcell, p); + continue; + } + if (!strcmp(cmd, ".attr") || !strcmp(cmd, ".param")) { char *n = strtok(NULL, " \t\r\n"); char *v = strtok(NULL, "\r\n"); @@ -281,12 +300,16 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo const_v.bits[i] = v[n-i-1] != '0' ? State::S1 : State::S0; } if (!strcmp(cmd, ".attr")) { - if (obj_attributes == nullptr) + if (obj_attributes == nullptr) { + log_error("No object to attach .attr too.\n"); goto error; + } (*obj_attributes)[id_n] = const_v; } else { - if (obj_parameters == nullptr) + if (obj_parameters == nullptr) { + log_error("No object to attach .param too.\n"); goto error; + } (*obj_parameters)[id_n] = const_v; } continue; @@ -331,6 +354,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo } } + lastcell = cell; obj_attributes = &cell->attributes; obj_parameters = &cell->parameters; continue; @@ -383,6 +407,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo cell->setPort(it.first, sig); } + lastcell = cell; obj_attributes = &cell->attributes; obj_parameters = &cell->parameters; continue; @@ -391,7 +416,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo obj_attributes = nullptr; obj_parameters = nullptr; - if (!strcmp(cmd, ".barbuf")) + if (!strcmp(cmd, ".barbuf") || !strcmp(cmd, ".conn")) { char *p = strtok(NULL, " \t\r\n"); if (p == NULL) @@ -459,6 +484,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo sopcell->setPort("\\A", input_sig); sopcell->setPort("\\Y", output_sig); sopmode = -1; + lastcell = sopcell; } else { @@ -469,6 +495,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo cell->setPort("\\Y", output_sig); lutptr = &cell->parameters.at("\\LUT"); lut_default_state = RTLIL::State::Sx; + lastcell = cell; } continue; } -- cgit v1.2.3 From 475c2af8120199f0acaa02e6e0993b27a553b22f Mon Sep 17 00:00:00 2001 From: litghost <537074+litghost@users.noreply.github.com> Date: Fri, 3 Aug 2018 08:02:49 -0700 Subject: Use log_warning which does not immediately terminate. --- frontends/blif/blifparse.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'frontends') diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc index e2be61da8..1d4cf39a8 100644 --- a/frontends/blif/blifparse.cc +++ b/frontends/blif/blifparse.cc @@ -275,7 +275,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo if(lastcell == nullptr || module == nullptr) { - log_error("No primative object to attach .cname %s.\n", p); + log_warning("No primative object to attach .cname %s.\n", p); goto error; } @@ -301,13 +301,13 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo } if (!strcmp(cmd, ".attr")) { if (obj_attributes == nullptr) { - log_error("No object to attach .attr too.\n"); + log_warning("No object to attach .attr too.\n"); goto error; } (*obj_attributes)[id_n] = const_v; } else { if (obj_parameters == nullptr) { - log_error("No object to attach .param too.\n"); + log_warning("No object to attach .param too.\n"); goto error; } (*obj_parameters)[id_n] = const_v; -- cgit v1.2.3 From 219f1e9fc9bda90422d1ec81db581a0f469ef192 Mon Sep 17 00:00:00 2001 From: litghost <537074+litghost@users.noreply.github.com> Date: Wed, 8 Aug 2018 10:22:55 -0700 Subject: Report error reason on same line as syntax error. Signed-off-by: litghost <537074+litghost@users.noreply.github.com> --- frontends/blif/blifparse.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'frontends') diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc index 1d4cf39a8..b81808b1e 100644 --- a/frontends/blif/blifparse.cc +++ b/frontends/blif/blifparse.cc @@ -85,6 +85,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo RTLIL::Cell *sopcell = NULL; RTLIL::Cell *lastcell = nullptr; RTLIL::State lut_default_state = RTLIL::State::Sx; + char err_reason[80]; int blif_maxnum = 0, sopmode = -1; auto blif_wire = [&](const std::string &wire_name) -> Wire* @@ -275,8 +276,8 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo if(lastcell == nullptr || module == nullptr) { - log_warning("No primative object to attach .cname %s.\n", p); - goto error; + snprintf(err_reason, sizeof(err_reason), "No primative object to attach .cname %s.", p); + goto error_with_reason; } module->rename(lastcell, p); @@ -301,14 +302,14 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo } if (!strcmp(cmd, ".attr")) { if (obj_attributes == nullptr) { - log_warning("No object to attach .attr too.\n"); - goto error; + snprintf(err_reason, sizeof(err_reason), "No object to attach .attr too."); + goto error_with_reason; } (*obj_attributes)[id_n] = const_v; } else { if (obj_parameters == nullptr) { - log_warning("No object to attach .param too.\n"); - goto error; + snprintf(err_reason, sizeof(err_reason), "No object to attach .param too."); + goto error_with_reason; } (*obj_parameters)[id_n] = const_v; } @@ -573,6 +574,8 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo error: log_error("Syntax error in line %d!\n", line_count); +error_with_reason: + log_error("Syntax error in line %d: %s\n", line_count, err_reason); } struct BlifFrontend : public Frontend { -- cgit v1.2.3 From 93efbd5d158e374a0abe2afb06484ccc14aa2c88 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 8 Aug 2018 19:41:47 +0200 Subject: Fixed use of char array for string in blifparse error handling Signed-off-by: Clifford Wolf --- frontends/blif/blifparse.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'frontends') diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc index b81808b1e..26cd14033 100644 --- a/frontends/blif/blifparse.cc +++ b/frontends/blif/blifparse.cc @@ -85,7 +85,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo RTLIL::Cell *sopcell = NULL; RTLIL::Cell *lastcell = nullptr; RTLIL::State lut_default_state = RTLIL::State::Sx; - char err_reason[80]; + std::string err_reason; int blif_maxnum = 0, sopmode = -1; auto blif_wire = [&](const std::string &wire_name) -> Wire* @@ -276,7 +276,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo if(lastcell == nullptr || module == nullptr) { - snprintf(err_reason, sizeof(err_reason), "No primative object to attach .cname %s.", p); + err_reason = stringf("No primative object to attach .cname %s.", p); goto error_with_reason; } @@ -302,13 +302,13 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo } if (!strcmp(cmd, ".attr")) { if (obj_attributes == nullptr) { - snprintf(err_reason, sizeof(err_reason), "No object to attach .attr too."); + err_reason = stringf("No object to attach .attr too."); goto error_with_reason; } (*obj_attributes)[id_n] = const_v; } else { if (obj_parameters == nullptr) { - snprintf(err_reason, sizeof(err_reason), "No object to attach .param too."); + err_reason = stringf("No object to attach .param too."); goto error_with_reason; } (*obj_parameters)[id_n] = const_v; @@ -575,7 +575,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo error: log_error("Syntax error in line %d!\n", line_count); error_with_reason: - log_error("Syntax error in line %d: %s\n", line_count, err_reason); + log_error("Syntax error in line %d: %s\n", line_count, err_reason.c_str()); } struct BlifFrontend : public Frontend { -- cgit v1.2.3 From 28cfc75a902574c3ad96876d2f5e01af6c583bac Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Wed, 15 Aug 2018 19:56:30 +0300 Subject: A few minor enhancements to specify block parsing. Just remember specify blocks are parsed but ignored. --- frontends/verilog/verilog_parser.y | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 78cac5543..61da12b76 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -688,8 +688,8 @@ path_declaration : ; simple_path_declaration : - parallel_path_description '=' path_delay_value ';' - // | full_path_description '=' path_delay_value ';' + parallel_path_description '=' path_delay_value ';' | + full_path_description '=' path_delay_value ';' ; path_delay_value : @@ -723,6 +723,17 @@ list_of_path_delay_expressions : parallel_path_description : '(' specify_input_terminal_descriptor opt_polarity_operator '=' '>' specify_output_terminal_descriptor ')' ; +full_path_description : + '(' list_of_path_inputs opt_polarity_operator '*' '>' list_of_path_outputs ')' ; + +list_of_path_inputs : + specify_input_terminal_descriptor | + list_of_path_inputs ',' specify_input_terminal_descriptor ; + +list_of_path_outputs : + specify_output_terminal_descriptor | + list_of_path_outputs ',' specify_output_terminal_descriptor ; + opt_polarity_operator : '+' | '-' -- cgit v1.2.3 From 0899a53bee39e209551a3122c7c820b7ed2b48c3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 16 Aug 2018 11:31:19 +0200 Subject: Verific workaround for VIPER ticket 13851 Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index e993eb740..2895d40c2 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1800,6 +1800,9 @@ struct VerificPass : public Pass { RuntimeFlags::SetVar("veri_extract_multiport_rams", 1); RuntimeFlags::SetVar("db_infer_wide_operators", 1); + // Workaround for VIPER #13851 + RuntimeFlags::SetVar("veri_create_name_for_unnamed_gen_block", 1); + // WARNING: instantiating unknown module 'XYZ' (VERI-1063) Message::SetMessageType("VERI-1063", VERIFIC_ERROR); -- cgit v1.2.3 From e343f3e6d475984c21611474bffe7dcd8f599497 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 16 Aug 2018 11:49:17 +0200 Subject: Add "verific -set- .." Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 66 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 14 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 2895d40c2..b8c0375ce 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1732,6 +1732,15 @@ struct VerificPass : public Pass { log("Remove Verilog defines previously set with -vlog-define.\n"); log("\n"); log("\n"); + log(" verific -set-error ..\n"); + log(" verific -set-warning ..\n"); + log(" verific -set-info ..\n"); + log(" verific -set-ignore ..\n"); + log("\n"); + log("Set message severity. is the string in square brackets when a message\n"); + log("is printed, such as VERI-1209.\n"); + log("\n"); + log("\n"); log(" verific -import [options] ..\n"); log("\n"); log("Elaborate the design for the specified top modules, import to Yosys and\n"); @@ -1786,25 +1795,32 @@ struct VerificPass : public Pass { #ifdef YOSYS_ENABLE_VERIFIC void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { + static bool set_verific_global_flags = true; + if (check_noverific_env()) log_cmd_error("This version of Yosys is built without Verific support.\n"); log_header(design, "Executing VERIFIC (loading SystemVerilog and VHDL designs using Verific).\n"); - Message::SetConsoleOutput(0); - Message::RegisterCallBackMsg(msg_func); - RuntimeFlags::SetVar("db_preserve_user_nets", 1); - RuntimeFlags::SetVar("db_allow_external_nets", 1); - RuntimeFlags::SetVar("vhdl_ignore_assertion_statements", 0); - RuntimeFlags::SetVar("veri_extract_dualport_rams", 0); - RuntimeFlags::SetVar("veri_extract_multiport_rams", 1); - RuntimeFlags::SetVar("db_infer_wide_operators", 1); - - // Workaround for VIPER #13851 - RuntimeFlags::SetVar("veri_create_name_for_unnamed_gen_block", 1); - - // WARNING: instantiating unknown module 'XYZ' (VERI-1063) - Message::SetMessageType("VERI-1063", VERIFIC_ERROR); + if (set_verific_global_flags) + { + Message::SetConsoleOutput(0); + Message::RegisterCallBackMsg(msg_func); + RuntimeFlags::SetVar("db_preserve_user_nets", 1); + RuntimeFlags::SetVar("db_allow_external_nets", 1); + RuntimeFlags::SetVar("vhdl_ignore_assertion_statements", 0); + RuntimeFlags::SetVar("veri_extract_dualport_rams", 0); + RuntimeFlags::SetVar("veri_extract_multiport_rams", 1); + RuntimeFlags::SetVar("db_infer_wide_operators", 1); + + // Workaround for VIPER #13851 + RuntimeFlags::SetVar("veri_create_name_for_unnamed_gen_block", 1); + + // WARNING: instantiating unknown module 'XYZ' (VERI-1063) + Message::SetMessageType("VERI-1063", VERIFIC_ERROR); + + set_verific_global_flags = false; + } verific_verbose = 0; @@ -1822,6 +1838,28 @@ struct VerificPass : public Pass { int argidx = 1; + if (GetSize(args) > argidx && (args[argidx] == "-set-error" || args[argidx] == "-set-warning" || + args[argidx] == "-set-info" || args[argidx] == "-set-ignore")) + { + msg_type_t new_type; + + if (args[argidx] == "-set-error") + new_type = VERIFIC_ERROR; + else if (args[argidx] == "-set-warning") + new_type = VERIFIC_WARNING; + else if (args[argidx] == "-set-info") + new_type = VERIFIC_INFO; + else if (args[argidx] == "-set-ignore") + new_type = VERIFIC_IGNORE; + else + log_abort(); + + for (argidx++; argidx < GetSize(args); argidx++) + Message::SetMessageType(args[argidx].c_str(), new_type); + + goto check_error; + } + if (GetSize(args) > argidx && args[argidx] == "-vlog-incdir") { for (argidx++; argidx < GetSize(args); argidx++) verific_incdirs.push_back(args[argidx]); -- cgit v1.2.3 From 95241c8f4d32c5bd644bef71509965a82582264c Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Mon, 20 Aug 2018 00:08:08 +0300 Subject: Yosys can now parse https://github.com/verilog-to-routing/vtr-verilog-to-routing/blob/master/vtr_flow/primitives.v , (specify block ignored). Must use 'read_verilog -defer' due to a parameter not assigned a default value. --- frontends/verilog/verilog_parser.y | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 61da12b76..58a6824d1 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -654,7 +654,7 @@ specify_item: // | pulsestyle_declaration // | showcancelled_declaration | path_declaration - // | system_timing_declaration + | system_timing_declaration ; specparam_declaration: @@ -693,8 +693,8 @@ simple_path_declaration : ; path_delay_value : - //list_of_path_delay_expressions - '(' list_of_path_delay_expressions ')' + list_of_path_delay_expressions | + %prec '(' list_of_path_delay_expressions ')' ; list_of_path_delay_expressions : @@ -724,12 +724,17 @@ parallel_path_description : '(' specify_input_terminal_descriptor opt_polarity_operator '=' '>' specify_output_terminal_descriptor ')' ; full_path_description : - '(' list_of_path_inputs opt_polarity_operator '*' '>' list_of_path_outputs ')' ; + '(' list_of_path_inputs '*' '>' list_of_path_outputs ')' ; +// This was broken into 2 rules to solve shift/reduce conflicts list_of_path_inputs : - specify_input_terminal_descriptor | - list_of_path_inputs ',' specify_input_terminal_descriptor ; - + specify_input_terminal_descriptor opt_polarity_operator | + specify_input_terminal_descriptor more_path_inputs opt_polarity_operator ; + +more_path_inputs : + ',' specify_input_terminal_descriptor | + more_path_inputs ',' specify_input_terminal_descriptor ; + list_of_path_outputs : specify_output_terminal_descriptor | list_of_path_outputs ',' specify_output_terminal_descriptor ; @@ -747,11 +752,18 @@ specify_input_terminal_descriptor : specify_output_terminal_descriptor : TOK_ID ; -/* system_timing_declaration : - ; -*/ + TOK_ID '(' system_timing_args ')' ';' ; + +system_timing_arg : + TOK_POSEDGE TOK_ID | + TOK_NEGEDGE TOK_ID | + expr ; +system_timing_args : + system_timing_arg | + system_timing_args ',' system_timing_arg ; + /* t_path_delay_expression : path_delay_expression; -- cgit v1.2.3 From fbfc677df3e54798faba3ab2f27c270759b96507 Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Mon, 20 Aug 2018 17:27:45 +0300 Subject: Fixed all known specify/endspecify issues, without breaking 'make test'. Some the of parser fixes may look strange but they were needed to avoid shift/reduce conflicts, due to the explicit parentheses in path_delay_value, and the mintypmax values without parentheses --- frontends/verilog/verilog_parser.y | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 58a6824d1..2389d7d31 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -682,22 +682,23 @@ showcancelled_declaration : */ path_declaration : - simple_path_declaration + simple_path_declaration ';' // | edge_sensitive_path_declaration // | state_dependent_path_declaration ; simple_path_declaration : - parallel_path_description '=' path_delay_value ';' | - full_path_description '=' path_delay_value ';' + parallel_path_description '=' path_delay_value | + full_path_description '=' path_delay_value ; path_delay_value : - list_of_path_delay_expressions | - %prec '(' list_of_path_delay_expressions ')' + '(' path_delay_expression list_of_path_delay_extra_expressions ')' + | path_delay_expression + | path_delay_expression list_of_path_delay_extra_expressions ; -list_of_path_delay_expressions : +list_of_path_delay_extra_expressions : /* t_path_delay_expression | trise_path_delay_expression ',' tfall_path_delay_expression @@ -709,12 +710,11 @@ list_of_path_delay_expressions : t0x_path_delay_expression ',' tx1_path_delay_expression ',' t1x_path_delay_expression ',' tx0_path_delay_expression ',' txz_path_delay_expression ',' tzx_path_delay_expression */ - path_delay_expression - | path_delay_expression ',' path_delay_expression - | path_delay_expression ',' path_delay_expression ',' path_delay_expression - | path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' + ',' path_delay_expression + | ',' path_delay_expression ',' path_delay_expression + | ',' path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' path_delay_expression - | path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' + | ',' path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' path_delay_expression @@ -815,7 +815,7 @@ tzx_path_delay_expression : */ path_delay_expression : - constant_mintypmax_expression; + constant_expression; constant_mintypmax_expression : constant_expression -- cgit v1.2.3 From 4b02ee91627c49bd4ea0e89d6c8531283501a24b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 22 Aug 2018 13:30:22 +0200 Subject: Add Verific -work parameter Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index b8c0375ce..cb31634dd 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1837,6 +1837,7 @@ struct VerificPass : public Pass { log("Built with Verific %s, released at %s.\n", release_str, release_tmstr); int argidx = 1; + std::string work = "work"; if (GetSize(args) > argidx && (args[argidx] == "-set-error" || args[argidx] == "-set-warning" || args[argidx] == "-set-info" || args[argidx] == "-set-ignore")) @@ -1895,6 +1896,15 @@ struct VerificPass : public Pass { goto check_error; } + for (; argidx < GetSize(args); argidx++) + { + if (args[argidx] == "-work" && argidx+1 < GetSize(args)) { + work = args[++argidx]; + continue; + } + break; + } + if (GetSize(args) > argidx && (args[argidx] == "-vlog95" || args[argidx] == "-vlog2k" || args[argidx] == "-sv2005" || args[argidx] == "-sv2009" || args[argidx] == "-sv2012" || args[argidx] == "-sv" || args[argidx] == "-formal")) { @@ -1942,7 +1952,7 @@ struct VerificPass : public Pass { while (argidx < GetSize(args)) file_names.Insert(args[argidx++].c_str()); - if (!veri_file::AnalyzeMultipleFiles(&file_names, verilog_mode, "work", veri_file::MFCU)) + if (!veri_file::AnalyzeMultipleFiles(&file_names, verilog_mode, work.c_str(), veri_file::MFCU)) log_cmd_error("Reading Verilog/SystemVerilog sources failed.\n"); verific_import_pending = true; @@ -1952,7 +1962,7 @@ struct VerificPass : public Pass { if (GetSize(args) > argidx && args[argidx] == "-vhdl87") { vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_1987").c_str()); for (argidx++; argidx < GetSize(args); argidx++) - if (!vhdl_file::Analyze(args[argidx].c_str(), "work", vhdl_file::VHDL_87)) + if (!vhdl_file::Analyze(args[argidx].c_str(), work.c_str(), vhdl_file::VHDL_87)) log_cmd_error("Reading `%s' in VHDL_87 mode failed.\n", args[argidx].c_str()); verific_import_pending = true; goto check_error; @@ -1961,7 +1971,7 @@ struct VerificPass : public Pass { if (GetSize(args) > argidx && args[argidx] == "-vhdl93") { vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_1993").c_str()); for (argidx++; argidx < GetSize(args); argidx++) - if (!vhdl_file::Analyze(args[argidx].c_str(), "work", vhdl_file::VHDL_93)) + if (!vhdl_file::Analyze(args[argidx].c_str(), work.c_str(), vhdl_file::VHDL_93)) log_cmd_error("Reading `%s' in VHDL_93 mode failed.\n", args[argidx].c_str()); verific_import_pending = true; goto check_error; @@ -1970,7 +1980,7 @@ struct VerificPass : public Pass { if (GetSize(args) > argidx && args[argidx] == "-vhdl2k") { vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_1993").c_str()); for (argidx++; argidx < GetSize(args); argidx++) - if (!vhdl_file::Analyze(args[argidx].c_str(), "work", vhdl_file::VHDL_2K)) + if (!vhdl_file::Analyze(args[argidx].c_str(), work.c_str(), vhdl_file::VHDL_2K)) log_cmd_error("Reading `%s' in VHDL_2K mode failed.\n", args[argidx].c_str()); verific_import_pending = true; goto check_error; @@ -1979,7 +1989,7 @@ struct VerificPass : public Pass { if (GetSize(args) > argidx && (args[argidx] == "-vhdl2008" || args[argidx] == "-vhdl")) { vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_2008").c_str()); for (argidx++; argidx < GetSize(args); argidx++) - if (!vhdl_file::Analyze(args[argidx].c_str(), "work", vhdl_file::VHDL_2008)) + if (!vhdl_file::Analyze(args[argidx].c_str(), work.c_str(), vhdl_file::VHDL_2008)) log_cmd_error("Reading `%s' in VHDL_2008 mode failed.\n", args[argidx].c_str()); verific_import_pending = true; goto check_error; @@ -2089,8 +2099,8 @@ struct VerificPass : public Pass { #else log("Running hier_tree::ElaborateAll().\n"); - VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary("work", 1); - VeriLibrary *veri_lib = veri_file::GetLibrary("work", 1); + VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary(work.c_str(), 1); + VeriLibrary *veri_lib = veri_file::GetLibrary(work.c_str(), 1); Array veri_libs, vhdl_libs; if (vhdl_lib) vhdl_libs.InsertLast(vhdl_lib); @@ -2137,7 +2147,7 @@ struct VerificPass : public Pass { continue; } - VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary("work", 1); + VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary(work.c_str(), 1); VhdlDesignUnit *vhdl_unit = vhdl_lib->GetPrimUnit(name); if (vhdl_unit) { log("Adding VHDL unit '%s' to elaboration queue.\n", name); -- cgit v1.2.3 From 408077769ff022f78f10ec1ffb60926361f8dc9f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 22 Aug 2018 17:22:24 +0200 Subject: Add "verific -work" help message Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index cb31634dd..1dd6d7e24 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1706,11 +1706,18 @@ struct VerificPass : public Pass { log("\n"); log("Like -sv, but define FORMAL instead of SYNTHESIS.\n"); log("\n"); + log("\n"); log(" verific {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} ..\n"); log("\n"); log("Load the specified VHDL files into Verific.\n"); log("\n"); log("\n"); + log(" verific -work {-sv|-vhdl|...} \n"); + log("\n"); + log("Load the specified Verilog/SystemVerilog/VHDL file into the specified library.\n"); + log("(default library when -work is not present: \"work\")\n"); + log("\n"); + log("\n"); log(" verific -vlog-incdir ..\n"); log("\n"); log("Add Verilog include directories.\n"); -- cgit v1.2.3 From 042b3074f8096212b3f2114d353b2ec75818810b Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Thu, 23 Aug 2018 15:19:46 +0300 Subject: Added -no_dump_ptr flag for AST dump options in 'read_verilog' This option disables the memory pointer display. This is useful when diff'ing different dumps because otherwise the node pointers makes every diff line different when the AST content is the same. --- frontends/ast/ast.cc | 15 +++++++++------ frontends/ast/ast.h | 4 ++-- frontends/verilog/verilog_frontend.cc | 10 +++++++++- 3 files changed, 20 insertions(+), 9 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 7c72a50d9..e79be953a 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -44,7 +44,7 @@ namespace AST { // instanciate global variables (private API) namespace AST_INTERNAL { - bool flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_dump_rtlil, flag_nolatches, flag_nomeminit; + bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog, flag_dump_rtlil, flag_nolatches, flag_nomeminit; bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire; AstNode *current_ast, *current_ast_mod; std::map current_scope; @@ -267,10 +267,12 @@ void AstNode::dumpAst(FILE *f, std::string indent) const std::string type_name = type2str(type); fprintf(f, "%s%s <%s:%d>", indent.c_str(), type_name.c_str(), filename.c_str(), linenum); - if (id2ast) - fprintf(f, " [%p -> %p]", this, id2ast); - else - fprintf(f, " [%p]", this); + if (!flag_no_dump_ptr) { + if (id2ast) + fprintf(f, " [%p -> %p]", this, id2ast); + else + fprintf(f, " [%p]", this); + } if (!str.empty()) fprintf(f, " str='%s'", str.c_str()); @@ -1008,12 +1010,13 @@ static AstModule* process_module(AstNode *ast, bool defer) } // create AstModule instances for all modules in the AST tree and add them to 'design' -void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool dump_vlog, bool dump_rtlil, +void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog, bool dump_rtlil, bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire) { current_ast = ast; flag_dump_ast1 = dump_ast1; flag_dump_ast2 = dump_ast2; + flag_no_dump_ptr = no_dump_ptr; flag_dump_vlog = dump_vlog; flag_dump_rtlil = dump_rtlil; flag_nolatches = nolatches; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index d94199643..7e97bdb3b 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -274,7 +274,7 @@ namespace AST }; // process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code - void process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool dump_vlog, bool dump_rtlil, bool nolatches, bool nomeminit, + void process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog, bool dump_rtlil, bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire); // parametric modules are supported directly by the AST library @@ -305,7 +305,7 @@ namespace AST namespace AST_INTERNAL { // internal state variables - extern bool flag_dump_ast1, flag_dump_ast2, flag_dump_rtlil, flag_nolatches, flag_nomeminit; + extern bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_rtlil, flag_nolatches, flag_nomeminit; extern bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire; extern AST::AstNode *current_ast, *current_ast_mod; extern std::map current_scope; diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 911e36112..8dcc7c5aa 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -78,6 +78,9 @@ struct VerilogFrontend : public Frontend { log(" -dump_ast2\n"); log(" dump abstract syntax tree (after simplification)\n"); log("\n"); + log(" -no_dump_ptr\n"); + log(" do not include hex memory addresses in dump (easier to diff dumps)\n"); + log("\n"); log(" -dump_vlog\n"); log(" dump ast as Verilog code (after simplification)\n"); log("\n"); @@ -184,6 +187,7 @@ struct VerilogFrontend : public Frontend { { bool flag_dump_ast1 = false; bool flag_dump_ast2 = false; + bool flag_no_dump_ptr = false; bool flag_dump_vlog = false; bool flag_dump_rtlil = false; bool flag_nolatches = false; @@ -241,6 +245,10 @@ struct VerilogFrontend : public Frontend { flag_dump_ast2 = true; continue; } + if (arg == "-no_dump_ptr") { + flag_no_dump_ptr = true; + continue; + } if (arg == "-dump_vlog") { flag_dump_vlog = true; continue; @@ -381,7 +389,7 @@ struct VerilogFrontend : public Frontend { if (flag_nodpi) error_on_dpi_function(current_ast); - AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_dump_rtlil, flag_nolatches, flag_nomeminit, flag_nomem2reg, flag_mem2reg, lib_mode, flag_noopt, flag_icells, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire); + AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog, flag_dump_rtlil, flag_nolatches, flag_nomeminit, flag_nomem2reg, flag_mem2reg, lib_mode, flag_noopt, flag_icells, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire); if (!flag_nopp) delete lexin; -- cgit v1.2.3 From ddc1761f1a443ea9560c67cfc126160ba7254a39 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 27 Aug 2018 14:22:21 +0200 Subject: Add "make coverage" Signed-off-by: Clifford Wolf --- frontends/ilang/.gitignore | 2 +- frontends/ilang/Makefile.inc | 7 +++---- frontends/ilang/ilang_lexer.l | 2 +- frontends/verilog/.gitignore | 2 +- frontends/verilog/Makefile.inc | 7 +++---- frontends/verilog/verilog_lexer.l | 2 +- 6 files changed, 10 insertions(+), 12 deletions(-) (limited to 'frontends') diff --git a/frontends/ilang/.gitignore b/frontends/ilang/.gitignore index 43106a814..f586b33c7 100644 --- a/frontends/ilang/.gitignore +++ b/frontends/ilang/.gitignore @@ -1,4 +1,4 @@ ilang_lexer.cc ilang_parser.output ilang_parser.tab.cc -ilang_parser.tab.h +ilang_parser.tab.hh diff --git a/frontends/ilang/Makefile.inc b/frontends/ilang/Makefile.inc index e2a476c93..6f1f0e8fc 100644 --- a/frontends/ilang/Makefile.inc +++ b/frontends/ilang/Makefile.inc @@ -1,15 +1,14 @@ GENFILES += frontends/ilang/ilang_parser.tab.cc -GENFILES += frontends/ilang/ilang_parser.tab.h +GENFILES += frontends/ilang/ilang_parser.tab.hh GENFILES += frontends/ilang/ilang_parser.output GENFILES += frontends/ilang/ilang_lexer.cc frontends/ilang/ilang_parser.tab.cc: frontends/ilang/ilang_parser.y $(Q) mkdir -p $(dir $@) - $(P) $(BISON) -d -r all -b frontends/ilang/ilang_parser $< - $(Q) mv frontends/ilang/ilang_parser.tab.c frontends/ilang/ilang_parser.tab.cc + $(P) $(BISON) -o $@ -d -r all -b frontends/ilang/ilang_parser $< -frontends/ilang/ilang_parser.tab.h: frontends/ilang/ilang_parser.tab.cc +frontends/ilang/ilang_parser.tab.hh: frontends/ilang/ilang_parser.tab.cc frontends/ilang/ilang_lexer.cc: frontends/ilang/ilang_lexer.l $(Q) mkdir -p $(dir $@) diff --git a/frontends/ilang/ilang_lexer.l b/frontends/ilang/ilang_lexer.l index 842388548..d8e01ae4d 100644 --- a/frontends/ilang/ilang_lexer.l +++ b/frontends/ilang/ilang_lexer.l @@ -30,7 +30,7 @@ #endif #include "frontends/ilang/ilang_frontend.h" -#include "ilang_parser.tab.h" +#include "ilang_parser.tab.hh" USING_YOSYS_NAMESPACE diff --git a/frontends/verilog/.gitignore b/frontends/verilog/.gitignore index 1d4ae9e5c..aadbcdcdd 100644 --- a/frontends/verilog/.gitignore +++ b/frontends/verilog/.gitignore @@ -1,4 +1,4 @@ verilog_lexer.cc verilog_parser.output verilog_parser.tab.cc -verilog_parser.tab.h +verilog_parser.tab.hh diff --git a/frontends/verilog/Makefile.inc b/frontends/verilog/Makefile.inc index a06c1d5ab..dbaace585 100644 --- a/frontends/verilog/Makefile.inc +++ b/frontends/verilog/Makefile.inc @@ -1,15 +1,14 @@ GENFILES += frontends/verilog/verilog_parser.tab.cc -GENFILES += frontends/verilog/verilog_parser.tab.h +GENFILES += frontends/verilog/verilog_parser.tab.hh GENFILES += frontends/verilog/verilog_parser.output GENFILES += frontends/verilog/verilog_lexer.cc frontends/verilog/verilog_parser.tab.cc: frontends/verilog/verilog_parser.y $(Q) mkdir -p $(dir $@) - $(P) $(BISON) -d -r all -b frontends/verilog/verilog_parser $< - $(Q) mv frontends/verilog/verilog_parser.tab.c frontends/verilog/verilog_parser.tab.cc + $(P) $(BISON) -o $@ -d -r all -b frontends/verilog/verilog_parser $< -frontends/verilog/verilog_parser.tab.h: frontends/verilog/verilog_parser.tab.cc +frontends/verilog/verilog_parser.tab.hh: frontends/verilog/verilog_parser.tab.cc frontends/verilog/verilog_lexer.cc: frontends/verilog/verilog_lexer.l $(Q) mkdir -p $(dir $@) diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 0134416c1..83921bf0b 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -42,7 +42,7 @@ #include "kernel/log.h" #include "frontends/verilog/verilog_frontend.h" #include "frontends/ast/ast.h" -#include "verilog_parser.tab.h" +#include "verilog_parser.tab.hh" USING_YOSYS_NAMESPACE using namespace AST; -- cgit v1.2.3 From 5d9d22f66d512d33b2c1a13c4f1a20f944e6acc3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 4 Sep 2018 20:06:10 +0200 Subject: Add "verific -L " option Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 11 +++++++++++ frontends/verific/verific.h | 2 ++ frontends/verific/verificsva.cc | 5 +++-- 3 files changed, 16 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 1dd6d7e24..c5fa58313 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -64,6 +64,7 @@ YOSYS_NAMESPACE_BEGIN int verific_verbose; bool verific_import_pending; string verific_error_msg; +int verific_sva_fsm_limit; vector verific_incdirs, verific_libdirs; @@ -1618,6 +1619,8 @@ struct VerificExtNets void verific_import(Design *design, std::string top) { + verific_sva_fsm_limit = 16; + std::set nl_todo, nl_done; { @@ -1789,6 +1792,9 @@ struct VerificPass : public Pass { log(" -nosva\n"); log(" Ignore SVA properties, do not infer checker logic.\n"); log("\n"); + log(" -L \n"); + log(" Maximum number of ctrl bits for SVA checker FSMs (default=16).\n"); + log("\n"); log(" -n\n"); log(" Keep all Verific names on instances and nets. By default only\n"); log(" user-declared names are preserved.\n"); @@ -1830,6 +1836,7 @@ struct VerificPass : public Pass { } verific_verbose = 0; + verific_sva_fsm_limit = 16; const char *release_str = Message::ReleaseString(); time_t release_time = Message::ReleaseDate(); @@ -2036,6 +2043,10 @@ struct VerificPass : public Pass { mode_nosva = true; continue; } + if (args[argidx] == "-L" && argidx+1 < GetSize(args)) { + verific_sva_fsm_limit = atoi(args[++argidx].c_str()); + continue; + } if (args[argidx] == "-n") { mode_names = true; continue; diff --git a/frontends/verific/verific.h b/frontends/verific/verific.h index cbd9314db..334a436af 100644 --- a/frontends/verific/verific.h +++ b/frontends/verific/verific.h @@ -101,6 +101,8 @@ void verific_import_sva_cover(VerificImporter *importer, Verific::Instance *inst void verific_import_sva_trigger(VerificImporter *importer, Verific::Instance *inst); bool verific_is_sva_net(VerificImporter *importer, Verific::Net *net); +extern int verific_sva_fsm_limit; + YOSYS_NAMESPACE_END #endif diff --git a/frontends/verific/verificsva.cc b/frontends/verific/verificsva.cc index 85b842186..cdc9ece8c 100644 --- a/frontends/verific/verificsva.cc +++ b/frontends/verific/verificsva.cc @@ -466,13 +466,14 @@ struct SvaFsm dnode.ctrl.sort_and_unify(); - if (GetSize(dnode.ctrl) > 16) { + if (GetSize(dnode.ctrl) > verific_sva_fsm_limit) { if (verific_verbose >= 2) { log(" detected state explosion in DFSM generation:\n"); dump(); log(" ctrl signal: %s\n", log_signal(dnode.ctrl)); } - log_error("SVA DFSM state ctrl signal has %d (>16) bits. Stopping to prevent exponential design size explosion.\n", GetSize(dnode.ctrl)); + log_error("SVA DFSM state ctrl signal has %d (>%d) bits. Stopping to prevent exponential design size explosion.\n", + GetSize(dnode.ctrl), verific_sva_fsm_limit); } for (int i = 0; i < (1 << GetSize(dnode.ctrl)); i++) -- cgit v1.2.3 From f6fe73b31f6e6d8966ad4ddae860b4d79133cce2 Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Tue, 18 Sep 2018 01:23:40 +0300 Subject: Fixed remaining cases where we check fo wire reg/wire incorrect assignments on Yosys-generated assignments. In this case, offending code was: module top(input in, output out); function func; input arg; func = arg; endfunction assign out = func(in); endmodule --- frontends/ast/simplify.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index a9608369c..ae46e4bc9 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1337,6 +1337,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, str.clear(); type = AST_ASSIGN; children.push_back(children_list.at(0)); + children.back()->was_checked = true; children.push_back(node); did_something = true; } @@ -1373,6 +1374,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, str.clear(); type = AST_ASSIGN; children.push_back(children_list[0]); + children.back()->was_checked = true; children.push_back(node); did_something = true; } @@ -1531,6 +1533,7 @@ skip_dynamic_range_lvalue_expansion:; wire_tmp_id->str = wire_tmp->str; newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, wire_tmp_id, children[1]->clone())); + newNode->children.back()->was_checked = true; int cursor = 0; for (auto child : children[0]->children) @@ -1816,6 +1819,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *regid = new AstNode(AST_IDENTIFIER); regid->str = reg->str; regid->id2ast = reg; + regid->was_checked = true; AstNode *rhs = nullptr; @@ -2202,6 +2206,8 @@ skip_dynamic_range_lvalue_expansion:; AstNode *always = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_EQ, lvalue, clone()))); + always->children[0]->children[0]->was_checked = true; + current_ast_mod->children.push_back(always); goto replace_fcall_with_id; @@ -2251,6 +2257,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *assign = child->is_input ? new AstNode(AST_ASSIGN_EQ, wire_id->clone(), arg) : new AstNode(AST_ASSIGN_EQ, arg, wire_id->clone()); + assign->children[0]->was_checked = true; for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) { if (*it != current_block_child) @@ -2321,6 +2328,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *assign = child->is_input ? new AstNode(AST_ASSIGN_EQ, wire_id, arg) : new AstNode(AST_ASSIGN_EQ, arg, wire_id); + assign->children[0]->was_checked = true; for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) { if (*it != current_block_child) @@ -2760,6 +2768,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor, false))), value)); block->children.back()->children[0]->str = memory->str; block->children.back()->children[0]->id2ast = memory; + block->children.back()->children[0]->was_checked = true; } cursor += increment; @@ -3021,6 +3030,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *newNode = clone(); newNode->type = AST_ASSIGN_EQ; async_block->children[0]->children.push_back(newNode); + async_block->children[0]->children.back()->children[0]->was_checked = true; newNode = new AstNode(AST_NONE); newNode->cloneInto(this); @@ -3065,6 +3075,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone()); assign_addr->children[0]->str = id_addr; + assign_addr->children[0]->str = was_checked; block->children.insert(block->children.begin()+assign_idx+1, assign_addr); AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER)); @@ -3088,6 +3099,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, children[0]->id2ast = NULL; children[0]->str = id_data; type = AST_ASSIGN_EQ; + children[0]->was_checked = true; did_something = true; } -- cgit v1.2.3 From eb452ffb2861ceac572a4bef6dddb8db3b79deb7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 23 Sep 2018 10:32:54 +0200 Subject: Added support for ommited "parameter" in Verilog-2001 style parameter decl in SV mode Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_parser.y | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 2389d7d31..63cf646e9 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -881,9 +881,15 @@ param_decl_list: single_param_decl: TOK_ID '=' expr { - if (astbuf1 == nullptr) - frontend_verilog_yyerror("syntax error"); - AstNode *node = astbuf1->clone(); + AstNode *node; + if (astbuf1 == nullptr) { + if (!sv_mode) + frontend_verilog_yyerror("syntax error"); + node = new AstNode(AST_PARAMETER); + node->children.push_back(AstNode::mkconst_int(0, true)); + } else { + node = astbuf1->clone(); + } node->str = *$1; delete node->children[0]; node->children[0] = $3; -- cgit v1.2.3 From 8fde05dfa58d87ff2e71495c77f698af19a0d80b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 24 Sep 2018 20:51:16 +0200 Subject: Add "read_verilog -noassert -noassume -assert-assumes" Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_frontend.cc | 23 ++++++++++++++++++++++- frontends/verilog/verilog_frontend.h | 9 +++++++++ frontends/verilog/verilog_parser.y | 23 ++++++++++++++++++----- 3 files changed, 49 insertions(+), 6 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 8dcc7c5aa..aeea36a2b 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -66,12 +66,21 @@ struct VerilogFrontend : public Frontend { log(" enable support for SystemVerilog assertions and some Yosys extensions\n"); log(" replace the implicit -D SYNTHESIS with -D FORMAL\n"); log("\n"); + log(" -noassert\n"); + log(" ignore assert() statements\n"); + log("\n"); + log(" -noassume\n"); + log(" ignore assume() statements\n"); + log("\n"); log(" -norestrict\n"); - log(" ignore restrict() assertions\n"); + log(" ignore restrict() statements\n"); log("\n"); log(" -assume-asserts\n"); log(" treat all assert() statements like assume() statements\n"); log("\n"); + log(" -assert-assumes\n"); + log(" treat all assume() statements like assert() statements\n"); + log("\n"); log(" -dump_ast1\n"); log(" dump abstract syntax tree (before simplification)\n"); log("\n"); @@ -229,6 +238,14 @@ struct VerilogFrontend : public Frontend { formal_mode = true; continue; } + if (arg == "-noassert") { + noassert_mode = true; + continue; + } + if (arg == "-noassume") { + noassume_mode = true; + continue; + } if (arg == "-norestrict") { norestrict_mode = true; continue; @@ -237,6 +254,10 @@ struct VerilogFrontend : public Frontend { assume_asserts_mode = true; continue; } + if (arg == "-assert-assumes") { + assert_assumes_mode = true; + continue; + } if (arg == "-dump_ast1") { flag_dump_ast1 = true; continue; diff --git a/frontends/verilog/verilog_frontend.h b/frontends/verilog/verilog_frontend.h index 16edc7985..523bbc897 100644 --- a/frontends/verilog/verilog_frontend.h +++ b/frontends/verilog/verilog_frontend.h @@ -54,12 +54,21 @@ namespace VERILOG_FRONTEND // running in -formal mode extern bool formal_mode; + // running in -noassert mode + extern bool noassert_mode; + + // running in -noassume mode + extern bool noassume_mode; + // running in -norestrict mode extern bool norestrict_mode; // running in -assume-asserts mode extern bool assume_asserts_mode; + // running in -assert-assumes mode + extern bool assert_assumes_mode; + // running in -lib mode extern bool lib_mode; diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 63cf646e9..16cac1460 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -58,7 +58,8 @@ namespace VERILOG_FRONTEND { bool do_not_require_port_stubs; bool default_nettype_wire; bool sv_mode, formal_mode, lib_mode; - bool norestrict_mode, assume_asserts_mode; + bool noassert_mode, noassume_mode, norestrict_mode; + bool assume_asserts_mode, assert_assumes_mode; bool current_wire_rand, current_wire_const; std::istream *lexin; } @@ -1281,16 +1282,28 @@ opt_stmt_label: assert: opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5)); + if (noassert_mode) + delete $5; + else + ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5)); } | opt_stmt_label TOK_ASSUME opt_property '(' expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); + if (noassume_mode) + delete $5; + else + ast_stack.back()->children.push_back(new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5)); } | opt_stmt_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6)); + if (noassert_mode) + delete $6; + else + ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6)); } | opt_stmt_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); + if (noassume_mode) + delete $6; + else + ast_stack.back()->children.push_back(new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6)); } | opt_stmt_label TOK_COVER opt_property '(' expr ')' ';' { ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5)); -- cgit v1.2.3 From 80a07652f2eb5e13190f46dcc116207a0427dc65 Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Tue, 25 Sep 2018 00:32:57 +0300 Subject: Fixed issue #630 by fixing a minor typo in the previous commit (as well as a non critical minor code optimization) --- frontends/ast/simplify.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index e741bd92a..e1c2cb26a 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -3028,8 +3028,8 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *newNode = clone(); newNode->type = AST_ASSIGN_EQ; + newNode->children[0]->was_checked = true; async_block->children[0]->children.push_back(newNode); - async_block->children[0]->children.back()->children[0]->was_checked = true; newNode = new AstNode(AST_NONE); newNode->cloneInto(this); @@ -3074,7 +3074,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone()); assign_addr->children[0]->str = id_addr; - assign_addr->children[0]->str = was_checked; + assign_addr->children[0]->was_checked = true; block->children.insert(block->children.begin()+assign_idx+1, assign_addr); AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER)); -- cgit v1.2.3 From 9f9fe94b3522d465d98fa491c5992b14d268f09d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 30 Sep 2018 18:43:35 +0200 Subject: Fix handling of $past 2nd argument in read_verilog Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 04c429f7f..aa3b982d8 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1781,7 +1781,7 @@ skip_dynamic_range_lvalue_expansion:; if (GetSize(children) == 2) { AstNode *buf = children[1]->clone(); - while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } + while (buf->simplify(true, false, false, stage, -1, false, false)) { } if (buf->type != AST_CONSTANT) log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant value.\n", str.c_str()); -- cgit v1.2.3 From 62424ef3de67dc8077a0ca03b302966f0284730f Mon Sep 17 00:00:00 2001 From: Dan Gisselquist Date: Mon, 1 Oct 2018 19:41:35 +0200 Subject: Add read_verilog $changed support Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index aa3b982d8..71eba547c 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1836,7 +1836,7 @@ skip_dynamic_range_lvalue_expansion:; goto apply_newNode; } - if (str == "\\$stable" || str == "\\$rose" || str == "\\$fell") + if (str == "\\$stable" || str == "\\$rose" || str == "\\$fell" || str == "\\$changed") { if (GetSize(children) != 1) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", @@ -1853,6 +1853,9 @@ skip_dynamic_range_lvalue_expansion:; if (str == "\\$stable") newNode = new AstNode(AST_EQ, past, present); + else if (str == "\\$changed") + newNode = new AstNode(AST_NE, past, present); + else if (str == "\\$rose") newNode = new AstNode(AST_LOGIC_AND, new AstNode(AST_LOGIC_NOT, past), present); -- cgit v1.2.3 From cb214fc01d95ed9df7de10ccffa3471a1dc91659 Mon Sep 17 00:00:00 2001 From: Tom Verbeure Date: Tue, 2 Oct 2018 07:44:23 +0000 Subject: Fix for issue 594. --- frontends/ast/genrtlil.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 0f7e910f3..c9345ff08 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -985,7 +985,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) use_const_chunk: if (children.size() != 0) { - log_assert(children[0]->type == AST_RANGE); + if (children[0]->type != AST_RANGE) + log_file_error(filename, linenum, "Single range expected.\n"); int source_width = id2ast->range_left - id2ast->range_right + 1; int source_offset = id2ast->range_right; if (!children[0]->range_valid) { -- cgit v1.2.3 From 4b0448fc2cc707f312813b4e0826371fa384e3d9 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 5 Oct 2018 09:26:10 +0200 Subject: Fix compiler warning in verific.cc Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index c5fa58313..06d98611a 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1676,6 +1676,7 @@ YOSYS_NAMESPACE_END PRIVATE_NAMESPACE_BEGIN +#ifdef YOSYS_ENABLE_VERIFIC bool check_noverific_env() { const char *e = getenv("YOSYS_NOVERIFIC"); @@ -1685,6 +1686,7 @@ bool check_noverific_env() return false; return true; } +#endif struct VerificPass : public Pass { VerificPass() : Pass("verific", "load Verilog and VHDL designs using Verific") { } -- cgit v1.2.3 From 9850de405a11fe93e4562c86be0a0830b83c2785 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 7 Oct 2018 19:48:42 +0200 Subject: Improve Verific importer blackbox handling Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 06d98611a..dba3b0f0c 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -118,6 +118,18 @@ RTLIL::SigBit VerificImporter::net_map_at(Net *net) return net_map.at(net); } +bool is_blackbox(Netlist *nl) +{ + if (nl->IsBlackBox()) + return true; + + const char *attr = nl->GetAttValue("blackbox"); + if (attr != nullptr && strcmp(attr, "0")) + return true; + + return false; +} + void VerificImporter::import_attributes(dict &attributes, DesignObj *obj) { MapIter mi; @@ -709,7 +721,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se netlist = nl; if (design->has(module_name)) { - if (!nl->IsOperator()) + if (!nl->IsOperator() && !is_blackbox(nl)) log_cmd_error("Re-definition of module `%s'.\n", nl->Owner()->Name()); return; } @@ -718,7 +730,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se module->name = module_name; design->add(module); - if (nl->IsBlackBox()) { + if (is_blackbox(nl)) { log("Importing blackbox module %s.\n", RTLIL::id2cstr(module->name)); module->set_bool_attribute("\\blackbox"); } else { -- cgit v1.2.3 From 75009ada3c2a4bcd38c52c8fb871c9e8c1f2e6b1 Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Thu, 11 Oct 2018 23:33:31 +0200 Subject: Synthesis support for SystemVerilog interfaces This time doing the changes mostly in AST before RTLIL generation --- frontends/ast/ast.cc | 133 ++++++++++++++++++++++++++++++++++--- frontends/ast/ast.h | 6 ++ frontends/ast/genrtlil.cc | 48 ++++++++++++- frontends/ast/simplify.cc | 2 +- frontends/verilog/verilog_lexer.l | 8 +++ frontends/verilog/verilog_parser.y | 60 +++++++++++++++++ 6 files changed, 243 insertions(+), 14 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index e79be953a..256c08776 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -905,7 +905,7 @@ RTLIL::Const AstNode::realAsConst(int width) // create a new AstModule from an AST_MODULE AST node static AstModule* process_module(AstNode *ast, bool defer) { - log_assert(ast->type == AST_MODULE); + log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE); if (defer) log("Storing AST representation for module `%s'.\n", ast->str.c_str()); @@ -916,6 +916,7 @@ static AstModule* process_module(AstNode *ast, bool defer) current_module->ast = NULL; current_module->name = ast->str; current_module->attributes["\\src"] = stringf("%s:%d", ast->filename.c_str(), ast->linenum); + current_module->set_bool_attribute("\\cells_not_processed"); current_ast_mod = ast; AstNode *ast_before_simplify = ast->clone(); @@ -989,6 +990,8 @@ static AstModule* process_module(AstNode *ast, bool defer) ignoreThisSignalsInInitial = RTLIL::SigSpec(); } + if (ast->type == AST_INTERFACE) + current_module->set_bool_attribute("\\is_interface"); current_module->ast = ast_before_simplify; current_module->nolatches = flag_nolatches; current_module->nomeminit = flag_nomeminit; @@ -1031,7 +1034,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump log_assert(current_ast->type == AST_DESIGN); for (auto it = current_ast->children.begin(); it != current_ast->children.end(); it++) { - if ((*it)->type == AST_MODULE) + if ((*it)->type == AST_MODULE || (*it)->type == AST_INTERFACE) { for (auto n : design->verilog_globals) (*it)->children.push_back(n->clone()); @@ -1083,8 +1086,123 @@ AstModule::~AstModule() delete ast; } +void AstModule::reprocess_module(RTLIL::Design *design, dict local_interfaces) +{ + bool is_top = false; + AstNode *new_ast = ast->clone(); + for (auto &intf : local_interfaces) { + std::string intfname = intf.first.str(); + RTLIL::Module *intfmodule = intf.second; + for (auto &wire_it : intfmodule->wires_){ + AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); + std::string newname = log_id(wire_it.first); + newname = intfname + "." + newname; + wire->str = newname; + new_ast->children.push_back(wire); + } + } + std::string original_name = this->name.str(); + std::string changed_name = original_name + "_before_replacing_local_interfaces"; + design->rename(this, changed_name); + this->set_bool_attribute("\\to_delete"); + if (this->get_bool_attribute("\\initial_top")) { + this->attributes.erase("\\initial_top"); + is_top = true; + } + AstModule *newmod = process_module(new_ast, false); + design->add(newmod); + RTLIL::Module* mod = design->module(original_name); + if (is_top) + mod->set_bool_attribute("\\top"); + mod->set_bool_attribute("\\interfaces_replaced_in_module"); +} + +// create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces +RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters, dict interfaces, bool mayfail) +{ + AstNode *new_ast = NULL; + std::string modname = derive_common(design, parameters, &new_ast, mayfail); + + // Since interfaces themselves may be instantiated with different parameters, + // "modname" must also take those into account, so that unique modules + // are derived for any variant of interface connections: + std::string interf_info = ""; + + bool has_interfaces = false; + for(auto &intf : interfaces) { + interf_info += log_id(intf.second->name); + has_interfaces = true; + } + + if (has_interfaces) + modname += "$interfaces$" + interf_info; + + + if (!design->has(modname)) { + new_ast->str = modname; + for(auto &intf : interfaces) { + RTLIL::Module * intfmodule = intf.second; + std::string intfname = intf.first.str(); + for (auto &wire_it : intfmodule->wires_){ + AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); + std::string origname = log_id(wire_it.first); + std::string newname = intfname + "." + origname; + wire->str = newname; + wire->is_input = true; + wire->is_output = true; + new_ast->children.push_back(wire); + } + } + + design->add(process_module(new_ast, false)); + design->module(modname)->check(); + + RTLIL::Module* mod = design->module(modname); + + for(auto &intf : interfaces) { + if(mod->wires_.count(intf.first)) { + mod->wires_.erase(intf.first); + mod->fixup_ports(); + RTLIL::Cell * new_subcell = mod->addCell(intf.first, intf.second->name); + new_subcell->set_bool_attribute("\\is_interface"); + } + else { + log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf.first), modname); + } + } + + if (interfaces.size() > 0) { + mod->set_bool_attribute("\\interfaces_replaced_in_module"); + } + + } else { + log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); + } + + delete new_ast; + return modname; +} + +// create a new parametric module (when needed) and return the name of the generated module - without support for interfaces +RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters, bool mayfail) +{ + AstNode *new_ast = NULL; + std::string modname = derive_common(design, parameters, &new_ast, mayfail); + + if (!design->has(modname)) { + new_ast->str = modname; + design->add(process_module(new_ast, false)); + design->module(modname)->check(); + } else { + log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); + } + + delete new_ast; + return modname; +} + // create a new parametric module (when needed) and return the name of the generated module -RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters, bool) +std::string AstModule::derive_common(RTLIL::Design *design, dict parameters, AstNode **new_ast_out, bool) { std::string stripped_name = name.str(); @@ -1156,15 +1274,8 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dicthas(modname)) { - new_ast->str = modname; - design->add(process_module(new_ast, false)); - design->module(modname)->check(); - } else { - log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); - } - delete new_ast; + (*new_ast_out) = new_ast; return modname; } diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 7e97bdb3b..6b93832b4 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -142,6 +142,9 @@ namespace AST AST_NEGEDGE, AST_EDGE, + AST_INTERFACE, + AST_INTERFACEPORT, + AST_INTERFACEPORTTYPE, AST_PACKAGE }; @@ -284,6 +287,9 @@ namespace AST bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire; ~AstModule() YS_OVERRIDE; RTLIL::IdString derive(RTLIL::Design *design, dict parameters, bool mayfail) YS_OVERRIDE; + RTLIL::IdString derive(RTLIL::Design *design, dict parameters, dict interfaces, bool mayfail) YS_OVERRIDE; + std::string derive_common(RTLIL::Design *design, dict parameters, AstNode **new_ast_out, bool mayfail); + void reprocess_module(RTLIL::Design *design, dict local_interfaces) YS_OVERRIDE; RTLIL::Module *clone() const YS_OVERRIDE; }; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index c9345ff08..1dd1a9130 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -854,6 +854,22 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_GENCASE: case AST_PACKAGE: break; + case AST_INTERFACEPORT: { + // If a port in a module with unknown type is found, mark it as "is_interface=true" + // This is used by the hierarchy pass to know when it can replace interface connection with the individual + // signals. + RTLIL::Wire *wire = current_module->addWire(str, 1); + wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); + wire->start_offset = 0; + wire->port_id = port_id; + wire->port_input = true; + wire->port_output = true; + wire->set_bool_attribute("\\is_interface"); + wire->upto = 0; + } + break; + case AST_INTERFACEPORTTYPE: + break; // remember the parameter, needed for example in techmap case AST_PARAMETER: @@ -949,6 +965,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) { RTLIL::Wire *wire = NULL; RTLIL::SigChunk chunk; + bool is_interface = false; int add_undef_bits_msb = 0; int add_undef_bits_lsb = 0; @@ -969,15 +986,41 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) chunk = RTLIL::Const(id2ast->children[0]->bits); goto use_const_chunk; } - else if (!id2ast || (id2ast->type != AST_WIRE && id2ast->type != AST_AUTOWIRE && - id2ast->type != AST_MEMORY) || current_module->wires_.count(str) == 0) + else if (id2ast && (id2ast->type == AST_WIRE || id2ast->type == AST_AUTOWIRE || id2ast->type == AST_MEMORY) && current_module->wires_.count(str) != 0) { + RTLIL::Wire *current_wire = current_module->wire(str); + if (current_wire->get_bool_attribute("\\is_interface")) + is_interface = true; + // Ignore + } + // If an identifier is found that is not already known, assume that it is an interface: + else if (1) { // FIXME: Check if sv_mode first? + is_interface = true; + } + else { log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n", str.c_str()); + } if (id2ast->type == AST_MEMORY) log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n", str.c_str()); + // If identifier is an interface, create a RTLIL::SigSpec object and set is_interface to true. + // This makes it possible for the hierarchy pass to see what are interface connections and then replace them + // with the individual signals: + if (is_interface) { + RTLIL::Wire *dummy_wire; + std::string dummy_wire_name = "$dummywireforinterface" + str; + if (current_module->wires_.count(dummy_wire_name)) + dummy_wire = current_module->wires_[dummy_wire_name]; + else { + dummy_wire = current_module->addWire(dummy_wire_name); + dummy_wire->set_bool_attribute("\\is_interface"); + } + RTLIL::SigSpec tmp = RTLIL::SigSpec(dummy_wire); + return tmp; + } + wire = current_module->wires_[str]; chunk.wire = wire; chunk.width = wire->width; @@ -1423,6 +1466,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) RTLIL::Cell *cell = current_module->addCell(str, ""); cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); + cell->set_bool_attribute("\\module_not_derived"); for (auto it = children.begin(); it != children.end(); it++) { AstNode *child = *it; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 71eba547c..2a561ea5f 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -71,7 +71,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (stage == 0) { - log_assert(type == AST_MODULE); + log_assert(type == AST_MODULE || type == AST_INTERFACE); last_blocking_assignment_warn = pair(); deep_recursion_warning = true; diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 83921bf0b..8808c2675 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -150,6 +150,9 @@ YOSYS_NAMESPACE_END "specparam" { return TOK_SPECPARAM; } "package" { SV_KEYWORD(TOK_PACKAGE); } "endpackage" { SV_KEYWORD(TOK_ENDPACKAGE); } +"interface" { SV_KEYWORD(TOK_INTERFACE); } +"endinterface" { SV_KEYWORD(TOK_ENDINTERFACE); } +"modport" { SV_KEYWORD(TOK_MODPORT); } "parameter" { return TOK_PARAMETER; } "localparam" { return TOK_LOCALPARAM; } "defparam" { return TOK_DEFPARAM; } @@ -295,6 +298,11 @@ supply1 { return TOK_SUPPLY1; } return TOK_ID; } +[a-zA-Z_$][a-zA-Z0-9_$\.]* { + frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); + return TOK_ID; +} + "/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" { static bool printed_warning = false; if (!printed_warning) { diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 16cac1460..0ff5d576e 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -106,6 +106,7 @@ static void free_attr(std::map *al) %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_INTERFACE TOK_ENDINTERFACE TOK_MODPORT %token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG TOK_LOGIC %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 @@ -168,6 +169,7 @@ design: param_decl design | localparam_decl design | package design | + interface design | /* empty */; attr: @@ -320,6 +322,21 @@ module_arg: } delete $1; } module_arg_opt_assignment | + TOK_ID { + astbuf1 = new AstNode(AST_INTERFACEPORT); + astbuf1->children.push_back(new AstNode(AST_INTERFACEPORTTYPE)); + astbuf1->children[0]->str = *$1; + delete $1; + } TOK_ID { /* SV interfaces */ + if (!sv_mode) + frontend_verilog_yyerror("Interface found in port list (%s). This is not supported unless read_verilog is called with -sv!", $3->c_str()); + astbuf2 = astbuf1->clone(); // really only needed if multiple instances of same type. + astbuf2->str = *$3; + delete $3; + astbuf2->port_id = ++port_counter; + ast_stack.back()->children.push_back(astbuf2); + delete astbuf1; // really only needed if multiple instances of same type. + } module_arg_opt_assignment | attr wire_type range TOK_ID { AstNode *node = $2; node->str = *$4; @@ -357,6 +374,33 @@ package_body: package_body_stmt: localparam_decl; +interface: + TOK_INTERFACE TOK_ID { + do_not_require_port_stubs = false; + AstNode *intf = new AstNode(AST_INTERFACE); + ast_stack.back()->children.push_back(intf); + ast_stack.push_back(intf); + current_ast_mod = intf; + port_stubs.clear(); + port_counter = 0; + intf->str = *$2; + delete $2; + } module_para_opt module_args_opt ';' interface_body TOK_ENDINTERFACE { + if (port_stubs.size() != 0) + frontend_verilog_yyerror("Missing details for module port `%s'.", + port_stubs.begin()->first.c_str()); + ast_stack.pop_back(); + log_assert(ast_stack.size() == 1); + current_ast_mod = NULL; + }; + +interface_body: + interface_body interface_body_stmt |; + +interface_body_stmt: + param_decl | localparam_decl | defparam_decl | wire_decl | always_stmt | assign_stmt | + modport_stmt; + non_opt_delay: '#' TOK_ID { delete $2; } | '#' TOK_CONSTVAL { delete $2; } | @@ -1280,6 +1324,22 @@ opt_property: opt_stmt_label: TOK_ID ':' | /* empty */; +modport_stmt: + TOK_MODPORT TOK_ID modport_args_opt ';' + +modport_args_opt: + '(' ')' | '(' modport_args optional_comma ')'; + +modport_args: + modport_arg | modport_args ',' modport_arg; + +modport_arg: + modport_type_token TOK_ID | + TOK_ID + +modport_type_token: + TOK_INPUT | TOK_OUTPUT + assert: opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' { if (noassert_mode) -- cgit v1.2.3 From 458a94059e6738d93a87ddb9af282d0e1d28791d Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Fri, 12 Oct 2018 20:58:37 +0200 Subject: Support for 'modports' for System Verilog interfaces --- frontends/ast/ast.cc | 40 ++++++++++++++++++++++++++++++++++---- frontends/ast/ast.h | 4 +++- frontends/ast/genrtlil.cc | 29 +++++++++++++++++++++++++++ frontends/verilog/verilog_parser.y | 24 ++++++++++++++++++++--- 4 files changed, 89 insertions(+), 8 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 256c08776..10fd5277a 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1118,7 +1118,7 @@ void AstModule::reprocess_module(RTLIL::Design *design, dict parameters, dict interfaces, bool mayfail) +RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters, dict interfaces, dict modports, bool mayfail) { AstNode *new_ast = NULL; std::string modname = derive_common(design, parameters, &new_ast, mayfail); @@ -1143,14 +1143,46 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict 0) { + std::string interface_modport = modports.at(intfname).str(); + AstModule *ast_module_of_interface = (AstModule*)intfmodule; + AstNode *ast_node_of_interface = ast_module_of_interface->ast; + for (auto &ch : ast_node_of_interface->children) { + if (ch->type == AST_MODPORT) { + if (ch->str == interface_modport) { + modport = ch; + } + } + } + } for (auto &wire_it : intfmodule->wires_){ AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); std::string origname = log_id(wire_it.first); std::string newname = intfname + "." + origname; wire->str = newname; - wire->is_input = true; - wire->is_output = true; - new_ast->children.push_back(wire); + if (modport != NULL) { + bool found_in_modport = false; + for (auto &ch : modport->children) { + if (ch->type == AST_MODPORTMEMBER) { + std::string compare_name = "\\" + origname; + if (ch->str == compare_name) { + found_in_modport = true; + wire->is_input = ch->is_input; + wire->is_output = ch->is_output; + break; + } + } + } + if (found_in_modport) { // If not found in modport, do not create port + new_ast->children.push_back(wire); + } + } + else { // If no modport, set inout + wire->is_input = true; + wire->is_output = true; + new_ast->children.push_back(wire); + } } } diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 6b93832b4..8187b1ac6 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -145,6 +145,8 @@ namespace AST AST_INTERFACE, AST_INTERFACEPORT, AST_INTERFACEPORTTYPE, + AST_MODPORT, + AST_MODPORTMEMBER, AST_PACKAGE }; @@ -287,7 +289,7 @@ namespace AST bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire; ~AstModule() YS_OVERRIDE; RTLIL::IdString derive(RTLIL::Design *design, dict parameters, bool mayfail) YS_OVERRIDE; - RTLIL::IdString derive(RTLIL::Design *design, dict parameters, dict interfaces, bool mayfail) YS_OVERRIDE; + RTLIL::IdString derive(RTLIL::Design *design, dict parameters, dict interfaces, dict modports, bool mayfail) YS_OVERRIDE; std::string derive_common(RTLIL::Design *design, dict parameters, AstNode **new_ast_out, bool mayfail); void reprocess_module(RTLIL::Design *design, dict local_interfaces) YS_OVERRIDE; RTLIL::Module *clone() const YS_OVERRIDE; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 1dd1a9130..d87163dc2 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -853,6 +853,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_GENIF: case AST_GENCASE: case AST_PACKAGE: + case AST_MODPORT: + case AST_MODPORTMEMBER: break; case AST_INTERFACEPORT: { // If a port in a module with unknown type is found, mark it as "is_interface=true" @@ -865,6 +867,33 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) wire->port_input = true; wire->port_output = true; wire->set_bool_attribute("\\is_interface"); + if (children.size() > 0) { + for(size_t i=0; itype == AST_INTERFACEPORTTYPE) { + std::string name_type = children[i]->str; + size_t ndots = std::count(name_type.begin(), name_type.end(), '.'); + if (ndots == 0) { + wire->attributes["\\interface_type"] = name_type; + } + else { + std::stringstream name_type_stream(name_type); + std::string segment; + std::vector seglist; + while(std::getline(name_type_stream, segment, '.')) { + seglist.push_back(segment); + } + if (ndots == 1) { + wire->attributes["\\interface_type"] = seglist[0]; + wire->attributes["\\interface_modport"] = seglist[1]; + } + else { + log_error("More than two '.' in signal port type (%s)\n", name_type.c_str()); + } + } + break; + } + } + } wire->upto = 0; } break; diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 0ff5d576e..a6f37008a 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -61,6 +61,7 @@ namespace VERILOG_FRONTEND { bool noassert_mode, noassume_mode, norestrict_mode; bool assume_asserts_mode, assert_assumes_mode; bool current_wire_rand, current_wire_const; + bool current_modport_input, current_modport_output; std::istream *lexin; } YOSYS_NAMESPACE_END @@ -1325,7 +1326,16 @@ opt_stmt_label: TOK_ID ':' | /* empty */; modport_stmt: - TOK_MODPORT TOK_ID modport_args_opt ';' + TOK_MODPORT TOK_ID { + AstNode *modport = new AstNode(AST_MODPORT); + ast_stack.back()->children.push_back(modport); + ast_stack.push_back(modport); + modport->str = *$2; + delete $2; + } modport_args_opt { + ast_stack.pop_back(); + log_assert(ast_stack.size() == 2); + } ';' modport_args_opt: '(' ')' | '(' modport_args optional_comma ')'; @@ -1334,11 +1344,19 @@ modport_args: modport_arg | modport_args ',' modport_arg; modport_arg: - modport_type_token TOK_ID | + modport_type_token TOK_ID { + AstNode *modport_member = new AstNode(AST_MODPORTMEMBER); + ast_stack.back()->children.push_back(modport_member); + modport_member->str = *$2; + modport_member->is_input = current_modport_input; + modport_member->is_output = current_modport_output; + delete $2; + } | TOK_ID + /* FIXME for TOK_ID without modport_type_token */ modport_type_token: - TOK_INPUT | TOK_OUTPUT + TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;} assert: opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' { -- cgit v1.2.3 From a36d1701dd99736b82f64ed870e7464f2deae220 Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Fri, 12 Oct 2018 22:02:29 +0200 Subject: Fix build error with clang --- frontends/ast/ast.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 10fd5277a..b3f78c922 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1199,7 +1199,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dictset_bool_attribute("\\is_interface"); } else { - log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf.first), modname); + log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf.first), modname.c_str()); } } -- cgit v1.2.3 From 455638e00dff4951e666fb91fbd80de6b9e95f9f Mon Sep 17 00:00:00 2001 From: argama Date: Sun, 14 Oct 2018 01:42:48 +0800 Subject: detect ff/latch before processing other nodes --- frontends/liberty/liberty.cc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'frontends') diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index 0a5bd84de..0018d6dac 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -634,6 +634,8 @@ struct LibertyFrontend : public Frontend { } } + // some liberty files do not put ff/latch at the beginning of a cell + // try to find "ff" or "latch" and create FF/latch before processing all other nodes for (auto node : cell->children) { if (!flag_lib) { @@ -645,6 +647,21 @@ struct LibertyFrontend : public Frontend { goto skip_cell; } } + } + + for (auto node : cell->children) + { + /* + if (!flag_lib) { + if (node->id == "ff" && node->args.size() == 2) + create_ff(module, node); + if (node->id == "latch" && node->args.size() == 2) + if (!create_latch(module, node, flag_ignore_miss_data_latch)) { + delete module; + goto skip_cell; + } + } + */ if (node->id == "pin" && node->args.size() == 1) { -- cgit v1.2.3 From c50afc4246d552db079aec303b0d79ae92107a67 Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Sat, 13 Oct 2018 20:34:44 +0200 Subject: Documentation improvements etc. - Mention new feature in the SystemVerilog section in the README file - Commented changes much better - Rename a few signals to make it clearer - Prevent warning for unused signals in an easier way - Add myself as copyright holder to 2 files - Fix one potential memory leak (delete 'wire' if not in modport) --- frontends/ast/ast.cc | 31 ++++++++++++++++++++++++++++--- frontends/ast/genrtlil.cc | 12 +++++++----- 2 files changed, 35 insertions(+), 8 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index b3f78c922..7600e2912 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -2,6 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf + * Copyright (C) 2018 Ruben Undheim * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -1086,6 +1087,8 @@ AstModule::~AstModule() delete ast; } +// When an interface instance is found in a module, the whole RTLIL for the module will be rederived again +// from AST. The interface members are copied into the AST module with the prefix of the interface. void AstModule::reprocess_module(RTLIL::Design *design, dict local_interfaces) { bool is_top = false; @@ -1101,23 +1104,33 @@ void AstModule::reprocess_module(RTLIL::Design *design, dictchildren.push_back(wire); } } + + // The old module will be deleted. Rename and mark for deletion: std::string original_name = this->name.str(); std::string changed_name = original_name + "_before_replacing_local_interfaces"; design->rename(this, changed_name); this->set_bool_attribute("\\to_delete"); + + // Check if the module was the top module. If it was, we need to remove the top attribute and put it on the + // new module. if (this->get_bool_attribute("\\initial_top")) { this->attributes.erase("\\initial_top"); is_top = true; } + + // Generate RTLIL from AST for the new module and add to the design: AstModule *newmod = process_module(new_ast, false); design->add(newmod); RTLIL::Module* mod = design->module(original_name); if (is_top) mod->set_bool_attribute("\\top"); + + // Set the attribute "interfaces_replaced_in_module" so that it does not happen again. mod->set_bool_attribute("\\interfaces_replaced_in_module"); } // create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces +// This method is used to explode the interface when the interface is a port of the module (not instantiated inside) RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters, dict interfaces, dict modports, bool mayfail) { AstNode *new_ast = NULL; @@ -1140,9 +1153,12 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dicthas(modname)) { new_ast->str = modname; + + // Iterate over all interfaces which are ports in this module: for(auto &intf : interfaces) { RTLIL::Module * intfmodule = intf.second; std::string intfname = intf.first.str(); + // Check if a modport applies for the interface port: AstNode *modport = NULL; if (modports.count(intfname) > 0) { std::string interface_modport = modports.at(intfname).str(); @@ -1150,12 +1166,13 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dictast; for (auto &ch : ast_node_of_interface->children) { if (ch->type == AST_MODPORT) { - if (ch->str == interface_modport) { + if (ch->str == interface_modport) { // Modport found modport = ch; } } } } + // Iterate over all wires in the interface and add them to the module: for (auto &wire_it : intfmodule->wires_){ AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); std::string origname = log_id(wire_it.first); @@ -1163,10 +1180,11 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dictstr = newname; if (modport != NULL) { bool found_in_modport = false; + // Search for the current wire in the wire list for the current modport for (auto &ch : modport->children) { if (ch->type == AST_MODPORTMEMBER) { std::string compare_name = "\\" + origname; - if (ch->str == compare_name) { + if (ch->str == compare_name) { // Found signal. The modport decides whether it is input or output found_in_modport = true; wire->is_input = ch->is_input; wire->is_output = ch->is_output; @@ -1174,9 +1192,12 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dictchildren.push_back(wire); } + else { // If not found in modport, do not create port + delete wire; + } } else { // If no modport, set inout wire->is_input = true; @@ -1191,10 +1212,13 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dictmodule(modname); + // Now that the interfaces have been exploded, we can delete the dummy port related to every interface. for(auto &intf : interfaces) { if(mod->wires_.count(intf.first)) { mod->wires_.erase(intf.first); mod->fixup_ports(); + // We copy the cell of the interface to the sub-module such that it can further be found if it is propagated + // down to sub-sub-modules etc. RTLIL::Cell * new_subcell = mod->addCell(intf.first, intf.second->name); new_subcell->set_bool_attribute("\\is_interface"); } @@ -1203,6 +1227,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict 0) { mod->set_bool_attribute("\\interfaces_replaced_in_module"); } diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index d87163dc2..32b9af6e9 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -857,7 +857,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_MODPORTMEMBER: break; case AST_INTERFACEPORT: { - // If a port in a module with unknown type is found, mark it as "is_interface=true" + // If a port in a module with unknown type is found, mark it with the attribute 'is_interface' // This is used by the hierarchy pass to know when it can replace interface connection with the individual // signals. RTLIL::Wire *wire = current_module->addWire(str, 1); @@ -872,7 +872,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if(children[i]->type == AST_INTERFACEPORTTYPE) { std::string name_type = children[i]->str; size_t ndots = std::count(name_type.begin(), name_type.end(), '.'); - if (ndots == 0) { + // Separate the interface instance name from any modports: + if (ndots == 0) { // Does not have modport wire->attributes["\\interface_type"] = name_type; } else { @@ -882,11 +883,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) while(std::getline(name_type_stream, segment, '.')) { seglist.push_back(segment); } - if (ndots == 1) { + if (ndots == 1) { // Has modport wire->attributes["\\interface_type"] = seglist[0]; wire->attributes["\\interface_modport"] = seglist[1]; } - else { + else { // Erroneous port type log_error("More than two '.' in signal port type (%s)\n", name_type.c_str()); } } @@ -1034,7 +1035,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n", str.c_str()); - // If identifier is an interface, create a RTLIL::SigSpec object and set is_interface to true. + // If identifier is an interface, create a RTLIL::SigSpec with a dummy wire with a attribute called 'is_interface' // This makes it possible for the hierarchy pass to see what are interface connections and then replace them // with the individual signals: if (is_interface) { @@ -1495,6 +1496,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) RTLIL::Cell *cell = current_module->addCell(str, ""); cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); + // Set attribute 'module_not_derived' which will be cleared again after the hierarchy pass cell->set_bool_attribute("\\module_not_derived"); for (auto it = children.begin(); it != children.end(); it++) { -- cgit v1.2.3 From 736105b0468f9468f00915cad60949535ce5a496 Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Sat, 13 Oct 2018 20:48:55 +0200 Subject: Handle FIXME for modport members without type directly in front --- frontends/verilog/verilog_parser.y | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index a6f37008a..4dbe028a0 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1344,16 +1344,18 @@ modport_args: modport_arg | modport_args ',' modport_arg; modport_arg: - modport_type_token TOK_ID { + modport_type_token modport_member | + modport_member + +modport_member: + TOK_ID { AstNode *modport_member = new AstNode(AST_MODPORTMEMBER); ast_stack.back()->children.push_back(modport_member); - modport_member->str = *$2; + modport_member->str = *$1; modport_member->is_input = current_modport_input; modport_member->is_output = current_modport_output; - delete $2; - } | - TOK_ID - /* FIXME for TOK_ID without modport_type_token */ + delete $1; + } modport_type_token: TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;} -- cgit v1.2.3 From 097da32e1a8cfe29d64666c1b2c9b47129b07c7e Mon Sep 17 00:00:00 2001 From: argama Date: Tue, 16 Oct 2018 21:33:37 +0800 Subject: ignore protect endprotect --- frontends/verilog/verilog_lexer.l | 3 +++ 1 file changed, 3 insertions(+) (limited to 'frontends') diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 83921bf0b..2c4880b84 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -135,6 +135,9 @@ YOSYS_NAMESPACE_END frontend_verilog_yyerror("Unsupported default nettype: %s", p); } +"`protect"[^\n]* /* ignore `protect*/ +"`endprotect"[^\n]* /* ignore `endprotect*/ + "`"[a-zA-Z_$][a-zA-Z0-9_$]* { frontend_verilog_yyerror("Unimplemented compiler directive or undefined macro %s.", yytext); } -- cgit v1.2.3 From 6ca493b88ca101f357e9de4dfdad4f3c913512c8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 17 Oct 2018 12:23:36 +0200 Subject: Minor code cleanups in liberty front-end Signed-off-by: Clifford Wolf --- frontends/liberty/liberty.cc | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'frontends') diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index 0018d6dac..66db43baf 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -634,11 +634,12 @@ struct LibertyFrontend : public Frontend { } } - // some liberty files do not put ff/latch at the beginning of a cell - // try to find "ff" or "latch" and create FF/latch before processing all other nodes - for (auto node : cell->children) + if (!flag_lib) { - if (!flag_lib) { + // some liberty files do not put ff/latch at the beginning of a cell + // try to find "ff" or "latch" and create FF/latch _before_ processing all other nodes + for (auto node : cell->children) + { if (node->id == "ff" && node->args.size() == 2) create_ff(module, node); if (node->id == "latch" && node->args.size() == 2) @@ -651,18 +652,6 @@ struct LibertyFrontend : public Frontend { for (auto node : cell->children) { - /* - if (!flag_lib) { - if (node->id == "ff" && node->args.size() == 2) - create_ff(module, node); - if (node->id == "latch" && node->args.size() == 2) - if (!create_latch(module, node, flag_ignore_miss_data_latch)) { - delete module; - goto skip_cell; - } - } - */ - if (node->id == "pin" && node->args.size() == 1) { LibertyAst *dir = node->find("direction"); -- cgit v1.2.3 From d9a438101298710b9dadd4e7a1cb0041e8ba4199 Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Sat, 20 Oct 2018 11:57:39 +0200 Subject: Fixed memory leak --- frontends/ast/ast.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 7600e2912..1f2ecffde 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1120,6 +1120,7 @@ void AstModule::reprocess_module(RTLIL::Design *design, dictadd(newmod); RTLIL::Module* mod = design->module(original_name); if (is_top) -- cgit v1.2.3 From 397dfccb304a12a40d34c4454a5cb4acee8be75f Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Sat, 20 Oct 2018 11:58:25 +0200 Subject: Support for SystemVerilog interfaces as a port in the top level module + test case --- frontends/ast/ast.cc | 108 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 105 insertions(+), 3 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 1f2ecffde..412e04f6e 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -904,7 +904,7 @@ RTLIL::Const AstNode::realAsConst(int width) } // create a new AstModule from an AST_MODULE AST node -static AstModule* process_module(AstNode *ast, bool defer) +static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast = NULL) { log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE); @@ -920,7 +920,11 @@ static AstModule* process_module(AstNode *ast, bool defer) current_module->set_bool_attribute("\\cells_not_processed"); current_ast_mod = ast; - AstNode *ast_before_simplify = ast->clone(); + AstNode *ast_before_simplify; + if (original_ast != NULL) + ast_before_simplify = original_ast; + else + ast_before_simplify = ast->clone(); if (flag_dump_ast1) { log("Dumping Verilog AST before simplification:\n"); @@ -1105,6 +1109,104 @@ void AstModule::reprocess_module(RTLIL::Design *design, dictclone(); + + // Explode all interface ports. Note this will only have any effect on top + // level modules. Other sub-modules will have their interface ports + // exploded in derive(..) + for (size_t i =0; ichildren.size(); i++) + { + AstNode *ch2 = new_ast->children[i]; + std::string interface_type = ""; + std::string interface_modport = ""; + if (ch2->type == AST_INTERFACEPORT) { + std::string name_port = ch2->str; + if (ch2->children.size() > 0) { + for(size_t j=0; jchildren.size();j++) { + AstNode *ch = ch2->children[j]; + if(ch->type == AST_INTERFACEPORTTYPE) { + std::string name_type = ch->str; + size_t ndots = std::count(name_type.begin(), name_type.end(), '.'); + // Separate the interface instance name from any modports: + if (ndots == 0) { // Does not have modport + interface_type = name_type; + } + else { + std::stringstream name_type_stream(name_type); + std::string segment; + std::vector seglist; + while(std::getline(name_type_stream, segment, '.')) { + seglist.push_back(segment); + } + if (ndots == 1) { // Has modport + interface_type = seglist[0]; + interface_modport = seglist[1]; + } + else { // Erroneous port type + log_error("More than two '.' in signal port type (%s)\n", name_type.c_str()); + } + } + if (design->modules_.count(interface_type) > 0) { + AstNode *celltype_for_intf = new AstNode(AST_CELLTYPE); + celltype_for_intf->str = interface_type; + AstNode *cell_for_intf = new AstNode(AST_CELL, celltype_for_intf); + cell_for_intf->str = name_port + "_inst_from_top_dummy"; + new_ast->children.push_back(cell_for_intf); + + RTLIL::Module *intfmodule = design->modules_[interface_type]; + AstModule *ast_module_of_interface = (AstModule*)intfmodule; + AstNode *ast_node_of_interface = ast_module_of_interface->ast; + AstNode *modport = NULL; + std::string interface_modport_compare_str = "\\" + interface_modport; + for (auto &chm : ast_node_of_interface->children) { + if (chm->type == AST_MODPORT) { + if (chm->str == interface_modport_compare_str) { // Modport found + modport = chm; + } + } + } + + std::string intfname = name_port; + for (auto &wire_it : intfmodule->wires_){ + AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); + std::string origname = log_id(wire_it.first); + std::string newname = intfname + "." + origname; + wire->str = newname; + if (modport != NULL) { + bool found_in_modport = false; + // Search for the current wire in the wire list for the current modport + for (auto &ch : modport->children) { + if (ch->type == AST_MODPORTMEMBER) { + std::string compare_name = "\\" + origname; + if (ch->str == compare_name) { // Found signal. The modport decides whether it is input or output + found_in_modport = true; + wire->is_input = ch->is_input; + wire->is_output = ch->is_output; + break; + } + } + } + if (found_in_modport) { + new_ast->children.push_back(wire); + } + else { // If not found in modport, do not create port + delete wire; + } + } + else { // If no modport, set inout + wire->is_input = true; + wire->is_output = true; + new_ast->children.push_back(wire); + } + } + } + } + } + } + } + } + + // The old module will be deleted. Rename and mark for deletion: std::string original_name = this->name.str(); std::string changed_name = original_name + "_before_replacing_local_interfaces"; @@ -1119,7 +1221,7 @@ void AstModule::reprocess_module(RTLIL::Design *design, dictadd(newmod); RTLIL::Module* mod = design->module(original_name); -- cgit v1.2.3 From 436e3c0a7cbe5a482e14857e4e5a1d02b3464ae8 Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Sat, 20 Oct 2018 12:45:51 +0200 Subject: Refactor code to avoid code duplication + added comments --- frontends/ast/ast.cc | 212 ++++++++++++++++++++++------------------------ frontends/ast/ast.h | 5 ++ frontends/ast/genrtlil.cc | 25 +----- 3 files changed, 108 insertions(+), 134 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 412e04f6e..cc275959a 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1091,6 +1091,84 @@ AstModule::~AstModule() delete ast; } + +// An interface port with modport is specified like this: +// . +// This function splits the interface_name from the modport_name, and fails if it is not a valid combination +std::pair AST::split_modport_from_type(std::string name_type) +{ + std::string interface_type = ""; + std::string interface_modport = ""; + size_t ndots = std::count(name_type.begin(), name_type.end(), '.'); + // Separate the interface instance name from any modports: + if (ndots == 0) { // Does not have modport + interface_type = name_type; + } + else { + std::stringstream name_type_stream(name_type); + std::string segment; + std::vector seglist; + while(std::getline(name_type_stream, segment, '.')) { + seglist.push_back(segment); + } + if (ndots == 1) { // Has modport + interface_type = seglist[0]; + interface_modport = seglist[1]; + } + else { // Erroneous port type + log_error("More than two '.' in signal port type (%s)\n", name_type.c_str()); + } + } + return std::pair(interface_type, interface_modport); + +} + +AstNode * AST::find_modport(AstNode *intf, std::string name) +{ + for (auto &ch : intf->children) + if (ch->type == AST_MODPORT) + if (ch->str == name) // Modport found + return ch; + return NULL; +} + +// Iterate over all wires in an interface and add them as wires in the AST module: +void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport) +{ + for (auto &wire_it : intfmodule->wires_){ + AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); + std::string origname = log_id(wire_it.first); + std::string newname = intfname + "." + origname; + wire->str = newname; + if (modport != NULL) { + bool found_in_modport = false; + // Search for the current wire in the wire list for the current modport + for (auto &ch : modport->children) { + if (ch->type == AST_MODPORTMEMBER) { + std::string compare_name = "\\" + origname; + if (ch->str == compare_name) { // Found signal. The modport decides whether it is input or output + found_in_modport = true; + wire->is_input = ch->is_input; + wire->is_output = ch->is_output; + break; + } + } + } + if (found_in_modport) { + module_ast->children.push_back(wire); + } + else { // If not found in modport, do not create port + delete wire; + } + } + else { // If no modport, set inout + wire->is_input = true; + wire->is_output = true; + module_ast->children.push_back(wire); + } + } +} + // When an interface instance is found in a module, the whole RTLIL for the module will be rederived again // from AST. The interface members are copied into the AST module with the prefix of the interface. void AstModule::reprocess_module(RTLIL::Design *design, dict local_interfaces) @@ -1111,102 +1189,47 @@ void AstModule::reprocess_module(RTLIL::Design *design, dictclone(); - // Explode all interface ports. Note this will only have any effect on top - // level modules. Other sub-modules will have their interface ports - // exploded in derive(..) + // Explode all interface ports. Note this will only have an effect on 'top + // level' modules. Other sub-modules will have their interface ports + // exploded via the derive(..) function for (size_t i =0; ichildren.size(); i++) { AstNode *ch2 = new_ast->children[i]; - std::string interface_type = ""; - std::string interface_modport = ""; - if (ch2->type == AST_INTERFACEPORT) { - std::string name_port = ch2->str; + if (ch2->type == AST_INTERFACEPORT) { // Is an interface port + std::string name_port = ch2->str; // Name of the interface port if (ch2->children.size() > 0) { for(size_t j=0; jchildren.size();j++) { AstNode *ch = ch2->children[j]; - if(ch->type == AST_INTERFACEPORTTYPE) { - std::string name_type = ch->str; - size_t ndots = std::count(name_type.begin(), name_type.end(), '.'); - // Separate the interface instance name from any modports: - if (ndots == 0) { // Does not have modport - interface_type = name_type; - } - else { - std::stringstream name_type_stream(name_type); - std::string segment; - std::vector seglist; - while(std::getline(name_type_stream, segment, '.')) { - seglist.push_back(segment); - } - if (ndots == 1) { // Has modport - interface_type = seglist[0]; - interface_modport = seglist[1]; - } - else { // Erroneous port type - log_error("More than two '.' in signal port type (%s)\n", name_type.c_str()); - } - } + if(ch->type == AST_INTERFACEPORTTYPE) { // Found the AST node containing the type of the interface + std::pair res = split_modport_from_type(ch->str); + std::string interface_type = res.first; + std::string interface_modport = res.second; // Is "", if no modport if (design->modules_.count(interface_type) > 0) { + // Add a cell to the module corresponding to the interface port such that + // it can further propagated down if needed: AstNode *celltype_for_intf = new AstNode(AST_CELLTYPE); celltype_for_intf->str = interface_type; AstNode *cell_for_intf = new AstNode(AST_CELL, celltype_for_intf); cell_for_intf->str = name_port + "_inst_from_top_dummy"; new_ast->children.push_back(cell_for_intf); - RTLIL::Module *intfmodule = design->modules_[interface_type]; + // Get all members of this non-overridden dummy interface instance: + RTLIL::Module *intfmodule = design->modules_[interface_type]; // All interfaces should at this point in time (assuming + // reprocess_module is called from the hierarchy pass) be + // present in design->modules_ AstModule *ast_module_of_interface = (AstModule*)intfmodule; - AstNode *ast_node_of_interface = ast_module_of_interface->ast; - AstNode *modport = NULL; std::string interface_modport_compare_str = "\\" + interface_modport; - for (auto &chm : ast_node_of_interface->children) { - if (chm->type == AST_MODPORT) { - if (chm->str == interface_modport_compare_str) { // Modport found - modport = chm; - } - } - } - - std::string intfname = name_port; - for (auto &wire_it : intfmodule->wires_){ - AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); - std::string origname = log_id(wire_it.first); - std::string newname = intfname + "." + origname; - wire->str = newname; - if (modport != NULL) { - bool found_in_modport = false; - // Search for the current wire in the wire list for the current modport - for (auto &ch : modport->children) { - if (ch->type == AST_MODPORTMEMBER) { - std::string compare_name = "\\" + origname; - if (ch->str == compare_name) { // Found signal. The modport decides whether it is input or output - found_in_modport = true; - wire->is_input = ch->is_input; - wire->is_output = ch->is_output; - break; - } - } - } - if (found_in_modport) { - new_ast->children.push_back(wire); - } - else { // If not found in modport, do not create port - delete wire; - } - } - else { // If no modport, set inout - wire->is_input = true; - wire->is_output = true; - new_ast->children.push_back(wire); - } - } + AstNode *modport = find_modport(ast_module_of_interface->ast, interface_modport_compare_str); // modport == NULL if no modport + // Iterate over all wires in the interface and add them to the module: + explode_interface_port(new_ast, intfmodule, name_port, modport); } + break; } } } } } - // The old module will be deleted. Rename and mark for deletion: std::string original_name = this->name.str(); std::string changed_name = original_name + "_before_replacing_local_interfaces"; @@ -1267,47 +1290,10 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dictast; - for (auto &ch : ast_node_of_interface->children) { - if (ch->type == AST_MODPORT) { - if (ch->str == interface_modport) { // Modport found - modport = ch; - } - } - } + modport = find_modport(ast_node_of_interface, interface_modport); } // Iterate over all wires in the interface and add them to the module: - for (auto &wire_it : intfmodule->wires_){ - AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); - std::string origname = log_id(wire_it.first); - std::string newname = intfname + "." + origname; - wire->str = newname; - if (modport != NULL) { - bool found_in_modport = false; - // Search for the current wire in the wire list for the current modport - for (auto &ch : modport->children) { - if (ch->type == AST_MODPORTMEMBER) { - std::string compare_name = "\\" + origname; - if (ch->str == compare_name) { // Found signal. The modport decides whether it is input or output - found_in_modport = true; - wire->is_input = ch->is_input; - wire->is_output = ch->is_output; - break; - } - } - } - if (found_in_modport) { - new_ast->children.push_back(wire); - } - else { // If not found in modport, do not create port - delete wire; - } - } - else { // If no modport, set inout - wire->is_input = true; - wire->is_output = true; - new_ast->children.push_back(wire); - } - } + explode_interface_port(new_ast, intfmodule, intfname, modport); } design->add(process_module(new_ast, false)); diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 8187b1ac6..08f91c9c3 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -308,6 +308,11 @@ namespace AST // call a DPI function AstNode *dpi_call(const std::string &rtype, const std::string &fname, const std::vector &argtypes, const std::vector &args); + + // Helper functions related to handling SystemVerilog interfaces + std::pair split_modport_from_type(std::string name_type); + AstNode * find_modport(AstNode *intf, std::string name); + void explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport); } namespace AST_INTERNAL diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 32b9af6e9..8a6849faa 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -870,27 +870,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (children.size() > 0) { for(size_t i=0; itype == AST_INTERFACEPORTTYPE) { - std::string name_type = children[i]->str; - size_t ndots = std::count(name_type.begin(), name_type.end(), '.'); - // Separate the interface instance name from any modports: - if (ndots == 0) { // Does not have modport - wire->attributes["\\interface_type"] = name_type; - } - else { - std::stringstream name_type_stream(name_type); - std::string segment; - std::vector seglist; - while(std::getline(name_type_stream, segment, '.')) { - seglist.push_back(segment); - } - if (ndots == 1) { // Has modport - wire->attributes["\\interface_type"] = seglist[0]; - wire->attributes["\\interface_modport"] = seglist[1]; - } - else { // Erroneous port type - log_error("More than two '.' in signal port type (%s)\n", name_type.c_str()); - } - } + std::pair res = AST::split_modport_from_type(children[i]->str); + wire->attributes["\\interface_type"] = res.first; + if (res.second != "") + wire->attributes["\\interface_modport"] = res.second; break; } } -- cgit v1.2.3 From 23b69ca32b2ef93fc4b3f724099bfecdee0af869 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 20 Oct 2018 23:48:53 +0200 Subject: Improve read_verilog range out of bounds warning Signed-off-by: Clifford Wolf --- frontends/ast/genrtlil.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 8a6849faa..59c309665 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -1083,8 +1083,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting result bit to undef.\n", str.c_str()); else - log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting all %d result bits to undef.\n", - str.c_str(), chunk.width); + log_file_warning(filename, linenum, "Range select [%d:%d] out of bounds on signal `%s': Setting all %d result bits to undef.\n", + children[0]->range_left, children[0]->range_right, str.c_str(), chunk.width); chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width); } else { if (chunk.width + chunk.offset > source_width) { @@ -1097,11 +1097,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) chunk.offset += add_undef_bits_lsb; } if (add_undef_bits_lsb) - log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d LSB bits to undef.\n", - str.c_str(), add_undef_bits_lsb); + log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d LSB bits to undef.\n", + children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_lsb); if (add_undef_bits_msb) - log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d MSB bits to undef.\n", - str.c_str(), add_undef_bits_msb); + log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d MSB bits to undef.\n", + children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_msb); } } } -- cgit v1.2.3 From 536ae16c3abcf3fef1dd14df8733bf51fa1bce1a Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Thu, 25 Oct 2018 02:37:56 +0300 Subject: Rename the generic "Syntax error" message from the Verilog/SystemVerilog parser into unique, meaningful info on the error. Also add 13 compilation examples that triggers each of these messages. --- frontends/verilog/verilog_parser.y | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 4dbe028a0..f8eee5d22 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -305,7 +305,7 @@ module_arg_opt_assignment: else ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2)); } else - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("SystemVerilog interface in module port list cannot have a default value."); } | /* empty */; @@ -672,7 +672,7 @@ task_func_port: astbuf2 = $3; if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) { if (astbuf2) { - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions (task/function arguments)"); } else { astbuf2 = new AstNode(AST_RANGE); astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true)); @@ -680,7 +680,7 @@ task_func_port: } } if (astbuf2 && astbuf2->children.size() != 2) - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("task/function argument range must be of the form: [:], [+:], or [-:]"); } wire_name | wire_name; task_func_body: @@ -883,7 +883,7 @@ param_signed: param_integer: TOK_INTEGER { if (astbuf1->children.size() != 1) - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("Internal error in param_integer - should not happen?"); astbuf1->children.push_back(new AstNode(AST_RANGE)); astbuf1->children.back()->children.push_back(AstNode::mkconst_int(31, true)); astbuf1->children.back()->children.push_back(AstNode::mkconst_int(0, true)); @@ -893,7 +893,7 @@ param_integer: param_real: TOK_REAL { if (astbuf1->children.size() != 1) - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("Parameter already declared as integer, cannot set to real."); astbuf1->children.push_back(new AstNode(AST_REALVALUE)); } | /* empty */; @@ -901,7 +901,7 @@ param_range: range { if ($1 != NULL) { if (astbuf1->children.size() != 1) - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("integer/real parameters should not have a range."); astbuf1->children.push_back($1); } }; @@ -930,7 +930,7 @@ single_param_decl: AstNode *node; if (astbuf1 == nullptr) { if (!sv_mode) - frontend_verilog_yyerror("syntax error"); + frontend_verilog_yyerror("In pure Verilog (not SystemVerilog), parameter/localparam with an initializer must use the parameter/localparam keyword"); node = new AstNode(AST_PARAMETER); node->children.push_back(AstNode::mkconst_int(0, true)); } else { @@ -966,7 +966,7 @@ wire_decl: astbuf2 = $3; if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) { if (astbuf2) { - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions."); } else { astbuf2 = new AstNode(AST_RANGE); astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true)); @@ -974,7 +974,7 @@ wire_decl: } } if (astbuf2 && astbuf2->children.size() != 2) - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [:], [+:], or [-:]"); } wire_name_list { delete astbuf1; if (astbuf2 != NULL) @@ -1068,7 +1068,7 @@ wire_name_and_opt_assign: wire_name: TOK_ID range_or_multirange { if (astbuf1 == nullptr) - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("Internal error - should not happen - no AST_WIRE node."); AstNode *node = astbuf1->clone(); node->str = *$1; append_attr_clone(node, albuf); @@ -1076,7 +1076,7 @@ wire_name: node->children.push_back(astbuf2->clone()); if ($2 != NULL) { if (node->is_input || node->is_output) - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("input/output/inout ports cannot have unpacked dimensions."); if (!astbuf2) { AstNode *rng = new AstNode(AST_RANGE); rng->children.push_back(AstNode::mkconst_int(0, true)); @@ -1478,7 +1478,7 @@ behavioral_stmt: node->str = *$3; } behavioral_stmt_list TOK_END opt_label { if ($3 != NULL && $7 != NULL && *$3 != *$7) - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("Begin label (%s) and end label (%s) doesn't match.", $3->c_str()+1, $7->c_str()+1); if ($3 != NULL) delete $3; if ($7 != NULL) @@ -1794,7 +1794,7 @@ basic_expr: } | '(' expr ')' TOK_CONSTVAL { if ($4->substr(0, 1) != "'") - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("Cast operation must be applied on sized constants e.g. () , while %s is not a sized constant.", $4->c_str()); AstNode *bits = $2; AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); if (val == NULL) @@ -1804,7 +1804,7 @@ basic_expr: } | hierarchical_id TOK_CONSTVAL { if ($2->substr(0, 1) != "'") - frontend_verilog_yyerror("Syntax error."); + frontend_verilog_yyerror("Cast operation must be applied on sized constants, e.g. \'d0, while %s is not a sized constant.", $2->c_str()); AstNode *bits = new AstNode(AST_IDENTIFIER); bits->str = *$1; AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); -- cgit v1.2.3 From 5ab58d49308a670178a404e6e11bd8758f33c16d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 25 Oct 2018 13:20:00 +0200 Subject: Fix minor typo in error message Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_parser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index f8eee5d22..1fe08903c 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1478,7 +1478,7 @@ behavioral_stmt: node->str = *$3; } behavioral_stmt_list TOK_END opt_label { if ($3 != NULL && $7 != NULL && *$3 != *$7) - frontend_verilog_yyerror("Begin label (%s) and end label (%s) doesn't match.", $3->c_str()+1, $7->c_str()+1); + frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $3->c_str()+1, $7->c_str()+1); if ($3 != NULL) delete $3; if ($7 != NULL) -- cgit v1.2.3 From d86ea6badd1911064138c32fc8e65934f923f90e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 1 Nov 2018 15:25:24 +0100 Subject: Do not generate "reg assigned in a continuous assignment" warnings for "rand reg" Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index e56a62563..fcadd329a 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -450,8 +450,21 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, children[0]->id2ast->is_reg = true; // if logic type is used in a block asignment if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && !children[0]->id2ast->is_reg) log_warning("wire '%s' is assigned in a block at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); - if (type == AST_ASSIGN && children[0]->id2ast->is_reg) - log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); + if (type == AST_ASSIGN && children[0]->id2ast->is_reg) { + bool is_rand_reg = false; + if (children[1]->type == AST_FCALL) { + if (children[1]->str == "\\$anyconst") + is_rand_reg = true; + if (children[1]->str == "\\$anyseq") + is_rand_reg = true; + if (children[1]->str == "\\$allconst") + is_rand_reg = true; + if (children[1]->str == "\\$allseq") + is_rand_reg = true; + } + if (!is_rand_reg) + log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); + } children[0]->was_checked = true; } break; -- cgit v1.2.3 From 39f891aebce87b4a6124c2f7dc5b6b2d04ec2899 Mon Sep 17 00:00:00 2001 From: ZipCPU Date: Sat, 3 Nov 2018 13:39:32 -0400 Subject: Make and dependent upon LSB only --- frontends/ast/simplify.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index fcadd329a..9688b77bc 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1874,10 +1874,16 @@ skip_dynamic_range_lvalue_expansion:; newNode = new AstNode(AST_NE, past, present); else if (str == "\\$rose") - newNode = new AstNode(AST_LOGIC_AND, new AstNode(AST_LOGIC_NOT, past), present); + newNode = new AstNode(AST_LOGIC_AND, + new AstNode(AST_LOGIC_NOT, + new AstNode(AST_BIT_AND, past, mkconst_int(1,false))), + new AstNode(AST_BIT_AND, present, mkconst_int(1,false))); else if (str == "\\$fell") - newNode = new AstNode(AST_LOGIC_AND, past, new AstNode(AST_LOGIC_NOT, present)); + newNode = new AstNode(AST_LOGIC_AND, + new AstNode(AST_BIT_AND, past, mkconst_int(1,false)), + new AstNode(AST_LOGIC_NOT, + new AstNode(AST_BIT_AND, present, mkconst_int(1,false)))); else log_abort(); -- cgit v1.2.3 From 64e0582c292ca1f3a64c01d9a1faa96ef2f74588 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 4 Nov 2018 10:19:32 +0100 Subject: Various indenting fixes in AST front-end (mostly space vs tab issues) Signed-off-by: Clifford Wolf --- frontends/ast/ast.cc | 9 ++--- frontends/ast/genrtlil.cc | 88 ++++++++++++++++++----------------------------- frontends/ast/simplify.cc | 71 ++++++++++++++++++-------------------- 3 files changed, 69 insertions(+), 99 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index cc275959a..2c1561552 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -172,8 +172,7 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id) AstNode *attr = attributes.at(id); if (attr->type != AST_CONSTANT) - log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n", - id.c_str()); + log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n", id.c_str()); return attr->integer != 0; } @@ -969,8 +968,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast for (auto &attr : ast->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); current_module->attributes[attr.first] = attr.second->asAttrConst(); } for (size_t i = 0; i < ast->children.size(); i++) { @@ -1061,8 +1059,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump if (design->has((*it)->str)) { RTLIL::Module *existing_mod = design->module((*it)->str); if (!nooverwrite && !overwrite && !existing_mod->get_bool_attribute("\\blackbox")) { - log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n", - (*it)->str.c_str()); + log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n", (*it)->str.c_str()); } else if (nooverwrite) { log("Ignoring re-definition of module `%s' at %s:%d.\n", (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum); diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 59c309665..9531dd356 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -55,8 +55,7 @@ static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_wi if (gen_attributes) for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -89,8 +88,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s if (that != NULL) for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -117,8 +115,7 @@ static RTLIL::SigSpec binop2rtlil(AstNode *that, std::string type, int result_wi for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -152,8 +149,7 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const for (auto &attr : that->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -480,8 +476,7 @@ struct AST_INTERNAL::ProcessGenerator for (auto &attr : ast->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); sw->attributes[attr.first] = attr.second->asAttrConst(); } @@ -648,8 +643,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) - log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); this_width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1; delete left_at_zero_ast; delete right_at_zero_ast; @@ -778,7 +772,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { } if (children[0]->type != AST_CONSTANT) log_file_error(filename, linenum, "System function %s called with non-const argument!\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); width_hint = max(width_hint, int(children[0]->asInt(true))); } break; @@ -799,8 +793,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun default: for (auto f : log_files) current_ast->dumpAst(f, "verilog-ast> "); - log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n", - type2str(type).c_str()); + log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n", type2str(type).c_str()); } if (*found_real) @@ -892,11 +885,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // create an RTLIL::Wire for an AST_WIRE node case AST_WIRE: { if (current_module->wires_.count(str) != 0) - log_file_error(filename, linenum, "Re-definition of signal `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Re-definition of signal `%s'!\n", str.c_str()); if (!range_valid) - log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n", - str.c_str()); + log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n", str.c_str()); log_assert(range_left >= range_right || (range_left == -1 && range_right == 0)); @@ -910,8 +901,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); wire->attributes[attr.first] = attr.second->asAttrConst(); } } @@ -920,16 +910,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // create an RTLIL::Memory for an AST_MEMORY node case AST_MEMORY: { if (current_module->memories.count(str) != 0) - log_file_error(filename, linenum, "Re-definition of memory `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Re-definition of memory `%s'!\n", str.c_str()); log_assert(children.size() >= 2); log_assert(children[0]->type == AST_RANGE); log_assert(children[1]->type == AST_RANGE); if (!children[0]->range_valid || !children[1]->range_valid) - log_file_error(filename, linenum, "Memory `%s' with non-constant width or size!\n", - str.c_str()); + log_file_error(filename, linenum, "Memory `%s' with non-constant width or size!\n", str.c_str()); RTLIL::Memory *memory = new RTLIL::Memory; memory->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); @@ -946,8 +934,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); memory->attributes[attr.first] = attr.second->asAttrConst(); } } @@ -966,8 +953,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_REALVALUE: { RTLIL::SigSpec sig = realAsConst(width_hint); - log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", - realvalue, log_signal(sig)); + log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", realvalue, log_signal(sig)); return sig; } @@ -994,8 +980,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM) { if (id2ast->children[0]->type != AST_CONSTANT) - log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n", - str.c_str()); + log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n", str.c_str()); chunk = RTLIL::Const(id2ast->children[0]->bits); goto use_const_chunk; } @@ -1010,13 +995,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) is_interface = true; } else { - log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n", - str.c_str()); + log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n", str.c_str()); } if (id2ast->type == AST_MEMORY) - log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n", - str.c_str()); + log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n", str.c_str()); // If identifier is an interface, create a RTLIL::SigSpec with a dummy wire with a attribute called 'is_interface' // This makes it possible for the hierarchy pass to see what are interface connections and then replace them @@ -1051,8 +1034,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) - log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1; AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ? children[0]->children[1]->clone() : children[0]->children[0]->clone()); @@ -1081,7 +1063,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (chunk.offset >= source_width || chunk.offset + chunk.width < 0) { if (chunk.width == 1) log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting result bit to undef.\n", - str.c_str()); + str.c_str()); else log_file_warning(filename, linenum, "Range select [%d:%d] out of bounds on signal `%s': Setting all %d result bits to undef.\n", children[0]->range_left, children[0]->range_right, str.c_str(), chunk.width); @@ -1098,10 +1080,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } if (add_undef_bits_lsb) log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d LSB bits to undef.\n", - children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_lsb); + children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_lsb); if (add_undef_bits_msb) log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d MSB bits to undef.\n", - children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_msb); + children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_msb); } } } @@ -1436,8 +1418,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } @@ -1459,9 +1440,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) new_right.append(right[i]); } log_file_warning(filename, linenum, "Ignoring assignment to constant bits:\n" - " old assignment: %s = %s\n new assignment: %s = %s.\n", - log_signal(left), log_signal(right), - log_signal(new_left), log_signal(new_right)); + " old assignment: %s = %s\n new assignment: %s = %s.\n", + log_signal(left), log_signal(right), + log_signal(new_left), log_signal(new_right)); left = new_left; right = new_right; } @@ -1494,14 +1475,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str; if (child->children[0]->type == AST_REALVALUE) { log_file_warning(filename, linenum, "Replacing floating point parameter %s.%s = %f with string.\n", - log_id(cell), log_id(paraname), child->children[0]->realvalue); + log_id(cell), log_id(paraname), child->children[0]->realvalue); auto strnode = AstNode::mkconst_str(stringf("%f", child->children[0]->realvalue)); strnode->cloneInto(child->children[0]); delete strnode; } if (child->children[0]->type != AST_CONSTANT) log_file_error(filename, linenum, "Parameter %s.%s with non-constant value!\n", - log_id(cell), log_id(paraname)); + log_id(cell), log_id(paraname)); cell->parameters[paraname] = child->children[0]->asParaConst(); continue; } @@ -1522,8 +1503,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", - attr.first.c_str()); + log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); cell->attributes[attr.first] = attr.second->asAttrConst(); } } @@ -1551,18 +1531,17 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (GetSize(children) > 1) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 0.\n", - RTLIL::unescape_id(str).c_str(), GetSize(children)); + RTLIL::unescape_id(str).c_str(), GetSize(children)); if (GetSize(children) == 1) { if (children[0]->type != AST_CONSTANT) log_file_error(filename, linenum, "System function %s called with non-const argument!\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); width = children[0]->asInt(true); } if (width <= 0) - log_file_error(filename, linenum, "Failed to detect width of %s!\n", - RTLIL::unescape_id(str).c_str()); + log_file_error(filename, linenum, "Failed to detect width of %s!\n", RTLIL::unescape_id(str).c_str()); Cell *cell = current_module->addCell(myid, str.substr(1)); cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); @@ -1589,8 +1568,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) for (auto f : log_files) current_ast->dumpAst(f, "verilog-ast> "); type_name = type2str(type); - log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n", - type_name.c_str()); + log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n", type_name.c_str()); } return RTLIL::SigSpec(); diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 9688b77bc..bb4c9735d 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -196,7 +196,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int nargs = GetSize(children); if (nargs < 1) log_file_error(filename, linenum, "System task `%s' got %d arguments, expected >= 1.\n", - str.c_str(), int(children.size())); + str.c_str(), int(children.size())); // First argument is the format string AstNode *node_string = children[0]; @@ -240,7 +240,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, case 'X': if (next_arg >= GetSize(children)) log_file_error(filename, linenum, "Missing argument for %%%c format specifier in system task `%s'.\n", - cformat, str.c_str()); + cformat, str.c_str()); node_arg = children[next_arg++]; while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } @@ -745,7 +745,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (current_scope.at(modname)->type != AST_CELL) log_file_error(filename, linenum, "Defparam argument `%s . %s` does not match a cell!\n", - RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str()); + RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str()); AstNode *paraset = new AstNode(AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : NULL); paraset->str = paramname; @@ -893,7 +893,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (children[0]->type == AST_REALVALUE) { RTLIL::Const constvalue = children[0]->realAsConst(width); log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", - children[0]->realvalue, log_signal(constvalue)); + children[0]->realvalue, log_signal(constvalue)); delete children[0]; children[0] = mkconst_bits(constvalue.bits, sign_hint); did_something = true; @@ -1312,8 +1312,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_PRIMITIVE) { if (children.size() < 2) - log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n", str.c_str()); std::vector children_list; for (auto child : children) { @@ -1328,8 +1327,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1") { if (children_list.size() != 3) - log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n", str.c_str()); std::vector z_const(1, RTLIL::State::Sz); @@ -1416,8 +1414,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, while (left_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { } while (right_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) - log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", - str.c_str()); + log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; } did_something = true; @@ -1788,11 +1785,11 @@ skip_dynamic_range_lvalue_expansion:; if (GetSize(children) != 1 && GetSize(children) != 2) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); if (!current_always_clocked) log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); if (GetSize(children) == 2) { @@ -1857,11 +1854,11 @@ skip_dynamic_range_lvalue_expansion:; { if (GetSize(children) != 1) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); if (!current_always_clocked) log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); AstNode *present = children.at(0)->clone(); AstNode *past = clone(); @@ -1875,15 +1872,13 @@ skip_dynamic_range_lvalue_expansion:; else if (str == "\\$rose") newNode = new AstNode(AST_LOGIC_AND, - new AstNode(AST_LOGIC_NOT, - new AstNode(AST_BIT_AND, past, mkconst_int(1,false))), + new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, past, mkconst_int(1,false))), new AstNode(AST_BIT_AND, present, mkconst_int(1,false))); else if (str == "\\$fell") newNode = new AstNode(AST_LOGIC_AND, - new AstNode(AST_BIT_AND, past, mkconst_int(1,false)), - new AstNode(AST_LOGIC_NOT, - new AstNode(AST_BIT_AND, present, mkconst_int(1,false)))); + new AstNode(AST_BIT_AND, past, mkconst_int(1,false)), + new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, present, mkconst_int(1,false)))); else log_abort(); @@ -1901,7 +1896,7 @@ skip_dynamic_range_lvalue_expansion:; { if (children.size() != 1) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); AstNode *buf = children[0]->clone(); while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } @@ -1926,11 +1921,11 @@ skip_dynamic_range_lvalue_expansion:; { if (str == "\\$bits" && children.size() != 1) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); if (str == "\\$size" && children.size() != 1 && children.size() != 2) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); int dim = 1; if (str == "\\$size" && children.size() == 2) { @@ -2004,18 +1999,18 @@ skip_dynamic_range_lvalue_expansion:; if (func_with_two_arguments) { if (children.size() != 2) log_file_error(filename, linenum, "System function %s got %d arguments, expected 2.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); } else { if (children.size() != 1) log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); } if (children.size() >= 1) { while (children[0]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (!children[0]->isConst()) log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); int child_width_hint = width_hint; bool child_sign_hint = sign_hint; children[0]->detectSignWidth(child_width_hint, child_sign_hint); @@ -2026,7 +2021,7 @@ skip_dynamic_range_lvalue_expansion:; while (children[1]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } if (!children[1]->isConst()) log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str).c_str()); int child_width_hint = width_hint; bool child_sign_hint = sign_hint; children[1]->detectSignWidth(child_width_hint, child_sign_hint); @@ -2114,7 +2109,7 @@ skip_dynamic_range_lvalue_expansion:; { if (GetSize(children) < 2 || GetSize(children) > 4) log_file_error(filename, linenum, "System function %s got %d arguments, expected 2-4.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str).c_str(), int(children.size())); AstNode *node_filename = children[0]->clone(); while (node_filename->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } @@ -3278,12 +3273,12 @@ void AstNode::replace_variables(std::map &varia if (!children.empty()) { if (children.size() != 1 || children.at(0)->type != AST_RANGE) log_file_error(filename, linenum, "Memory access in constant function is not supported\n%s:%d: ...called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); children.at(0)->replace_variables(variables, fcall); while (simplify(true, false, false, 1, -1, false, true)) { } if (!children.at(0)->range_valid) log_file_error(filename, linenum, "Non-constant range\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); offset = min(children.at(0)->range_left, children.at(0)->range_right); width = min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width); } @@ -3323,7 +3318,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) while (child->simplify(true, false, false, 1, -1, false, true)) { } if (!child->range_valid) log_file_error(child->filename, child->linenum, "Can't determine size of variable %s\n%s:%d: ... called from here.\n", - child->str.c_str(), fcall->filename.c_str(), fcall->linenum); + child->str.c_str(), fcall->filename.c_str(), fcall->linenum); variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1); variables[child->str].offset = min(child->range_left, child->range_right); variables[child->str].is_signed = child->is_signed; @@ -3367,15 +3362,15 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) if (stmt->children.at(1)->type != AST_CONSTANT) log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here. X\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); if (stmt->children.at(0)->type != AST_IDENTIFIER) log_file_error(stmt->filename, stmt->linenum, "Unsupported composite left hand side in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); if (!variables.count(stmt->children.at(0)->str)) log_file_error(stmt->filename, stmt->linenum, "Assignment to non-local variable in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); if (stmt->children.at(0)->children.empty()) { variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.bits.size()); @@ -3383,7 +3378,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) AstNode *range = stmt->children.at(0)->children.at(0); if (!range->range_valid) log_file_error(range->filename, range->linenum, "Non-constant range\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); int offset = min(range->range_left, range->range_right); int width = std::abs(range->range_left - range->range_right) + 1; varinfo_t &v = variables[stmt->children.at(0)->str]; @@ -3415,7 +3410,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) if (cond->type != AST_CONSTANT) log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); if (cond->asBool()) { block->children.insert(block->children.begin(), stmt->children.at(1)->clone()); @@ -3436,7 +3431,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) if (num->type != AST_CONSTANT) log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); block->children.erase(block->children.begin()); for (int i = 0; i < num->bitsAsConst().as_int(); i++) @@ -3474,7 +3469,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) if (cond->type != AST_CONSTANT) log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); found_match = cond->asBool(); delete cond; @@ -3504,7 +3499,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) } log_file_error(stmt->filename, stmt->linenum, "Unsupported language construct in constant function\n%s:%d: ... called from here.\n", - fcall->filename.c_str(), fcall->linenum); + fcall->filename.c_str(), fcall->linenum); log_abort(); } -- cgit v1.2.3 From 36ea98385f30107369479d2e682c544863c4f1af Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 4 Nov 2018 15:57:17 +0100 Subject: Add warning for SV "restrict" without "property" Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_parser.y | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 1fe08903c..5ab1b62df 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -125,7 +125,7 @@ static void free_attr(std::map *al) %type range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int %type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list %type opt_label tok_prim_wrapper hierarchical_id -%type opt_signed unique_case_attr +%type opt_signed opt_property unique_case_attr %type attr case_attr // operator precedence from low to high @@ -1320,7 +1320,12 @@ opt_label: }; opt_property: - TOK_PROPERTY | /* empty */; + TOK_PROPERTY { + $$ = true; + } | + /* empty */ { + $$ = false; + }; opt_stmt_label: TOK_ID ':' | /* empty */; @@ -1399,12 +1404,16 @@ assert: delete $5; else ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); + if (!$3) + log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); } | opt_stmt_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { if (norestrict_mode) delete $6; else ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); + if (!$3) + log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); }; assert_property: -- cgit v1.2.3 From 719e29404a74db8f994c9c3dc0d6b6e8d7f114a7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 5 Nov 2018 12:33:21 +0100 Subject: Allow square brackets in liberty identifiers Signed-off-by: Clifford Wolf --- frontends/liberty/liberty.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index 66db43baf..4acfbf1cb 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -36,7 +36,8 @@ static RTLIL::SigSpec parse_func_identifier(RTLIL::Module *module, const char *& int id_len = 0; while (('a' <= expr[id_len] && expr[id_len] <= 'z') || ('A' <= expr[id_len] && expr[id_len] <= 'Z') || - ('0' <= expr[id_len] && expr[id_len] <= '9') || expr[id_len] == '.' || expr[id_len] == '_') id_len++; + ('0' <= expr[id_len] && expr[id_len] <= '9') || expr[id_len] == '.' || + expr[id_len] == '_' || expr[id_len] == '[' || expr[id_len] == ']') id_len++; if (id_len == 0) log_error("Expected identifier at `%s'.\n", expr); -- cgit v1.2.3 From 5387ccb041f4acafc96c7b3fcf8db04dddfb8ab5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 9 Nov 2018 21:03:13 +0100 Subject: Set Verific flag vhdl_support_variable_slice=1 Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index dba3b0f0c..971f0b24a 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1835,6 +1835,7 @@ struct VerificPass : public Pass { Message::RegisterCallBackMsg(msg_func); RuntimeFlags::SetVar("db_preserve_user_nets", 1); RuntimeFlags::SetVar("db_allow_external_nets", 1); + RuntimeFlags::SetVar("vhdl_support_variable_slice", 1); RuntimeFlags::SetVar("vhdl_ignore_assertion_statements", 0); RuntimeFlags::SetVar("veri_extract_dualport_rams", 0); RuntimeFlags::SetVar("veri_extract_multiport_rams", 1); -- cgit v1.2.3 From 86ce43999eaed10c3b9d141bb2f66bf98ad45eb6 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Sat, 24 Nov 2018 18:49:23 +0100 Subject: Make return value of $clog2 signed As per Verilog 2005 - 17.11.1. Fixes #708 Signed-off-by: Sylvain Munaut --- frontends/ast/simplify.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index bb4c9735d..55abe165f 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1913,7 +1913,7 @@ skip_dynamic_range_lvalue_expansion:; if (arg_value.bits.at(i) == RTLIL::State::S1) result = i + 1; - newNode = mkconst_int(result, false); + newNode = mkconst_int(result, true); goto apply_newNode; } -- cgit v1.2.3 From 910d94b21214b78d841cfb32a724c4f0ea8b365d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 6 Dec 2018 07:21:50 +0100 Subject: Verific updates Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 53 -------------------------------------------- 1 file changed, 53 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 971f0b24a..bc035c31a 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -2094,42 +2094,6 @@ struct VerificPass : public Pass { if (mode_all) { -#if 0 - log("Running veri_file::ElaborateAll().\n"); - if (!veri_file::ElaborateAll()) - log_cmd_error("Elaboration of Verilog modules failed.\n"); - - log("Running vhdl_file::ElaborateAll().\n"); - if (!vhdl_file::ElaborateAll()) - log_cmd_error("Elaboration of VHDL modules failed.\n"); - - Library *lib = Netlist::PresentDesign()->Owner()->Owner(); - - if (argidx == GetSize(args)) - { - MapIter iter; - char *iter_name; - Verific::Cell *iter_cell; - - FOREACH_MAP_ITEM(lib->GetCells(), iter, &iter_name, &iter_cell) { - if (*iter_name != '$') - nl_todo.insert(iter_cell->GetFirstNetlist()); - } - } - else - { - for (; argidx < GetSize(args); argidx++) - { - Verific::Cell *cell = lib->GetCell(args[argidx].c_str()); - - if (cell == nullptr) - log_cmd_error("Module not found: %s\n", args[argidx].c_str()); - - nl_todo.insert(cell->GetFirstNetlist()); - cell->GetFirstNetlist()->SetPresentDesign(); - } - } -#else log("Running hier_tree::ElaborateAll().\n"); VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary(work.c_str(), 1); @@ -2146,28 +2110,12 @@ struct VerificPass : public Pass { FOREACH_ARRAY_ITEM(netlists, i, nl) nl_todo.insert(nl); delete netlists; -#endif } else { if (argidx == GetSize(args)) log_cmd_error("No top module specified.\n"); -#if 0 - for (; argidx < GetSize(args); argidx++) { - if (veri_file::GetModule(args[argidx].c_str())) { - log("Running veri_file::Elaborate(\"%s\").\n", args[argidx].c_str()); - if (!veri_file::Elaborate(args[argidx].c_str())) - log_cmd_error("Elaboration of top module `%s' failed.\n", args[argidx].c_str()); - nl_todo.insert(Netlist::PresentDesign()); - } else { - log("Running vhdl_file::Elaborate(\"%s\").\n", args[argidx].c_str()); - if (!vhdl_file::Elaborate(args[argidx].c_str())) - log_cmd_error("Elaboration of top module `%s' failed.\n", args[argidx].c_str()); - nl_todo.insert(Netlist::PresentDesign()); - } - } -#else Array veri_modules, vhdl_units; for (; argidx < GetSize(args); argidx++) { @@ -2199,7 +2147,6 @@ struct VerificPass : public Pass { FOREACH_ARRAY_ITEM(netlists, i, nl) nl_todo.insert(nl); delete netlists; -#endif } if (!verific_error_msg.empty()) -- cgit v1.2.3 From 58fb2ac818d07021b6929cb9ff14e13e993a231f Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Thu, 13 Dec 2018 18:47:05 +0100 Subject: verilog_parser: Properly handle recursion when processing attributes Fixes #737 Signed-off-by: Sylvain Munaut --- frontends/verilog/verilog_parser.y | 48 +++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 19 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 5ab1b62df..51e112ed3 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -35,6 +35,7 @@ %{ #include +#include #include #include "frontends/verilog/verilog_frontend.h" #include "kernel/log.h" @@ -47,7 +48,8 @@ YOSYS_NAMESPACE_BEGIN namespace VERILOG_FRONTEND { int port_counter; std::map port_stubs; - std::map attr_list, default_attr_list; + std::map *attr_list, default_attr_list; + std::stack *> attr_list_stack; std::map *albuf; std::vector ast_stack; struct AstNode *astbuf1, *astbuf2, *astbuf3; @@ -175,15 +177,18 @@ design: attr: { - for (auto &it : attr_list) - delete it.second; - attr_list.clear(); + if (attr_list != nullptr) + attr_list_stack.push(attr_list); + attr_list = new std::map; for (auto &it : default_attr_list) - attr_list[it.first] = it.second->clone(); + (*attr_list)[it.first] = it.second->clone(); } attr_opt { - std::map *al = new std::map; - al->swap(attr_list); - $$ = al; + $$ = attr_list; + if (!attr_list_stack.empty()) { + attr_list = attr_list_stack.top(); + attr_list_stack.pop(); + } else + attr_list = nullptr; }; attr_opt: @@ -192,15 +197,20 @@ attr_opt: defattr: DEFATTR_BEGIN { + if (attr_list != nullptr) + attr_list_stack.push(attr_list); + attr_list = new std::map; for (auto &it : default_attr_list) delete it.second; default_attr_list.clear(); - for (auto &it : attr_list) - delete it.second; - attr_list.clear(); } opt_attr_list { - default_attr_list = attr_list; - attr_list.clear(); + attr_list->swap(default_attr_list); + delete attr_list; + if (!attr_list_stack.empty()) { + attr_list = attr_list_stack.top(); + attr_list_stack.pop(); + } else + attr_list = nullptr; } DEFATTR_END; opt_attr_list: @@ -212,15 +222,15 @@ attr_list: attr_assign: hierarchical_id { - if (attr_list.count(*$1) != 0) - delete attr_list[*$1]; - attr_list[*$1] = AstNode::mkconst_int(1, false); + if (attr_list->count(*$1) != 0) + delete (*attr_list)[*$1]; + (*attr_list)[*$1] = AstNode::mkconst_int(1, false); delete $1; } | hierarchical_id '=' expr { - if (attr_list.count(*$1) != 0) - delete attr_list[*$1]; - attr_list[*$1] = $3; + if (attr_list->count(*$1) != 0) + delete (*attr_list)[*$1]; + (*attr_list)[*$1] = $3; delete $1; }; -- cgit v1.2.3 From 4effb38e6d318e2e233bdfa9f2e0bb67e4998bf0 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sun, 16 Dec 2018 17:50:36 +0000 Subject: read_ilang: allow slicing sigspecs. --- frontends/ilang/ilang_parser.y | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'frontends') diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y index bfc062fec..b957ecd96 100644 --- a/frontends/ilang/ilang_parser.y +++ b/frontends/ilang/ilang_parser.y @@ -387,17 +387,13 @@ sigspec: $$ = new RTLIL::SigSpec(current_module->wires_[$1]); free($1); } | - TOK_ID '[' TOK_INT ']' { - if (current_module->wires_.count($1) == 0) - rtlil_frontend_ilang_yyerror(stringf("ilang error: wire %s not found", $1).c_str()); - $$ = new RTLIL::SigSpec(current_module->wires_[$1], $3); - free($1); + sigspec '[' TOK_INT ']' { + $$ = new RTLIL::SigSpec($1->extract($3)); + delete $1; } | - TOK_ID '[' TOK_INT ':' TOK_INT ']' { - if (current_module->wires_.count($1) == 0) - rtlil_frontend_ilang_yyerror(stringf("ilang error: wire %s not found", $1).c_str()); - $$ = new RTLIL::SigSpec(current_module->wires_[$1], $5, $3 - $5 + 1); - free($1); + sigspec '[' TOK_INT ':' TOK_INT ']' { + $$ = new RTLIL::SigSpec($1->extract($5, $3 - $5 + 1)); + delete $1; } | '{' sigspec_list '}' { $$ = $2; -- cgit v1.2.3 From 3d671630e2bf78cd53ef1b678a1bbb63338cbcd2 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 18 Dec 2018 16:01:22 +0100 Subject: Improve src tagging (using names and attrs) of cells and wires in verific front-end Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 258 ++++++++++++++++++++++++++----------------- frontends/verific/verific.h | 1 + 2 files changed, 160 insertions(+), 99 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index bc035c31a..61d9d593c 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -130,6 +130,15 @@ bool is_blackbox(Netlist *nl) return false; } +RTLIL::IdString VerificImporter::new_verific_id(Verific::DesignObj *obj) +{ + std::string s = stringf("$verific$%s", obj->Name()); + if (obj->Linefile()) + s += stringf("$%s:%d", Verific::LineFile::GetFileName(obj->Linefile()), Verific::LineFile::GetLineNo(obj->Linefile())); + s += stringf("$%d", autoidx++); + return s; +} + void VerificImporter::import_attributes(dict &attributes, DesignObj *obj) { MapIter mi; @@ -215,7 +224,7 @@ RTLIL::SigSpec VerificImporter::operatorOutput(Instance *inst, const pooladdWire(NEW_ID); + dummy_wire = module->addWire(new_verific_id(inst)); else dummy_wire->width++; sig.append(RTLIL::SigSpec(dummy_wire, dummy_wire->width - 1)); @@ -231,8 +240,8 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr } if (inst->Type() == PRIM_NAND) { - RTLIL::SigSpec tmp = module->addWire(NEW_ID); - module->addAndGate(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); + RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst)); + module->addAndGate(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); module->addNotGate(inst_name, tmp, net_map_at(inst->GetOutput())); return true; } @@ -243,8 +252,8 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr } if (inst->Type() == PRIM_NOR) { - RTLIL::SigSpec tmp = module->addWire(NEW_ID); - module->addOrGate(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); + RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst)); + module->addOrGate(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); module->addNotGate(inst_name, tmp, net_map_at(inst->GetOutput())); return true; } @@ -284,16 +293,16 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr if (inst->Type() == PRIM_FADD) { RTLIL::SigSpec a = net_map_at(inst->GetInput1()), b = net_map_at(inst->GetInput2()), c = net_map_at(inst->GetCin()); - RTLIL::SigSpec x = inst->GetCout() ? net_map_at(inst->GetCout()) : module->addWire(NEW_ID); - RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(NEW_ID); - RTLIL::SigSpec tmp1 = module->addWire(NEW_ID); - RTLIL::SigSpec tmp2 = module->addWire(NEW_ID); - RTLIL::SigSpec tmp3 = module->addWire(NEW_ID); - module->addXorGate(NEW_ID, a, b, tmp1); + RTLIL::SigSpec x = inst->GetCout() ? net_map_at(inst->GetCout()) : module->addWire(new_verific_id(inst)); + RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(new_verific_id(inst)); + RTLIL::SigSpec tmp1 = module->addWire(new_verific_id(inst)); + RTLIL::SigSpec tmp2 = module->addWire(new_verific_id(inst)); + RTLIL::SigSpec tmp3 = module->addWire(new_verific_id(inst)); + module->addXorGate(new_verific_id(inst), a, b, tmp1); module->addXorGate(inst_name, tmp1, c, y); - module->addAndGate(NEW_ID, tmp1, c, tmp2); - module->addAndGate(NEW_ID, a, b, tmp3); - module->addOrGate(NEW_ID, tmp2, tmp3, x); + module->addAndGate(new_verific_id(inst), tmp1, c, tmp2); + module->addAndGate(new_verific_id(inst), a, b, tmp3); + module->addOrGate(new_verific_id(inst), tmp2, tmp3, x); return true; } @@ -320,63 +329,78 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdString inst_name) { + RTLIL::Cell *cell = nullptr; + if (inst->Type() == PRIM_AND) { - module->addAnd(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); + cell = module->addAnd(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_NAND) { - RTLIL::SigSpec tmp = module->addWire(NEW_ID); - module->addAnd(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); - module->addNot(inst_name, tmp, net_map_at(inst->GetOutput())); + RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst)); + cell = module->addAnd(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); + import_attributes(cell->attributes, inst); + cell = module->addNot(inst_name, tmp, net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_OR) { - module->addOr(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); + cell = module->addOr(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_NOR) { - RTLIL::SigSpec tmp = module->addWire(NEW_ID); - module->addOr(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); - module->addNot(inst_name, tmp, net_map_at(inst->GetOutput())); + RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst)); + cell = module->addOr(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); + import_attributes(cell->attributes, inst); + cell = module->addNot(inst_name, tmp, net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_XOR) { - module->addXor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); + cell = module->addXor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_XNOR) { - module->addXnor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); + cell = module->addXnor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_INV) { - module->addNot(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); + cell = module->addNot(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_MUX) { - module->addMux(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput())); + cell = module->addMux(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_TRI) { - module->addMux(inst_name, RTLIL::State::Sz, net_map_at(inst->GetInput()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput())); + cell = module->addMux(inst_name, RTLIL::State::Sz, net_map_at(inst->GetInput()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_FADD) { - RTLIL::SigSpec a_plus_b = module->addWire(NEW_ID, 2); - RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(NEW_ID); + RTLIL::SigSpec a_plus_b = module->addWire(new_verific_id(inst), 2); + RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(new_verific_id(inst)); if (inst->GetCout()) y.append(net_map_at(inst->GetCout())); - module->addAdd(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), a_plus_b); - module->addAdd(inst_name, a_plus_b, net_map_at(inst->GetCin()), y); + cell = module->addAdd(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), a_plus_b); + import_attributes(cell->attributes, inst); + cell = module->addAdd(inst_name, a_plus_b, net_map_at(inst->GetCin()), y); + import_attributes(cell->attributes, inst); return true; } @@ -387,24 +411,26 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr log_assert(clocking.body_net == nullptr); if (inst->GetSet()->IsGnd() && inst->GetReset()->IsGnd()) - clocking.addDff(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); + cell = clocking.addDff(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); else if (inst->GetSet()->IsGnd()) - clocking.addAdff(inst_name, net_map_at(inst->GetReset()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S0); + cell = clocking.addAdff(inst_name, net_map_at(inst->GetReset()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S0); else if (inst->GetReset()->IsGnd()) - clocking.addAdff(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S1); + cell = clocking.addAdff(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S1); else - clocking.addDffsr(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetReset()), + cell = clocking.addDffsr(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetReset()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == PRIM_DLATCHRS) { if (inst->GetSet()->IsGnd() && inst->GetReset()->IsGnd()) - module->addDlatch(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); + cell = module->addDlatch(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); else - module->addDlatchsr(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetSet()), net_map_at(inst->GetReset()), + cell = module->addDlatchsr(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetSet()), net_map_at(inst->GetReset()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } @@ -420,37 +446,45 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr if (inst->GetCout() != NULL) out.append(net_map_at(inst->GetCout())); if (inst->GetCin()->IsGnd()) { - module->addAdd(inst_name, IN1, IN2, out, SIGNED); + cell = module->addAdd(inst_name, IN1, IN2, out, SIGNED); + import_attributes(cell->attributes, inst); } else { - RTLIL::SigSpec tmp = module->addWire(NEW_ID, GetSize(out)); - module->addAdd(NEW_ID, IN1, IN2, tmp, SIGNED); - module->addAdd(inst_name, tmp, net_map_at(inst->GetCin()), out, false); + RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst), GetSize(out)); + cell = module->addAdd(new_verific_id(inst), IN1, IN2, tmp, SIGNED); + import_attributes(cell->attributes, inst); + cell = module->addAdd(inst_name, tmp, net_map_at(inst->GetCin()), out, false); + import_attributes(cell->attributes, inst); } return true; } if (inst->Type() == OPER_MULTIPLIER) { - module->addMul(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addMul(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_DIVIDER) { - module->addDiv(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addDiv(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_MODULO) { - module->addMod(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addMod(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_REMAINDER) { - module->addMod(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addMod(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_SHIFT_LEFT) { - module->addShl(inst_name, IN1, IN2, OUT, false); + cell = module->addShl(inst_name, IN1, IN2, OUT, false); + import_attributes(cell->attributes, inst); return true; } @@ -460,7 +494,8 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr for (unsigned i = 1; i < inst->OutputSize(); i++) { vec.append(RTLIL::State::S0); } - module->addShl(inst_name, vec, IN, OUT, false); + cell = module->addShl(inst_name, vec, IN, OUT, false); + import_attributes(cell->attributes, inst); return true; } @@ -470,7 +505,8 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr for (unsigned i = 1; i < inst->OutputSize(); i++) { vec.append(RTLIL::State::S0); } - module->addShl(inst_name, vec, IN, OUT, false); + cell = module->addShl(inst_name, vec, IN, OUT, false); + import_attributes(cell->attributes, inst); return true; } @@ -478,108 +514,127 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr Net *net_cin = inst->GetCin(); Net *net_a_msb = inst->GetInput1Bit(0); if (net_cin->IsGnd()) - module->addShr(inst_name, IN1, IN2, OUT, false); + cell = module->addShr(inst_name, IN1, IN2, OUT, false); else if (net_cin == net_a_msb) - module->addSshr(inst_name, IN1, IN2, OUT, true); + cell = module->addSshr(inst_name, IN1, IN2, OUT, true); else log_error("Can't import Verific OPER_SHIFT_RIGHT instance %s: carry_in is neither 0 nor msb of left input\n", inst->Name()); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_REDUCE_AND) { - module->addReduceAnd(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); + cell = module->addReduceAnd(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_REDUCE_OR) { - module->addReduceOr(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); + cell = module->addReduceOr(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_REDUCE_XOR) { - module->addReduceXor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); + cell = module->addReduceXor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_REDUCE_XNOR) { - module->addReduceXnor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); + cell = module->addReduceXnor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_REDUCE_NOR) { - SigSpec t = module->ReduceOr(NEW_ID, IN, SIGNED); - module->addNot(inst_name, t, net_map_at(inst->GetOutput())); + SigSpec t = module->ReduceOr(new_verific_id(inst), IN, SIGNED); + cell = module->addNot(inst_name, t, net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_LESSTHAN) { Net *net_cin = inst->GetCin(); if (net_cin->IsGnd()) - module->addLt(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); + cell = module->addLt(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); else if (net_cin->IsPwr()) - module->addLe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); + cell = module->addLe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); else log_error("Can't import Verific OPER_LESSTHAN instance %s: carry_in is neither 0 nor 1\n", inst->Name()); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_AND) { - module->addAnd(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addAnd(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_OR) { - module->addOr(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addOr(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_XOR) { - module->addXor(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addXor(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_XNOR) { - module->addXnor(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addXnor(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_BUF) { - module->addPos(inst_name, IN, FILTERED_OUT, SIGNED); + cell = module->addPos(inst_name, IN, FILTERED_OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_INV) { - module->addNot(inst_name, IN, OUT, SIGNED); + cell = module->addNot(inst_name, IN, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_MINUS) { - module->addSub(inst_name, IN1, IN2, OUT, SIGNED); + cell = module->addSub(inst_name, IN1, IN2, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_UMINUS) { - module->addNeg(inst_name, IN, OUT, SIGNED); + cell = module->addNeg(inst_name, IN, OUT, SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_EQUAL) { - module->addEq(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); + cell = module->addEq(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_NEQUAL) { - module->addNe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); + cell = module->addNe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_MUX) { - module->addMux(inst_name, IN1, IN2, net_map_at(inst->GetControl()), OUT); + cell = module->addMux(inst_name, IN1, IN2, net_map_at(inst->GetControl()), OUT); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_NTO1MUX) { - module->addShr(inst_name, IN2, IN1, net_map_at(inst->GetOutput())); + cell = module->addShr(inst_name, IN2, IN1, net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } @@ -599,25 +654,29 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr padded_data.append(d); } - module->addShr(inst_name, padded_data, sel, out); + cell = module->addShr(inst_name, padded_data, sel, out); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_SELECTOR) { - module->addPmux(inst_name, State::S0, IN2, IN1, net_map_at(inst->GetOutput())); + cell = module->addPmux(inst_name, State::S0, IN2, IN1, net_map_at(inst->GetOutput())); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_SELECTOR) { SigSpec out = OUT; - module->addPmux(inst_name, SigSpec(State::S0, GetSize(out)), IN2, IN1, out); + cell = module->addPmux(inst_name, SigSpec(State::S0, GetSize(out)), IN2, IN1, out); + import_attributes(cell->attributes, inst); return true; } if (inst->Type() == OPER_WIDE_TRI) { - module->addMux(inst_name, RTLIL::SigSpec(RTLIL::State::Sz, inst->OutputSize()), IN, net_map_at(inst->GetControl()), OUT); + cell = module->addMux(inst_name, RTLIL::SigSpec(RTLIL::State::Sz, inst->OutputSize()), IN, net_map_at(inst->GetControl()), OUT); + import_attributes(cell->attributes, inst); return true; } @@ -631,9 +690,10 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr RTLIL::SigSpec sig_reset = operatorInport(inst, "reset"); if (sig_set.is_fully_const() && !sig_set.as_bool() && sig_reset.is_fully_const() && !sig_reset.as_bool()) - clocking.addDff(inst_name, IN, OUT); + cell = clocking.addDff(inst_name, IN, OUT); else - clocking.addDffsr(inst_name, sig_set, sig_reset, IN, OUT); + cell = clocking.addDffsr(inst_name, sig_set, sig_reset, IN, OUT); + import_attributes(cell->attributes, inst); return true; } @@ -862,7 +922,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se ascii_initdata++; } if (initval_valid) { - RTLIL::Cell *cell = module->addCell(NEW_ID, "$meminit"); + RTLIL::Cell *cell = module->addCell(new_verific_id(net), "$meminit"); cell->parameters["\\WORDS"] = 1; if (net->GetOrigTypeRange()->LeftRangeBound() < net->GetOrigTypeRange()->RightRangeBound()) cell->setPort("\\ADDR", word_idx); @@ -925,7 +985,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se if (net->Bus()) continue; - RTLIL::IdString wire_name = module->uniquify(mode_names || net->IsUserDeclared() ? RTLIL::escape_id(net->Name()) : NEW_ID); + RTLIL::IdString wire_name = module->uniquify(mode_names || net->IsUserDeclared() ? RTLIL::escape_id(net->Name()) : new_verific_id(net)); if (verific_verbose) log(" importing net %s as %s.\n", net->Name(), log_id(wire_name)); @@ -949,7 +1009,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se if (found_new_net) { - RTLIL::IdString wire_name = module->uniquify(mode_names || netbus->IsUserDeclared() ? RTLIL::escape_id(netbus->Name()) : NEW_ID); + RTLIL::IdString wire_name = module->uniquify(mode_names || netbus->IsUserDeclared() ? RTLIL::escape_id(netbus->Name()) : new_verific_id(netbus)); if (verific_verbose) log(" importing netbus %s as %s.\n", netbus->Name(), log_id(wire_name)); @@ -1025,16 +1085,16 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se } if (GetSize(anyconst_sig)) - module->connect(anyconst_sig, module->Anyconst(NEW_ID, GetSize(anyconst_sig))); + module->connect(anyconst_sig, module->Anyconst(new_verific_id(netbus), GetSize(anyconst_sig))); if (GetSize(anyseq_sig)) - module->connect(anyseq_sig, module->Anyseq(NEW_ID, GetSize(anyseq_sig))); + module->connect(anyseq_sig, module->Anyseq(new_verific_id(netbus), GetSize(anyseq_sig))); if (GetSize(allconst_sig)) - module->connect(allconst_sig, module->Allconst(NEW_ID, GetSize(allconst_sig))); + module->connect(allconst_sig, module->Allconst(new_verific_id(netbus), GetSize(allconst_sig))); if (GetSize(allseq_sig)) - module->connect(allseq_sig, module->Allseq(NEW_ID, GetSize(allseq_sig))); + module->connect(allseq_sig, module->Allseq(new_verific_id(netbus), GetSize(allseq_sig))); } for (auto it : init_nets) @@ -1058,10 +1118,10 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se } for (auto net : anyconst_nets) - module->connect(net_map_at(net), module->Anyconst(NEW_ID)); + module->connect(net_map_at(net), module->Anyconst(new_verific_id(net))); for (auto net : anyseq_nets) - module->connect(net_map_at(net), module->Anyseq(NEW_ID)); + module->connect(net_map_at(net), module->Anyseq(new_verific_id(net))); pool sva_asserts; pool sva_assumes; @@ -1072,7 +1132,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se FOREACH_INSTANCE_OF_NETLIST(nl, mi, inst) { - RTLIL::IdString inst_name = module->uniquify(mode_names || inst->IsUserDeclared() ? RTLIL::escape_id(inst->Name()) : NEW_ID); + RTLIL::IdString inst_name = module->uniquify(mode_names || inst->IsUserDeclared() ? RTLIL::escape_id(inst->Name()) : new_verific_id(inst)); if (verific_verbose) log(" importing cell %s (%s) as %s.\n", inst->Name(), inst->View()->Owner()->Name(), log_id(inst_name)); @@ -1196,7 +1256,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se log_assert(inst->Input1Size() == inst->OutputSize()); SigSpec sig_d, sig_q, sig_o; - sig_q = module->addWire(NEW_ID, inst->Input1Size()); + sig_q = module->addWire(new_verific_id(inst), inst->Input1Size()); for (int i = int(inst->Input1Size())-1; i >= 0; i--){ sig_d.append(net_map_at(inst->GetInput1Bit(i))); @@ -1210,8 +1270,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se log_signal(sig_d), log_signal(sig_q), log_signal(sig_o)); } - clocking.addDff(NEW_ID, sig_d, sig_q); - module->addXnor(NEW_ID, sig_d, sig_q, sig_o); + clocking.addDff(new_verific_id(inst), sig_d, sig_q); + module->addXnor(new_verific_id(inst), sig_d, sig_q, sig_o); if (!mode_keep) continue; @@ -1225,7 +1285,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se SigSpec sig_d = net_map_at(inst->GetInput1()); SigSpec sig_o = net_map_at(inst->GetOutput()); - SigSpec sig_q = module->addWire(NEW_ID); + SigSpec sig_q = module->addWire(new_verific_id(inst)); if (verific_verbose) { log(" %sedge FF with D=%s, Q=%s, C=%s.\n", clocking.posedge ? "pos" : "neg", @@ -1234,8 +1294,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se log_signal(sig_d), log_signal(sig_q), log_signal(sig_o)); } - clocking.addDff(NEW_ID, sig_d, sig_q); - module->addXnor(NEW_ID, sig_d, sig_q, sig_o); + clocking.addDff(new_verific_id(inst), sig_d, sig_q); + module->addXnor(new_verific_id(inst), sig_d, sig_q, sig_o); if (!mode_keep) continue; @@ -1254,7 +1314,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se log(" %sedge FF with D=%s, Q=%s, C=%s.\n", clocking.posedge ? "pos" : "neg", log_signal(sig_d), log_signal(sig_q), log_signal(clocking.clock_sig)); - past_ffs.insert(clocking.addDff(NEW_ID, sig_d, sig_q)); + past_ffs.insert(clocking.addDff(new_verific_id(inst), sig_d, sig_q)); if (!mode_keep) continue; @@ -1268,14 +1328,14 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se SigBit sig_d = net_map_at(inst->GetInput1()); SigBit sig_o = net_map_at(inst->GetOutput()); - SigBit sig_q = module->addWire(NEW_ID); + SigBit sig_q = module->addWire(new_verific_id(inst)); if (verific_verbose) log(" %sedge FF with D=%s, Q=%s, C=%s.\n", clocking.posedge ? "pos" : "neg", log_signal(sig_d), log_signal(sig_q), log_signal(clocking.clock_sig)); - clocking.addDff(NEW_ID, sig_d, sig_q); - module->addEq(NEW_ID, {sig_q, sig_d}, Const(inst->Type() == PRIM_SVA_ROSE ? 1 : 2, 2), sig_o); + clocking.addDff(new_verific_id(inst), sig_d, sig_q); + module->addEq(new_verific_id(inst), {sig_q, sig_d}, Const(inst->Type() == PRIM_SVA_ROSE ? 1 : 2, 2), sig_o); if (!mode_keep) continue; @@ -1298,9 +1358,9 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se Cell *cell = nullptr; if (assume_attr != nullptr && !strcmp(assume_attr, "1")) - cell = module->addAssume(NEW_ID, cond, State::S1); + cell = module->addAssume(new_verific_id(inst), cond, State::S1); else - cell = module->addAssert(NEW_ID, cond, State::S1); + cell = module->addAssert(new_verific_id(inst), cond, State::S1); import_attributes(cell->attributes, inst); continue; @@ -1342,7 +1402,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se IdString port_name_id = RTLIL::escape_id(port_name); auto &sigvec = cell_port_conns[port_name_id]; if (GetSize(sigvec) <= port_offset) { - SigSpec zwires = module->addWire(NEW_ID, port_offset+1-GetSize(sigvec)); + SigSpec zwires = module->addWire(new_verific_id(inst), port_offset+1-GetSize(sigvec)); for (auto bit : zwires) sigvec.push_back(bit); } diff --git a/frontends/verific/verific.h b/frontends/verific/verific.h index 334a436af..b331dd4b9 100644 --- a/frontends/verific/verific.h +++ b/frontends/verific/verific.h @@ -78,6 +78,7 @@ struct VerificImporter RTLIL::SigBit net_map_at(Verific::Net *net); + RTLIL::IdString new_verific_id(Verific::DesignObj *obj); void import_attributes(dict &attributes, Verific::DesignObj *obj); RTLIL::SigSpec operatorInput(Verific::Instance *inst); -- cgit v1.2.3 From fdf7c421810e8718f7ee312ddd3cfdbfb65aa2ce Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 18 Dec 2018 17:49:38 +0100 Subject: Fix segfault in AST simplify (as proposed by Dan Gisselquist) Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 55abe165f..83714f897 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1810,6 +1810,11 @@ skip_dynamic_range_lvalue_expansion:; log_assert(block != nullptr); + if (num_steps == 0) { + newNode = children[0]->clone(); + goto apply_newNode; + } + int myidx = autoidx++; AstNode *outreg = nullptr; -- cgit v1.2.3 From 6dad1913779f729222f65e1098a4facb36c5837a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 23 Dec 2018 15:45:09 +0100 Subject: Add "read_ilang -[no]overwrite" Signed-off-by: Clifford Wolf --- frontends/ilang/ilang_frontend.cc | 30 +++++++++++++++++++++++++++++- frontends/ilang/ilang_frontend.h | 2 ++ frontends/ilang/ilang_parser.y | 26 +++++++++++++++++++++++--- 3 files changed, 54 insertions(+), 4 deletions(-) (limited to 'frontends') diff --git a/frontends/ilang/ilang_frontend.cc b/frontends/ilang/ilang_frontend.cc index d8783ac1d..6b302a796 100644 --- a/frontends/ilang/ilang_frontend.cc +++ b/frontends/ilang/ilang_frontend.cc @@ -44,11 +44,39 @@ struct IlangFrontend : public Frontend { log("Load modules from an ilang file to the current design. (ilang is a text\n"); log("representation of a design in yosys's internal format.)\n"); log("\n"); + log(" -nooverwrite\n"); + log(" ignore re-definitions of modules. (the default behavior is to\n"); + log(" create an error message if the existing module is not a blackbox\n"); + log(" module, and overwrite the existing module if it is a blackbox module.)\n"); + log("\n"); + log(" -overwrite\n"); + log(" overwrite existing modules with the same name\n"); + log("\n"); } void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { + ILANG_FRONTEND::flag_nooverwrite = false; + ILANG_FRONTEND::flag_overwrite = false; + log_header(design, "Executing ILANG frontend.\n"); - extra_args(f, filename, args, 1); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + std::string arg = args[argidx]; + if (arg == "-nooverwrite") { + ILANG_FRONTEND::flag_nooverwrite = true; + ILANG_FRONTEND::flag_overwrite = false; + continue; + } + if (arg == "-overwrite") { + ILANG_FRONTEND::flag_nooverwrite = false; + ILANG_FRONTEND::flag_overwrite = true; + continue; + } + break; + } + extra_args(f, filename, args, argidx); + log("Input filename: %s\n", filename.c_str()); ILANG_FRONTEND::lexin = f; diff --git a/frontends/ilang/ilang_frontend.h b/frontends/ilang/ilang_frontend.h index ad3ffec90..052dd4cb2 100644 --- a/frontends/ilang/ilang_frontend.h +++ b/frontends/ilang/ilang_frontend.h @@ -32,6 +32,8 @@ YOSYS_NAMESPACE_BEGIN namespace ILANG_FRONTEND { extern std::istream *lexin; extern RTLIL::Design *current_design; + extern bool flag_nooverwrite; + extern bool flag_overwrite; } YOSYS_NAMESPACE_END diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y index b957ecd96..5bcc01f42 100644 --- a/frontends/ilang/ilang_parser.y +++ b/frontends/ilang/ilang_parser.y @@ -37,6 +37,8 @@ namespace ILANG_FRONTEND { std::vector*> switch_stack; std::vector case_stack; dict attrbuf; + bool flag_nooverwrite, flag_overwrite; + bool delete_current_module; } using namespace ILANG_FRONTEND; YOSYS_NAMESPACE_END @@ -93,18 +95,36 @@ design: module: TOK_MODULE TOK_ID EOL { - if (current_design->has($2)) - rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of module %s.", $2).c_str()); + delete_current_module = false; + if (current_design->has($2)) { + RTLIL::Module *existing_mod = current_design->module($2); + if (!flag_overwrite && attrbuf.count("\\blackbox") && attrbuf.at("\\blackbox").as_bool()) { + log("Ignoring blackbox re-definition of module %s.\n", $2); + delete_current_module = true; + } else if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute("\\blackbox")) { + rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of module %s.", $2).c_str()); + } else if (flag_nooverwrite) { + log("Ignoring re-definition of module %s.\n", $2); + delete_current_module = true; + } else { + log("Replacing existing%s module %s.\n", existing_mod->get_bool_attribute("\\blackbox") ? " blackbox" : "", $2); + current_design->remove(existing_mod); + } + } current_module = new RTLIL::Module; current_module->name = $2; current_module->attributes = attrbuf; - current_design->add(current_module); + if (!delete_current_module) + current_design->add(current_module); attrbuf.clear(); free($2); } module_body TOK_END { if (attrbuf.size() != 0) rtlil_frontend_ilang_yyerror("dangling attribute"); current_module->fixup_ports(); + if (delete_current_module) + delete current_module; + current_module = nullptr; } EOL; module_body: -- cgit v1.2.3 From efa278e232d20ea080743801bd91d55ec62955cf Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 7 Dec 2018 19:14:07 +0000 Subject: Fix typographical and grammatical errors and inconsistencies. The initial list of hits was generated with the codespell command below, and each hit was evaluated and fixed manually while taking context into consideration. DIRS="kernel/ frontends/ backends/ passes/ techlibs/" DIRS="${DIRS} libs/ezsat/ libs/subcircuit" codespell $DIRS -S *.o -L upto,iff,thru,synopsys,uint More hits were found by looking through comments and strings manually. --- frontends/ast/ast.cc | 4 ++-- frontends/blif/blifparse.cc | 2 +- frontends/liberty/liberty.cc | 2 +- frontends/verific/verificsva.cc | 8 ++++---- frontends/verilog/verilog_parser.y | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 2c1561552..5a1bae7a7 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -36,14 +36,14 @@ YOSYS_NAMESPACE_BEGIN using namespace AST; using namespace AST_INTERNAL; -// instanciate global variables (public API) +// instantiate global variables (public API) namespace AST { std::string current_filename; void (*set_line_num)(int) = NULL; int (*get_line_num)() = NULL; } -// instanciate global variables (private API) +// instantiate global variables (private API) namespace AST_INTERNAL { bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog, flag_dump_rtlil, flag_nolatches, flag_nomeminit; bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire; diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc index 034b3e70c..9116b257f 100644 --- a/frontends/blif/blifparse.cc +++ b/frontends/blif/blifparse.cc @@ -276,7 +276,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo if(lastcell == nullptr || module == nullptr) { - err_reason = stringf("No primative object to attach .cname %s.", p); + err_reason = stringf("No primitive object to attach .cname %s.", p); goto error_with_reason; } diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index 4acfbf1cb..6e3cffaca 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -616,7 +616,7 @@ struct LibertyFrontend : public Frontend { LibertyAst *bus_type_node = node->find("bus_type"); if (!bus_type_node || !type_map.count(bus_type_node->value)) - log_error("Unkown or unsupported type for bus interface %s on cell %s.\n", + log_error("Unknown or unsupported type for bus interface %s on cell %s.\n", node->args.at(0).c_str(), log_id(cell_name)); int bus_type_width = std::get<0>(type_map.at(bus_type_node->value)); diff --git a/frontends/verific/verificsva.cc b/frontends/verific/verificsva.cc index cdc9ece8c..6681115df 100644 --- a/frontends/verific/verificsva.cc +++ b/frontends/verific/verificsva.cc @@ -827,9 +827,9 @@ struct SvaFsm for (auto &it : nodes[i].edges) { if (it.second != State::S1) - log(" egde %s -> %d\n", log_signal(it.second), it.first); + log(" edge %s -> %d\n", log_signal(it.second), it.first); else - log(" egde -> %d\n", it.first); + log(" edge -> %d\n", it.first); } for (auto &it : nodes[i].links) { @@ -856,9 +856,9 @@ struct SvaFsm for (auto &it : unodes[i].edges) { if (!it.second.empty()) - log(" egde %s -> %d\n", log_signal(it.second), it.first); + log(" edge %s -> %d\n", log_signal(it.second), it.first); else - log(" egde -> %d\n", it.first); + log(" edge -> %d\n", it.first); } for (auto &ctrl : unodes[i].accept) { diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 51e112ed3..a6718b020 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -794,7 +794,7 @@ more_path_inputs : list_of_path_outputs : specify_output_terminal_descriptor | list_of_path_outputs ',' specify_output_terminal_descriptor ; - + opt_polarity_operator : '+' | '-' @@ -819,7 +819,7 @@ system_timing_arg : system_timing_args : system_timing_arg | system_timing_args ',' system_timing_arg ; - + /* t_path_delay_expression : path_delay_expression; @@ -881,7 +881,7 @@ constant_mintypmax_expression : // for the time being this is OK, but we may write our own expr here. // as I'm not sure it is legal to use a full expr here (probably not) // On the other hand, other rules requiring constant expressions also use 'expr' -// (such as param assignment), so we may leave this as-is, perhaps assing runtime checks for constant-ness +// (such as param assignment), so we may leave this as-is, perhaps adding runtime checks for constant-ness constant_expression: expr ; -- cgit v1.2.3 From 50b09de03320843660636c663629c649ab242321 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 2 Jan 2019 15:05:23 +0100 Subject: Fix VerificImporter asymmetric memories error message Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 61d9d593c..5280a2b9c 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1201,7 +1201,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se { RTLIL::Memory *memory = module->memories.at(RTLIL::escape_id(inst->GetOutput()->Name())); if (memory->width != int(inst->Input2Size())) - log_error("Import of asymmetric memories of this type is not supported yet: %s %s\n", inst->Name(), inst->GetInput()->Name()); + log_error("Import of asymmetric memories of this type is not supported yet: %s %s\n", inst->Name(), inst->GetOutput()->Name()); RTLIL::SigSpec addr = operatorInput1(inst); RTLIL::SigSpec data = operatorInput2(inst); -- cgit v1.2.3 From 1eb101a38a0e6ca99cb1dfbcc77f16a6bff79465 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 2 Jan 2019 15:33:43 +0100 Subject: Improve VerificImporter support for writes to asymmetric memories Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 57 +++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 22 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 5280a2b9c..94138cdd6 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1200,27 +1200,34 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se if (inst->Type() == OPER_WRITE_PORT || inst->Type() == OPER_CLOCKED_WRITE_PORT) { RTLIL::Memory *memory = module->memories.at(RTLIL::escape_id(inst->GetOutput()->Name())); - if (memory->width != int(inst->Input2Size())) + int numchunks = int(inst->Input2Size()) / memory->width; + int chunksbits = ceil_log2(numchunks); + + if ((numchunks * memory->width) != int(inst->Input2Size()) || (numchunks & (numchunks - 1)) != 0) log_error("Import of asymmetric memories of this type is not supported yet: %s %s\n", inst->Name(), inst->GetOutput()->Name()); - RTLIL::SigSpec addr = operatorInput1(inst); - RTLIL::SigSpec data = operatorInput2(inst); - - RTLIL::Cell *cell = module->addCell(inst_name, "$memwr"); - cell->parameters["\\MEMID"] = memory->name.str(); - cell->parameters["\\CLK_ENABLE"] = false; - cell->parameters["\\CLK_POLARITY"] = true; - cell->parameters["\\PRIORITY"] = 0; - cell->parameters["\\ABITS"] = GetSize(addr); - cell->parameters["\\WIDTH"] = GetSize(data); - cell->setPort("\\EN", RTLIL::SigSpec(net_map_at(inst->GetControl())).repeat(GetSize(data))); - cell->setPort("\\CLK", RTLIL::State::S0); - cell->setPort("\\ADDR", addr); - cell->setPort("\\DATA", data); - - if (inst->Type() == OPER_CLOCKED_WRITE_PORT) { - cell->parameters["\\CLK_ENABLE"] = true; - cell->setPort("\\CLK", net_map_at(inst->GetClock())); + for (int i = 0; i < numchunks; i++) + { + RTLIL::SigSpec addr = {operatorInput1(inst), RTLIL::Const(i, chunksbits)}; + RTLIL::SigSpec data = operatorInput2(inst).extract(i * memory->width, memory->width); + + RTLIL::Cell *cell = module->addCell(numchunks == 1 ? inst_name : + RTLIL::IdString(stringf("%s_%d", inst_name.c_str(), i)), "$memwr"); + cell->parameters["\\MEMID"] = memory->name.str(); + cell->parameters["\\CLK_ENABLE"] = false; + cell->parameters["\\CLK_POLARITY"] = true; + cell->parameters["\\PRIORITY"] = 0; + cell->parameters["\\ABITS"] = GetSize(addr); + cell->parameters["\\WIDTH"] = GetSize(data); + cell->setPort("\\EN", RTLIL::SigSpec(net_map_at(inst->GetControl())).repeat(GetSize(data))); + cell->setPort("\\CLK", RTLIL::State::S0); + cell->setPort("\\ADDR", addr); + cell->setPort("\\DATA", data); + + if (inst->Type() == OPER_CLOCKED_WRITE_PORT) { + cell->parameters["\\CLK_ENABLE"] = true; + cell->setPort("\\CLK", net_map_at(inst->GetClock())); + } } continue; } @@ -1893,13 +1900,19 @@ struct VerificPass : public Pass { { Message::SetConsoleOutput(0); Message::RegisterCallBackMsg(msg_func); + RuntimeFlags::SetVar("db_preserve_user_nets", 1); RuntimeFlags::SetVar("db_allow_external_nets", 1); - RuntimeFlags::SetVar("vhdl_support_variable_slice", 1); - RuntimeFlags::SetVar("vhdl_ignore_assertion_statements", 0); + RuntimeFlags::SetVar("db_infer_wide_operators", 1); + RuntimeFlags::SetVar("veri_extract_dualport_rams", 0); RuntimeFlags::SetVar("veri_extract_multiport_rams", 1); - RuntimeFlags::SetVar("db_infer_wide_operators", 1); + + RuntimeFlags::SetVar("vhdl_extract_dualport_rams", 0); + RuntimeFlags::SetVar("vhdl_extract_multiport_rams", 1); + + RuntimeFlags::SetVar("vhdl_support_variable_slice", 1); + RuntimeFlags::SetVar("vhdl_ignore_assertion_statements", 0); // Workaround for VIPER #13851 RuntimeFlags::SetVar("veri_create_name_for_unnamed_gen_block", 1); -- cgit v1.2.3 From 6d1e7e9403c81289492af889922df9aa3e3842b0 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 4 Jan 2019 15:03:29 +0100 Subject: Remove -m32 Verific eval lib build instructions Signed-off-by: Clifford Wolf --- frontends/verific/README | 29 ----------------------------- 1 file changed, 29 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/README b/frontends/verific/README index b4c436a3a..c76cdd637 100644 --- a/frontends/verific/README +++ b/frontends/verific/README @@ -4,35 +4,6 @@ This directory contains Verific bindings for Yosys. See http://www.verific.com/ for details. -Building Yosys with the 32 bit Verific eval library on amd64: -============================================================= - -1.) Use a Makefile.conf like the following one: - ---snip-- -CONFIG := gcc -ENABLE_TCL := 0 -ENABLE_PLUGINS := 0 -ENABLE_VERIFIC := 1 -CXXFLAGS += -m32 -LDFLAGS += -m32 -VERIFIC_DIR = /usr/local/src/verific_lib_eval ---snap-- - - -2.) Install the necessary multilib packages - -Hint: On debian/ubuntu the multilib packages have names such as -libreadline-dev:i386 or lib32readline6-dev, depending on the -exact version of debian/ubuntu you are working with. - - -3.) Build and test - -make -j8 -./yosys -p 'verific -sv frontends/verific/example.sv; verific -import top' - - Verific Features that should be enabled in your Verific library =============================================================== -- cgit v1.2.3 From 17ceab92a93f5d2ef0eb26f3fd04df65e4393f9f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 5 Jan 2019 12:10:24 +0100 Subject: Bugfix in Verilog string handling Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_lexer.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index f9118e142..1b1873e24 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -274,7 +274,7 @@ YOSYS_NAMESPACE_END yystr[j++] = yystr[i++]; } yystr[j] = 0; - frontend_verilog_yylval.string = new std::string(yystr); + frontend_verilog_yylval.string = new std::string(yystr, j); free(yystr); return TOK_STRING; } -- cgit v1.2.3 From cc0b723484d27424a65336662b7e8c19e21589c2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 6 Feb 2019 12:19:48 -0800 Subject: WIP --- frontends/aiger/Makefile.inc | 3 + frontends/aiger/aigerparse.cc | 213 ++++++++++++++++++++++++++++++++++++++++++ frontends/aiger/aigerparse.h | 31 ++++++ 3 files changed, 247 insertions(+) create mode 100644 frontends/aiger/Makefile.inc create mode 100644 frontends/aiger/aigerparse.cc create mode 100644 frontends/aiger/aigerparse.h (limited to 'frontends') diff --git a/frontends/aiger/Makefile.inc b/frontends/aiger/Makefile.inc new file mode 100644 index 000000000..bc1112452 --- /dev/null +++ b/frontends/aiger/Makefile.inc @@ -0,0 +1,3 @@ + +OBJS += frontends/aiger/aigerparse.o + diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc new file mode 100644 index 000000000..c7a9aecb9 --- /dev/null +++ b/frontends/aiger/aigerparse.cc @@ -0,0 +1,213 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * Eddie Hung + * + * 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 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +// [[CITE]] The AIGER And-Inverter Graph (AIG) Format Version 20071012 +// Armin Biere. The AIGER And-Inverter Graph (AIG) Format Version 20071012. Technical Report 07/1, October 2011, FMV Reports Series, Institute for Formal Models and Verification, Johannes Kepler University, Altenbergerstr. 69, 4040 Linz, Austria. +// http://fmv.jku.at/papers/Biere-FMV-TR-07-1.pdf + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" +#include "aigerparse.h" + +YOSYS_NAMESPACE_BEGIN + +#define log_debug log + +void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name) +{ + std::string header; + f >> header; + if (header != "aag") { + log_error("Unsupported AIGER file!\n"); + return; + } + + int M, I, L, O, A; + int B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 + if (!(f >> M >> I >> L >> O >> A)) { + log_error("Invalid AIGER header\n"); + return; + } + for (auto &i : std::array,4>{B, C, J, F}) { + if (f.peek() != ' ') break; + if (!(f >> i)) { + log_error("Invalid AIGER header\n"); + return; + } + } + + std::string line; + std::getline(f, line); // Ignore up to start of next ine, as standard + // says anything that follows could be used for + // optional sections + + log_debug("M=%d I=%d L=%d O=%d A=%d B=%d C=%d J=%d F=%d\n", M, I, L, O, A, B, C, J, F); + + int line_count = 1; + std::stringstream ss; + + auto module = new RTLIL::Module; + module->name = RTLIL::escape_id("aig"); // TODO: Name? + if (design->module(module->name)) + log_error("Duplicate definition of module %s in line %d!\n", log_id(module->name), line_count); + design->add(module); + + auto createWireIfNotExists = [module](int literal) { + const int variable = literal >> 1; + const bool invert = literal & 1; + RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? + RTLIL::Wire *wire = module->wire(wire_name); + if (wire) return wire; + log_debug("Creating %s\n", wire_name.c_str()); + wire = module->addWire(wire_name); + if (!invert) return wire; + RTLIL::IdString wire_inv_name(stringf("\\n%d", variable)); + RTLIL::Wire *wire_inv = module->wire(wire_inv_name); + if (wire_inv) { + if (module->cell(wire_inv_name)) return wire; + } + else { + log_debug("Creating %s\n", wire_inv_name.c_str()); + wire_inv = module->addWire(wire_inv_name); + } + + log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); + RTLIL::Cell *inv = module->addCell(stringf("\\n%d_not", variable), "$_NOT_"); // FIXME: is "_not" the right suffix? + inv->setPort("\\A", wire_inv); + inv->setPort("\\Y", wire); + + return wire; + }; + + int l1, l2, l3; + + // Parse inputs + for (int i = 0; i < I; ++i, ++line_count) { + if (!(f >> l1)) { + log_error("Line %d cannot be interpreted as an input!\n", line_count); + return; + } + log_debug("%d is an input\n", l1); + log_assert(!(l1 & 1)); // TODO: Inputs can't be inverted? + RTLIL::Wire *wire = createWireIfNotExists(l1); + wire->port_input = true; + } + + // Parse latches + for (int i = 0; i < L; ++i, ++line_count) { + if (!(f >> l1 >> l2)) { + log_error("Line %d cannot be interpreted as a latch!\n", line_count); + return; + } + log_debug("%d %d is a latch\n", l1, l2); + log_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted? + RTLIL::Wire *q_wire = createWireIfNotExists(l1); + RTLIL::Wire *d_wire = createWireIfNotExists(l2); + RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str()); + RTLIL::Wire *clk_wire = module->wire(clk_id); + if (!clk_wire) { + log_debug("Creating %s\n", clk_id.c_str()); + clk_wire = module->addWire(clk_id); + clk_wire->port_input = true; + } + + module->addDff(NEW_ID, clk_wire, d_wire, q_wire); + // AIGER latches are assumed to be initialized to zero + q_wire->attributes["\\init"] = RTLIL::Const(0); + } + + // Parse outputs + for (int i = 0; i < O; ++i, ++line_count) { + if (!(f >> l1)) { + log_error("Line %d cannot be interpreted as an output!\n", line_count); + return; + } + + log_debug("%d is an output\n", l1); + RTLIL::Wire *wire = createWireIfNotExists(l1); + wire->port_output = true; + } + std::getline(f, line); // Ignore up to start of next line + + // TODO: Parse bad state properties + for (int i = 0; i < B; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line + + // TODO: Parse invariant constraints + for (int i = 0; i < C; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line + + // TODO: Parse justice properties + for (int i = 0; i < J; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line + + // TODO: Parse fairness constraints + for (int i = 0; i < F; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line + + // Parse AND + for (int i = 0; i < A; ++i, ++line_count) { + if (!(f >> l1 >> l2 >> l3)) { + log_error("Line %d cannot be interpreted as an AND!\n", line_count); + return; + } + + log_debug("%d %d %d is an AND\n", l1, l2, l3); + log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? + RTLIL::Wire *o_wire = createWireIfNotExists(l1); + RTLIL::Wire *i1_wire = createWireIfNotExists(l2); + RTLIL::Wire *i2_wire = createWireIfNotExists(l3); + + RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); + and_cell->setPort("\\A", i1_wire); + and_cell->setPort("\\B", i2_wire); + and_cell->setPort("\\Y", o_wire); + } + + module->fixup_ports(); +} + +struct AigerFrontend : public Frontend { + AigerFrontend() : Frontend("aiger", "read AIGER file") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" read_aiger [options] [filename]\n"); + log("\n"); + log("Load modules from an AIGER file into the current design.\n"); + log("\n"); + } + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing AIGER frontend.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + std::string arg = args[argidx]; + break; + } + extra_args(f, filename, args, argidx); + + parse_aiger(design, *f); + } +} AigerFrontend; + +YOSYS_NAMESPACE_END diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h new file mode 100644 index 000000000..6a250aa67 --- /dev/null +++ b/frontends/aiger/aigerparse.h @@ -0,0 +1,31 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * 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 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef ABC_AIGERPARSE +#define ABC_AIGERPARSE + +#include "kernel/yosys.h" + +YOSYS_NAMESPACE_BEGIN + +extern void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name="clk"); + +YOSYS_NAMESPACE_END + +#endif -- cgit v1.2.3 From 40db2f2eb61287071f59f3e15bd1cd1bf2838d1d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 6 Feb 2019 14:58:47 -0800 Subject: Refactor --- frontends/aiger/aigerparse.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index c7a9aecb9..7f9feee4a 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -30,15 +30,22 @@ YOSYS_NAMESPACE_BEGIN #define log_debug log +static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::string clk_name); + void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name) { std::string header; f >> header; - if (header != "aag") { + if (header == "aag") + return parse_aiger_ascii(design, f, clk_name); + else { log_error("Unsupported AIGER file!\n"); return; } +} +static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::string clk_name) +{ int M, I, L, O, A; int B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 if (!(f >> M >> I >> L >> O >> A)) { -- cgit v1.2.3 From 791f93181df091877e0b233fa21ee5fa34b24b27 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 07:31:04 -0800 Subject: Stub for binary AIGER --- frontends/aiger/aigerparse.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 7f9feee4a..a33110ed0 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -31,6 +31,7 @@ YOSYS_NAMESPACE_BEGIN #define log_debug log static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::string clk_name); +static void parse_aiger_binary(RTLIL::Design *design, std::istream &f, std::string clk_name); void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name) { @@ -38,10 +39,10 @@ void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name) f >> header; if (header == "aag") return parse_aiger_ascii(design, f, clk_name); - else { + else if (header == "aig") + return parse_aiger_binary(design, f, clk_name); + else log_error("Unsupported AIGER file!\n"); - return; - } } static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::string clk_name) @@ -191,6 +192,10 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin module->fixup_ports(); } +static void parse_aiger_binary(RTLIL::Design *design, std::istream &f, std::string clk_name) +{ +} + struct AigerFrontend : public Frontend { AigerFrontend() : Frontend("aiger", "read AIGER file") { } void help() YS_OVERRIDE -- cgit v1.2.3 From 6dbeda1807b285ff079c15067e2f649180524c08 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 08:03:40 -0800 Subject: Add support for symbol tables --- frontends/aiger/aigerparse.cc | 50 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index a33110ed0..7a53bb808 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -107,6 +107,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin int l1, l2, l3; // Parse inputs + std::vector inputs; for (int i = 0; i < I; ++i, ++line_count) { if (!(f >> l1)) { log_error("Line %d cannot be interpreted as an input!\n", line_count); @@ -116,9 +117,11 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_assert(!(l1 & 1)); // TODO: Inputs can't be inverted? RTLIL::Wire *wire = createWireIfNotExists(l1); wire->port_input = true; + inputs.push_back(wire); } // Parse latches + std::vector latches; for (int i = 0; i < L; ++i, ++line_count) { if (!(f >> l1 >> l2)) { log_error("Line %d cannot be interpreted as a latch!\n", line_count); @@ -139,9 +142,11 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin module->addDff(NEW_ID, clk_wire, d_wire, q_wire); // AIGER latches are assumed to be initialized to zero q_wire->attributes["\\init"] = RTLIL::Const(0); + latches.push_back(q_wire); } // Parse outputs + std::vector outputs; for (int i = 0; i < O; ++i, ++line_count) { if (!(f >> l1)) { log_error("Line %d cannot be interpreted as an output!\n", line_count); @@ -151,9 +156,10 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_debug("%d is an output\n", l1); RTLIL::Wire *wire = createWireIfNotExists(l1); wire->port_output = true; + outputs.push_back(wire); } std::getline(f, line); // Ignore up to start of next line - + // TODO: Parse bad state properties for (int i = 0; i < B; ++i, ++line_count) std::getline(f, line); // Ignore up to start of next line @@ -188,6 +194,48 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin and_cell->setPort("\\B", i2_wire); and_cell->setPort("\\Y", o_wire); } + std::getline(f, line); // Ignore up to start of next line + + std::string s; + for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { + if (c == 'i' || c == 'o') { + f.ignore(1); + if (!(f >> l1 >> s)) { + log_error("Line %d cannot be interpreted as a symbol entry!\n", line_count); + return; + } + + if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size())) { + log_error("Line %d has invalid symbol position!\n", line_count); + return; + } + + RTLIL::Wire* wire; + if (c == 'i') wire = inputs[l1]; + else if (c == 'l') wire = latches[l1]; + else if (c == 'o') wire = outputs[l1]; + else log_abort(); + + module->rename(wire, stringf("\\%s", s.c_str())); + } + else if (c == 'l') { + } + else if (c == 'b' || c == 'j' || c == 'f') { + // TODO + } + else if (c == 'c') { + f.ignore(1); + if (f.peek() == '\n') + break; + // Else constraint (TODO) + break; + } + else { + log_error("Line %d: cannot interpret first character '%c'!\n", line_count, c); + return; + } + std::getline(f, line); // Ignore up to start of next line + } module->fixup_ports(); } -- cgit v1.2.3 From 5a593ff41c44329e9a103d8c9f7a7351b1848043 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 08:04:48 -0800 Subject: Remove return after log_error --- frontends/aiger/aigerparse.cc | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 7a53bb808..950432578 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -49,16 +49,12 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin { int M, I, L, O, A; int B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 - if (!(f >> M >> I >> L >> O >> A)) { + if (!(f >> M >> I >> L >> O >> A)) log_error("Invalid AIGER header\n"); - return; - } for (auto &i : std::array,4>{B, C, J, F}) { if (f.peek() != ' ') break; - if (!(f >> i)) { + if (!(f >> i)) log_error("Invalid AIGER header\n"); - return; - } } std::string line; @@ -109,10 +105,8 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Parse inputs std::vector inputs; for (int i = 0; i < I; ++i, ++line_count) { - if (!(f >> l1)) { + if (!(f >> l1)) log_error("Line %d cannot be interpreted as an input!\n", line_count); - return; - } log_debug("%d is an input\n", l1); log_assert(!(l1 & 1)); // TODO: Inputs can't be inverted? RTLIL::Wire *wire = createWireIfNotExists(l1); @@ -123,10 +117,8 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Parse latches std::vector latches; for (int i = 0; i < L; ++i, ++line_count) { - if (!(f >> l1 >> l2)) { + if (!(f >> l1 >> l2)) log_error("Line %d cannot be interpreted as a latch!\n", line_count); - return; - } log_debug("%d %d is a latch\n", l1, l2); log_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted? RTLIL::Wire *q_wire = createWireIfNotExists(l1); @@ -148,10 +140,8 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Parse outputs std::vector outputs; for (int i = 0; i < O; ++i, ++line_count) { - if (!(f >> l1)) { + if (!(f >> l1)) log_error("Line %d cannot be interpreted as an output!\n", line_count); - return; - } log_debug("%d is an output\n", l1); RTLIL::Wire *wire = createWireIfNotExists(l1); @@ -178,10 +168,8 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Parse AND for (int i = 0; i < A; ++i, ++line_count) { - if (!(f >> l1 >> l2 >> l3)) { + if (!(f >> l1 >> l2 >> l3)) log_error("Line %d cannot be interpreted as an AND!\n", line_count); - return; - } log_debug("%d %d %d is an AND\n", l1, l2, l3); log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? @@ -200,15 +188,11 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { if (c == 'i' || c == 'o') { f.ignore(1); - if (!(f >> l1 >> s)) { + if (!(f >> l1 >> s)) log_error("Line %d cannot be interpreted as a symbol entry!\n", line_count); - return; - } - if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size())) { + if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size())) log_error("Line %d has invalid symbol position!\n", line_count); - return; - } RTLIL::Wire* wire; if (c == 'i') wire = inputs[l1]; @@ -230,10 +214,8 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Else constraint (TODO) break; } - else { + else log_error("Line %d: cannot interpret first character '%c'!\n", line_count, c); - return; - } std::getline(f, line); // Ignore up to start of next line } -- cgit v1.2.3 From 02f603ac1a43f3f98048c146b1950c776f73c070 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 08:05:27 -0800 Subject: Handle latch symbols too --- frontends/aiger/aigerparse.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 950432578..a2b2f611e 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -186,7 +186,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin std::string s; for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { - if (c == 'i' || c == 'o') { + if (c == 'i' || c == 'l' || c == 'o') { f.ignore(1); if (!(f >> l1 >> s)) log_error("Line %d cannot be interpreted as a symbol entry!\n", line_count); @@ -202,8 +202,6 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin module->rename(wire, stringf("\\%s", s.c_str())); } - else if (c == 'l') { - } else if (c == 'b' || c == 'j' || c == 'f') { // TODO } -- cgit v1.2.3 From fafa972238e91f6d25bfa307a4ead4035477df18 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 08:08:49 -0800 Subject: Create clk outside of latch loop --- frontends/aiger/aigerparse.cc | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index a2b2f611e..abff6d8d9 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -116,6 +116,15 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Parse latches std::vector latches; + RTLIL::Wire *clk_wire = nullptr; + if (L > 0) { + RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str()); + clk_wire = module->wire(clk_id); + log_assert(!clk_wire); + log_debug("Creating %s\n", clk_id.c_str()); + clk_wire = module->addWire(clk_id); + clk_wire->port_input = true; + } for (int i = 0; i < L; ++i, ++line_count) { if (!(f >> l1 >> l2)) log_error("Line %d cannot be interpreted as a latch!\n", line_count); @@ -123,13 +132,6 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted? RTLIL::Wire *q_wire = createWireIfNotExists(l1); RTLIL::Wire *d_wire = createWireIfNotExists(l2); - RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str()); - RTLIL::Wire *clk_wire = module->wire(clk_id); - if (!clk_wire) { - log_debug("Creating %s\n", clk_id.c_str()); - clk_wire = module->addWire(clk_id); - clk_wire->port_input = true; - } module->addDff(NEW_ID, clk_wire, d_wire, q_wire); // AIGER latches are assumed to be initialized to zero -- cgit v1.2.3 From 652e414392b8e9e8c7dde74e6f2c2369d8d65a20 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 08:09:30 -0800 Subject: Change literal vars from int to unsigned --- frontends/aiger/aigerparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index abff6d8d9..0414d3db3 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -100,7 +100,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin return wire; }; - int l1, l2, l3; + unsigned l1, l2, l3; // Parse inputs std::vector inputs; -- cgit v1.2.3 From 5e24251a61b8798e597ac49bdc8aff2f378f625d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 08:37:18 -0800 Subject: Handle reset logic in latches --- frontends/aiger/aigerparse.cc | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 0414d3db3..c3cc6b321 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -134,8 +134,23 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin RTLIL::Wire *d_wire = createWireIfNotExists(l2); module->addDff(NEW_ID, clk_wire, d_wire, q_wire); - // AIGER latches are assumed to be initialized to zero - q_wire->attributes["\\init"] = RTLIL::Const(0); + + if (f.peek() == ' ') { + if (!(f >> l3)) + log_error("Line %d cannot be interpreted as a latch!\n", line_count); + + if (l3 == 0 || l3 == 1) + q_wire->attributes["\\init"] = RTLIL::Const(0); + else if (l3 == l1) { + //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); + } + else + log_error("Line %d has invalid reset literal for latch!\n", line_count); + } + else { + // AIGER latches are assumed to be initialized to zero + q_wire->attributes["\\init"] = RTLIL::Const(0); + } latches.push_back(q_wire); } -- cgit v1.2.3 From 36c56bf4127edc1ed0f8fbbd62bd70a859263570 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 08:37:44 -0800 Subject: Add comment --- frontends/aiger/aigerparse.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index c3cc6b321..56e4f3b2c 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -135,6 +135,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin module->addDff(NEW_ID, clk_wire, d_wire, q_wire); + // Reset logic is optional in AIGER 1.9 if (f.peek() == ' ') { if (!(f >> l3)) log_error("Line %d cannot be interpreted as a latch!\n", line_count); -- cgit v1.2.3 From 09d758f0a31e3b4290bfcd3d9864733e84c83628 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 10:54:31 -0800 Subject: Refactor to parse_aiger_header() --- frontends/aiger/aigerparse.cc | 58 ++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 26 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 56e4f3b2c..4c15e34d2 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -45,13 +45,11 @@ void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name) log_error("Unsupported AIGER file!\n"); } -static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::string clk_name) +static void parse_aiger_header(std::istream &f, unsigned &M, unsigned &I, unsigned &L, unsigned &O, unsigned &A, unsigned &B, unsigned &C, unsigned &J, unsigned &F) { - int M, I, L, O, A; - int B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 if (!(f >> M >> I >> L >> O >> A)) log_error("Invalid AIGER header\n"); - for (auto &i : std::array,4>{B, C, J, F}) { + for (auto &i : std::array,4>{B, C, J, F}) { if (f.peek() != ' ') break; if (!(f >> i)) log_error("Invalid AIGER header\n"); @@ -62,19 +60,27 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // says anything that follows could be used for // optional sections - log_debug("M=%d I=%d L=%d O=%d A=%d B=%d C=%d J=%d F=%d\n", M, I, L, O, A, B, C, J, F); + log_debug("M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u\n", M, I, L, O, A, B, C, J, F); +} + +static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::string clk_name) +{ + unsigned M, I, L, O, A; + unsigned B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 + parse_aiger_header(f, M, I, L, O, A, B, C, J, F); - int line_count = 1; + unsigned line_count = 1; + std::string line; std::stringstream ss; auto module = new RTLIL::Module; module->name = RTLIL::escape_id("aig"); // TODO: Name? if (design->module(module->name)) - log_error("Duplicate definition of module %s in line %d!\n", log_id(module->name), line_count); + log_error("Duplicate definition of module %s in line %u!\n", log_id(module->name), line_count); design->add(module); - auto createWireIfNotExists = [module](int literal) { - const int variable = literal >> 1; + auto createWireIfNotExists = [module](unsigned literal) { + const unsigned variable = literal >> 1; const bool invert = literal & 1; RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? RTLIL::Wire *wire = module->wire(wire_name); @@ -104,9 +110,9 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Parse inputs std::vector inputs; - for (int i = 0; i < I; ++i, ++line_count) { + for (unsigned i = 0; i < I; ++i, ++line_count) { if (!(f >> l1)) - log_error("Line %d cannot be interpreted as an input!\n", line_count); + log_error("Line %u cannot be interpreted as an input!\n", line_count); log_debug("%d is an input\n", l1); log_assert(!(l1 & 1)); // TODO: Inputs can't be inverted? RTLIL::Wire *wire = createWireIfNotExists(l1); @@ -125,9 +131,9 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin clk_wire = module->addWire(clk_id); clk_wire->port_input = true; } - for (int i = 0; i < L; ++i, ++line_count) { + for (unsigned i = 0; i < L; ++i, ++line_count) { if (!(f >> l1 >> l2)) - log_error("Line %d cannot be interpreted as a latch!\n", line_count); + log_error("Line %u cannot be interpreted as a latch!\n", line_count); log_debug("%d %d is a latch\n", l1, l2); log_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted? RTLIL::Wire *q_wire = createWireIfNotExists(l1); @@ -138,7 +144,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Reset logic is optional in AIGER 1.9 if (f.peek() == ' ') { if (!(f >> l3)) - log_error("Line %d cannot be interpreted as a latch!\n", line_count); + log_error("Line %u cannot be interpreted as a latch!\n", line_count); if (l3 == 0 || l3 == 1) q_wire->attributes["\\init"] = RTLIL::Const(0); @@ -146,7 +152,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); } else - log_error("Line %d has invalid reset literal for latch!\n", line_count); + log_error("Line %u has invalid reset literal for latch!\n", line_count); } else { // AIGER latches are assumed to be initialized to zero @@ -157,9 +163,9 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin // Parse outputs std::vector outputs; - for (int i = 0; i < O; ++i, ++line_count) { + for (unsigned i = 0; i < O; ++i, ++line_count) { if (!(f >> l1)) - log_error("Line %d cannot be interpreted as an output!\n", line_count); + log_error("Line %u cannot be interpreted as an output!\n", line_count); log_debug("%d is an output\n", l1); RTLIL::Wire *wire = createWireIfNotExists(l1); @@ -169,25 +175,25 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin std::getline(f, line); // Ignore up to start of next line // TODO: Parse bad state properties - for (int i = 0; i < B; ++i, ++line_count) + for (unsigned i = 0; i < B; ++i, ++line_count) std::getline(f, line); // Ignore up to start of next line // TODO: Parse invariant constraints - for (int i = 0; i < C; ++i, ++line_count) + for (unsigned i = 0; i < C; ++i, ++line_count) std::getline(f, line); // Ignore up to start of next line // TODO: Parse justice properties - for (int i = 0; i < J; ++i, ++line_count) + for (unsigned i = 0; i < J; ++i, ++line_count) std::getline(f, line); // Ignore up to start of next line // TODO: Parse fairness constraints - for (int i = 0; i < F; ++i, ++line_count) + for (unsigned i = 0; i < F; ++i, ++line_count) std::getline(f, line); // Ignore up to start of next line // Parse AND - for (int i = 0; i < A; ++i, ++line_count) { + for (unsigned i = 0; i < A; ++i, ++line_count) { if (!(f >> l1 >> l2 >> l3)) - log_error("Line %d cannot be interpreted as an AND!\n", line_count); + log_error("Line %u cannot be interpreted as an AND!\n", line_count); log_debug("%d %d %d is an AND\n", l1, l2, l3); log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? @@ -207,10 +213,10 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin if (c == 'i' || c == 'l' || c == 'o') { f.ignore(1); if (!(f >> l1 >> s)) - log_error("Line %d cannot be interpreted as a symbol entry!\n", line_count); + log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count); if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size())) - log_error("Line %d has invalid symbol position!\n", line_count); + log_error("Line %u has invalid symbol position!\n", line_count); RTLIL::Wire* wire; if (c == 'i') wire = inputs[l1]; @@ -231,7 +237,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin break; } else - log_error("Line %d: cannot interpret first character '%c'!\n", line_count, c); + log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); std::getline(f, line); // Ignore up to start of next line } -- cgit v1.2.3 From 2a8cc36578be9a9d1645e435c3a79eb7d1abc7b2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 11:45:16 -0800 Subject: Parse binary AIG files --- frontends/aiger/aigerparse.cc | 213 ++++++++++++++++++++++++++++++++---------- 1 file changed, 164 insertions(+), 49 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 4c15e34d2..4bc3918be 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -30,19 +30,55 @@ YOSYS_NAMESPACE_BEGIN #define log_debug log -static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::string clk_name); -static void parse_aiger_binary(RTLIL::Design *design, std::istream &f, std::string clk_name); +static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::string clk_name); +static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::string clk_name); void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name) { + auto module = new RTLIL::Module; + module->name = RTLIL::escape_id("aig"); // TODO: Name? + if (design->module(module->name)) + log_error("Duplicate definition of module %s!\n", log_id(module->name)); + std::string header; f >> header; if (header == "aag") - return parse_aiger_ascii(design, f, clk_name); + parse_aiger_ascii(module, f, clk_name); else if (header == "aig") - return parse_aiger_binary(design, f, clk_name); + parse_aiger_binary(module, f, clk_name); else log_error("Unsupported AIGER file!\n"); + + module->fixup_ports(); + design->add(module); +} + +static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal) +{ + const unsigned variable = literal >> 1; + const bool invert = literal & 1; + RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? + RTLIL::Wire *wire = module->wire(wire_name); + if (wire) return wire; + log_debug("Creating %s\n", wire_name.c_str()); + wire = module->addWire(wire_name); + if (!invert) return wire; + RTLIL::IdString wire_inv_name(stringf("\\n%d", variable)); + RTLIL::Wire *wire_inv = module->wire(wire_inv_name); + if (wire_inv) { + if (module->cell(wire_inv_name)) return wire; + } + else { + log_debug("Creating %s\n", wire_inv_name.c_str()); + wire_inv = module->addWire(wire_inv_name); + } + + log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); + RTLIL::Cell *inv = module->addCell(stringf("\\n%d_not", variable), "$_NOT_"); // FIXME: is "_not" the right suffix? + inv->setPort("\\A", wire_inv); + inv->setPort("\\Y", wire); + + return wire; } static void parse_aiger_header(std::istream &f, unsigned &M, unsigned &I, unsigned &L, unsigned &O, unsigned &A, unsigned &B, unsigned &C, unsigned &J, unsigned &F) @@ -56,14 +92,14 @@ static void parse_aiger_header(std::istream &f, unsigned &M, unsigned &I, unsign } std::string line; - std::getline(f, line); // Ignore up to start of next ine, as standard + std::getline(f, line); // Ignore up to start of next line, as standard // says anything that follows could be used for // optional sections log_debug("M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u\n", M, I, L, O, A, B, C, J, F); } -static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::string clk_name) +static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::string clk_name) { unsigned M, I, L, O, A; unsigned B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 @@ -73,39 +109,6 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin std::string line; std::stringstream ss; - auto module = new RTLIL::Module; - module->name = RTLIL::escape_id("aig"); // TODO: Name? - if (design->module(module->name)) - log_error("Duplicate definition of module %s in line %u!\n", log_id(module->name), line_count); - design->add(module); - - auto createWireIfNotExists = [module](unsigned literal) { - const unsigned variable = literal >> 1; - const bool invert = literal & 1; - RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? - RTLIL::Wire *wire = module->wire(wire_name); - if (wire) return wire; - log_debug("Creating %s\n", wire_name.c_str()); - wire = module->addWire(wire_name); - if (!invert) return wire; - RTLIL::IdString wire_inv_name(stringf("\\n%d", variable)); - RTLIL::Wire *wire_inv = module->wire(wire_inv_name); - if (wire_inv) { - if (module->cell(wire_inv_name)) return wire; - } - else { - log_debug("Creating %s\n", wire_inv_name.c_str()); - wire_inv = module->addWire(wire_inv_name); - } - - log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); - RTLIL::Cell *inv = module->addCell(stringf("\\n%d_not", variable), "$_NOT_"); // FIXME: is "_not" the right suffix? - inv->setPort("\\A", wire_inv); - inv->setPort("\\Y", wire); - - return wire; - }; - unsigned l1, l2, l3; // Parse inputs @@ -115,7 +118,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_error("Line %u cannot be interpreted as an input!\n", line_count); log_debug("%d is an input\n", l1); log_assert(!(l1 & 1)); // TODO: Inputs can't be inverted? - RTLIL::Wire *wire = createWireIfNotExists(l1); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); wire->port_input = true; inputs.push_back(wire); } @@ -136,8 +139,8 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_error("Line %u cannot be interpreted as a latch!\n", line_count); log_debug("%d %d is a latch\n", l1, l2); log_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted? - RTLIL::Wire *q_wire = createWireIfNotExists(l1); - RTLIL::Wire *d_wire = createWireIfNotExists(l2); + RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); module->addDff(NEW_ID, clk_wire, d_wire, q_wire); @@ -147,7 +150,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_error("Line %u cannot be interpreted as a latch!\n", line_count); if (l3 == 0 || l3 == 1) - q_wire->attributes["\\init"] = RTLIL::Const(0); + q_wire->attributes["\\init"] = RTLIL::Const(l3); else if (l3 == l1) { //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); } @@ -168,7 +171,7 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_error("Line %u cannot be interpreted as an output!\n", line_count); log_debug("%d is an output\n", l1); - RTLIL::Wire *wire = createWireIfNotExists(l1); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); wire->port_output = true; outputs.push_back(wire); } @@ -197,9 +200,9 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_debug("%d %d %d is an AND\n", l1, l2, l3); log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? - RTLIL::Wire *o_wire = createWireIfNotExists(l1); - RTLIL::Wire *i1_wire = createWireIfNotExists(l2); - RTLIL::Wire *i2_wire = createWireIfNotExists(l3); + RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); + RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); and_cell->setPort("\\A", i1_wire); @@ -240,12 +243,124 @@ static void parse_aiger_ascii(RTLIL::Design *design, std::istream &f, std::strin log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); std::getline(f, line); // Ignore up to start of next line } +} - module->fixup_ports(); +static unsigned parse_next_delta_literal(std::istream &f, unsigned ref) +{ + unsigned x = 0, i = 0; + unsigned char ch; + while ((ch = f.get()) & 0x80) + x |= (ch & 0x7f) << (7 * i++); + return ref - (x | (ch << (7 * i))); } -static void parse_aiger_binary(RTLIL::Design *design, std::istream &f, std::string clk_name) +static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::string clk_name) { + unsigned M, I, L, O, A; + unsigned B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 + parse_aiger_header(f, M, I, L, O, A, B, C, J, F); + + unsigned line_count = 1; + unsigned l1, l2, l3; + std::string line; + + // Parse inputs + std::vector inputs; + for (unsigned i = 1; i <= I; ++i) { + RTLIL::Wire *wire = createWireIfNotExists(module, i << 1); + wire->port_input = true; + inputs.push_back(wire); + } + + // Parse latches + std::vector latches; + RTLIL::Wire *clk_wire = nullptr; + if (L > 0) { + RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str()); + clk_wire = module->wire(clk_id); + log_assert(!clk_wire); + log_debug("Creating %s\n", clk_id.c_str()); + clk_wire = module->addWire(clk_id); + clk_wire->port_input = true; + } + l1 = (I+1) * 2; + for (unsigned i = 0; i < L; ++i, ++line_count, l1 += 2) { + if (!(f >> l2)) + log_error("Line %u cannot be interpreted as a latch!\n", line_count); + log_debug("%d %d is a latch\n", l1, l2); + RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); + + module->addDff(NEW_ID, clk_wire, d_wire, q_wire); + + // Reset logic is optional in AIGER 1.9 + if (f.peek() == ' ') { + if (!(f >> l3)) + log_error("Line %u cannot be interpreted as a latch!\n", line_count); + + if (l3 == 0 || l3 == 1) + q_wire->attributes["\\init"] = RTLIL::Const(l3); + else if (l3 == l1) { + //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx); + } + else + log_error("Line %u has invalid reset literal for latch!\n", line_count); + } + else { + // AIGER latches are assumed to be initialized to zero + q_wire->attributes["\\init"] = RTLIL::Const(0); + } + latches.push_back(q_wire); + } + + // Parse outputs + std::vector outputs; + for (unsigned i = 0; i < O; ++i, ++line_count) { + if (!(f >> l1)) + log_error("Line %u cannot be interpreted as an output!\n", line_count); + + log_debug("%d is an output\n", l1); + RTLIL::Wire *wire = createWireIfNotExists(module, l1); + wire->port_output = true; + outputs.push_back(wire); + } + std::getline(f, line); // Ignore up to start of next line + + // TODO: Parse bad state properties + for (unsigned i = 0; i < B; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line + + // TODO: Parse invariant constraints + for (unsigned i = 0; i < C; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line + + // TODO: Parse justice properties + for (unsigned i = 0; i < J; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line + + // TODO: Parse fairness constraints + for (unsigned i = 0; i < F; ++i, ++line_count) + std::getline(f, line); // Ignore up to start of next line + + // Parse AND + l1 = (I+L+1) << 1; + for (unsigned i = 0; i < A; ++i, ++line_count, l1 += 2) { + l2 = parse_next_delta_literal(f, l1); + l3 = parse_next_delta_literal(f, l2); + + log_debug("%d %d %d is an AND\n", l1, l2, l3); + log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? + RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); + RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); + + RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); + and_cell->setPort("\\A", i1_wire); + and_cell->setPort("\\B", i2_wire); + and_cell->setPort("\\Y", o_wire); + } + std::getline(f, line); // Ignore up to start of next line + } struct AigerFrontend : public Frontend { -- cgit v1.2.3 From f1befe1b44ada400e979f43e1b35ebe022ff8fe8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 12:04:26 -0800 Subject: Refactor into AigerReader class --- frontends/aiger/aigerparse.cc | 150 ++++++++++++++++++++---------------------- frontends/aiger/aigerparse.h | 21 +++++- 2 files changed, 92 insertions(+), 79 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 4bc3918be..365bf1b69 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -30,24 +30,84 @@ YOSYS_NAMESPACE_BEGIN #define log_debug log -static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::string clk_name); -static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::string clk_name); - -void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name) +AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, std::string clk_name) + : design(design), f(f), clk_name(clk_name) { - auto module = new RTLIL::Module; + module = new RTLIL::Module; module->name = RTLIL::escape_id("aig"); // TODO: Name? if (design->module(module->name)) log_error("Duplicate definition of module %s!\n", log_id(module->name)); +} +void AigerReader::parse_aiger() +{ std::string header; f >> header; + if (header != "aag" && header != "aig") + log_error("Unsupported AIGER file!\n"); + + // Parse rest of header + if (!(f >> M >> I >> L >> O >> A)) + log_error("Invalid AIGER header\n"); + + // Optional values + B = C = J = F = 0; + for (auto &i : std::array,4>{B, C, J, F}) { + if (f.peek() != ' ') break; + if (!(f >> i)) + log_error("Invalid AIGER header\n"); + } + + std::string line; + std::getline(f, line); // Ignore up to start of next line, as standard + // says anything that follows could be used for + // optional sections + + log_debug("M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u\n", M, I, L, O, A, B, C, J, F); + + line_count = 1; + if (header == "aag") - parse_aiger_ascii(module, f, clk_name); + parse_aiger_ascii(); else if (header == "aig") - parse_aiger_binary(module, f, clk_name); + parse_aiger_binary(); else - log_error("Unsupported AIGER file!\n"); + log_abort(); + + // Parse footer (symbol table, comments, etc.) + unsigned l1; + std::string s; + for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { + if (c == 'i' || c == 'l' || c == 'o') { + f.ignore(1); + if (!(f >> l1 >> s)) + log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count); + + if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size())) + log_error("Line %u has invalid symbol position!\n", line_count); + + RTLIL::Wire* wire; + if (c == 'i') wire = inputs[l1]; + else if (c == 'l') wire = latches[l1]; + else if (c == 'o') wire = outputs[l1]; + else log_abort(); + + module->rename(wire, stringf("\\%s", s.c_str())); + } + else if (c == 'b' || c == 'j' || c == 'f') { + // TODO + } + else if (c == 'c') { + f.ignore(1); + if (f.peek() == '\n') + break; + // Else constraint (TODO) + break; + } + else + log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); + std::getline(f, line); // Ignore up to start of next line + } module->fixup_ports(); design->add(module); @@ -81,38 +141,14 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera return wire; } -static void parse_aiger_header(std::istream &f, unsigned &M, unsigned &I, unsigned &L, unsigned &O, unsigned &A, unsigned &B, unsigned &C, unsigned &J, unsigned &F) +void AigerReader::parse_aiger_ascii() { - if (!(f >> M >> I >> L >> O >> A)) - log_error("Invalid AIGER header\n"); - for (auto &i : std::array,4>{B, C, J, F}) { - if (f.peek() != ' ') break; - if (!(f >> i)) - log_error("Invalid AIGER header\n"); - } - - std::string line; - std::getline(f, line); // Ignore up to start of next line, as standard - // says anything that follows could be used for - // optional sections - - log_debug("M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u\n", M, I, L, O, A, B, C, J, F); -} - -static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::string clk_name) -{ - unsigned M, I, L, O, A; - unsigned B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 - parse_aiger_header(f, M, I, L, O, A, B, C, J, F); - - unsigned line_count = 1; std::string line; std::stringstream ss; unsigned l1, l2, l3; // Parse inputs - std::vector inputs; for (unsigned i = 0; i < I; ++i, ++line_count) { if (!(f >> l1)) log_error("Line %u cannot be interpreted as an input!\n", line_count); @@ -124,7 +160,6 @@ static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::strin } // Parse latches - std::vector latches; RTLIL::Wire *clk_wire = nullptr; if (L > 0) { RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str()); @@ -165,7 +200,6 @@ static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::strin } // Parse outputs - std::vector outputs; for (unsigned i = 0; i < O; ++i, ++line_count) { if (!(f >> l1)) log_error("Line %u cannot be interpreted as an output!\n", line_count); @@ -210,39 +244,6 @@ static void parse_aiger_ascii(RTLIL::Module *module, std::istream &f, std::strin and_cell->setPort("\\Y", o_wire); } std::getline(f, line); // Ignore up to start of next line - - std::string s; - for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) { - if (c == 'i' || c == 'l' || c == 'o') { - f.ignore(1); - if (!(f >> l1 >> s)) - log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count); - - if ((c == 'i' && l1 > inputs.size()) || (c == 'l' && l1 > latches.size()) || (c == 'o' && l1 > outputs.size())) - log_error("Line %u has invalid symbol position!\n", line_count); - - RTLIL::Wire* wire; - if (c == 'i') wire = inputs[l1]; - else if (c == 'l') wire = latches[l1]; - else if (c == 'o') wire = outputs[l1]; - else log_abort(); - - module->rename(wire, stringf("\\%s", s.c_str())); - } - else if (c == 'b' || c == 'j' || c == 'f') { - // TODO - } - else if (c == 'c') { - f.ignore(1); - if (f.peek() == '\n') - break; - // Else constraint (TODO) - break; - } - else - log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); - std::getline(f, line); // Ignore up to start of next line - } } static unsigned parse_next_delta_literal(std::istream &f, unsigned ref) @@ -254,18 +255,12 @@ static unsigned parse_next_delta_literal(std::istream &f, unsigned ref) return ref - (x | (ch << (7 * i))); } -static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::string clk_name) +void AigerReader::parse_aiger_binary() { - unsigned M, I, L, O, A; - unsigned B=0, C=0, J=0, F=0; // Optional in AIGER 1.9 - parse_aiger_header(f, M, I, L, O, A, B, C, J, F); - - unsigned line_count = 1; unsigned l1, l2, l3; std::string line; // Parse inputs - std::vector inputs; for (unsigned i = 1; i <= I; ++i) { RTLIL::Wire *wire = createWireIfNotExists(module, i << 1); wire->port_input = true; @@ -273,7 +268,6 @@ static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::stri } // Parse latches - std::vector latches; RTLIL::Wire *clk_wire = nullptr; if (L > 0) { RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str()); @@ -314,7 +308,6 @@ static void parse_aiger_binary(RTLIL::Module *module, std::istream &f, std::stri } // Parse outputs - std::vector outputs; for (unsigned i = 0; i < O; ++i, ++line_count) { if (!(f >> l1)) log_error("Line %u cannot be interpreted as an output!\n", line_count); @@ -385,7 +378,8 @@ struct AigerFrontend : public Frontend { } extra_args(f, filename, args, argidx); - parse_aiger(design, *f); + AigerReader reader(design, *f); + reader.parse_aiger(); } } AigerFrontend; diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index 6a250aa67..3e8ef09fc 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -24,7 +24,26 @@ YOSYS_NAMESPACE_BEGIN -extern void parse_aiger(RTLIL::Design *design, std::istream &f, std::string clk_name="clk"); +struct AigerReader +{ + RTLIL::Design *design; + std::istream &f; + std::string clk_name; + RTLIL::Module *module; + + unsigned M, I, L, O, A; + unsigned B, C, J, F; // Optional in AIGER 1.9 + unsigned line_count; + + std::vector inputs; + std::vector latches; + std::vector outputs; + + AigerReader(RTLIL::Design *design, std::istream &f, std::string clk_name="clk"); + void parse_aiger(); + void parse_aiger_ascii(); + void parse_aiger_binary(); +}; YOSYS_NAMESPACE_END -- cgit v1.2.3 From fb8ad440a32da850e32765ec29119cacb3f3c27c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 12:40:43 -0800 Subject: Allow module name to be determined by argument too --- frontends/aiger/aigerparse.cc | 54 +++++++++++++++++++++++++++++++++---------- frontends/aiger/aigerparse.h | 4 ++-- 2 files changed, 44 insertions(+), 14 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 365bf1b69..6ebb524bd 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -30,11 +30,11 @@ YOSYS_NAMESPACE_BEGIN #define log_debug log -AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, std::string clk_name) +AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name) : design(design), f(f), clk_name(clk_name) { module = new RTLIL::Module; - module->name = RTLIL::escape_id("aig"); // TODO: Name? + module->name = module_name; if (design->module(module->name)) log_error("Duplicate definition of module %s!\n", log_id(module->name)); } @@ -162,11 +162,10 @@ void AigerReader::parse_aiger_ascii() // Parse latches RTLIL::Wire *clk_wire = nullptr; if (L > 0) { - RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str()); - clk_wire = module->wire(clk_id); + clk_wire = module->wire(clk_name); log_assert(!clk_wire); - log_debug("Creating %s\n", clk_id.c_str()); - clk_wire = module->addWire(clk_id); + log_debug("Creating %s\n", clk_name.c_str()); + clk_wire = module->addWire(clk_name); clk_wire->port_input = true; } for (unsigned i = 0; i < L; ++i, ++line_count) { @@ -270,11 +269,10 @@ void AigerReader::parse_aiger_binary() // Parse latches RTLIL::Wire *clk_wire = nullptr; if (L > 0) { - RTLIL::IdString clk_id = RTLIL::escape_id(clk_name.c_str()); - clk_wire = module->wire(clk_id); + clk_wire = module->wire(clk_name); log_assert(!clk_wire); - log_debug("Creating %s\n", clk_id.c_str()); - clk_wire = module->addWire(clk_id); + log_debug("Creating %s\n", clk_name.c_str()); + clk_wire = module->addWire(clk_name); clk_wire->port_input = true; } l1 = (I+1) * 2; @@ -364,21 +362,53 @@ struct AigerFrontend : public Frontend { log("\n"); log(" read_aiger [options] [filename]\n"); log("\n"); - log("Load modules from an AIGER file into the current design.\n"); + log("Load module from an AIGER file into the current design.\n"); + log("\n"); + log(" -clk_name \n"); + log(" AIGER latches to be transformed into posedge DFFs clocked by wire of"); + log(" this name (default: clk)\n"); + log("\n"); + log(" -module_name \n"); + log(" Name of module to be created (default: )" +#ifdef _WIN32 + "top" // FIXME +#else + "" +#endif + ")\n"); log("\n"); } void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing AIGER frontend.\n"); + RTLIL::IdString clk_name = "\\clk"; + RTLIL::IdString module_name; + size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { std::string arg = args[argidx]; + if (arg == "-clk_name" && argidx+1 < args.size()) { + clk_name = RTLIL::escape_id(args[++argidx]); + continue; + } + if (arg == "-module_name" && argidx+1 < args.size()) { + module_name = RTLIL::escape_id(args[++argidx]); + continue; + } break; } extra_args(f, filename, args, argidx); - AigerReader reader(design, *f); + if (module_name.empty()) { +#ifdef _WIN32 + module_name = "top"; // FIXME: basename equivalent on Win32? +#else + module_name = RTLIL::escape_id(basename(filename.c_str())); +#endif + } + + AigerReader reader(design, *f, module_name, clk_name); reader.parse_aiger(); } } AigerFrontend; diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index 3e8ef09fc..39a77bd93 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -28,7 +28,7 @@ struct AigerReader { RTLIL::Design *design; std::istream &f; - std::string clk_name; + RTLIL::IdString clk_name; RTLIL::Module *module; unsigned M, I, L, O, A; @@ -39,7 +39,7 @@ struct AigerReader std::vector latches; std::vector outputs; - AigerReader(RTLIL::Design *design, std::istream &f, std::string clk_name="clk"); + AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name); void parse_aiger(); void parse_aiger_ascii(); void parse_aiger_binary(); -- cgit v1.2.3 From 391ec75b07cc8c10818884f19329d719847957d3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 12:41:39 -0800 Subject: Add missing "[options]" to read_blif help --- frontends/blif/blifparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc index 9116b257f..a6a07863f 100644 --- a/frontends/blif/blifparse.cc +++ b/frontends/blif/blifparse.cc @@ -584,7 +584,7 @@ struct BlifFrontend : public Frontend { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" read_blif [filename]\n"); + log(" read_blif [options] [filename]\n"); log("\n"); log("Load modules from a BLIF file into the current design.\n"); log("\n"); -- cgit v1.2.3 From aa66d8f12f89b457a4a23c04de706a36ee8fc114 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 12:49:55 -0800 Subject: -module_name arg to go before -clk_name --- frontends/aiger/aigerparse.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 6ebb524bd..5c982fb59 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -363,13 +363,13 @@ struct AigerFrontend : public Frontend { log(" read_aiger [options] [filename]\n"); log("\n"); log("Load module from an AIGER file into the current design.\n"); + log("\n"); + log(" -module_name \n"); + log(" Name of module to be created (default: )" log("\n"); log(" -clk_name \n"); log(" AIGER latches to be transformed into posedge DFFs clocked by wire of"); log(" this name (default: clk)\n"); - log("\n"); - log(" -module_name \n"); - log(" Name of module to be created (default: )" #ifdef _WIN32 "top" // FIXME #else @@ -388,14 +388,14 @@ struct AigerFrontend : public Frontend { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { std::string arg = args[argidx]; - if (arg == "-clk_name" && argidx+1 < args.size()) { - clk_name = RTLIL::escape_id(args[++argidx]); - continue; - } if (arg == "-module_name" && argidx+1 < args.size()) { module_name = RTLIL::escape_id(args[++argidx]); continue; } + if (arg == "-clk_name" && argidx+1 < args.size()) { + clk_name = RTLIL::escape_id(args[++argidx]); + continue; + } break; } extra_args(f, filename, args, argidx); -- cgit v1.2.3 From afc3c4b6139db528b58062f544fb0b098ab212b0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 13:17:02 -0800 Subject: Fix tabulation --- frontends/aiger/aigerparse.cc | 56 +++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 5c982fb59..154581179 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -237,10 +237,10 @@ void AigerReader::parse_aiger_ascii() RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); - and_cell->setPort("\\A", i1_wire); - and_cell->setPort("\\B", i2_wire); - and_cell->setPort("\\Y", o_wire); + RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); + and_cell->setPort("\\A", i1_wire); + and_cell->setPort("\\B", i2_wire); + and_cell->setPort("\\Y", o_wire); } std::getline(f, line); // Ignore up to start of next line } @@ -345,42 +345,42 @@ void AigerReader::parse_aiger_binary() RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); - and_cell->setPort("\\A", i1_wire); - and_cell->setPort("\\B", i2_wire); - and_cell->setPort("\\Y", o_wire); + RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); + and_cell->setPort("\\A", i1_wire); + and_cell->setPort("\\B", i2_wire); + and_cell->setPort("\\Y", o_wire); } std::getline(f, line); // Ignore up to start of next line } struct AigerFrontend : public Frontend { - AigerFrontend() : Frontend("aiger", "read AIGER file") { } - void help() YS_OVERRIDE - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" read_aiger [options] [filename]\n"); - log("\n"); - log("Load module from an AIGER file into the current design.\n"); + AigerFrontend() : Frontend("aiger", "read AIGER file") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" -module_name \n"); - log(" Name of module to be created (default: )" - log("\n"); - log(" -clk_name \n"); - log(" AIGER latches to be transformed into posedge DFFs clocked by wire of"); - log(" this name (default: clk)\n"); + log(" read_aiger [options] [filename]\n"); + log("\n"); + log("Load module from an AIGER file into the current design.\n"); + log("\n"); + log(" -module_name \n"); + log(" Name of module to be created (default: )" #ifdef _WIN32 "top" // FIXME #else "" #endif ")\n"); - log("\n"); - } - void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE - { - log_header(design, "Executing AIGER frontend.\n"); + log("\n"); + log(" -clk_name \n"); + log(" AIGER latches to be transformed into posedge DFFs clocked by wire of"); + log(" this name (default: clk)\n"); + log("\n"); + } + void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing AIGER frontend.\n"); RTLIL::IdString clk_name = "\\clk"; RTLIL::IdString module_name; @@ -410,7 +410,7 @@ struct AigerFrontend : public Frontend { AigerReader reader(design, *f, module_name, clk_name); reader.parse_aiger(); - } + } } AigerFrontend; YOSYS_NAMESPACE_END -- cgit v1.2.3 From 8886fa5506b227229398e5ac884203e799bce22c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 13:17:53 -0800 Subject: addDff -> addDffGate as per @daveshah1 --- frontends/aiger/aigerparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 154581179..c45de8531 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -176,7 +176,7 @@ void AigerReader::parse_aiger_ascii() RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); - module->addDff(NEW_ID, clk_wire, d_wire, q_wire); + module->addDffGate(NEW_ID, clk_wire, d_wire, q_wire); // Reset logic is optional in AIGER 1.9 if (f.peek() == ' ') { -- cgit v1.2.3 From bb4164481d8b6eeec6bbc6f5b36f1286ada51eb5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 11 Feb 2019 11:51:44 -0800 Subject: Do not ignore newline after AND in binary AIG --- frontends/aiger/aigerparse.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index c45de8531..ed91b6990 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -242,7 +242,6 @@ void AigerReader::parse_aiger_ascii() and_cell->setPort("\\B", i2_wire); and_cell->setPort("\\Y", o_wire); } - std::getline(f, line); // Ignore up to start of next line } static unsigned parse_next_delta_literal(std::istream &f, unsigned ref) -- cgit v1.2.3 From 727ba52504c65be1fcda9b03f6c2e1498e10061d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 11 Feb 2019 13:24:21 -0800 Subject: No increment line_count for binary ANDs --- frontends/aiger/aigerparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index ed91b6990..096e269b2 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -227,7 +227,7 @@ void AigerReader::parse_aiger_ascii() std::getline(f, line); // Ignore up to start of next line // Parse AND - for (unsigned i = 0; i < A; ++i, ++line_count) { + for (unsigned i = 0; i < A; ++i) { if (!(f >> l1 >> l2 >> l3)) log_error("Line %u cannot be interpreted as an AND!\n", line_count); -- cgit v1.2.3 From 04c580fde7a0d1d50c2d93bb6661b3f17a7d61a9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 11 Feb 2019 13:28:00 -0800 Subject: Do not break for constraints --- frontends/aiger/aigerparse.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 096e269b2..1e13e1124 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -102,7 +102,6 @@ void AigerReader::parse_aiger() if (f.peek() == '\n') break; // Else constraint (TODO) - break; } else log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c); -- cgit v1.2.3 From a2ae39381124ccfec348293c7c7926597c26a5b8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 12 Feb 2019 09:21:15 -0800 Subject: Use module->add{Not,And}Gate() functions --- frontends/aiger/aigerparse.cc | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index c45de8531..888a4afe6 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -134,9 +134,7 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera } log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); - RTLIL::Cell *inv = module->addCell(stringf("\\n%d_not", variable), "$_NOT_"); // FIXME: is "_not" the right suffix? - inv->setPort("\\A", wire_inv); - inv->setPort("\\Y", wire); + module->addNotGate(stringf("\\n%d_not", variable), wire_inv, wire); // FIXME: is "_not" the right suffix? return wire; } @@ -236,11 +234,7 @@ void AigerReader::parse_aiger_ascii() RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - - RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); - and_cell->setPort("\\A", i1_wire); - and_cell->setPort("\\B", i2_wire); - and_cell->setPort("\\Y", o_wire); + module->addAndGate(NEW_ID, i1_wire, i2_wire, o_wire); } std::getline(f, line); // Ignore up to start of next line } -- cgit v1.2.3 From 807b3c769733b8cf07f5b14674df41bd2788e09d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 13 Feb 2019 12:36:47 +0100 Subject: Fix sign handling of real constants Signed-off-by: Clifford Wolf --- frontends/ast/genrtlil.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 9531dd356..e66625228 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -942,16 +942,15 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // simply return the corresponding RTLIL::SigSpec for an AST_CONSTANT node case AST_CONSTANT: + case AST_REALVALUE: { if (width_hint < 0) detectSignWidth(width_hint, sign_hint); - is_signed = sign_hint; - return RTLIL::SigSpec(bitsAsConst()); - } - case AST_REALVALUE: - { + if (type == AST_CONSTANT) + return RTLIL::SigSpec(bitsAsConst()); + RTLIL::SigSpec sig = realAsConst(width_hint); log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", realvalue, log_signal(sig)); return sig; -- cgit v1.2.3 From 9268a271fb8b22b089927d63f0b36d620e19704c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 17 Feb 2019 12:07:14 -0800 Subject: read_aiger to ignore line after ands for ascii, not binary --- frontends/aiger/aigerparse.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 7df28fe87..a1a0a08a0 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -235,6 +235,7 @@ void AigerReader::parse_aiger_ascii() RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); module->addAndGate(NEW_ID, i1_wire, i2_wire, o_wire); } + std::getline(f, line); // Ignore up to start of next line } static unsigned parse_next_delta_literal(std::istream &f, unsigned ref) @@ -342,8 +343,6 @@ void AigerReader::parse_aiger_binary() and_cell->setPort("\\B", i2_wire); and_cell->setPort("\\Y", o_wire); } - std::getline(f, line); // Ignore up to start of next line - } struct AigerFrontend : public Frontend { -- cgit v1.2.3 From 8e1dbfac3af64339f021ed674bdd98e71cd7fb90 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 17 Feb 2019 20:59:53 -0800 Subject: Missing OSX headers? --- frontends/aiger/aigerparse.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index a1a0a08a0..778b8b070 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -22,6 +22,11 @@ // Armin Biere. The AIGER And-Inverter Graph (AIG) Format Version 20071012. Technical Report 07/1, October 2011, FMV Reports Series, Institute for Formal Models and Verification, Johannes Kepler University, Altenbergerstr. 69, 4040 Linz, Austria. // http://fmv.jku.at/papers/Biere-FMV-TR-07-1.pdf +#ifdef __linux__ +#include +#endif +#include + #include "kernel/yosys.h" #include "kernel/sigtools.h" #include "aigerparse.h" -- cgit v1.2.3 From 843e7fc8a70b7510ae8dfbad2c9f66d2d64d0e64 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Feb 2019 09:02:37 -0800 Subject: Fix for using POSIX basename --- frontends/aiger/aigerparse.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 778b8b070..cf7950c85 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -22,7 +22,7 @@ // Armin Biere. The AIGER And-Inverter Graph (AIG) Format Version 20071012. Technical Report 07/1, October 2011, FMV Reports Series, Institute for Formal Models and Verification, Johannes Kepler University, Altenbergerstr. 69, 4040 Linz, Austria. // http://fmv.jku.at/papers/Biere-FMV-TR-07-1.pdf -#ifdef __linux__ +#ifndef _WIN32 #include #endif #include @@ -400,7 +400,9 @@ struct AigerFrontend : public Frontend { #ifdef _WIN32 module_name = "top"; // FIXME: basename equivalent on Win32? #else - module_name = RTLIL::escape_id(basename(filename.c_str())); + char* bn = strdup(filename.c_str()); + module_name = RTLIL::escape_id(bn); + free(bn); #endif } -- cgit v1.2.3 From 28fba903c595710c401a6c7d49e7bfd3f8c64efc Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 21 Feb 2019 17:36:51 +0100 Subject: Fix segfault in printing of some internal error messages Signed-off-by: Clifford Wolf --- frontends/ast/genrtlil.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index e66625228..bdc34d490 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -792,7 +792,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun // everything should have been handled above -> print error if not. default: for (auto f : log_files) - current_ast->dumpAst(f, "verilog-ast> "); + current_ast_mod->dumpAst(f, "verilog-ast> "); log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n", type2str(type).c_str()); } @@ -1565,7 +1565,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) // everything should have been handled above -> print error if not. default: for (auto f : log_files) - current_ast->dumpAst(f, "verilog-ast> "); + current_ast_mod->dumpAst(f, "verilog-ast> "); type_name = type2str(type); log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n", type_name.c_str()); } -- cgit v1.2.3 From 974927adcf916fc953ae4b756fd1806cfa423655 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 21 Feb 2019 17:55:33 +0100 Subject: Fix handling of expression width in $past, fixes #810 Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 83714f897..6ae62ead8 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1778,7 +1778,7 @@ skip_dynamic_range_lvalue_expansion:; if (str == "\\$past") { - if (width_hint <= 0) + if (width_hint < 0) goto replace_fcall_later; int num_steps = 1; -- cgit v1.2.3 From 23148ffae14318bb34cb311eb13494e25ebf4593 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 21 Feb 2019 18:40:11 +0100 Subject: Fixes related to handling of autowires and upto-ranges, fixes #814 Signed-off-by: Clifford Wolf --- frontends/ast/genrtlil.cc | 4 ++-- frontends/ast/simplify.cc | 17 ++++++++++------- 2 files changed, 12 insertions(+), 9 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index bdc34d490..2d591b29d 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -644,7 +644,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); - this_width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1; + this_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; delete left_at_zero_ast; delete right_at_zero_ast; } else @@ -1034,7 +1034,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); - int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1; + int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ? children[0]->children[1]->clone() : children[0]->children[0]->clone()); fake_ast->children[0]->delete_children(); diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 6ae62ead8..737fb300c 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -934,12 +934,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } } if (current_scope.count(str) == 0) { - // log_warning("Creating auto-wire `%s' in module `%s'.\n", str.c_str(), current_ast_mod->str.c_str()); - AstNode *auto_wire = new AstNode(AST_AUTOWIRE); - auto_wire->str = str; - current_ast_mod->children.push_back(auto_wire); - current_scope[str] = auto_wire; - did_something = true; + if (flag_autowire) { + AstNode *auto_wire = new AstNode(AST_AUTOWIRE); + auto_wire->str = str; + current_ast_mod->children.push_back(auto_wire); + current_scope[str] = auto_wire; + did_something = true; + } else { + log_file_error(filename, linenum, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str()); + } } if (id2ast != current_scope[str]) { id2ast = current_scope[str]; @@ -1689,7 +1692,7 @@ skip_dynamic_range_lvalue_expansion:; while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { } if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); - int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1; + int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_SHIFT_LEFT, children[1]->clone(), offset_ast->clone())); -- cgit v1.2.3 From a516b4fb5af0d8389fa8aede95ae5a76bec13dcf Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 24 Feb 2019 19:51:30 +0100 Subject: Check if Verific was built with DB_PRESERVE_INITIAL_VALUE Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 94138cdd6..8ee951d20 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1920,6 +1920,10 @@ struct VerificPass : public Pass { // WARNING: instantiating unknown module 'XYZ' (VERI-1063) Message::SetMessageType("VERI-1063", VERIFIC_ERROR); +#ifndef DB_PRESERVE_INITIAL_VALUE +# warning Verific was built without DB_PRESERVE_INITIAL_VALUE. +#endif + set_verific_global_flags = false; } -- cgit v1.2.3 From 1816fe06af9ab2c50bd293dc10359238acc88f12 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 24 Feb 2019 20:09:41 +0100 Subject: Fix handling of defparam for when default_nettype is none Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 737fb300c..46013544b 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -642,6 +642,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // (iterate by index as e.g. auto wires can add new children in the process) for (size_t i = 0; i < children.size(); i++) { bool did_something_here = true; + bool backup_flag_autowire = flag_autowire; if ((type == AST_GENFOR || type == AST_FOR) && i >= 3) break; if ((type == AST_GENIF || type == AST_GENCASE) && i >= 1) @@ -652,6 +653,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, break; if (type == AST_PREFIX && i >= 1) break; + if (type == AST_DEFPARAM && i == 0) + flag_autowire = true; while (did_something_here && i < children.size()) { bool const_fold_here = const_fold, in_lvalue_here = in_lvalue; int width_hint_here = width_hint; @@ -686,6 +689,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, children.erase(children.begin() + (i--)); did_something = true; } + flag_autowire = backup_flag_autowire; } for (auto &attr : attributes) { while (attr.second->simplify(true, false, false, stage, -1, false, true)) -- cgit v1.2.3 From 60e3c38054f10251021fa2f504ad2424da33aa1d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 28 Feb 2019 20:34:42 -0800 Subject: Improve "read" error msg Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 8ee951d20..9f52ffdc2 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -2316,7 +2316,7 @@ struct ReadPass : public Pass { } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - if (args.size() < 2) + if (args.size() < 2 || args[1][0] != '-') log_cmd_error("Missing mode parameter.\n"); if (args.size() < 3) -- cgit v1.2.3 From 7cfae2c52fb8e210a68032a109646785e4353dcc Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 1 Mar 2019 13:35:09 -0800 Subject: Use mem2reg on memories that only have constant-index write ports Signed-off-by: Clifford Wolf --- frontends/ast/ast.h | 2 ++ frontends/ast/simplify.cc | 11 +++++++++++ 2 files changed, 13 insertions(+) (limited to 'frontends') diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 08f91c9c3..89f7e6e4f 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -214,6 +214,8 @@ namespace AST MEM2REG_FL_SET_ASYNC = 0x00000800, MEM2REG_FL_EQ2 = 0x00001000, MEM2REG_FL_CMPLX_LHS = 0x00002000, + MEM2REG_FL_CONST_LHS = 0x00004000, + MEM2REG_FL_VAR_LHS = 0x00008000, /* proc flags */ MEM2REG_FL_EQ1 = 0x01000000, diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 46013544b..589c683f8 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -113,6 +113,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (memflags & AstNode::MEM2REG_FL_CMPLX_LHS) goto verbose_activate; + if ((memflags & AstNode::MEM2REG_FL_CONST_LHS) && !(memflags & AstNode::MEM2REG_FL_VAR_LHS)) + goto verbose_activate; + // log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags)); continue; @@ -2936,6 +2939,14 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1; } + // remember if this is a constant index or not + if (children[0]->children.size() && children[0]->children[0]->type == AST_RANGE && children[0]->children[0]->children.size()) { + if (children[0]->children[0]->children[0]->type == AST_CONSTANT) + mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CONST_LHS; + else + mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_VAR_LHS; + } + // remember where this is if (flags & MEM2REG_FL_INIT) { if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT)) -- cgit v1.2.3 From 5d93dcce862d281f0df495eeee755cd4bfca342d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 2 Mar 2019 09:58:20 -0800 Subject: Fix $readmem[hb] for mem2reg memories, fixes #785 Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 589c683f8..1c35516d4 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2172,6 +2172,8 @@ skip_dynamic_range_lvalue_expansion:; } newNode = readmem(str == "\\$readmemh", node_filename->bitsAsConst().decode_string(), node_memory->id2ast, start_addr, finish_addr, unconditional_init); + delete node_filename; + delete node_memory; goto apply_newNode; } @@ -3059,6 +3061,39 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, if (type == AST_FUNCTION || type == AST_TASK) return false; + if (type == AST_MEMINIT && id2ast && mem2reg_set.count(id2ast)) + { + log_assert(children[0]->type == AST_CONSTANT); + log_assert(children[1]->type == AST_CONSTANT); + log_assert(children[2]->type == AST_CONSTANT); + + int cursor = children[0]->asInt(false); + Const data = children[1]->bitsAsConst(); + int length = children[2]->asInt(false); + + if (length != 0) + { + AstNode *block = new AstNode(AST_INITIAL, new AstNode(AST_BLOCK)); + mod->children.push_back(block); + block = block->children[0]; + + int wordsz = GetSize(data) / length; + + for (int i = 0; i < length; i++) { + block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor+i, false))), mkconst_bits(data.extract(i*wordsz, wordsz).bits, false))); + block->children.back()->children[0]->str = str; + block->children.back()->children[0]->id2ast = id2ast; + block->children.back()->children[0]->was_checked = true; + } + } + + AstNode *newNode = new AstNode(AST_NONE); + newNode->cloneInto(this); + delete newNode; + + did_something = true; + } + if (type == AST_ASSIGN && block == NULL && children[0]->mem2reg_check(mem2reg_set)) { if (async_block == NULL) { -- cgit v1.2.3 From ce6695e22c7d2b8856ec5bb93a94264555aa55b5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 2 Mar 2019 10:38:13 -0800 Subject: Fix $global_clock handling vs autowire Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 1c35516d4..d0b31078a 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -941,7 +941,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } } if (current_scope.count(str) == 0) { - if (flag_autowire) { + if (flag_autowire || str == "\\$global_clock") { AstNode *auto_wire = new AstNode(AST_AUTOWIRE); auto_wire->str = str; current_ast_mod->children.push_back(auto_wire); -- cgit v1.2.3 From 3a51714451dbd5a0aec5d5167429f899950f2c4e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 2 Mar 2019 11:40:57 -0800 Subject: Fix error for wire decl in always block, fixes #763 Signed-off-by: Clifford Wolf --- frontends/ast/genrtlil.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 2d591b29d..13383845a 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -544,7 +544,11 @@ struct AST_INTERNAL::ProcessGenerator break; case AST_WIRE: - log_file_error(ast->filename, ast->linenum, "Found wire declaration in block without label!\n"); + log_file_error(ast->filename, ast->linenum, "Found reg declaration in block without label!\n"); + break; + + case AST_ASSIGN: + log_file_error(ast->filename, ast->linenum, "Found continous assignment in always/initial block!\n"); break; case AST_PARAMETER: -- cgit v1.2.3 From ae9286386de117991f887f919f5af3fac40173cc Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 2 Mar 2019 12:36:46 -0800 Subject: Only run derive on blackbox modules when ports have dynamic size Signed-off-by: Clifford Wolf --- frontends/ast/ast.h | 1 + frontends/ast/simplify.cc | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) (limited to 'frontends') diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 89f7e6e4f..8b185ff51 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -239,6 +239,7 @@ namespace AST bool has_const_only_constructs(bool &recommend_const_eval); void replace_variables(std::map &variables, AstNode *fcall); AstNode *eval_const_function(AstNode *fcall); + bool is_simple_const_expr(); // create a human-readable text representation of the AST (for debugging) void dumpAst(FILE *f, std::string indent) const; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index d0b31078a..7160c6c0f 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -328,6 +328,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, for (size_t i = 0; i < children.size(); i++) { AstNode *node = children[i]; if (node->type == AST_WIRE) { + if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) { + for (auto c : node->children[0]->children) { + if (!c->is_simple_const_expr()) { + if (attributes.count("\\dynports")) + delete attributes.at("\\dynports"); + attributes["\\dynports"] = AstNode::mkconst_int(1, true); + } + } + } if (this_wire_scope.count(node->str) > 0) { AstNode *first_node = this_wire_scope[node->str]; if (first_node->is_input && node->is_reg) @@ -3323,6 +3332,16 @@ bool AstNode::has_const_only_constructs(bool &recommend_const_eval) return false; } +bool AstNode::is_simple_const_expr() +{ + if (type == AST_IDENTIFIER) + return false; + for (auto child : children) + if (!child->is_simple_const_expr()) + return false; + return true; +} + // helper function for AstNode::eval_const_function() void AstNode::replace_variables(std::map &variables, AstNode *fcall) { -- cgit v1.2.3 From cda37830b060fd46834d8eb7af1171a1ffaee8ca Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 7 Mar 2019 10:52:44 -0800 Subject: Add hack for handling SVA labels via Verific Signed-off-by: Clifford Wolf --- frontends/verific/verificsva.cc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/verific/verificsva.cc b/frontends/verific/verificsva.cc index 6681115df..8ea8372d3 100644 --- a/frontends/verific/verificsva.cc +++ b/frontends/verific/verificsva.cc @@ -1666,7 +1666,20 @@ struct VerificSvaImporter log(" importing SVA property at root cell %s (%s) at %s:%d.\n", root->Name(), root->View()->Owner()->Name(), LineFile::GetFileName(root->Linefile()), LineFile::GetLineNo(root->Linefile())); - RTLIL::IdString root_name = module->uniquify(importer->mode_names || root->IsUserDeclared() ? RTLIL::escape_id(root->Name()) : NEW_ID); + bool is_user_declared = root->IsUserDeclared(); + + // FIXME + if (!is_user_declared) { + const char *name = root->Name(); + for (int i = 0; name[i]; i++) { + if (i ? (name[i] < '0' || name[i] > '9') : (name[i] != 'i')) { + is_user_declared = true; + break; + } + } + } + + RTLIL::IdString root_name = module->uniquify(importer->mode_names || is_user_declared ? RTLIL::escape_id(root->Name()) : NEW_ID); // parse SVA sequence into trigger signal -- cgit v1.2.3 From 22ff60850e68b5e98d4693a9a06ec688dac6d5ee Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 7 Mar 2019 11:17:32 -0800 Subject: Add support for SVA labels in read_verilog Signed-off-by: Clifford Wolf --- frontends/ast/genrtlil.cc | 12 +++-- frontends/ast/simplify.cc | 1 + frontends/verilog/verilog_parser.y | 102 ++++++++++++++++++++++++++++--------- 3 files changed, 89 insertions(+), 26 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 13383845a..d7da6fb40 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -1413,10 +1413,16 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (GetSize(en) != 1) en = current_module->ReduceBool(NEW_ID, en); - std::stringstream sstr; - sstr << celltype << "$" << filename << ":" << linenum << "$" << (autoidx++); + IdString cellname; + if (str.empty()) { + std::stringstream sstr; + sstr << celltype << "$" << filename << ":" << linenum << "$" << (autoidx++); + cellname = sstr.str(); + } else { + cellname = str; + } - RTLIL::Cell *cell = current_module->addCell(sstr.str(), celltype); + RTLIL::Cell *cell = current_module->addCell(cellname, celltype); cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); for (auto &attr : attributes) { diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 7160c6c0f..bdd8ccb17 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1511,6 +1511,7 @@ skip_dynamic_range_lvalue_expansion:; newNode->children.push_back(assign_en); AstNode *assertnode = new AstNode(type); + assertnode->str = str; assertnode->children.push_back(new AstNode(AST_IDENTIFIER)); assertnode->children.push_back(new AstNode(AST_IDENTIFIER)); assertnode->children[0]->str = id_check; diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index a6718b020..2258f3f6f 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -126,7 +126,7 @@ static void free_attr(std::map *al) %type range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int %type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list -%type opt_label tok_prim_wrapper hierarchical_id +%type opt_label opt_stmt_label tok_prim_wrapper hierarchical_id %type opt_signed opt_property unique_case_attr %type attr case_attr @@ -1338,7 +1338,12 @@ opt_property: }; opt_stmt_label: - TOK_ID ':' | /* empty */; + TOK_ID ':' { + $$ = $1; + } | + /* empty */ { + $$ = NULL; + }; modport_stmt: TOK_MODPORT TOK_ID { @@ -1377,53 +1382,104 @@ modport_type_token: assert: opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' { - if (noassert_mode) + if (noassert_mode) { delete $5; - else - ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5)); + } else { + AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5); + if ($1 != nullptr) + node->str = *$1; + ast_stack.back()->children.push_back(node); + } + if ($1 != nullptr) + delete $1; } | opt_stmt_label TOK_ASSUME opt_property '(' expr ')' ';' { - if (noassume_mode) + if (noassume_mode) { delete $5; - else - ast_stack.back()->children.push_back(new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5)); + } else { + AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5); + if ($1 != nullptr) + node->str = *$1; + ast_stack.back()->children.push_back(node); + } + if ($1 != nullptr) + delete $1; } | opt_stmt_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' { - if (noassert_mode) + if (noassert_mode) { delete $6; - else - ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6)); + } else { + AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6); + if ($1 != nullptr) + node->str = *$1; + ast_stack.back()->children.push_back(node); + } + if ($1 != nullptr) + delete $1; } | opt_stmt_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' { - if (noassume_mode) + if (noassume_mode) { delete $6; - else - ast_stack.back()->children.push_back(new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6)); + } else { + AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6); + if ($1 != nullptr) + node->str = *$1; + ast_stack.back()->children.push_back(node); + } + if ($1 != nullptr) + delete $1; } | opt_stmt_label TOK_COVER opt_property '(' expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5)); + AstNode *node = new AstNode(AST_COVER, $5); + if ($1 != nullptr) { + node->str = *$1; + delete $1; + } + ast_stack.back()->children.push_back(node); } | opt_stmt_label TOK_COVER opt_property '(' ')' ';' { - ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false))); + AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); + if ($1 != nullptr) { + node->str = *$1; + delete $1; + } + ast_stack.back()->children.push_back(node); } | opt_stmt_label TOK_COVER ';' { - ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false))); + AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); + if ($1 != nullptr) { + node->str = *$1; + delete $1; + } + ast_stack.back()->children.push_back(node); } | opt_stmt_label TOK_RESTRICT opt_property '(' expr ')' ';' { - if (norestrict_mode) + if (norestrict_mode) { delete $5; - else - ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); + } else { + AstNode *node = new AstNode(AST_ASSUME, $5); + if ($1 != nullptr) + node->str = *$1; + ast_stack.back()->children.push_back(node); + } if (!$3) log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); + if ($1 != nullptr) + delete $1; } | opt_stmt_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { - if (norestrict_mode) + if (norestrict_mode) { delete $6; - else - ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); + } else { + AstNode *node = new AstNode(AST_FAIR, $6); + if ($1 != nullptr) + node->str = *$1; + ast_stack.back()->children.push_back(node); + } if (!$3) log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); + if ($1 != nullptr) + delete $1; }; assert_property: -- cgit v1.2.3 From a330c6836318d43d52cda68959f2b86c2b2ede9c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 7 Mar 2019 22:44:37 -0800 Subject: Fix handling of task output ports in clocked always blocks, fixes #857 Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 7160c6c0f..d0274cf78 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2224,6 +2224,8 @@ skip_dynamic_range_lvalue_expansion:; std::map replace_rules; vector added_mod_children; dict wire_cache; + vector new_stmts; + vector output_assignments; if (current_block == NULL) { @@ -2348,8 +2350,8 @@ skip_dynamic_range_lvalue_expansion:; wire->port_id = 0; wire->is_input = false; wire->is_output = false; - if (!child->is_output) - wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false); + wire->is_reg = true; + wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false); wire_cache[child->str] = wire; current_ast_mod->children.push_back(wire); @@ -2371,13 +2373,10 @@ skip_dynamic_range_lvalue_expansion:; new AstNode(AST_ASSIGN_EQ, wire_id, arg) : new AstNode(AST_ASSIGN_EQ, arg, wire_id); assign->children[0]->was_checked = true; - - for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) { - if (*it != current_block_child) - continue; - current_block->children.insert(it, assign); - break; - } + if (child->is_input) + new_stmts.push_back(assign); + else + output_assignments.push_back(assign); } } @@ -2391,14 +2390,18 @@ skip_dynamic_range_lvalue_expansion:; { AstNode *stmt = child->clone(); stmt->replace_ids(prefix, replace_rules); + new_stmts.push_back(stmt); + } - for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) { - if (*it != current_block_child) - continue; - current_block->children.insert(it, stmt); - break; - } + new_stmts.insert(new_stmts.end(), output_assignments.begin(), output_assignments.end()); + + for (auto it = current_block->children.begin(); ; it++) { + log_assert(it != current_block->children.end()); + if (*it == current_block_child) { + current_block->children.insert(it, new_stmts.begin(), new_stmts.end()); + break; } + } replace_fcall_with_id: if (type == AST_FCALL) { -- cgit v1.2.3 From 1dc060f32eea0df2ba45770365060251163b2857 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 9 Mar 2019 00:43:50 +0000 Subject: Fix spelling --- frontends/verific/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/verific/README b/frontends/verific/README index c76cdd637..89584f2e8 100644 --- a/frontends/verific/README +++ b/frontends/verific/README @@ -21,7 +21,7 @@ Then run in the following command in this directory: sby -f example.sby -This will generate approximately one page of text outpout. The last lines +This will generate approximately one page of text output. The last lines should be something like this: SBY [example] summary: Elapsed clock time [H:MM:SS (secs)]: 0:00:00 (0) -- cgit v1.2.3 From 2aa3903757642616f38d1069e1b706fcbf3168c4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 9 Mar 2019 01:54:01 +0000 Subject: Add -chparam option to verific command --- frontends/verific/verific.cc | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 9f52ffdc2..4ba96d251 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1855,6 +1855,12 @@ struct VerificPass : public Pass { log(" -autocover\n"); log(" Generate automatic cover statements for all asserts\n"); log("\n"); + log(" -chparam name value \n"); + log(" Elaborate the specified top modules (all modules when -all given) using\n"); + log(" this parameter value, for modules where this parameter exists. This option\n"); + log(" can be specified multiple times to override multiple parameters.\n"); + log(" String values must be passed in double quotes (\").\n"); + log("\n"); log(" -v, -vv\n"); log(" Verbose log messages. (-vv is even more verbose than -v.)\n"); log("\n"); @@ -2109,6 +2115,7 @@ struct VerificPass : public Pass { bool mode_autocover = false; bool flatten = false, extnets = false; string dumpfile; + Map parameters(STRING_HASH); for (argidx++; argidx < GetSize(args); argidx++) { if (args[argidx] == "-all") { @@ -2147,6 +2154,15 @@ struct VerificPass : public Pass { mode_autocover = true; continue; } + if (args[argidx] == "-chparam" && argidx+2 < GetSize(args)) { + const std::string &key = args[++argidx]; + const std::string &value = args[++argidx]; + unsigned new_insertion = parameters.Insert(key.c_str(), value.c_str(), + 1 /* force_overwrite */); + if (!new_insertion) + log_warning_noprefix("-chparam %s already specified: overwriting.\n", key.c_str()); + continue; + } if (args[argidx] == "-V") { mode_verific = true; continue; @@ -2180,7 +2196,7 @@ struct VerificPass : public Pass { if (vhdl_lib) vhdl_libs.InsertLast(vhdl_lib); if (veri_lib) veri_libs.InsertLast(veri_lib); - Array *netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs); + Array *netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs, ¶meters); Netlist *nl; int i; @@ -2217,7 +2233,7 @@ struct VerificPass : public Pass { } log("Running hier_tree::Elaborate().\n"); - Array *netlists = hier_tree::Elaborate(&veri_modules, &vhdl_units); + Array *netlists = hier_tree::Elaborate(&veri_modules, &vhdl_units, ¶meters); Netlist *nl; int i; -- cgit v1.2.3 From ee013fba54f8bca0940143f655f5b4ad3d7b7b96 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 9 Mar 2019 01:56:16 +0000 Subject: Update help message for -chparam --- frontends/verific/verific.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 4ba96d251..c412cd3a3 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1857,7 +1857,8 @@ struct VerificPass : public Pass { log("\n"); log(" -chparam name value \n"); log(" Elaborate the specified top modules (all modules when -all given) using\n"); - log(" this parameter value, for modules where this parameter exists. This option\n"); + log(" this parameter value. Modules on which this parameter does not exist will\n"); + log(" cause Verific to produce a VERI-1928 or VHDL-1676 message. This option\n"); log(" can be specified multiple times to override multiple parameters.\n"); log(" String values must be passed in double quotes (\").\n"); log("\n"); -- cgit v1.2.3 From e7a34d342ed1dd01074acdafca4f8f5557f8150f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 8 Mar 2019 22:53:58 -0800 Subject: Also add support for labels on sva module items, fixes #699 Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_lexer.l | 57 +++++++++++++++++++-- frontends/verilog/verilog_parser.y | 100 ++++++++++++++++++++++--------------- 2 files changed, 113 insertions(+), 44 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 1b1873e24..e51a12f76 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -189,10 +189,57 @@ YOSYS_NAMESPACE_END "always_ff" { SV_KEYWORD(TOK_ALWAYS); } "always_latch" { SV_KEYWORD(TOK_ALWAYS); } -"assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } -"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } -"cover" { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); } -"restrict" { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); } + /* parse labels on assert, assume, cover, and restrict right here because it's insanley complex + to do it in the parser (because we force the parser too early to reduce when parsing cells..) */ +([a-zA-Z_$][a-zA-Z0-9_$]*[ \t\r\n]*:[ \t\r\n]*)?(assert|assume|cover|restrict)/[^a-zA-Z0-9_$\.] { + frontend_verilog_yylval.string = new std::string(yytext); + auto &str = *frontend_verilog_yylval.string; + std::string keyword; + int cursor = 0; + + while (1) { + if (cursor == GetSize(str)) { + keyword = str; + delete frontend_verilog_yylval.string; + frontend_verilog_yylval.string = nullptr; + goto sva_without_label; + } + char c = str[cursor]; + if (c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != ':') { + cursor++; + continue; + } + + keyword = str.substr(cursor); + str = "\\" + str.substr(0, cursor); + break; + } + + cursor = 0; + while (1) { + log_assert(cursor < GetSize(keyword)); + char c = keyword[cursor]; + if (c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != ':') { + keyword = keyword.substr(cursor); + break; + } + cursor++; + } + + if (keyword == "assert") { return TOK_ASSERT; } + else if (keyword == "assume") { return TOK_ASSUME; } + else if (keyword == "cover") { return TOK_COVER; } + else if (keyword == "restrict") { return TOK_RESTRICT; } + else log_abort(); + +sva_without_label: + if (keyword == "assert") { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } + else if (keyword == "assume") { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } + else if (keyword == "cover") { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); } + else if (keyword == "restrict") { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); } + else log_abort(); +} + "property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); } "rand" { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); } "const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); } @@ -303,7 +350,7 @@ supply1 { return TOK_SUPPLY1; } [a-zA-Z_$][a-zA-Z0-9_$\.]* { frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); - return TOK_ID; + return TOK_ID; } "/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" { diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 2258f3f6f..649dd384f 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -106,6 +106,7 @@ static void free_attr(std::map *al) } %token TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE +%token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER %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 @@ -119,14 +120,13 @@ static void free_attr(std::map *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_ASSUME -%token TOK_RESTRICT TOK_COVER TOK_PROPERTY TOK_ENUM TOK_TYPEDEF +%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_PROPERTY TOK_ENUM TOK_TYPEDEF %token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY %token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY %type range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int %type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list -%type opt_label opt_stmt_label tok_prim_wrapper hierarchical_id +%type opt_label tok_prim_wrapper hierarchical_id %type opt_signed opt_property unique_case_attr %type attr case_attr @@ -1337,14 +1337,6 @@ opt_property: $$ = false; }; -opt_stmt_label: - TOK_ID ':' { - $$ = $1; - } | - /* empty */ { - $$ = NULL; - }; - modport_stmt: TOK_MODPORT TOK_ID { AstNode *modport = new AstNode(AST_MODPORT); @@ -1381,11 +1373,11 @@ modport_type_token: TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;} assert: - opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' { + TOK_ASSERT opt_property '(' expr ')' ';' { if (noassert_mode) { - delete $5; + delete $4; } else { - AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5); + AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -1393,11 +1385,11 @@ assert: if ($1 != nullptr) delete $1; } | - opt_stmt_label TOK_ASSUME opt_property '(' expr ')' ';' { + TOK_ASSUME opt_property '(' expr ')' ';' { if (noassume_mode) { - delete $5; + delete $4; } else { - AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5); + AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $4); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -1405,11 +1397,11 @@ assert: if ($1 != nullptr) delete $1; } | - opt_stmt_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' { + TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' { if (noassert_mode) { - delete $6; + delete $5; } else { - AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6); + AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -1417,11 +1409,11 @@ assert: if ($1 != nullptr) delete $1; } | - opt_stmt_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' { + TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' { if (noassume_mode) { - delete $6; + delete $5; } else { - AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6); + AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $5); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -1429,15 +1421,15 @@ assert: if ($1 != nullptr) delete $1; } | - opt_stmt_label TOK_COVER opt_property '(' expr ')' ';' { - AstNode *node = new AstNode(AST_COVER, $5); + TOK_COVER opt_property '(' expr ')' ';' { + AstNode *node = new AstNode(AST_COVER, $4); if ($1 != nullptr) { node->str = *$1; delete $1; } ast_stack.back()->children.push_back(node); } | - opt_stmt_label TOK_COVER opt_property '(' ')' ';' { + TOK_COVER opt_property '(' ')' ';' { AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); if ($1 != nullptr) { node->str = *$1; @@ -1445,7 +1437,7 @@ assert: } ast_stack.back()->children.push_back(node); } | - opt_stmt_label TOK_COVER ';' { + TOK_COVER ';' { AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); if ($1 != nullptr) { node->str = *$1; @@ -1453,30 +1445,30 @@ assert: } ast_stack.back()->children.push_back(node); } | - opt_stmt_label TOK_RESTRICT opt_property '(' expr ')' ';' { + TOK_RESTRICT opt_property '(' expr ')' ';' { if (norestrict_mode) { - delete $5; + delete $4; } else { - AstNode *node = new AstNode(AST_ASSUME, $5); + AstNode *node = new AstNode(AST_ASSUME, $4); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); } - if (!$3) + if (!$2) log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); if ($1 != nullptr) delete $1; } | - opt_stmt_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { + TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { if (norestrict_mode) { - delete $6; + delete $5; } else { - AstNode *node = new AstNode(AST_FAIR, $6); + AstNode *node = new AstNode(AST_FAIR, $5); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); } - if (!$3) + if (!$2) log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); if ($1 != nullptr) delete $1; @@ -1485,30 +1477,60 @@ assert: assert_property: TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' { ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4)); + if ($1 != nullptr) { + ast_stack.back()->children.back()->str = *$1; + delete $1; + } } | TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' { ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4)); + if ($1 != nullptr) { + ast_stack.back()->children.back()->str = *$1; + delete $1; + } } | TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5)); + if ($1 != nullptr) { + ast_stack.back()->children.back()->str = *$1; + delete $1; + } } | TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5)); + if ($1 != nullptr) { + ast_stack.back()->children.back()->str = *$1; + delete $1; + } } | TOK_COVER TOK_PROPERTY '(' expr ')' ';' { ast_stack.back()->children.push_back(new AstNode(AST_COVER, $4)); + if ($1 != nullptr) { + ast_stack.back()->children.back()->str = *$1; + delete $1; + } } | TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' { - if (norestrict_mode) + if (norestrict_mode) { delete $4; - else + } else { ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4)); + if ($1 != nullptr) { + ast_stack.back()->children.back()->str = *$1; + delete $1; + } + } } | TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { - if (norestrict_mode) + if (norestrict_mode) { delete $5; - else + } else { ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5)); + if ($1 != nullptr) { + ast_stack.back()->children.back()->str = *$1; + delete $1; + } + } }; simple_behavioral_stmt: -- cgit v1.2.3 From b02d9c2634de0898b2c483c438ba56540e0f3f69 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 10 Mar 2019 16:27:18 -0700 Subject: Fix handling of cases that look like sva labels, fixes #862 Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_lexer.l | 59 ++++------------------- frontends/verilog/verilog_parser.y | 99 +++++++++++++++++++++----------------- 2 files changed, 66 insertions(+), 92 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index e51a12f76..6ef38252a 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -189,57 +189,18 @@ YOSYS_NAMESPACE_END "always_ff" { SV_KEYWORD(TOK_ALWAYS); } "always_latch" { SV_KEYWORD(TOK_ALWAYS); } - /* parse labels on assert, assume, cover, and restrict right here because it's insanley complex - to do it in the parser (because we force the parser too early to reduce when parsing cells..) */ -([a-zA-Z_$][a-zA-Z0-9_$]*[ \t\r\n]*:[ \t\r\n]*)?(assert|assume|cover|restrict)/[^a-zA-Z0-9_$\.] { - frontend_verilog_yylval.string = new std::string(yytext); - auto &str = *frontend_verilog_yylval.string; - std::string keyword; - int cursor = 0; - - while (1) { - if (cursor == GetSize(str)) { - keyword = str; - delete frontend_verilog_yylval.string; - frontend_verilog_yylval.string = nullptr; - goto sva_without_label; - } - char c = str[cursor]; - if (c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != ':') { - cursor++; - continue; - } - - keyword = str.substr(cursor); - str = "\\" + str.substr(0, cursor); - break; - } - - cursor = 0; - while (1) { - log_assert(cursor < GetSize(keyword)); - char c = keyword[cursor]; - if (c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != ':') { - keyword = keyword.substr(cursor); - break; - } - cursor++; - } - - if (keyword == "assert") { return TOK_ASSERT; } - else if (keyword == "assume") { return TOK_ASSUME; } - else if (keyword == "cover") { return TOK_COVER; } - else if (keyword == "restrict") { return TOK_RESTRICT; } - else log_abort(); - -sva_without_label: - if (keyword == "assert") { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } - else if (keyword == "assume") { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } - else if (keyword == "cover") { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); } - else if (keyword == "restrict") { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); } - else log_abort(); + /* use special token for labels on assert, assume, cover, and restrict because it's insanley complex + to fix parsing of cells otherwise. (the current cell parser forces a reduce very early to update some + global state.. its a mess) */ +[a-zA-Z_$][a-zA-Z0-9_$]*/[ \t\r\n]*:[ \t\r\n]*(assert|assume|cover|restrict)[^a-zA-Z0-9_$\.] { + frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); + return TOK_SVA_LABEL; } +"assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } +"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } +"cover" { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); } +"restrict" { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); } "property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); } "rand" { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); } "const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 649dd384f..52685f637 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -105,8 +105,8 @@ static void free_attr(std::map *al) bool boolean; } -%token TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE -%token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER +%token TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE TOK_SVA_LABEL +%token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER %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 @@ -126,7 +126,7 @@ static void free_attr(std::map *al) %type range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int %type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list -%type opt_label tok_prim_wrapper hierarchical_id +%type opt_label opt_sva_label tok_prim_wrapper hierarchical_id %type opt_signed opt_property unique_case_attr %type attr case_attr @@ -1329,6 +1329,14 @@ opt_label: $$ = NULL; }; +opt_sva_label: + TOK_SVA_LABEL ':' { + $$ = $1; + } | + /* empty */ { + $$ = NULL; + }; + opt_property: TOK_PROPERTY { $$ = true; @@ -1373,11 +1381,11 @@ modport_type_token: TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;} assert: - TOK_ASSERT opt_property '(' expr ')' ';' { + opt_sva_label TOK_ASSERT opt_property '(' expr ')' ';' { if (noassert_mode) { - delete $4; + delete $5; } else { - AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4); + AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -1385,11 +1393,11 @@ assert: if ($1 != nullptr) delete $1; } | - TOK_ASSUME opt_property '(' expr ')' ';' { + opt_sva_label TOK_ASSUME opt_property '(' expr ')' ';' { if (noassume_mode) { - delete $4; + delete $5; } else { - AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $4); + AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -1397,11 +1405,11 @@ assert: if ($1 != nullptr) delete $1; } | - TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' { + opt_sva_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' { if (noassert_mode) { - delete $5; + delete $6; } else { - AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5); + AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -1409,11 +1417,11 @@ assert: if ($1 != nullptr) delete $1; } | - TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' { + opt_sva_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' { if (noassume_mode) { - delete $5; + delete $6; } else { - AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $5); + AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); @@ -1421,15 +1429,15 @@ assert: if ($1 != nullptr) delete $1; } | - TOK_COVER opt_property '(' expr ')' ';' { - AstNode *node = new AstNode(AST_COVER, $4); + opt_sva_label TOK_COVER opt_property '(' expr ')' ';' { + AstNode *node = new AstNode(AST_COVER, $5); if ($1 != nullptr) { node->str = *$1; delete $1; } ast_stack.back()->children.push_back(node); } | - TOK_COVER opt_property '(' ')' ';' { + opt_sva_label TOK_COVER opt_property '(' ')' ';' { AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); if ($1 != nullptr) { node->str = *$1; @@ -1437,7 +1445,7 @@ assert: } ast_stack.back()->children.push_back(node); } | - TOK_COVER ';' { + opt_sva_label TOK_COVER ';' { AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false)); if ($1 != nullptr) { node->str = *$1; @@ -1445,87 +1453,87 @@ assert: } ast_stack.back()->children.push_back(node); } | - TOK_RESTRICT opt_property '(' expr ')' ';' { + opt_sva_label TOK_RESTRICT opt_property '(' expr ')' ';' { if (norestrict_mode) { - delete $4; + delete $5; } else { - AstNode *node = new AstNode(AST_ASSUME, $4); + AstNode *node = new AstNode(AST_ASSUME, $5); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); } - if (!$2) + if (!$3) log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); if ($1 != nullptr) delete $1; } | - TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { + opt_sva_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { if (norestrict_mode) { - delete $5; + delete $6; } else { - AstNode *node = new AstNode(AST_FAIR, $5); + AstNode *node = new AstNode(AST_FAIR, $6); if ($1 != nullptr) node->str = *$1; ast_stack.back()->children.push_back(node); } - if (!$2) + if (!$3) log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n"); if ($1 != nullptr) delete $1; }; assert_property: - TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4)); + opt_sva_label TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; } } | - TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4)); + opt_sva_label TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; } } | - TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5)); + opt_sva_label TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; } } | - TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5)); + opt_sva_label TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; } } | - TOK_COVER TOK_PROPERTY '(' expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(AST_COVER, $4)); + opt_sva_label TOK_COVER TOK_PROPERTY '(' expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; } } | - TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' { + opt_sva_label TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' { if (norestrict_mode) { - delete $4; + delete $5; } else { - ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4)); + ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; } } } | - TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { + opt_sva_label TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { if (norestrict_mode) { - delete $5; + delete $6; } else { - ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5)); + ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); if ($1 != nullptr) { ast_stack.back()->children.back()->str = *$1; delete $1; @@ -1748,6 +1756,11 @@ case_expr_list: TOK_DEFAULT { ast_stack.back()->children.push_back(new AstNode(AST_DEFAULT)); } | + TOK_SVA_LABEL { + ast_stack.back()->children.push_back(new AstNode(AST_IDENTIFIER)); + ast_stack.back()->children.back()->str = *$1; + delete $1; + } | expr { ast_stack.back()->children.push_back($1); } | -- cgit v1.2.3 From ab5b50ae3c9e63fe3da3ae0451500c1cb5be1743 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 12 Mar 2019 20:09:47 +0100 Subject: Only set MEM2REG_FL_CONST_LHS/MEM2REG_FL_VAR_LHS for non-init writes, fixes #867 Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index ae7dec88d..f747a07cd 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2954,12 +2954,14 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1; } - // remember if this is a constant index or not - if (children[0]->children.size() && children[0]->children[0]->type == AST_RANGE && children[0]->children[0]->children.size()) { - if (children[0]->children[0]->children[0]->type == AST_CONSTANT) - mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CONST_LHS; - else - mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_VAR_LHS; + // for proper (non-init) writes: remember if this is a constant index or not + if ((flags & MEM2REG_FL_INIT) == 0) { + if (children[0]->children.size() && children[0]->children[0]->type == AST_RANGE && children[0]->children[0]->children.size()) { + if (children[0]->children[0]->children[0]->type == AST_CONSTANT) + mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CONST_LHS; + else + mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_VAR_LHS; + } } // remember where this is -- cgit v1.2.3 From a4ddc569b4c0e51e89317ade8c4183f41acc1cb5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 12 Mar 2019 20:10:55 +0100 Subject: Remove outdated "blocking assignment to memory" warning Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index f747a07cd..de300bbce 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -50,7 +50,6 @@ using namespace AST_INTERNAL; bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param) { static int recursion_counter = 0; - static pair last_blocking_assignment_warn; static bool deep_recursion_warning = false; if (recursion_counter++ == 1000 && deep_recursion_warning) { @@ -72,7 +71,6 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (stage == 0) { log_assert(type == AST_MODULE || type == AST_INTERFACE); - last_blocking_assignment_warn = pair(); deep_recursion_warning = true; while (simplify(const_fold, at_zero, in_lvalue, 1, width_hint, sign_hint, in_param)) { } @@ -1592,14 +1590,6 @@ skip_dynamic_range_lvalue_expansion:; sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++); std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN"; - if (type == AST_ASSIGN_EQ) { - pair this_blocking_assignment_warn(filename, linenum); - if (this_blocking_assignment_warn != last_blocking_assignment_warn) - log_warning("Blocking assignment to memory in line %s:%d is handled like a non-blocking assignment.\n", - filename.c_str(), linenum); - last_blocking_assignment_warn = this_blocking_assignment_warn; - } - int mem_width, mem_size, addr_bits; bool mem_signed = children[0]->id2ast->is_signed; children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits); -- cgit v1.2.3 From d25a0c8adeb421246732539b19738a8e68fc1315 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 12 Mar 2019 20:12:02 +0100 Subject: Improve handling of memories used in mem index expressions on LHS of an assignment Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index de300bbce..1c9932ee0 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2918,7 +2918,7 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg dict &mem2reg_candidates, dict &proc_flags, uint32_t &flags) { uint32_t children_flags = 0; - int ignore_children_counter = 0; + int lhs_children_counter = 0; if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) { @@ -2966,7 +2966,7 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg } } - ignore_children_counter = 1; + lhs_children_counter = 1; } if (type == AST_IDENTIFIER && id2ast && id2ast->type == AST_MEMORY) @@ -3009,12 +3009,23 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg log_assert((flags & ~0x000000ff) == 0); for (auto child : children) - if (ignore_children_counter > 0) - ignore_children_counter--; - else if (proc_flags_p) + { + if (lhs_children_counter > 0) { + lhs_children_counter--; + if (child->children.size() && child->children[0]->type == AST_RANGE && child->children[0]->children.size()) { + for (auto c : child->children[0]->children) { + if (proc_flags_p) + c->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags); + else + c->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags); + } + } + } else + if (proc_flags_p) child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags); else child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags); + } flags &= ~children_flags | backup_flags; -- cgit v1.2.3 From 17caaa3fa898e39d1dbcfd8b92750a9d713a24af Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 14 Mar 2019 17:51:21 +0100 Subject: Improve handling of "full_case" attributes Signed-off-by: Clifford Wolf --- frontends/ast/genrtlil.cc | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'frontends') diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index d7da6fb40..b3a2a84be 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -525,7 +525,16 @@ struct AST_INTERNAL::ProcessGenerator } if (last_generated_case != NULL && ast->get_bool_attribute("\\full_case") && default_case == NULL) { + #if 0 + // this is a valid transformation, but as optimization it is premature. + // better: add a default case that assigns 'x' to everything, and let later + // optimizations take care of the rest last_generated_case->compare.clear(); + #else + default_case = new RTLIL::CaseRule; + addChunkActions(default_case->actions, this_case_eq_ltemp, SigSpec(State::Sx, GetSize(this_case_eq_rvalue))); + sw->cases.push_back(default_case); + #endif } else { if (default_case == NULL) { default_case = new RTLIL::CaseRule; -- cgit v1.2.3 From a5f4b836376e1457847da4946c1e12d2d41dc4f4 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Mon, 18 Mar 2019 20:34:21 -0400 Subject: fix local name resolution in prefix constructs --- frontends/ast/simplify.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 1c9932ee0..d525c6b8a 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2863,7 +2863,11 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma for (size_t i = 0; i < children.size(); i++) { AstNode *child = children[i]; - if (child->type != AST_FUNCTION && child->type != AST_TASK && child->type != AST_PREFIX) + // AST_PREFIX member names should not be prefixed; a nested AST_PREFIX + // still needs to recursed-into + if (type == AST_PREFIX && i == 1 && child->type == AST_IDENTIFIER) + continue; + if (child->type != AST_FUNCTION && child->type != AST_TASK) child->expand_genblock(index_var, prefix, name_map); } -- cgit v1.2.3 From 3e89cf68bdc4e9eeb55bd9450121f421bcdc554a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 08:52:06 -0700 Subject: Add author name --- frontends/aiger/aigerparse.h | 1 + 1 file changed, 1 insertion(+) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index 39a77bd93..c49cd152d 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -2,6 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf + * Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above -- cgit v1.2.3 From 9b0e7af6d7c84d9b252acbe0fbbf596c75fc1498 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 21 Mar 2019 20:52:29 +0100 Subject: Improve read_verilog debug output capabilities Signed-off-by: Clifford Wolf --- frontends/ast/ast.cc | 26 +++++++++++++++++--------- frontends/ast/ast.h | 2 +- frontends/verilog/verilog_frontend.cc | 29 ++++++++++++++++++++++++----- 3 files changed, 42 insertions(+), 15 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 5a1bae7a7..0442ea0db 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -45,7 +45,7 @@ namespace AST { // instantiate global variables (private API) namespace AST_INTERNAL { - bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog, flag_dump_rtlil, flag_nolatches, flag_nomeminit; + bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches, flag_nomeminit; bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire; AstNode *current_ast, *current_ast_mod; std::map current_scope; @@ -562,7 +562,8 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const case AST_CONCAT: fprintf(f, "{"); - for (auto child : children) { + for (int i = GetSize(children)-1; i >= 0; i--) { + auto child = children[i]; if (!first) fprintf(f, ", "); child->dumpVlog(f, ""); @@ -926,23 +927,28 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast ast_before_simplify = ast->clone(); if (flag_dump_ast1) { - log("Dumping Verilog AST before simplification:\n"); + log("Dumping AST before simplification:\n"); ast->dumpAst(NULL, " "); log("--- END OF AST DUMP ---\n"); } + if (flag_dump_vlog1) { + log("Dumping Verilog AST before simplification:\n"); + ast->dumpVlog(NULL, " "); + log("--- END OF AST DUMP ---\n"); + } if (!defer) { while (ast->simplify(!flag_noopt, false, false, 0, -1, false, false)) { } if (flag_dump_ast2) { - log("Dumping Verilog AST after simplification:\n"); + log("Dumping AST after simplification:\n"); ast->dumpAst(NULL, " "); log("--- END OF AST DUMP ---\n"); } - if (flag_dump_vlog) { - log("Dumping Verilog AST (as requested by dump_vlog option):\n"); + if (flag_dump_vlog2) { + log("Dumping Verilog AST after simplification:\n"); ast->dumpVlog(NULL, " "); log("--- END OF AST DUMP ---\n"); } @@ -1016,14 +1022,15 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast } // create AstModule instances for all modules in the AST tree and add them to 'design' -void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog, bool dump_rtlil, +void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil, bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire) { current_ast = ast; flag_dump_ast1 = dump_ast1; flag_dump_ast2 = dump_ast2; flag_no_dump_ptr = no_dump_ptr; - flag_dump_vlog = dump_vlog; + flag_dump_vlog1 = dump_vlog1; + flag_dump_vlog2 = dump_vlog2; flag_dump_rtlil = dump_rtlil; flag_nolatches = nolatches; flag_nomeminit = nomeminit; @@ -1357,7 +1364,8 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict Date: Thu, 21 Mar 2019 22:20:16 +0100 Subject: Improve "read_verilog -dump_vlog[12]" handling of upto ranges Signed-off-by: Clifford Wolf --- frontends/ast/ast.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 0442ea0db..d48996167 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -431,9 +431,12 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const break; case AST_RANGE: - if (range_valid) - fprintf(f, "[%d:%d]", range_left, range_right); - else { + if (range_valid) { + if (range_swapped) + fprintf(f, "[%d:%d]", range_right, range_left); + else + fprintf(f, "[%d:%d]", range_left, range_right); + } else { for (auto child : children) { fprintf(f, "%c", first ? '[' : ':'); child->dumpVlog(f, ""); -- cgit v1.2.3 From 638be461c3a6d33aa294700249ee0bc27da69403 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 21 Mar 2019 22:19:17 +0100 Subject: Fix mem2reg handling of memories with upto data ports, fixes #888 Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index d525c6b8a..63b71b800 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -138,9 +138,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int mem_width, mem_size, addr_bits; node->meminfo(mem_width, mem_size, addr_bits); + int data_range_left = node->children[0]->range_left; + int data_range_right = node->children[0]->range_right; + + if (node->children[0]->range_swapped) + std::swap(data_range_left, data_range_right); + for (int i = 0; i < mem_size; i++) { AstNode *reg = new AstNode(AST_WIRE, new AstNode(AST_RANGE, - mkconst_int(mem_width-1, true), mkconst_int(0, true))); + mkconst_int(data_range_left, true), mkconst_int(data_range_right, true))); reg->str = stringf("%s[%d]", node->str.c_str(), i); reg->is_reg = true; reg->is_signed = node->is_signed; @@ -976,6 +982,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int data_range_left = id2ast->children[0]->range_left; int data_range_right = id2ast->children[0]->range_right; + if (id2ast->children[0]->range_swapped) + std::swap(data_range_left, data_range_right); + std::stringstream sstr; sstr << "$mem2bits$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++); std::string wire_id = sstr.str(); -- cgit v1.2.3 From c863796e9ff91c76f0f8679b6871b8ffcb75edb6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 26 Mar 2019 14:17:46 +0100 Subject: Fix "verific -extnets" for more complex situations Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 86 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 15 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index c412cd3a3..95b7d3586 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1619,30 +1619,35 @@ struct VerificExtNets int portname_cnt = 0; // a map from Net to the same Net one level up in the design hierarchy - std::map net_level_up; + std::map net_level_up_drive_up; + std::map net_level_up_drive_down; - Net *get_net_level_up(Net *net) + Net *route_up(Net *net, bool drive_up, Net *final_net = nullptr) { + auto &net_level_up = drive_up ? net_level_up_drive_up : net_level_up_drive_down; + if (net_level_up.count(net) == 0) { Netlist *nl = net->Owner(); // Simply return if Netlist is not unique - if (nl->NumOfRefs() != 1) - return net; + log_assert(nl->NumOfRefs() == 1); Instance *up_inst = (Instance*)nl->GetReferences()->GetLast(); Netlist *up_nl = up_inst->Owner(); // create new Port string name = stringf("___extnets_%d", portname_cnt++); - Port *new_port = new Port(name.c_str(), DIR_OUT); + Port *new_port = new Port(name.c_str(), drive_up ? DIR_OUT : DIR_IN); nl->Add(new_port); net->Connect(new_port); // create new Net in up Netlist - Net *new_net = new Net(name.c_str()); - up_nl->Add(new_net); + Net *new_net = final_net; + if (new_net == nullptr || new_net->Owner() != up_nl) { + new_net = new Net(name.c_str()); + up_nl->Add(new_net); + } up_inst->Connect(new_port, new_net); net_level_up[net] = new_net; @@ -1651,6 +1656,39 @@ struct VerificExtNets return net_level_up.at(net); } + Net *route_up(Net *net, bool drive_up, Netlist *dest, Net *final_net = nullptr) + { + while (net->Owner() != dest) + net = route_up(net, drive_up, final_net); + if (final_net != nullptr) + log_assert(net == final_net); + return net; + } + + Netlist *find_common_ancestor(Netlist *A, Netlist *B) + { + std::set ancestors_of_A; + + Netlist *cursor = A; + while (1) { + ancestors_of_A.insert(cursor); + if (cursor->NumOfRefs() != 1) + break; + cursor = ((Instance*)cursor->GetReferences()->GetLast())->Owner(); + } + + cursor = B; + while (1) { + if (ancestors_of_A.count(cursor)) + return cursor; + if (cursor->NumOfRefs() != 1) + break; + cursor = ((Instance*)cursor->GetReferences()->GetLast())->Owner(); + } + + log_error("No common ancestor found between %s and %s.\n", get_full_netlist_name(A).c_str(), get_full_netlist_name(B).c_str()); + } + void run(Netlist *nl) { MapIter mi, mi2; @@ -1674,19 +1712,37 @@ struct VerificExtNets if (verific_verbose) log("Fixing external net reference on port %s.%s.%s:\n", get_full_netlist_name(nl).c_str(), inst->Name(), port->Name()); - while (net->IsExternalTo(nl)) - { - Net *newnet = get_net_level_up(net); - if (newnet == net) break; + Netlist *ext_nl = net->Owner(); + if (verific_verbose) + log(" external net owner: %s\n", get_full_netlist_name(ext_nl).c_str()); + + Netlist *ca_nl = find_common_ancestor(nl, ext_nl); + + if (verific_verbose) + log(" common ancestor: %s\n", get_full_netlist_name(ca_nl).c_str()); + + Net *ca_net = route_up(net, !port->IsOutput(), ca_nl); + Net *new_net = ca_net; + + if (ca_nl != nl) + { if (verific_verbose) - log(" external net: %s.%s\n", get_full_netlist_name(net->Owner()).c_str(), net->Name()); - net = newnet; + log(" net in common ancestor: %s\n", ca_net->Name()); + + string name = stringf("___extnets_%d", portname_cnt++); + new_net = new Net(name.c_str()); + nl->Add(new_net); + + Net *n = route_up(new_net, port->IsOutput(), ca_nl, ca_net); + log_assert(n == ca_net); } if (verific_verbose) - log(" final net: %s.%s%s\n", get_full_netlist_name(net->Owner()).c_str(), net->Name(), net->IsExternalTo(nl) ? " (external)" : ""); - todo_connect.push_back(tuple(inst, port, net)); + log(" new local net: %s\n", new_net->Name()); + + log_assert(!new_net->IsExternalTo(nl)); + todo_connect.push_back(tuple(inst, port, new_net)); } for (auto it : todo_connect) { -- cgit v1.2.3 From 7682629b79fd59f5ed49fb35a3a2441a405bfd63 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 27 Mar 2019 14:03:35 +0100 Subject: Add "read -verific" and "read -noverific" Signed-off-by: Clifford Wolf --- frontends/verific/verific.cc | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) (limited to 'frontends') diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 95b7d3586..ed9727b88 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -2386,21 +2386,43 @@ struct ReadPass : public Pass { log("\n"); log("Add directory to global Verilog/SystemVerilog include directories.\n"); log("\n"); + log("\n"); + log(" read -verific\n"); + log(" read -noverific\n"); + log("\n"); + log("Subsequent calls to 'read' will either use or not use Verific. Calling 'read'\n"); + log("with -verific will result in an error on Yosys binaries that are built without\n"); + log("Verific support. The default is to use Verific if it is available.\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { +#ifdef YOSYS_ENABLE_VERIFIC + static bool verific_available = !check_noverific_env(); +#else + static bool verific_available = false; +#endif + static bool use_verific = verific_available; + if (args.size() < 2 || args[1][0] != '-') log_cmd_error("Missing mode parameter.\n"); + if (args[1] == "-verific" || args[1] == "-noverific") { + if (args.size() != 2) + log_cmd_error("Additional arguments to -verific/-noverific.\n"); + if (args[1] == "-verific") { + if (!verific_available) + log_cmd_error("This version of Yosys is built without Verific support.\n"); + use_verific = true; + } else { + use_verific = false; + } + return; + } + if (args.size() < 3) log_cmd_error("Missing file name parameter.\n"); -#ifdef YOSYS_ENABLE_VERIFIC - bool use_verific = !check_noverific_env(); -#else - bool use_verific = false; -#endif - if (args[1] == "-vlog95" || args[1] == "-vlog2k") { if (use_verific) { args[0] = "verific"; -- cgit v1.2.3