From 591d2c2473148777bc516694e3e6f15f4c75ca20 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 3 Aug 2026 21:31:18 -0700 Subject: [PATCH] Fix for GH 1140 --- elab_expr.cc | 33 +++++++++++++++--------- ivtest/gold/br_gh1140a.gold | 9 +++++++ ivtest/gold/br_gh1140b.gold | 17 +++++++++++++ ivtest/gold/br_gh1140c.gold | 9 +++++++ ivtest/ivltests/br_gh1140a.v | 11 ++++++++ ivtest/ivltests/br_gh1140b.v | 16 ++++++++++++ ivtest/ivltests/br_gh1140c.v | 12 +++++++++ ivtest/regress-sv.list | 2 +- ivtest/regress-vlg.list | 2 ++ netmisc.cc | 49 ++++++++++++++++++++---------------- 10 files changed, 126 insertions(+), 34 deletions(-) create mode 100644 ivtest/gold/br_gh1140a.gold create mode 100644 ivtest/gold/br_gh1140b.gold create mode 100644 ivtest/gold/br_gh1140c.gold create mode 100644 ivtest/ivltests/br_gh1140a.v create mode 100644 ivtest/ivltests/br_gh1140b.v create mode 100644 ivtest/ivltests/br_gh1140c.v diff --git a/elab_expr.cc b/elab_expr.cc index 69b8f7e87..e76d5f063 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1674,21 +1674,30 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope, PExpr *pexpr = parms_[1].parm; if (pexpr == 0) { cerr << get_fileline() << ": error: " - << "Missing $ivlh_to_unsigned width." << endl; + << "The width is missing for " << name << "()." << endl; + des->errors += 1; return 0; } const NetExpr*nexpr = elab_and_eval(des, scope, pexpr, -1, true); if (nexpr == 0) { cerr << get_fileline() << ": error: " - << "Unable to evaluate " << name - << " width argument: " << *pexpr << endl; + << "Unable to evaluate width argument for " << name + << "(): " << *pexpr << endl; + des->errors += 1; return 0; } long value = 0; bool rc = eval_as_long(value, nexpr); - ivl_assert(*this, rc && value>=0); + if (! rc || value < 0) { + cerr << get_fileline() << ": error: " + << "The width argument for " << name + << "() must be defined and greater than or equal to zero, given: " + << *pexpr << endl; + des->errors += 1; + return 0; + } // The argument width is self-determined and doesn't // affect the result width. @@ -2756,7 +2765,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li, << "Unpacked structures not supported here." << endl; des->errors += 1; - return 0; + return nullptr; } // These make up the "part" select that is the equivilent of @@ -2796,7 +2805,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li, << net->name() << "." << completed_path << endl; des->errors += 1; - return 0; + return nullptr; } member_type = member->net_type; if (debug_elaborate) { @@ -2837,13 +2846,13 @@ static NetExpr* check_for_struct_members(const LineInfo*li, cerr << li->get_fileline() << ": error: " << "Too many index expressions for enum member." << endl; des->errors += 1; - return 0; + return nullptr; } long tail_off = 0; unsigned long tail_wid = 0; bool rc = calculate_part(li, des, scope, member_comp.index.back(), tail_off, tail_wid); - if (! rc) return 0; + if (! rc) return nullptr; off += tail_off; use_width = tail_wid; @@ -2882,7 +2891,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li, cerr << li->get_fileline() << ": error: " << "Too many index expressions for member." << endl; des->errors += 1; - return 0; + return nullptr; } // Evaluate all but the last index expression, into prefix_indices. @@ -2900,7 +2909,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li, long tail_off = 0; unsigned long tail_wid = 0; rc = calculate_part(li, des, scope, member_comp.index.back(), tail_off, tail_wid); - if (! rc) return 0; + if (! rc) return nullptr; if (debug_elaborate) { cerr << li->get_fileline() << ": check_for_struct_member: " @@ -2962,7 +2971,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li, << "Too many index expressions for member " << member_name << "." << endl; des->errors += 1; - return 0; + return nullptr; } // Evaluate all but the last index expression, into prefix_indices. @@ -2978,7 +2987,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li, << "Array index expressions for member " << member_name << " must be constant here." << endl; des->errors += 1; - return 0; + return nullptr; } delete texpr; diff --git a/ivtest/gold/br_gh1140a.gold b/ivtest/gold/br_gh1140a.gold new file mode 100644 index 000000000..1ae00dfd8 --- /dev/null +++ b/ivtest/gold/br_gh1140a.gold @@ -0,0 +1,9 @@ +./ivltests/br_gh1140a.v:5: error: Dimensions must be a constant with no unknown or high-Z bits. +./ivltests/br_gh1140a.v:5 : This MSB expression violates the rule: LPX +./ivltests/br_gh1140a.v:6: error: Dimensions must be a constant with no unknown or high-Z bits. +./ivltests/br_gh1140a.v:6 : This MSB expression violates the rule: LPZ +./ivltests/br_gh1140a.v:7: error: Dimensions must be a constant with no unknown or high-Z bits. +./ivltests/br_gh1140a.v:7: : This LSB expression violates the rule: LPX +./ivltests/br_gh1140a.v:8: error: Dimensions must be a constant with no unknown or high-Z bits. +./ivltests/br_gh1140a.v:8: : This LSB expression violates the rule: LPZ +4 error(s) during elaboration. diff --git a/ivtest/gold/br_gh1140b.gold b/ivtest/gold/br_gh1140b.gold new file mode 100644 index 000000000..695803757 --- /dev/null +++ b/ivtest/gold/br_gh1140b.gold @@ -0,0 +1,17 @@ +./ivltests/br_gh1140b.v:10: error: Dimensions must be a constant with no unknown or high-Z bits. +./ivltests/br_gh1140b.v:10 : This MSB expression violates the rule: LPX +./ivltests/br_gh1140b.v:11: error: Dimensions must be a constant with no unknown or high-Z bits. +./ivltests/br_gh1140b.v:11 : This MSB expression violates the rule: LPZ +./ivltests/br_gh1140b.v:12: error: Dimensions must be a constant with no unknown or high-Z bits. +./ivltests/br_gh1140b.v:12: : This LSB expression violates the rule: LPX +./ivltests/br_gh1140b.v:13: error: Dimensions must be a constant with no unknown or high-Z bits. +./ivltests/br_gh1140b.v:13: : This LSB expression violates the rule: LPZ +./ivltests/br_gh1140b.v:5: error: Dimensions must be a constant with no unknown or high-Z bits. +./ivltests/br_gh1140b.v:5 : This MSB expression violates the rule: LPX +./ivltests/br_gh1140b.v:6: error: Dimensions must be a constant with no unknown or high-Z bits. +./ivltests/br_gh1140b.v:6 : This MSB expression violates the rule: LPZ +./ivltests/br_gh1140b.v:7: error: Dimensions must be a constant with no unknown or high-Z bits. +./ivltests/br_gh1140b.v:7: : This LSB expression violates the rule: LPX +./ivltests/br_gh1140b.v:8: error: Dimensions must be a constant with no unknown or high-Z bits. +./ivltests/br_gh1140b.v:8: : This LSB expression violates the rule: LPZ +8 error(s) during elaboration. diff --git a/ivtest/gold/br_gh1140c.gold b/ivtest/gold/br_gh1140c.gold new file mode 100644 index 000000000..e6179b24b --- /dev/null +++ b/ivtest/gold/br_gh1140c.gold @@ -0,0 +1,9 @@ +./ivltests/br_gh1140c.v:8: error: Dimensions must be a constant with no unknown or high-Z bits. +./ivltests/br_gh1140c.v:8 : This size expression violates the rule: LPX +./ivltests/br_gh1140c.v:9: error: Dimensions must be a constant with no unknown or high-Z bits. +./ivltests/br_gh1140c.v:9 : This size expression violates the rule: LPZ +./ivltests/br_gh1140c.v:5: error: Dimensions must be a constant with no unknown or high-Z bits. +./ivltests/br_gh1140c.v:5 : This size expression violates the rule: LPX +./ivltests/br_gh1140c.v:6: error: Dimensions must be a constant with no unknown or high-Z bits. +./ivltests/br_gh1140c.v:6 : This size expression violates the rule: LPZ +4 error(s) during elaboration. diff --git a/ivtest/ivltests/br_gh1140a.v b/ivtest/ivltests/br_gh1140a.v new file mode 100644 index 000000000..02fa83f73 --- /dev/null +++ b/ivtest/ivltests/br_gh1140a.v @@ -0,0 +1,11 @@ +module top; + localparam integer LPX = 32'b01x; + localparam integer LPZ = 32'b01z; + // It is illegal to use an x or z in the dimensions. + localparam [LPX:0] pr1 = 1; + localparam [LPZ:0] pr2 = 2; + localparam [0:LPX] pr3 = 1; + localparam [0:LPZ] pr4 = 2; + + initial $display("Compiling should fail."); +endmodule diff --git a/ivtest/ivltests/br_gh1140b.v b/ivtest/ivltests/br_gh1140b.v new file mode 100644 index 000000000..738a2800c --- /dev/null +++ b/ivtest/ivltests/br_gh1140b.v @@ -0,0 +1,16 @@ +module top; + localparam integer LPX = 32'b01x; + localparam integer LPZ = 32'b01z; + // It is illegal to use an x or z in the dimensions. + reg [LPX:0] rg1; + reg [LPZ:0] rg2; + reg [0:LPX] rg3; + reg [0:LPZ] rg4; + + reg arg1 [LPX:0]; + reg arg2 [LPZ:0]; + reg arg3 [0:LPX]; + reg arg4 [0:LPZ]; + + initial $display("Compiling should fail."); +endmodule diff --git a/ivtest/ivltests/br_gh1140c.v b/ivtest/ivltests/br_gh1140c.v new file mode 100644 index 000000000..d37a8852d --- /dev/null +++ b/ivtest/ivltests/br_gh1140c.v @@ -0,0 +1,12 @@ +module top; + localparam integer LPX = 32'b01x; + localparam integer LPZ = 32'b01z; + // It is illegal to use an x or z in the dimensions. + reg [LPX] rg1; + reg [LPZ] rg2; + + reg arg1 [LPX]; + reg arg2 [LPZ]; + + initial $display("Compiling should fail."); +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index ee2dc7757..d2c122c3f 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -228,6 +228,7 @@ br_gh782b normal,-g2009 ivltests gold=br_gh782b.gold br_gh800 normal,-g2009 ivltests br_gh801 normal,-g2012 ivltests br_gh801b normal,-g2012 ivltests +br_gh1140c CE,-g2009 ivltests gold=br_gh1140c.gold br_gh1222 CE,-g2009 ivltests gold=br_gh1222.gold br_gh1223a normal,-g2009 ivltests br_gh1223b normal,-g2009 ivltests @@ -968,7 +969,6 @@ wild_cmp_err2 CE,-g2009 ivltests gold=wild_cmp_err2.gold gh161a normal,-g2012 ivltests gh161b normal,-g2012 ivltests pull371b normal,-g2012 ivltests - br_gh175 normal,-g2012 ivltests br_gh307 normal,-g2012 ivltests br_gh390a CE,-g2012 ivltests diff --git a/ivtest/regress-vlg.list b/ivtest/regress-vlg.list index a2a1f86ed..a2cc6d192 100644 --- a/ivtest/regress-vlg.list +++ b/ivtest/regress-vlg.list @@ -356,6 +356,8 @@ br_gh889 normal,-gspecify ivltests gold=br_gh889.gold br_gh956a CE ivltests gold=br_gh956a.gold br_gh956b CE ivltests gold=br_gh956b.gold br_gh1117 CE ivltests gold=br_gh1117.gold +br_gh1140a CE ivltests gold=br_gh1140a.gold +br_gh1140b CE ivltests gold=br_gh1140b.gold br_gh1173 CE ivltests gold=br_gh1173.gold br_gh1174a CE ivltests gold=br_gh1174a.gold br_gh1174b CE ivltests gold=br_gh1174b.gold diff --git a/netmisc.cc b/netmisc.cc index 39cc4540c..0620eb359 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -1095,14 +1095,15 @@ bool evaluate_range(Design*des, NetScope*scope, const LineInfo*li, } else { NetExpr*texpr = elab_and_eval(des, scope, range.first, -1, true); if (! eval_as_long(index_l, texpr)) { - cerr << range.first->get_fileline() << ": error: " - "Dimensions must be constant." << endl; - cerr << range.first->get_fileline() << " : " - << (range.second ? "This MSB" : "This size") - << " expression violates the rule: " - << *range.first << endl; - dimension_ok = false; - des->errors += 1; + cerr << range.first->get_fileline() << ": error: " + "Dimensions must be a constant with no unknown or high-Z bits." + << endl; + cerr << range.first->get_fileline() << " : " + << (range.second ? "This MSB" : "This size") + << " expression violates the rule: " + << *range.first << endl; + dimension_ok = false; + des->errors += 1; } delete texpr; @@ -1118,7 +1119,7 @@ bool evaluate_range(Design*des, NetScope*scope, const LineInfo*li, } else { cerr << range.first->get_fileline() << ": error: " "Dimension size must be greater than zero." << endl; - cerr << range.first->get_fileline() << " : " + cerr << range.first->get_fileline() << ": : " "This size expression violates the rule: " << *range.first << endl; dimension_ok = false; @@ -1127,13 +1128,14 @@ bool evaluate_range(Design*des, NetScope*scope, const LineInfo*li, } else { texpr = elab_and_eval(des, scope, range.second, -1, true); if (! eval_as_long(index_r, texpr)) { - cerr << range.second->get_fileline() << ": error: " - "Dimensions must be constant." << endl; - cerr << range.second->get_fileline() << " : " - "This LSB expression violates the rule: " - << *range.second << endl; - dimension_ok = false; - des->errors += 1; + cerr << range.second->get_fileline() << ": error: " + "Dimensions must be a constant with no unknown or high-Z bits." + << endl; + cerr << range.second->get_fileline() << ": : " + "This LSB expression violates the rule: " + << *range.second << endl; + dimension_ok = false; + des->errors += 1; } delete texpr; } @@ -1196,7 +1198,7 @@ bool eval_as_long(long&value, const NetExpr*expr) { if (const NetEConst*tmp = dynamic_cast(expr) ) { value = tmp->value().as_long(); - return true; + return tmp->value().is_defined(); } if (const NetECReal*rtmp = dynamic_cast(expr)) { @@ -1530,8 +1532,8 @@ bool evaluate_index_prefix(Design*des, NetScope*scope, assert(icur != indices.end()); if (icur->sel != index_component_t::SEL_BIT) { cerr << icur->msb->get_fileline() << ": error: " - "All but the final index in a chain of indices must be " - "a single value, not a range." << endl; + "All but the final index in a chain of indices must " + "be a single value, not a range." << endl; des->errors += 1; return false; } @@ -1540,7 +1542,12 @@ bool evaluate_index_prefix(Design*des, NetScope*scope, long tmp; if (texpr == 0 || !eval_as_long(tmp, texpr)) { cerr << icur->msb->get_fileline() << ": error: " - "Array index expressions must be constant here." << endl; + "All but the final index in a chain of indices must " + "be a constant with no unknown or high-Z bits." + << endl; + cerr << icur->msb->get_fileline() << ": : " + "This index expressions violate the rule: " + << *icur->msb << endl; des->errors += 1; return false; } @@ -1622,7 +1629,7 @@ NetExpr*collapse_array_indices(Design*des, NetScope*scope, const NetNet*net, { listprefix_indices; bool rc = evaluate_index_prefix(des, scope, prefix_indices, indices); - assert(rc); + if (! rc) return nullptr; const index_component_t&back_index = indices.back(); assert(back_index.sel == index_component_t::SEL_BIT);