Modified errors into warnings
authorUdi Finkelstein <github@udifink.com>
Tue, 5 Jun 2018 14:44:24 +0000 (17:44 +0300)
committerUnknown <github@udifink.com>
Tue, 5 Jun 2018 15:03:22 +0000 (18:03 +0300)
No longer false warnings for memories and assertions

frontends/ast/ast.cc
frontends/ast/ast.h
frontends/ast/simplify.cc
frontends/verilog/verilog_parser.y
tests/various/reg_wire_error.sv

index 25267775a1e5589097dc2e853841db2e69e96489..b8f25e53eceb0be93b8efe0f0a420b50a59673e6 100644 (file)
@@ -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;
index 9b71249346582aa89be418ea0697d55254c80dbc..8a640b1cc7a8c9ad07038fe89b5cc7171a1153bf 100644 (file)
@@ -168,7 +168,7 @@ namespace AST
                // node content - most of it is unused in most node types
                std::string str;
                std::vector<RTLIL::State> 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;
index c9c5e5263a27d796d456795f757e2280b4b6d2ff..a9608369c0a1c640afe7c3b34aa8a4477fea53b6 100644 (file)
@@ -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<AstNode*> &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<AstNode*> &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<AstNode*> &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<AstNode*> &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<AstNode*> &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<AstNode*> &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<AstNode*> &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);
 
index 722febf130841a27319acd482494aa0b047c4c6c..dfdeabbdb93c998864cee8100a98f063ec53151d 100644 (file)
@@ -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;
index ab461b95a1a0af91ec5cb6100cd1bde21951a5d1..fe5ff3abd027c5f2b6ec6f992152ccbb77f09ef6 100644 (file)
@@ -2,11 +2,13 @@ module sub_mod(input i_in, output o_out);
 assign o_out = i_in;
 endmodule
 
-module test(i_clk, i_reg, o_reg, o_wire);
+module test(i_clk, i, i_reg, o_reg, o_wire, o_mr, o_mw, o_ml);
 input i_clk;
+input i;
 input i_reg;
 output o_reg;
 output o_wire;
+output o_mr, o_mw, o_ml;
 
 // Enable this to see how it doesn't fail on yosys although it should
 //reg o_wire;
@@ -15,12 +17,12 @@ logic o_wire;
 // Enable this to see how it doesn't fail on yosys although it should
 //reg i_reg;
 // Disable this to see how it doesn't fail on yosys although it should
-reg o_reg;
+//reg o_reg;
 
 logic l_reg;
 
 // Enable this to tst if logic-turne-reg will catch assignments even if done before it turned into a reg
-//assign l_reg = !o_reg;
+assign l_reg = !o_reg;
 initial o_reg = 1'b0;
 always @(posedge i_clk)
 begin
@@ -30,11 +32,43 @@ end
 
 assign o_wire = !o_reg;
 // Uncomment this to see how a logic already turned intoa reg can be freely assigned on yosys
-//assign l_reg = !o_reg;
+assign l_reg = !o_reg;
 
 sub_mod sm_inst (
   .i_in(1'b1),
   .o_out(o_reg)
 );
+
+wire   mw1[0:1];
+wire   mw2[0:1];
+wire   mw3[0:1];
+reg    mr1[0:1];
+reg    mr2[0:1];
+reg    mr3[0:1];
+logic  ml1[0:1];
+logic  ml2[0:1];
+logic  ml3[0:1];
+
+assign o_mw = mw1[i];
+assign o_mr = mr1[i];
+assign o_ml = ml1[i];
+
+assign mw1[1] = 1'b1;
+//assign mr1[1] = 1'b1;
+assign ml1[1] = 1'b1;
+always @(posedge i_clk)
+begin
+  mr2[0] = 1'b0;
+  mw2[0] = 1'b0;
+  ml2[0] = 1'b0;
+end
+
+always @(posedge i_clk)
+begin
+  mr3[0] <= 1'b0;
+  mw3[0] <= 1'b0;
+  ml3[0] <= 1'b0;
+end
+
 endmodule