From b11da7e16fb9b007c28fa691e8e6a9164bcbbef2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Jan 2022 10:18:22 +0100 Subject: [PATCH 1/5] tgt-vvp: Don't accidentally skip assignment pattern initialization The `%store/dar/...` and `%store/qdar/...` instructions are used to load a value into an entry in dynamic array or queue. These instructions will skip the load if VVP flag 4 is 1. For assignment pattern initialization these instructions are used to load the value of the individual assignment pattern expressions into the dynamic array. For queues flag 4 is never cleared when generating the code for the assignment pattern. This means the initialization might be skipped depending on what value the flag had before. ``` int a = 1; int q[$]; a = a == 1; q = {1, 2, 3, 4}; ``` For dynamic arrays it is cleared once in the beginning. But each item in the assignment pattern can be an arbitrary expression. Evaluating the expression can cause the flag to get overwritten. E.g. the following code will skip the assignments. ``` int a = 1; int d[]; d = {a ? 1 : 1, 2, 3, 4}; ``` To fix these issues make sure that the flag is cleared after evaluating each initialization expression and before executing the `%store/...` instruction. Signed-off-by: Lars-Peter Clausen --- tgt-vvp/stmt_assign.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index c467f983e..7eb98d7de 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -968,18 +968,21 @@ static int show_stmt_assign_darray_pattern(ivl_statement_t net) case IVL_VT_LOGIC: draw_eval_vec4(ivl_expr_parm(rval,idx)); fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx); + fprintf(vvp_out, " %%flag_set/imm 4, 0;\n"); fprintf(vvp_out, " %%store/dar/vec4 v%p_0;\n", var); break; case IVL_VT_REAL: draw_eval_real(ivl_expr_parm(rval,idx)); fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx); + fprintf(vvp_out, " %%flag_set/imm 4, 0;\n"); fprintf(vvp_out, " %%store/dar/r v%p_0;\n", var); break; case IVL_VT_STRING: draw_eval_string(ivl_expr_parm(rval,idx)); fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx); + fprintf(vvp_out, " %%flag_set/imm 4, 0;\n"); fprintf(vvp_out, " %%store/dar/str v%p_0;\n", var); break; @@ -1102,6 +1105,7 @@ static int show_stmt_assign_queue_pattern(ivl_signal_t var, ivl_expr_t rval, case IVL_VT_LOGIC: draw_eval_vec4(ivl_expr_parm(rval,idx)); fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx); + fprintf(vvp_out, " %%flag_set/imm 4, 0;\n"); fprintf(vvp_out, " %%store/qdar/v v%p_0, %d, %u;\n", var, max_idx, width_of_packed_type(element_type)); break; @@ -1109,12 +1113,14 @@ static int show_stmt_assign_queue_pattern(ivl_signal_t var, ivl_expr_t rval, case IVL_VT_REAL: draw_eval_real(ivl_expr_parm(rval,idx)); fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx); + fprintf(vvp_out, " %%flag_set/imm 4, 0;\n"); fprintf(vvp_out, " %%store/qdar/r v%p_0, %d;\n", var, max_idx); break; case IVL_VT_STRING: draw_eval_string(ivl_expr_parm(rval,idx)); fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx); + fprintf(vvp_out, " %%flag_set/imm 4, 0;\n"); fprintf(vvp_out, " %%store/qdar/str v%p_0, %d;\n", var, max_idx); break; From ff8a44b025e3dc011f0cbdea34571f7248310b94 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 25 Mar 2022 22:43:04 +0100 Subject: [PATCH 2/5] Add variant of elaborate_rval_expr() that only takes a data_type_t The `elaborate_rval_expr()` function takes a `data_type_t`, a `ivl_variable_type_t` and a `width` parameter. In most places the ivl_variable_type_t and width are directly derived from the data_type_t. This slightly simplifies the code. The only place where this is currently not possible is when assigning to a compound expression like a concatenation, e.g. `{a,b} = c;`. Signed-off-by: Lars-Peter Clausen --- elab_expr.cc | 19 ++++++++++++------- elaborate.cc | 14 +++----------- netmisc.h | 7 +++++++ 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 35e117f11..b6136fc53 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -91,6 +91,15 @@ static NetBranch* find_existing_implicit_branch(NetNet*sig, NetNet*gnd) return 0; } +NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type, + PExpr*expr, bool need_const, bool force_unsigned) +{ + return elaborate_rval_expr(des, scope, lv_net_type, + lv_net_type->base_type(), + lv_net_type->packed_width(), + expr, need_const, force_unsigned); +} + NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type, ivl_variable_type_t lv_type, unsigned lv_width, PExpr*expr, bool need_const, bool force_unsigned) @@ -2009,7 +2018,7 @@ static NetExpr* check_for_enum_methods(const LineInfo*li, NetExpr* count = 0; if (args != 0 && parg) { count = elaborate_rval_expr(des, scope, &netvector_t::atom2u32, - IVL_VT_BOOL, 32, parg); + parg); if (count == 0) { cerr << li->get_fileline() << ": error: unable to elaborate " "enumeration method argument " << use_path << "." @@ -2897,8 +2906,6 @@ unsigned PECallFunction::elaborate_arguments_(Design*des, NetScope*scope, if (tmp) { parms[pidx] = elaborate_rval_expr(des, scope, def->port(pidx)->net_type(), - def->port(pidx)->data_type(), - (unsigned)def->port(pidx)->vector_width(), tmp, need_const); if (parms[pidx] == 0) { parm_errors += 1; @@ -3222,11 +3229,11 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope, NetExpr*tmp; tmp = elaborate_rval_expr(des, scope, &netvector_t::atom2u32, - IVL_VT_BOOL, 32, parms_[0], false); + parms_[0], false); sys_expr->parm(1, tmp); tmp = elaborate_rval_expr(des, scope, &netvector_t::atom2u32, - IVL_VT_BOOL, 32, parms_[1], false); + parms_[1], false); sys_expr->parm(2, tmp); return sys_expr; @@ -6546,8 +6553,6 @@ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope, PExpr*tmp = parms_[idx-1]; parms[idx] = elaborate_rval_expr(des, scope, def->port(idx)->net_type(), - def->port(idx)->data_type(), - def->port(idx)->vector_width(), tmp, false); if (parms[idx] == 0) parm_errors += 1; diff --git a/elaborate.cc b/elaborate.cc index a5edabd63..d16aa6402 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -140,9 +140,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const << ", pin_count=" << lval->pin_count() << endl; } - NetExpr*rval_expr = elaborate_rval_expr(des, scope, lval->net_type(), - lval->data_type(), - lval->vector_width(), pin(1)); + NetExpr*rval_expr = elaborate_rval_expr(des, scope, lval->net_type(), pin(1)); if (rval_expr == 0) { cerr << get_fileline() << ": error: Unable to elaborate r-value: " @@ -3253,8 +3251,6 @@ NetProc* PChainConstructor::elaborate(Design*des, NetScope*scope) const PExpr*tmp = parms_[idx-1]; parms[idx] = elaborate_rval_expr(des, scope, def->port(idx)->net_type(), - def->port(idx)->data_type(), - def->port(idx)->vector_width(), tmp, false); continue; } @@ -4029,7 +4025,7 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope, if (parms_idx < parms_.size() && parms_[parms_idx]) { rv = elaborate_rval_expr(des, scope, port->net_type(), - lv_type, wid, parms_ [parms_idx]); + parms_ [parms_idx]); if (NetEEvent*evt = dynamic_cast (rv)) { cerr << evt->get_fileline() << ": error: An event '" << evt->event()->name() << "' can not be a user " @@ -5453,7 +5449,6 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const /* Make the r-value of the initial assignment, and size it properly. Then use it to build the assignment statement. */ initial_expr = elaborate_rval_expr(des, scope, sig->net_type(), - sig->data_type(), sig->vector_width(), expr1_); if (debug_elaborate && initial_expr) { @@ -5700,12 +5695,9 @@ NetProc* PReturn::elaborate(Design*des, NetScope*scope) const NetNet*res = target->find_signal(target->basename()); ivl_assert(*this, res); - ivl_variable_type_t lv_type = res->data_type(); - unsigned long wid = res->vector_width(); NetAssign_*lv = new NetAssign_(res); - NetExpr*val = elaborate_rval_expr(des, scope, res->net_type(), - lv_type, wid, expr_); + NetExpr*val = elaborate_rval_expr(des, scope, res->net_type(), expr_); NetBlock*proc = new NetBlock(NetBlock::SEQU, 0); proc->set_line( *this ); diff --git a/netmisc.h b/netmisc.h index 17f3d20b9..eb57289c8 100644 --- a/netmisc.h +++ b/netmisc.h @@ -408,6 +408,13 @@ extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, unsigned lv_width, PExpr*expr, bool need_const =false, bool force_unsigned =false); +/* + * Same as above, but lv_width and lv_type are derived from the lv_net_type. + */ +extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, + ivl_type_t lv_net_type, PExpr*expr, + bool need_const = false, + bool force_unsigned = false); extern bool evaluate_range(Design*des, NetScope*scope, const LineInfo*li, const pform_range_t&range, From f19ba646149f7242a697faeea1690ff7b2d0b531 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 17 Apr 2022 09:58:11 +0200 Subject: [PATCH 3/5] trash --- elaborate.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elaborate.cc b/elaborate.cc index d16aa6402..1fadc7219 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -5168,7 +5168,7 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const // better way to get a reasonable lv_net_type value, and that // probably will involve NetAssign_ having a method for // synthesizing one as needed. - NetExpr*rexp = elaborate_rval_expr(des, scope, 0, ltype, lwid, expr_); + NetExpr*rexp = elaborate_rval_expr(des, scope, lval->net_type(), ltype, lwid, expr_); if (rexp == 0) return 0; From 5b8fb089bf125db2e0630b075ac4a533ba8cd794 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 3 Apr 2022 20:21:32 +0200 Subject: [PATCH 4/5] Elaborate array assignment pattern values in the right context The expressions within an array assignment pattern should be evaluated in a context that is equivalent to an assignment to a variable of the element type of the l-value array. This is defined in section 10.9.1 ("Array assignment patterns") of the LRM (1800-2017). At the moment the values in an assignment pattern are evaluated in a self determined context, which can lead to incorrect behavior. Use the existing `elaborate_rval_expr()` function, which is meant for elaborating assignments, to elaborate the assignment pattern values. This solves the following issues: * implicit width conversion (including sign extension) * implicit type conversion (e.g. real to vector) * math operators that depend on the target width (e.g. addition) * use of expressions that require `test_width()` to be called. (e.g. unary operator) * use of concatenations * use of named constants (e.g. parameters or enums) Signed-off-by: Lars-Peter Clausen --- elab_expr.cc | 9 ++++++--- netmisc.h | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index b6136fc53..3f41c32bb 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -91,8 +91,8 @@ static NetBranch* find_existing_implicit_branch(NetNet*sig, NetNet*gnd) return 0; } -NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type, - PExpr*expr, bool need_const, bool force_unsigned) +NetExpr* elaborate_rval_expr(Design *des, NetScope *scope, ivl_type_t lv_net_type, + PExpr *expr, bool need_const, bool force_unsigned) { return elaborate_rval_expr(des, scope, lv_net_type, lv_net_type->base_type(), @@ -236,13 +236,16 @@ NetExpr*PEAssignPattern::elaborate_expr_darray_(Design*des, NetScope*scope, const netdarray_t*array_type = dynamic_cast (ntype); ivl_assert(*this, array_type); + bool need_const = NEED_CONST & flags; + // This is an array pattern, so run through the elements of // the expression and elaborate each as if they are // element_type expressions. ivl_type_t elem_type = array_type->element_type(); vector elem_exprs (parms_.size()); for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) { - NetExpr*tmp = parms_[idx]->elaborate_expr(des, scope, elem_type, flags); + NetExpr*tmp = elaborate_rval_expr(des, scope, elem_type, + parms_[idx], need_const); elem_exprs[idx] = tmp; } diff --git a/netmisc.h b/netmisc.h index eb57289c8..621a95757 100644 --- a/netmisc.h +++ b/netmisc.h @@ -411,8 +411,8 @@ extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, /* * Same as above, but lv_width and lv_type are derived from the lv_net_type. */ -extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, - ivl_type_t lv_net_type, PExpr*expr, +extern NetExpr* elaborate_rval_expr(Design *des, NetScope *scope, + ivl_type_t lv_net_type, PExpr *expr, bool need_const = false, bool force_unsigned = false); From a3c329ae84ac938624201df0e68e784e94267082 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 13 Apr 2022 13:33:49 +0200 Subject: [PATCH 5/5] Add regression tests for evaluating expression within assignment patterns Check that expressions within assignment patterns are evaluated as if they were assigned to a variable with the same type as the base type of the assignment pattern target. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/sv_assign_pattern_cast.v | 51 +++++++++++++++ ivtest/ivltests/sv_assign_pattern_concat.v | 34 ++++++++++ ivtest/ivltests/sv_assign_pattern_const.v | 39 ++++++++++++ ivtest/ivltests/sv_assign_pattern_expand.v | 45 +++++++++++++ ivtest/ivltests/sv_assign_pattern_func.v | 40 ++++++++++++ ivtest/ivltests/sv_assign_pattern_op.v | 73 ++++++++++++++++++++++ ivtest/ivltests/sv_assign_pattern_part.v | 37 +++++++++++ ivtest/regress-sv.list | 7 +++ ivtest/regress-vlog95.list | 7 +++ 9 files changed, 333 insertions(+) create mode 100644 ivtest/ivltests/sv_assign_pattern_cast.v create mode 100644 ivtest/ivltests/sv_assign_pattern_concat.v create mode 100644 ivtest/ivltests/sv_assign_pattern_const.v create mode 100644 ivtest/ivltests/sv_assign_pattern_expand.v create mode 100644 ivtest/ivltests/sv_assign_pattern_func.v create mode 100644 ivtest/ivltests/sv_assign_pattern_op.v create mode 100644 ivtest/ivltests/sv_assign_pattern_part.v diff --git a/ivtest/ivltests/sv_assign_pattern_cast.v b/ivtest/ivltests/sv_assign_pattern_cast.v new file mode 100644 index 000000000..a01245d3d --- /dev/null +++ b/ivtest/ivltests/sv_assign_pattern_cast.v @@ -0,0 +1,51 @@ +// Check that implicit cast works for expressions in assignment patterns. The +// result should be the same as assigning the expression to a variable with the +// same type as the base type of the assignment pattern target. + +module test; + + int dv[]; + real dr[]; + + int tmpv; + real tmpr; + + bit failed = 1'b0; + + `define check_v(expr) \ + dv = '{expr}; \ + tmpv = expr; \ + if (dv[0] !== tmpv) begin \ + $display("FAILED: `%s`, got %0d, expected %0d", `"expr`", dv[0], tmpv); \ + failed = 1'b1; \ + end + + `define check_r(expr) \ + dr = '{expr}; \ + tmpr = expr; \ + if (dr[0] != tmpr) begin \ + $display("FAILED: `%s`, got %0d, expected %0d", `"expr`", dr[0], tmpr); \ + failed = 1'b1; \ + end + + real r; + int i; + + initial begin + r = 4.56; + i = -11; + + // Implicit cast from real to vector + `check_v(1.234e16) + `check_v(r) + + // Implicit cast from vector to real + `check_r(32'hfffffff0) + `check_r(i) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_assign_pattern_concat.v b/ivtest/ivltests/sv_assign_pattern_concat.v new file mode 100644 index 000000000..e4e51de0f --- /dev/null +++ b/ivtest/ivltests/sv_assign_pattern_concat.v @@ -0,0 +1,34 @@ +// Check that concatenations are evaluated correctly in assignment patterns. +// The result should be the same as assigning the expression to a variable with +// the same type as the base type of the assignment pattern target. + +module test; + + int d[]; + int tmp; + + bit failed = 1'b0; + + `define check(expr) \ + d = '{expr}; \ + tmp = expr; \ + if (d[0] !== tmp) begin \ + $display("FAILED: `%s`, got %0d, expected %0d", `"expr`", d[0], tmp); \ + failed = 1'b1; \ + end + + shortint x; + byte y; + + initial begin + x = -1; + y = 10; + `check({x,y}) + `check({3{y}}) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_assign_pattern_const.v b/ivtest/ivltests/sv_assign_pattern_const.v new file mode 100644 index 000000000..24fbfb4c9 --- /dev/null +++ b/ivtest/ivltests/sv_assign_pattern_const.v @@ -0,0 +1,39 @@ +// Check that named constants can be accessed in assignment patterns. The +// result should be the same as assigning the expression to a variable with the +// same type as the base type of the assignment pattern target. + +module test; + + int d[]; + int tmp; + + bit failed = 1'b0; + + `define check(expr) \ + d = '{expr}; \ + tmp = expr; \ + if (d[0] !== tmp) begin \ + $display("FAILED: `%s`, got %0d, expected %0d", `"expr`", d[0], tmp); \ + failed = 1'b1; \ + end + + parameter A = -1; + localparam B = 10; + + typedef enum { + X = -1, Y = 0, Z = 1 + } T; + + initial begin + `check(A) + `check(B) + `check(X) + `check(Y) + `check(Z) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_assign_pattern_expand.v b/ivtest/ivltests/sv_assign_pattern_expand.v new file mode 100644 index 000000000..4d0a2d25f --- /dev/null +++ b/ivtest/ivltests/sv_assign_pattern_expand.v @@ -0,0 +1,45 @@ +// Check that the width of the element type of the target of an assignment +// pattern is considered when evaluating the expression. The result should be +// the same as assigning the expression to a variable with the same type as the +// base type of the assignment pattern target. + +module test; + + int d[]; + int tmp; + + bit failed = 1'b0; + + `define check(expr) \ + d = '{expr}; \ + tmp = expr; \ + if (d[0] !== tmp) begin \ + $display("FAILED: `%s`, got %0d, expected %0d", `"expr`", d[0], tmp); \ + failed = 1'b1; \ + end + + shortint x; + bit [7:0] y; + + initial begin + x = -11; + y = 8'h80; + + // Sign extension + `check(x) + `check(16'sh8000) + + // No sign extension + `check(8'hff) + `check(y) + + // Gets evaluated in a 32 bit context, the result is 2/-2 not 0 + `check(1'b1 + 1'b1) + `check(1'sb1 + 1'sb1) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_assign_pattern_func.v b/ivtest/ivltests/sv_assign_pattern_func.v new file mode 100644 index 000000000..02e682499 --- /dev/null +++ b/ivtest/ivltests/sv_assign_pattern_func.v @@ -0,0 +1,40 @@ +// Check that function calls within an assignment pattern are evaluated +// correctly. The result should be the same as assigning the expression to a +// variable with the same type as the base type of the assignment pattern +// target. + + +module test; + + int d[]; + int tmp; + + bit failed = 1'b0; + + `define check(expr) \ + d = '{expr}; \ + tmp = expr; \ + if (d[0] !== tmp) begin \ + $display("FAILED: `%s`, got %0d, expected %0d", `"expr`", d[0], tmp); \ + failed = 1'b1; \ + end + + int x, y; + + function int fn(int x); + return x*2; + endfunction + + initial begin + x = -3; + y = 10; + + `check(fn(x)) + `check($clog2(y)) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_assign_pattern_op.v b/ivtest/ivltests/sv_assign_pattern_op.v new file mode 100644 index 000000000..d73ad85e0 --- /dev/null +++ b/ivtest/ivltests/sv_assign_pattern_op.v @@ -0,0 +1,73 @@ +// Check that operators in an assignment pattern are evaluated correctly. The +// result should be the same as assigning the expression to a variable with the +// same type as the base type of the assignment pattern target. + +module test; + + int d[]; + int tmp; + + bit failed = 1'b0; + + `define check(expr) \ + d = '{expr}; \ + tmp = expr; \ + if (d[0] !== tmp) begin \ + $display("FAILED: `%s`, got %0d, expected %0d", `"expr`", d[0], tmp); \ + failed = 1'b1; \ + end + + int x, y; + + initial begin + x = -2; + y = 5; + + `check(+x); + `check(-x); + `check(!x); + `check(~x); + `check(&x); + `check(~&x); + `check(|x); + `check(~|x); + `check(^x); + `check(~^x); + + `check(x + y) + `check(x - y) + `check(x * y) + `check(x / y) + `check(x % y) + `check(x ** y) + + `check(x & y) + `check(x | y) + `check(x ^ y) + `check(x ^~ y) + + `check(x >> y); + `check(x << y); + `check(x >>> y); + `check(x <<< y); + + `check(x == y); + `check(x != y); + `check(x === y); + `check(x !== y); + `check(x < y); + `check(x <= y); + `check(x > y); + `check(x >= y); + + `check(x && y); + `check(x || y); + + `check(x ? x : y); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_assign_pattern_part.v b/ivtest/ivltests/sv_assign_pattern_part.v new file mode 100644 index 000000000..957aedd6a --- /dev/null +++ b/ivtest/ivltests/sv_assign_pattern_part.v @@ -0,0 +1,37 @@ +// Check that part selects are evaluated correctly within assignment patterns. +// The result should be the same as assigning the expression to a variable with +// the same type as the base type of the assignment pattern target. + +module test; + + int d[]; + int tmp; + + bit failed = 1'b0; + + `define check(expr) \ + d = '{expr}; \ + tmp = expr; \ + if (d[0] !== tmp) begin \ + $display("FAILED: `%s`, got %0d, expected %0d", `"expr`", d[0], tmp); \ + failed = 1'b1; \ + end + + logic [23:0] x; + int i = 13; + + initial begin + x = 24'ha5a5a5; + `check(x[0]) + `check(x[7:0]) + `check(x[3+:8]) + `check(x[23-:5]) + `check(x[i+:8]) + `check(x[i-:5]) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index e0503d23c..f776daa67 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -455,6 +455,13 @@ struct_packed_write_read2 normal,-g2009 ivltests struct_invalid_member CE,-g2009 ivltests gold=struct_invalid_member.gold struct_signed normal,-g2009 ivltests sv-constants normal,-g2005-sv ivltests +sv_assign_pattern_cast normal,-g2005-sv ivltests +sv_assign_pattern_const normal,-g2005-sv ivltests +sv_assign_pattern_concat normal,-g2005-sv ivltests +sv_assign_pattern_expand normal,-g2005-sv ivltests +sv_assign_pattern_func normal,-g2005-sv ivltests +sv_assign_pattern_op normal,-g2005-sv ivltests +sv_assign_pattern_part normal,-g2005-sv ivltests sv_array_assign_pattern2 normal,-g2009 ivltests sv_cast_integer normal,-g2005-sv ivltests sv_cast_integer2 normal,-g2005-sv ivltests diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index 7aa9989e8..28225dd6c 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -315,6 +315,13 @@ br_gh383c CE,-g2012,-pallowsigned=1 ivltests br_gh383d CE,-g2012,-pallowsigned=1 ivltests br_gh460 CE,-g2012 ivltests br_ml20191221 CE,-g2009,-pallowsigned=1 ivltests +sv_assign_pattern_cast CE,-g2005-sv,-pallowsigned=1 ivltests +sv_assign_pattern_const CE,-g2005-sv,-pallowsigned=1 ivltests +sv_assign_pattern_concat CE,-g2005-sv,-pallowsigned=1 ivltests +sv_assign_pattern_expand CE,-g2005,-sv-pallowsigned=1 ivltests +sv_assign_pattern_func CE,-g2005-sv,-pallowsigned=1 ivltests +sv_assign_pattern_op CE,-g2005-sv,-pallowsigned=1 ivltests +sv_assign_pattern_part CE,-g2005-sv,-pallowsigned=1 ivltests sv_array_assign_pattern2 CE,-g2009,-pallowsigned=1 ivltests sv_cast_darray CE,-g2005-sv,-pallowsigned=1 ivltests sv_darray1 CE,-g2009,-pallowsigned=1 ivltests