From eab37efb561259df7e27aa26f080a7b0f2ca48a1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 May 2022 10:16:13 +0200 Subject: [PATCH 1/5] vvp: Handle fully out-of-bounds write for `%assign/vec4/a/{d,e}` The `%assign/vec4/a/{d,e}` instructions, when checking for a full out-of-bounds write on the low side, uses the target signal width, while it should use the assigned value width. This can lead to a fully out-of-bounds write to be assumed to be a partial out-of-bounds access, which will trigger an assert later on. E.g. ``` integer a[1:0]; integer i = -4; a[0][i+:4] <= 4'h0; // Triggers assert ``` Signed-off-by: Lars-Peter Clausen --- vvp/vthread.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 439e7529b..eeaff8588 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -1159,7 +1159,7 @@ bool of_ASSIGN_VEC4_A_D(vthread_t thr, vvp_code_t cp) if (off >= (long)array_wid) return true; if (off < 0) { - if ((unsigned)-off >= array_wid) + if ((unsigned)-off >= wid) return true; int use_off = -off; @@ -1201,7 +1201,7 @@ bool of_ASSIGN_VEC4_A_E(vthread_t thr, vvp_code_t cp) if (off >= (long)array_wid) return true; if (off < 0) { - if ((unsigned)-off >= array_wid) + if ((unsigned)-off >= wid) return true; int use_off = -off; From ce9f3d5e591b38814d2f6a1b01fe337ae25908dc Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 17 May 2022 11:04:25 +0200 Subject: [PATCH 2/5] vvp: Add helper function for vector (partial) out-of-bounds write There are a few functions that handle implement different kinds of vector writes that have to handle that the assigned value partially or completely out-of-bounds. Each function has similar, but not identical, code for this, sometimes with small bugs for corner cases. Add a helper function that takes care of handling of updating the width and offset of the assigned value if necessary. This ensure consistent and correct behavior and allow to remove some duplicated code. Signed-off-by: Lars-Peter Clausen --- vvp/vthread.cc | 202 ++++++++++++++++--------------------------------- 1 file changed, 66 insertions(+), 136 deletions(-) diff --git a/vvp/vthread.cc b/vvp/vthread.cc index eeaff8588..5733fbc0a 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -1134,6 +1134,50 @@ bool of_ASSIGN_VEC4(vthread_t thr, vvp_code_t cp) return true; } +/* + * Resizes a vector value for a partial assignment so that the value is fully + * in-bounds of the target signal. Both `val` and `off` will be updated if + * necessary. + * + * Returns false if the value is fully out-of-bounds and the assignment should + * be skipped. Otherwise returns true. + */ +static bool resize_rval_vec(vvp_vector4_t &val, int64_t &off, + unsigned int sig_wid) +{ + unsigned int wid = val.size(); + + // Fully in bounds, most likely case + if (off >= 0 && (uint64_t)off + wid <= sig_wid) + return true; + + unsigned int base = 0; + if (off >= 0) { + // Fully out-of-bounds + if ((uint64_t)off >= sig_wid) + return false; + } else { + // Fully out-of-bounds */ + if ((uint64_t)(-off) >= wid) + return false; + + // If the index is below the vector, then only assign the high + // bits that overlap with the target + base = -off; + wid += off; + off = 0; + } + + // If the value is partly above the target, then only assign + // the bits that overlap + if ((uint64_t)off + wid > sig_wid) + wid = sig_wid - (uint64_t)off; + + val = val.subvalue(base, wid); + + return true; +} + /* * %assign/vec4/a/d , , */ @@ -1143,35 +1187,19 @@ bool of_ASSIGN_VEC4_A_D(vthread_t thr, vvp_code_t cp) int del_idx = cp->bit_idx[1]; int adr_idx = 3; - long off = off_idx? thr->words[off_idx].w_int : 0; + int64_t off = off_idx ? thr->words[off_idx].w_int : 0; vvp_time64_t del = del_idx? thr->words[del_idx].w_uint : 0; long adr = thr->words[adr_idx].w_int; vvp_vector4_t val = thr->pop_vec4(); - unsigned wid = val.size(); - const unsigned array_wid = cp->array->get_word_size(); // Abort if flags[4] is set. This can happen if the calculation // into an index register failed. if (thr->flags[4] == BIT4_1) return true; - if (off >= (long)array_wid) + if (!resize_rval_vec(val, off, cp->array->get_word_size())) return true; - if (off < 0) { - if ((unsigned)-off >= wid) - return true; - - int use_off = -off; - assert(wid > (unsigned)use_off); - unsigned use_wid = wid - use_off; - val = val.subvalue(use_off, use_wid); - off = 0; - wid = use_wid; - } - if (off+wid > array_wid) { - val = val.subvalue(0, array_wid-off); - } schedule_assign_array_word(cp->array, adr, off, val, del); @@ -1186,34 +1214,18 @@ bool of_ASSIGN_VEC4_A_E(vthread_t thr, vvp_code_t cp) int off_idx = cp->bit_idx[0]; int adr_idx = 3; - long off = off_idx? thr->words[off_idx].w_int : 0; + int64_t off = off_idx ? thr->words[off_idx].w_int : 0; long adr = thr->words[adr_idx].w_int; vvp_vector4_t val = thr->pop_vec4(); - unsigned wid = val.size(); - const unsigned array_wid = cp->array->get_word_size(); // Abort if flags[4] is set. This can happen if the calculation // into an index register failed. if (thr->flags[4] == BIT4_1) return true; - if (off >= (long)array_wid) + if (!resize_rval_vec(val, off, cp->array->get_word_size())) return true; - if (off < 0) { - if ((unsigned)-off >= wid) - return true; - - int use_off = -off; - assert(wid > (unsigned)use_off); - unsigned use_wid = wid - use_off; - val = val.subvalue(use_off, use_wid); - off = 0; - wid = use_wid; - } - if (off+wid > array_wid) { - val = val.subvalue(0, array_wid-off); - } if (thr->ecount == 0) { schedule_assign_array_word(cp->array, adr, off, val, 0); @@ -1233,9 +1245,8 @@ bool of_ASSIGN_VEC4_OFF_D(vthread_t thr, vvp_code_t cp) unsigned off_index = cp->bit_idx[0]; unsigned del_index = cp->bit_idx[1]; vvp_vector4_t val = thr->pop_vec4(); - unsigned wid = val.size(); - int off = thr->words[off_index].w_int; + int64_t off = thr->words[off_index].w_int; vvp_time64_t del = thr->words[del_index].w_uint; // Abort if flags[4] is set. This can happen if the calculation @@ -1246,22 +1257,8 @@ bool of_ASSIGN_VEC4_OFF_D(vthread_t thr, vvp_code_t cp) vvp_signal_value*sig = dynamic_cast (cp->net->fil); assert(sig); - if (off >= (long)sig->value_size()) + if (!resize_rval_vec(val, off, sig->value_size())) return true; - if (off < 0) { - if ((unsigned)-off >= wid) - return true; - - int use_off = -off; - assert(wid > (unsigned)use_off); - unsigned use_wid = wid - use_off; - val = val.subvalue(use_off, use_wid); - off = 0; - wid = use_wid; - } - if (off+wid > sig->value_size()) { - val = val.subvalue(0, sig->value_size()-off); - } schedule_assign_vector(ptr, off, sig->value_size(), val, del); return true; @@ -1275,9 +1272,8 @@ bool of_ASSIGN_VEC4_OFF_E(vthread_t thr, vvp_code_t cp) vvp_net_ptr_t ptr (cp->net, 0); unsigned off_index = cp->bit_idx[0]; vvp_vector4_t val = thr->pop_vec4(); - unsigned wid = val.size(); - int off = thr->words[off_index].w_int; + int64_t off = thr->words[off_index].w_int; // Abort if flags[4] is set. This can happen if the calculation // into an index register failed. @@ -1287,22 +1283,8 @@ bool of_ASSIGN_VEC4_OFF_E(vthread_t thr, vvp_code_t cp) vvp_signal_value*sig = dynamic_cast (cp->net->fil); assert(sig); - if (off >= (long)sig->value_size()) + if (!resize_rval_vec(val, off, sig->value_size())) return true; - if (off < 0) { - if ((unsigned)-off >= wid) - return true; - - int use_off = -off; - assert((int)wid > use_off); - unsigned use_wid = wid - use_off; - val = val.subvalue(use_off, use_wid); - off = 0; - wid = use_wid; - } - if (off+wid > sig->value_size()) { - val = val.subvalue(0, sig->value_size()-off); - } if (thr->ecount == 0) { schedule_assign_vector(ptr, off, sig->value_size(), val, 0); @@ -5455,58 +5437,31 @@ bool of_RET_VEC4(vthread_t thr, vvp_code_t cp) { size_t index = cp->number; unsigned off_index = cp->bit_idx[0]; - int wid = cp->bit_idx[1]; + unsigned int wid = cp->bit_idx[1]; vvp_vector4_t&val = thr->peek_vec4(); vthread_t fun_thr = get_func(thr); assert(index < get_max(fun_thr, val)); unsigned depth = get_depth(fun_thr, index, val); - int off = off_index? thr->words[off_index].w_int : 0; - const int sig_value_size = fun_thr->parent->peek_vec4(depth).size(); - - unsigned val_size = val.size(); + int64_t off = off_index ? thr->words[off_index].w_int : 0; + unsigned int sig_value_size = fun_thr->parent->peek_vec4(depth).size(); if (off_index!=0 && thr->flags[4] == BIT4_1) { thr->pop_vec4(1); return true; } - if (off <= -wid) { + if (!resize_rval_vec(val, off, sig_value_size)) { thr->pop_vec4(1); return true; } - if (off >= sig_value_size) { - thr->pop_vec4(1); - return true; - } - - // If the index is below the vector, then only assign the high - // bits that overlap with the target - if (off < 0) { - int use_off = -off; - wid -= use_off; - val = val.subvalue(use_off, wid); - val_size = wid; - off = 0; - } - - // If the value is partly above the target, then only assign - // the bits that overlap - if ((off+wid) > sig_value_size) { - wid = sig_value_size - off; - val = val.subvalue(0, wid); - val.resize(wid); - val_size = wid; - } - - if (off==0 && val_size==(unsigned)sig_value_size) { + if (off == 0 && val.size() == sig_value_size) { fun_thr->parent->poke_vec4(depth, val); - } else { vvp_vector4_t tmp_dst = fun_thr->parent->peek_vec4(depth); - assert(wid>=0 && val.size() == (unsigned)wid); + assert(val.size() == wid); tmp_dst.set_vec(off, val); fun_thr->parent->poke_vec4(depth, tmp_dst); } @@ -6247,23 +6202,22 @@ bool of_STORE_VEC4(vthread_t thr, vvp_code_t cp) vvp_net_ptr_t ptr(cp->net, 0); vvp_signal_value*sig = dynamic_cast (cp->net->fil); unsigned off_index = cp->bit_idx[0]; - int wid = cp->bit_idx[1]; + unsigned int wid = cp->bit_idx[1]; - int off = off_index? thr->words[off_index].w_int : 0; - const int sig_value_size = sig->value_size(); + int64_t off = off_index ? thr->words[off_index].w_int : 0; + unsigned int sig_value_size = sig->value_size(); vvp_vector4_t&val = thr->peek_vec4(); unsigned val_size = val.size(); - if ((int)val_size < wid) { + if (val_size < wid) { cerr << thr->get_fileline() << "XXXX Internal error: val.size()=" << val_size << ", expecting >= " << wid << endl; } - assert((int)val_size >= wid); - if ((int)val_size > wid) { + assert(val_size >= wid); + if (val_size > wid) { val.resize(wid); - val_size = wid; } // If there is a problem loading the index register, flags-4 @@ -6273,36 +6227,12 @@ bool of_STORE_VEC4(vthread_t thr, vvp_code_t cp) return true; } - if (off <= -wid) { - thr->pop_vec4(1); - return true; - } - if (off >= sig_value_size) { + if (!resize_rval_vec(val, off, sig_value_size)) { thr->pop_vec4(1); return true; } - // If the index is below the vector, then only assign the high - // bits that overlap with the target. - if (off < 0) { - int use_off = -off; - wid -= use_off; - val = val.subvalue(use_off, wid); - val_size = wid; - off = 0; - } - - // If the value is partly above the target, then only assign - // the bits that overlap. - if ((off+wid) > sig_value_size) { - wid = sig_value_size - off; - val = val.subvalue(0, wid); - val.resize(wid); - val_size = wid; - } - - - if (off==0 && val_size==(unsigned)sig_value_size) + if (off == 0 && val.size() == sig_value_size) vvp_send_vec4(ptr, val, thr->wt_context); else vvp_send_vec4_pv(ptr, val, off, sig_value_size, thr->wt_context); From 9a50956f5e459c316ef9d01df52b4748ca01c974 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 28 May 2022 09:59:16 +0200 Subject: [PATCH 3/5] vvp: Handle (partial) out-of-bounds writes for `%store/vec4a` The `%store/vec4a` instruction does not handle partial of full out-of-bounds writes to a vector array element. Trying to do so will trigger an assert. E.g. ``` integer a[3:0]; integer i = -10; a[0][i+:8] = 8'h0; // Triggers assert ``` For fully out-of-bounds writes the write should be skipped, for partial out-of-bounds writes the value needs to be resized to be within the bounds of the vector. Use the `resize_rval_vec()` helper function to implement this. Signed-off-by: Lars-Peter Clausen --- vvp/vthread.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 5733fbc0a..41950c58e 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -6249,10 +6249,8 @@ bool of_STORE_VEC4A(vthread_t thr, vvp_code_t cp) unsigned adr_index = cp->bit_idx[0]; unsigned off_index = cp->bit_idx[1]; - const vvp_vector4_t&value = thr->peek_vec4(); - long adr = adr_index? thr->words[adr_index].w_int : 0; - long off = off_index? thr->words[off_index].w_int : 0; + int64_t off = off_index ? thr->words[off_index].w_int : 0; // Suppress action if flags-4 is true. if (thr->flags[4] == BIT4_1) { @@ -6260,6 +6258,13 @@ bool of_STORE_VEC4A(vthread_t thr, vvp_code_t cp) return true; } + vvp_vector4_t &value = thr->peek_vec4(); + + if (!resize_rval_vec(value, off, cp->array->get_word_size())) { + thr->pop_vec4(1); + return true; + } + cp->array->set_word(adr, off, value); thr->pop_vec4(1); From 2346cc8b69f9de311b786eb4aa0f82dec12bf231 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Jan 2022 10:00:22 +0100 Subject: [PATCH 4/5] vvp: Implement partial writes to 2-state arrays Writes to 2-state arrays currently only support full writes. If the write is a partial write it will trigger an assert. E.g. ``` int a[3:0] int i = -1; a[i+:8] = 8'h0; // Triggers assert ``` Add support for partial writes by doing a read-modify-write in the same way as for 4-state arrays. Signed-off-by: Lars-Peter Clausen --- vvp/array.cc | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/vvp/array.cc b/vvp/array.cc index 6f7d01c5d..4727a4ebf 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -602,10 +602,21 @@ void __vpiArray::set_word(unsigned address, unsigned part_off, const vvp_vector4 if (vals) { assert(nets == 0); - // FIXME: For now, assume no part select of word? - assert(part_off==0); - assert(val.size() == vals_width); - vals->set_word(address, val); + if (part_off != 0 || val.size() != vals_width) { + vvp_vector4_t tmp; + vals->get_word(address, tmp); + if ((part_off + val.size()) > tmp.size()) { + cerr << "part_off=" << part_off + << " val.size()=" << val.size() + << " vals[address].size()=" << tmp.size() + << " vals_width=" << vals_width << endl; + assert(0); + } + tmp.set_vec(part_off, val); + vals->set_word(address, tmp); + } else { + vals->set_word(address, val); + } word_change(address); return; } From dbd92bd3cdffcc4824a648efd22615b20e5c9472 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 3 Jun 2022 10:35:37 +0200 Subject: [PATCH 5/5] Add regression tests for partial writes to vectors Add regression tests for the following types partial writes for both 2-state and 4-state vectors. * Non-blocking * Blocking * Blocking event control Check that all in-bounds partial writes, partial out-of-bounds and full out-of-bounds all works as expected. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/pv_wr_vec2.v | 95 +++++++++++++++++++++++ ivtest/ivltests/pv_wr_vec2_nb.v | 112 +++++++++++++++++++++++++++ ivtest/ivltests/pv_wr_vec2_nb_ec.v | 114 ++++++++++++++++++++++++++++ ivtest/ivltests/pv_wr_vec2a.v | 95 +++++++++++++++++++++++ ivtest/ivltests/pv_wr_vec2a_nb.v | 112 +++++++++++++++++++++++++++ ivtest/ivltests/pv_wr_vec2a_nb_ec.v | 114 ++++++++++++++++++++++++++++ ivtest/ivltests/pv_wr_vec4.v | 99 ++++++++++++++++++++++++ ivtest/ivltests/pv_wr_vec4_nb.v | 111 +++++++++++++++++++++++++++ ivtest/ivltests/pv_wr_vec4_nb_ec.v | 114 ++++++++++++++++++++++++++++ ivtest/ivltests/pv_wr_vec4a.v | 99 ++++++++++++++++++++++++ ivtest/ivltests/pv_wr_vec4a_nb.v | 112 +++++++++++++++++++++++++++ ivtest/ivltests/pv_wr_vec4a_nb_ec.v | 114 ++++++++++++++++++++++++++++ ivtest/regress-sv.list | 6 ++ ivtest/regress-vlg.list | 6 ++ 14 files changed, 1303 insertions(+) create mode 100644 ivtest/ivltests/pv_wr_vec2.v create mode 100644 ivtest/ivltests/pv_wr_vec2_nb.v create mode 100644 ivtest/ivltests/pv_wr_vec2_nb_ec.v create mode 100644 ivtest/ivltests/pv_wr_vec2a.v create mode 100644 ivtest/ivltests/pv_wr_vec2a_nb.v create mode 100644 ivtest/ivltests/pv_wr_vec2a_nb_ec.v create mode 100644 ivtest/ivltests/pv_wr_vec4.v create mode 100644 ivtest/ivltests/pv_wr_vec4_nb.v create mode 100644 ivtest/ivltests/pv_wr_vec4_nb_ec.v create mode 100644 ivtest/ivltests/pv_wr_vec4a.v create mode 100644 ivtest/ivltests/pv_wr_vec4a_nb.v create mode 100644 ivtest/ivltests/pv_wr_vec4a_nb_ec.v diff --git a/ivtest/ivltests/pv_wr_vec2.v b/ivtest/ivltests/pv_wr_vec2.v new file mode 100644 index 000000000..4d82175c0 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec2.v @@ -0,0 +1,95 @@ +// Check that blocking partial writes to a 2-state vector are correctly +// handlded. + +module test; + + reg failed = 1'b0; + + `define check(val, exp) \ + if (exp !== val) begin \ + $display("FAILED. Got %b, expected %b.", val, exp); \ + failed = 1'b1; \ + end + + bit [3:0] x; + integer i; + + initial begin + // Immediate index + + // Within bounds + x = 'h0; + x[2:1] = 2'b10; + `check(x, 4'b0100) + + // Partially oob at high and low side + x = 'h0; + x[4:-1] = 6'b101010; + `check(x, 4'b0101) + // Partially oob at low side + x = 'h0; + x[0:-1] = 2'b10; + `check(x, 4'b0001) + // Partially oob at high side + x = 'h0; + x[4:3] = 2'b01; + `check(x, 4'b1000) + // Fully oob at low side + x = 'h0; + x[-1:-2] = 2'b11; + `check(x, 4'b0000) + // Fully oob at high side + x = 'h0; + x[6:5] = 2'b11; + `check(x, 4'b0000) + + // Variable index + + // Within bounds + i = 1; + x = 'h0; + x[i+:2] = 2'b10; + `check(x, 4'b0100) + + // Partially oob at high and low side + i = -1; + x = 'h0; + x[i+:6] = 6'b101010; + `check(x, 4'b0101) + + // Partially oob at low side + i = -1; + x = 'h0; + x[i+:2] = 2'b10; + `check(x, 4'b0001) + + // Partially oob at high side + i = 3; + x = 'h0; + x[i+:2] = 2'b01; + `check(x, 4'b1000) + + // Fully oob at low side + i = -2; + x = 'h0; + x[i+:2] = 2'b11; + `check(x, 4'b0000) + + // Fully oob at high side + i = 5; + x = 'h0; + x[i+:2] = 2'b11; + `check(x, 4'b0000) + + // Undefined index + i = 'hx; + x = 'h0; + x[i+:2] = 2'b11; + `check(x, 4'b0000) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec2_nb.v b/ivtest/ivltests/pv_wr_vec2_nb.v new file mode 100644 index 000000000..a457551a6 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec2_nb.v @@ -0,0 +1,112 @@ +// Check that non-blocking partial writes to a 2-state vector are correctly +// handlded. + +module test; + + reg failed = 1'b0; + + `define check(val, exp) \ + if (exp !== val) begin \ + $display("FAILED. Got %b, expected %b.", val, exp); \ + failed = 1'b1; \ + end + + bit [3:0] x; + integer i; + + initial begin + // Immediate index + + // Within bounds + x = 'h0; + x[2:1] <= 2'b10; + #1 + `check(x, 4'b0100) + + // Partially oob at high and low side + x = 'h0; + x[4:-1] <= 6'b101010; + #1 + `check(x, 4'b0101) + + // Partially oob at low side + x = 'h0; + x[0:-1] <= 2'b10; + #1 + `check(x, 4'b0001) + + // Partially oob at high side + x = 'h0; + x[4:3] <= 2'b01; + #1 + `check(x, 4'b1000) + + // Fully oob at low side + x = 'h0; + x[-1:-2] <= 2'b11; + #1 + `check(x, 4'b0000) + + // Fully oob at high side + x = 'h0; + x[6:5] <= 2'b11; + #1 + `check(x, 4'b0000) + + // Variable index + + // Within bounds + i = 1; + x = 'h0; + x[i+:2] <= 2'b10; + #1 + `check(x, 4'b0100) + + // Partially oob at high and low side + i = -1; + x = 'h0; + x[i+:6] <= 6'b101010; + #1 + `check(x, 4'b0101) + + // Partially oob at low side + i = -1; + x = 'h0; + x[i+:2] <= 2'b10; + #1 + `check(x, 4'b0001) + + // Partially oob at high side + i = 3; + x = 'h0; + x[i+:2] <= 2'b01; + #1 + `check(x, 4'b1000) + + // Fully oob at low side + i = -2; + x = 'h0; + x[i+:2] <= 2'b11; + #1 + `check(x, 4'b0000) + + // Fully oob at high side + i = 5; + x = 'h0; + x[i+:2] <= 2'b11; + #1 + `check(x, 4'b0000) + + // Undefined index + i = 'hx; + x = 'h0; + x[i+:2] <= 2'b11; + #1 + `check(x, 4'b0000) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec2_nb_ec.v b/ivtest/ivltests/pv_wr_vec2_nb_ec.v new file mode 100644 index 000000000..c81966665 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec2_nb_ec.v @@ -0,0 +1,114 @@ +// Check that non-blocking event controlled partial writes to a 2-state vector +// are correctly handlded. + +module test; + + reg failed = 1'b0; + + `define check(val, exp) \ + if (exp !== val) begin \ + $display("FAILED. Got %b, expected %b.", val, exp); \ + failed = 1'b1; \ + end + + bit [3:0] x; + integer i; + + event e; + + initial begin + // Immediate index + + // Within bounds + x = 'h0; + x[2:1] <= @e 2'b10; + -> e; + `check(x, 4'b0100) + + // Partially oob at high and low side + x = 'h0; + x[4:-1] <= @e 6'b101010; + -> e; + `check(x, 4'b0101) + + // Partially oob at low side + x = 'h0; + x[0:-1] <= @e 2'b10; + -> e; + `check(x, 4'b0001) + + // Partially oob at high side + x = 'h0; + x[4:3] <= @e 2'b01; + -> e; + `check(x, 4'b1000) + + // Fully oob at low side + x = 'h0; + x[-1:-2] <= @e 2'b11; + -> e; + `check(x, 4'b0000) + + // Fully oob at high side + x = 'h0; + x[6:5] <= @e 2'b11; + -> e; + `check(x, 4'b0000) + + // Variable index + + // Within bounds + i = 1; + x = 'h0; + x[i+:2] <= @e 2'b10; + -> e; + `check(x, 4'b0100) + + // Partially oob at high and low side + i = -1; + x = 'h0; + x[i+:6] <= @e 6'b101010; + -> e; + `check(x, 4'b0101) + + // Partially oob at low side + i = -1; + x = 'h0; + x[i+:2] <= @e 2'b10; + -> e; + `check(x, 4'b0001) + + // Partially oob at high side + i = 3; + x = 'h0; + x[i+:2] <= @e 2'b01; + -> e; + `check(x, 4'b1000) + + // Fully oob at low side + i = -2; + x = 'h0; + x[i+:2] <= @e 2'b11; + -> e; + `check(x, 4'b0000) + + // Fully oob at high side + i = 5; + x = 'h0; + x[i+:2] <= @e 2'b11; + -> e; + `check(x, 4'b0000) + + // Undefined index + i = 'hx; + x = 'h0; + x[i+:2] <= @e 2'b11; + -> e; + `check(x, 4'b0000) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec2a.v b/ivtest/ivltests/pv_wr_vec2a.v new file mode 100644 index 000000000..d97d21d8d --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec2a.v @@ -0,0 +1,95 @@ +// Check that blocking partial writes to a 2-state vector array element are +// correctly handlded. + +module test; + + reg failed = 1'b0; + + `define check(val, exp) \ + if (exp !== val) begin \ + $display("FAILED. Got %b, expected %b.", val, exp); \ + failed = 1'b1; \ + end + + bit [3:0] x[1:0]; + integer i; + + initial begin + // Immediate index + + // Within bounds + x[0] = 'h0; + x[0][2:1] = 2'b10; + `check(x[0], 4'b0100) + + // Partially oob at high and low side + x[0] = 'h0; + x[0][4:-1] = 6'b101010; + `check(x[0], 4'b0101) + // Partially oob at low side + x[0] = 'h0; + x[0][0:-1] = 2'b10; + `check(x[0], 4'b0001) + // Partially oob at high side + x[0] = 'h0; + x[0][4:3] = 2'b01; + `check(x[0], 4'b1000) + // Fully oob at low side + x[0] = 'h0; + x[0][-1:-2] = 2'b11; + `check(x[0], 4'b0000) + // Fully oob at high side + x[0] = 'h0; + x[0][6:5] = 2'b11; + `check(x[0], 4'b0000) + + // Variable index + + // Within bounds + i = 1; + x[0] = 'h0; + x[0][i+:2] = 2'b10; + `check(x[0], 4'b0100) + + // Partially oob at high and low side + i = -1; + x[0] = 'h0; + x[0][i+:6] = 6'b101010; + `check(x[0], 4'b0101) + + // Partially oob at low side + i = -1; + x[0] = 'h0; + x[0][i+:2] = 2'b10; + `check(x[0], 4'b0001) + + // Partially oob at high side + i = 3; + x[0] = 'h0; + x[0][i+:2] = 2'b01; + `check(x[0], 4'b1000) + + // Fully oob at low side + i = -2; + x[0] = 'h0; + x[0][i+:2] = 2'b11; + `check(x[0], 4'b0000) + + // Fully oob at high side + i = 5; + x[0] = 'h0; + x[0][i+:2] = 2'b11; + `check(x[0], 4'b0000) + + // Undefined index + i = 'hx; + x[0] = 'h0; + x[0][i+:2] = 2'b11; + `check(x[0], 4'b0000) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec2a_nb.v b/ivtest/ivltests/pv_wr_vec2a_nb.v new file mode 100644 index 000000000..2093d9bf2 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec2a_nb.v @@ -0,0 +1,112 @@ +// Check that non-blocking partial writes to a 2-state vector array element are +// correctly handlded. + +module test; + + reg failed = 1'b0; + + `define check(val, exp) \ + if (exp !== val) begin \ + $display("FAILED. Got %b, expected %b.", val, exp); \ + failed = 1'b1; \ + end + + bit [3:0] x[1:0]; + integer i; + + initial begin + // Immediate index + + // Within bounds + x[0] = 'h0; + x[0][2:1] <= 2'b10; + #1 + `check(x[0], 4'b0100) + + // Partially oob at high and low side + x[0] = 'h0; + x[0][4:-1] <= 6'b101010; + #1 + `check(x[0], 4'b0101) + + // Partially oob at low side + x[0] = 'h0; + x[0][0:-1] <= 2'b10; + #1 + `check(x[0], 4'b0001) + + // Partially oob at high side + x[0] = 'h0; + x[0][4:3] <= 2'b01; + #1 + `check(x[0], 4'b1000) + + // Fully oob at low side + x[0] = 'h0; + x[0][-1:-2] <= 2'b11; + #1 + `check(x[0], 4'b0000) + + // Fully oob at high side + x[0] = 'h0; + x[0][6:5] <= 2'b11; + #1 + `check(x[0], 4'b0000) + + // Variable index + + // Within bounds + i = 1; + x[0] = 'h0; + x[0][i+:2] = 2'b10; + #1 + `check(x[0], 4'b0100) + + // Partially oob at high and low side + i = -1; + x[0] = 'h0; + x[0][i+:6] <= 6'b101010; + #1 + `check(x[0], 4'b0101) + + // Partially oob at low side + i = -1; + x[0] = 'h0; + x[0][i+:2] <= 2'b10; + #1 + `check(x[0], 4'b0001) + + // Partially oob at high side + i = 3; + x[0] = 'h0; + x[0][i+:2] <= 2'b01; + #1 + `check(x[0], 4'b1000) + + // Fully oob at low side + i = -2; + x[0] = 'h0; + x[0][i+:2] <= 2'b11; + #1 + `check(x[0], 4'b0000) + + // Fully oob at high side + i = 5; + x[0] = 'h0; + x[0][i+:2] <= 2'b11; + #1 + `check(x[0], 4'b0000) + + // Undefined index + i = 'hx; + x[0] = 'h0; + x[0][i+:2] <= 2'b11; + #1 + `check(x[0], 4'b0000) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec2a_nb_ec.v b/ivtest/ivltests/pv_wr_vec2a_nb_ec.v new file mode 100644 index 000000000..479dbe5a2 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec2a_nb_ec.v @@ -0,0 +1,114 @@ +// Check that non-blocking event controlled partial writes to a 2-state vector +// array element are correctly handlded. + +module test; + + reg failed = 1'b0; + + `define check(val, exp) \ + if (exp !== val) begin \ + $display("FAILED. Got %b, expected %b.", val, exp); \ + failed = 1'b1; \ + end + + bit [3:0] x[1:0]; + integer i; + + event e; + + initial begin + // Immediate index + + // Within bounds + x[0] = 'h0; + x[0][2:1] <= @e 2'b10; + -> e; + `check(x[0], 4'b0100) + + // Partially oob at high and low side + x[0] = 'h0; + x[0][4:-1] <= @e 6'b101010; + -> e; + `check(x[0], 4'b0101) + + // Partially oob at low side + x[0] = 'h0; + x[0][0:-1] <= @e 2'b10; + -> e; + `check(x[0], 4'b0001) + + // Partially oob at high side + x[0] = 'h0; + x[0][4:3] <= @e 2'b01; + -> e; + `check(x[0], 4'b1000) + + // Fully oob at low side + x[0] = 'h0; + x[0][-1:-2] <= @e 2'b11; + -> e; + `check(x[0], 4'b0000) + + // Fully oob at high side + x[0] = 'h0; + x[0][6:5] <= @e 2'b11; + -> e; + `check(x[0], 4'b0000) + + // Variable index + + // Within bounds + i = 1; + x[0] = 'h0; + x[0][i+:2] <= @e 2'b10; + -> e; + `check(x[0], 4'b0100) + + // Partially oob at high and low side + i = -1; + x[0] = 'h0; + x[0][i+:6] <= @e 6'b101010; + -> e; + `check(x[0], 4'b0101) + + // Partially oob at low side + i = -1; + x[0] = 'h0; + x[0][i+:2] <= @e 2'b10; + -> e; + `check(x[0], 4'b0001) + + // Partially oob at high side + i = 3; + x[0] = 'h0; + x[0][i+:2] <= @e 2'b01; + -> e; + `check(x[0], 4'b1000) + + // Fully oob at low side + i = -2; + x[0] = 'h0; + x[0][i+:2] <= @e 2'b11; + -> e; + `check(x[0], 4'b0000) + + // Fully oob at high side + i = 5; + x[0] = 'h0; + x[0][i+:2] <= @e 2'b11; + -> e; + `check(x[0], 4'b0000) + + // Undefined index + i = 'hx; + x[0] = 'h0; + x[0][i+:2] <= @e 2'b11; + -> e; + `check(x[0], 4'b0000) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec4.v b/ivtest/ivltests/pv_wr_vec4.v new file mode 100644 index 000000000..3db3ab043 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec4.v @@ -0,0 +1,99 @@ +// Check that blocking partial writes to a 4-state vector are correctly +// handlded. + +module test; + + reg failed = 1'b0; + + `define check(val, exp) \ + if (exp !== val) begin \ + $display("FAILED. Got %b, expected %b.", val, exp); \ + failed = 1'b1; \ + end + + reg [3:0] x; + integer i; + + initial begin + // Immediate index + + // Within bounds + x = 'hx; + x[2:1] = 2'b10; + `check(x, 4'bx10x) + + // Partially oob at high and low side + x = 'hx; + x[4:-1] = 6'b101010; + `check(x, 4'b0101) + + // Partially oob at low side + x = 'hx; + x[0:-1] = 2'b10; + `check(x, 4'bxxx1) + + // Partially oob at high side + x = 'hx; + x[4:3] = 2'b01; + `check(x, 4'b1xxx) + + // Fully oob at low side + x = 'hx; + x[-1:-2] = 2'b11; + `check(x, 4'bxxxx) + + // Fully oob at high side + x = 'hx; + x[6:5] = 2'b11; + `check(x, 4'bxxxx) + + // Variable index + + // Within bounds + i = 1; + x = 'hx; + x[i+:2] = 2'b10; + `check(x, 4'bx10x) + + // Partially oob at high and low side + i = -1; + x = 'hx; + x[i+:6] = 6'b101010; + `check(x, 4'b0101) + + // Partially oob at low side + i = -1; + x = 'hx; + x[i+:2] = 2'b10; + `check(x, 4'bxxx1) + + // Partially oob at high side + i = 3; + x = 'hx; + x[i+:2] = 2'b01; + `check(x, 4'b1xxx) + + // Fully oob at low side + i = -2; + x = 'hx; + x[i+:2] = 2'b11; + `check(x, 4'bxxxx) + + // Fully oob at high side + i = 5; + x = 'hx; + x[i+:2] = 2'b11; + `check(x, 4'bxxxx) + + // Undefined index + i = 'hx; + x = 'hx; + x[i+:2] = 2'b11; + `check(x, 4'bxxxx) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec4_nb.v b/ivtest/ivltests/pv_wr_vec4_nb.v new file mode 100644 index 000000000..2d8149b0d --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec4_nb.v @@ -0,0 +1,111 @@ +// Check that non-blocking partial writes to a 4-state vector are correctly +// handlded. + +module test; + + reg failed = 1'b0; + + `define check(val, exp) \ + if (exp !== val) begin \ + $display("FAILED. Got %b, expected %b.", val, exp); \ + failed = 1'b1; \ + end + + reg [3:0] x; + integer i; + + initial begin + // Immediate index + + // Within bounds + x = 'hx; + x[2:1] <= 2'b10; + #1 + `check(x, 4'bx10x) + + // Partially oob at high and low side + x = 'hx; + x[4:-1] <= 6'b101010; + #1 + `check(x, 4'b0101) + + // Partially oob at low side + x = 'hx; + x[0:-1] <= 2'b10; + #1 + `check(x, 4'bxxx1) + + // Partially oob at high side + x = 'hx; + x[4:3] <= 2'b01; + #1 + `check(x, 4'b1xxx) + + // Fully oob at low side + x = 'hx; + x[-1:-2] <= 2'b11; + #1 + `check(x, 4'bxxxx) + + // Fully oob at high side + x = 'hx; + x[6:5] <= 2'b11; + #1 + `check(x, 4'bxxxx) + + // Variable index + + // Within bounds + i = 1; + x = 'hx; + x[i+:2] = 2'b10; + `check(x, 4'bx10x) + + // Partially oob at high and low side + i = -1; + x = 'hx; + x[i+:6] <= 6'b101010; + #1 + `check(x, 4'b0101) + + // Partially oob at low side + i = -1; + x = 'hx; + x[i+:2] <= 2'b10; + #1 + `check(x, 4'bxxx1) + + // Partially oob at high side + i = 3; + x = 'hx; + x[i+:2] <= 2'b01; + #1 + `check(x, 4'b1xxx) + + // Fully oob at low side + i = -2; + x = 'hx; + x[i+:2] <= 2'b11; + #1 + `check(x, 4'bxxxx) + + // Fully oob at high side + i = 5; + x = 'hx; + x[i+:2] <= 2'b11; + #1 + `check(x, 4'bxxxx) + + // Undefined index + i = 'hx; + x = 'hx; + x[i+:2] <= 2'b11; + #1 + `check(x, 4'bxxxx) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec4_nb_ec.v b/ivtest/ivltests/pv_wr_vec4_nb_ec.v new file mode 100644 index 000000000..b89029871 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec4_nb_ec.v @@ -0,0 +1,114 @@ +// Check that non-blocking event controlled partial writes to a 4-state vector +// are correctly handlded. + +module test; + + reg failed = 1'b0; + + `define check(val, exp) \ + if (exp !== val) begin \ + $display("FAILED. Got %b, expected %b.", val, exp); \ + failed = 1'b1; \ + end + + reg [3:0] x; + integer i; + + event e; + + initial begin + // Immediate index + + // Within bounds + x = 'hx; + x[2:1] <= @e 2'b10; + -> e; + `check(x, 4'bx10x) + + // Partially oob at high and low side + x = 'hx; + x[4:-1] <= @e 6'b101010; + -> e; + `check(x, 4'b0101) + + // Partially oob at low side + x = 'hx; + x[0:-1] <= @e 2'b10; + -> e; + `check(x, 4'bxxx1) + + // Partially oob at high side + x = 'hx; + x[4:3] <= @e 2'b01; + -> e; + `check(x, 4'b1xxx) + + // Fully oob at low side + x = 'hx; + x[-1:-2] <= @e 2'b11; + -> e; + `check(x, 4'bxxxx) + + // Fully oob at high side + x = 'hx; + x[6:5] <= @e 2'b11; + -> e; + `check(x, 4'bxxxx) + + // Variable index + + // Within bounds + i = 1; + x = 'hx; + x[i+:2] <= @e 2'b10; + -> e; + `check(x, 4'bx10x) + + // Partially oob at high and low side + i = -1; + x = 'hx; + x[i+:6] <= @e 6'b101010; + -> e; + `check(x, 4'b0101) + + // Partially oob at low side + i = -1; + x = 'hx; + x[i+:2] <= @e 2'b10; + -> e; + `check(x, 4'bxxx1) + + // Partially oob at high side + i = 3; + x = 'hx; + x[i+:2] <= @e 2'b01; + -> e; + `check(x, 4'b1xxx) + + // Fully oob at low side + i = -2; + x = 'hx; + x[i+:2] <= @e 2'b11; + -> e; + `check(x, 4'bxxxx) + + // Fully oob at high side + i = 5; + x = 'hx; + x[i+:2] <= @e 2'b11; + -> e; + `check(x, 4'bxxxx) + + // Undefined index + i = 'hx; + x = 'hx; + x[i+:2] <= @e 2'b11; + -> e; + `check(x, 4'bxxxx) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec4a.v b/ivtest/ivltests/pv_wr_vec4a.v new file mode 100644 index 000000000..a4765c17c --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec4a.v @@ -0,0 +1,99 @@ +// Check that blocking partial writes to a 4-state vector array element are +// correctly handlded. + +module test; + + reg failed = 1'b0; + + `define check(val, exp) \ + if (exp !== val) begin \ + $display("FAILED. Got %b, expected %b.", val, exp); \ + failed = 1'b1; \ + end + + reg [3:0] x[1:0]; + integer i; + + initial begin + // Immediate index + + // Within bounds + x[0] = 'hx; + x[0][2:1] = 2'b10; + `check(x[0], 4'bx10x) + + // Partially oob at high and low side + x[0] = 'hx; + x[0][4:-1] = 6'b101010; + `check(x[0], 4'b0101) + + // Partially oob at low side + x[0] = 'hx; + x[0][0:-1] = 2'b10; + `check(x[0], 4'bxxx1) + + // Partially oob at high side + x[0] = 'hx; + x[0][4:3] = 2'b01; + `check(x[0], 4'b1xxx) + + // Fully oob at low side + x[0] = 'hx; + x[0][-1:-2] = 2'b11; + `check(x[0], 4'bxxxx) + + // Fully oob at high side + x[0] = 'hx; + x[0][6:5] = 2'b11; + `check(x[0], 4'bxxxx) + + // Variable index + + // Within bounds + i = 1; + x[0] = 'hx; + x[0][i+:2] = 2'b10; + `check(x[0], 4'bx10x) + + // Partially oob at high and low side + i = -1; + x[0] = 'hx; + x[0][i+:6] = 6'b101010; + `check(x[0], 4'b0101) + + // Partially oob at low side + i = -1; + x[0] = 'hx; + x[0][i+:2] = 2'b10; + `check(x[0], 4'bxxx1) + + // Partially oob at high side + i = 3; + x[0] = 'hx; + x[0][i+:2] = 2'b01; + `check(x[0], 4'b1xxx) + + // Fully oob at low side + i = -2; + x[0] = 'hx; + x[0][i+:2] = 2'b11; + `check(x[0], 4'bxxxx) + + // Fully oob at high side + i = 5; + x[0] = 'hx; + x[0][i+:2] = 2'b11; + `check(x[0], 4'bxxxx) + + // Undefined index + i = 'hx; + x[0] = 'hx; + x[0][i+:2] = 2'b11; + `check(x[0], 4'bxxxx) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec4a_nb.v b/ivtest/ivltests/pv_wr_vec4a_nb.v new file mode 100644 index 000000000..926991c92 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec4a_nb.v @@ -0,0 +1,112 @@ +// Check that non-blocking partial writes to a 4-state vector array element are +// correctly handlded. + +module test; + + reg failed = 1'b0; + + `define check(val, exp) \ + if (exp !== val) begin \ + $display("FAILED. Got %b, expected %b.", val, exp); \ + failed = 1'b1; \ + end + + reg [3:0] x[1:0]; + integer i; + + initial begin + // Immediate index + + // Within bounds + x[0] = 'hx; + x[0][2:1] <= 2'b10; + #1 + `check(x[0], 4'bx10x) + + // Partially oob at high and low side + x[0] = 'hx; + x[0][4:-1] <= 6'b101010; + #1 + `check(x[0], 4'b0101) + + // Partially oob at low side + x[0] = 'hx; + x[0][0:-1] <= 2'b10; + #1 + `check(x[0], 4'bxxx1) + + // Partially oob at high side + x[0] = 'hx; + x[0][4:3] <= 2'b01; + #1 + `check(x[0], 4'b1xxx) + + // Fully oob at low side + x[0] = 'hx; + x[0][-1:-2] <= 2'b11; + #1 + `check(x[0], 4'bxxxx) + + // Fully oob at high side + x[0] = 'hx; + x[0][6:5] <= 2'b11; + #1 + `check(x[0], 4'bxxxx) + + // Variable index + + // Within bounds + i = 1; + x[0] = 'hx; + x[0][i+:2] <= 2'b10; + #1 + `check(x[0], 4'bx10x) + + // Partially oob at high and low side + i = -1; + x[0] = 'hx; + x[0][i+:6] <= 6'b101010; + #1 + `check(x[0], 4'b0101) + + // Partially oob at low side + i = -1; + x[0] = 'hx; + x[0][i+:2] <= 2'b10; + #1 + `check(x[0], 4'bxxx1) + + // Partially oob at high side + i = 3; + x[0] = 'hx; + x[0][i+:2] <= 2'b01; + #1 + `check(x[0], 4'b1xxx) + + // Fully oob at low side + i = -2; + x[0] = 'hx; + x[0][i+:2] <= 2'b11; + #1 + `check(x[0], 4'bxxxx) + + // Fully oob at high side + i = 5; + x[0] = 'hx; + x[0][i+:2] <= 2'b11; + #1 + `check(x[0], 4'bxxxx) + + // Undefined index + i = 5; + x[0] = 'hx; + x[0][i+:2] <= 2'b11; + #1 + `check(x[0], 4'bxxxx) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/pv_wr_vec4a_nb_ec.v b/ivtest/ivltests/pv_wr_vec4a_nb_ec.v new file mode 100644 index 000000000..c2c08c024 --- /dev/null +++ b/ivtest/ivltests/pv_wr_vec4a_nb_ec.v @@ -0,0 +1,114 @@ +// Check that non-blocking event controlled partial writes to a 4-state vector +// array element are correctly handlded. + +module test; + + reg failed = 1'b0; + + `define check(val, exp) \ + if (exp !== val) begin \ + $display("FAILED. Got %b, expected %b.", val, exp); \ + failed = 1'b1; \ + end + + reg [3:0] x[1:0]; + integer i; + + event e; + + initial begin + // Immediate index + + // Within bounds + x[0] = 'hx; + x[0][2:1] <= @e 2'b10; + -> e; + `check(x[0], 4'bx10x) + + // Partially oob at high and low side + x[0] = 'hx; + x[0][4:-1] <= @e 6'b101010; + -> e; + `check(x[0], 4'b0101) + + // Partially oob at low side + x[0] = 'hx; + x[0][0:-1] <= @e 2'b10; + -> e; + `check(x[0], 4'bxxx1) + + // Partially oob at high side + x[0] = 'hx; + x[0][4:3] <= @e 2'b01; + -> e; + `check(x[0], 4'b1xxx) + + // Fully oob at low side + x[0] = 'hx; + x[0][-1:-2] <= @e 2'b11; + -> e; + `check(x[0], 4'bxxxx) + + // Fully oob at high side + x[0] = 'hx; + x[0][6:5] <= @e 2'b11; + -> e; + `check(x[0], 4'bxxxx) + + // Variable index + + // Within bounds + i = 1; + x[0] = 'hx; + x[0][i+:2] <= @e 2'b10; + -> e; + `check(x[0], 4'bx10x) + + // Partially oob at high and low side + i = -1; + x[0] = 'hx; + x[0][i+:6] <= @e 6'b101010; + -> e; + `check(x[0], 4'b0101) + + // Partially oob at low side + i = -1; + x[0] = 'hx; + x[0][i+:2] <= @e 2'b10; + -> e; + `check(x[0], 4'bxxx1) + + // Partially oob at high side + i = 3; + x[0] = 'hx; + x[0][i+:2] <= @e 2'b01; + -> e; + `check(x[0], 4'b1xxx) + + // Fully oob at low side + i = -2; + x[0] = 'hx; + x[0][i+:2] <= @e 2'b11; + -> e; + `check(x[0], 4'bxxxx) + + // Fully oob at high side + i = 5; + x[0] = 'hx; + x[0][i+:2] <= @e 2'b11; + -> e; + `check(x[0], 4'bxxxx) + + // Undefined index + i = 'hx; + x[0] = 'hx; + x[0][i+:2] <= @e 2'b11; + -> e; + `check(x[0], 4'bxxxx) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index 1c26458d5..a605f9843 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -415,6 +415,12 @@ program5a CE,-g2009 ivltests program5b CE,-g2009 ivltests program_hello normal,-g2009 ivltests program_hello2 CE,-g2009 ivltests +pv_wr_vec2 normal,-g2005-sv ivltests +pv_wr_vec2_nb normal,-g2005-sv ivltests +pv_wr_vec2_nb_ec normal,-g2005-sv ivltests +pv_wr_vec2a normal,-g2005-sv ivltests +pv_wr_vec2a_nb normal,-g2005-sv ivltests +pv_wr_vec2a_nb_ec normal,-g2005-sv ivltests recursive_func2 normal,-g2005-sv ivltests gold=recursive_func.gold recursive_func_const2 normal,-g2005-sv ivltests gold=recursive_func_const.gold sbyte_test normal,-g2005-sv ivltests diff --git a/ivtest/regress-vlg.list b/ivtest/regress-vlg.list index 5300f4d2b..b42886e66 100644 --- a/ivtest/regress-vlg.list +++ b/ivtest/regress-vlg.list @@ -1435,6 +1435,12 @@ pullupdown normal ivltests # Contributed test pullupdown2 normal ivltests # Contributed test pullupdown3 normal ivltests # Contributed test pv_undef_sig_sel normal ivltests +pv_wr_vec4 normal ivltests +pv_wr_vec4_nb normal ivltests +pv_wr_vec4_nb_ec normal ivltests +pv_wr_vec4a normal ivltests +pv_wr_vec4a_nb normal ivltests +pv_wr_vec4a_nb_ec normal ivltests qmark normal ivltests qmark1 normal ivltests qmark3 normal ivltests