diff --git a/ivtest/ivltests/nb_ec_array_pv.v b/ivtest/ivltests/nb_ec_array_pv.v index ad0b5ab8c..a23ce06bc 100644 --- a/ivtest/ivltests/nb_ec_array_pv.v +++ b/ivtest/ivltests/nb_ec_array_pv.v @@ -1,3 +1,6 @@ +// Check that non-blocking event control assignment to a part select on a vector +// array works when using an immediate index. + module top; reg pass = 1'b1; diff --git a/ivtest/ivltests/nb_ec_array_pv2.v b/ivtest/ivltests/nb_ec_array_pv2.v new file mode 100644 index 000000000..b8434b5cb --- /dev/null +++ b/ivtest/ivltests/nb_ec_array_pv2.v @@ -0,0 +1,90 @@ +// Check that non-blocking event control assignment to a part select on a vector +// array works when using a variable index. + +module top; + reg pass = 1'b1; + + integer i = 0; + integer j = 1; + integer count; + reg [2:0] icount; + reg clk = 0; + reg [3:0] in = 4'h0; + reg [7:0] result [1:0]; + + always #10 clk = ~clk; + always #20 in = in + 4'h1; + + initial begin + count = 3; + i = 0; + result[j][i+:4] <= repeat(count) @(posedge clk) in; + if ($simtime != 0 || result[j] !== 8'bx) begin + $display("Failed repeat(3) blocked at %0t, expected 8'hxx, got %h", + $simtime, result[j]); + pass = 1'b0; + end + @(result[j]); + if ($simtime != 50 || result[j] !== 8'hx0) begin + $display("Failed repeat(3) at %0t, expected 8'hx0, got %h", + $simtime, result[j]); + pass = 1'b0; + end + + #15; + count = 0; + result[j][i+4+:4] <= repeat(count) @(posedge clk) in; + @(result[j]); // Reals happen faster so they can use an #0, vectors are slower. + if ($simtime != 65 || result[j] !== 8'h30) begin + $display("Failed repeat(0) at %0t, expected 8'h30, got %h", + $simtime, result[j]); + pass = 1'b0; + end + + #20; + count = -1; + result[j][i+5+:4] <= repeat(count) @(posedge clk) in; + @(result[j]); // Reals happen faster so they can use an #0, vectors are slower. + if ($simtime != 85 || result[j] !== 8'h90) begin + $display("Failed repeat(-1) at %0t, expected 8'h80, got %h", + $simtime, result[j]); + pass = 1'b0; + end + + #20; + result[j][i+4+:4] <= @(posedge clk) 4'h0; + result[j][i+4+:4] <= @(posedge clk) in; // This one sets the final value. + @(result[j]); + if ($simtime != 110 || result[j] !== 8'h50) begin + $display("Failed @ at %0t, expected 8'h50, got %h", + $simtime, result[j]); + pass = 1'b0; + end + + icount = 3'd2; + result[j][i+:4] <= @(posedge clk) 4'h1; + result[j][i+4+:4] <= repeat(icount) @(posedge clk) 4'h2; + result[j][i+1-:4] <= repeat(3) @(posedge clk) 4'h3; + @(result[j]); + if ($simtime != 130 || result[j] !== 8'h51) begin + $display("Failed first @ at %0t, expected 8'h51, got %h", + $simtime, result[j]); + pass = 1'b0; + end + @(result[j]); + if ($simtime != 150 || result[j] !== 8'h21) begin + $display("Failed second @ at %0t, expected 8'h21, got %h", + $simtime, result[j]); + pass = 1'b0; + end + @(result[j]); + if ($simtime != 170 || result[j] !== 8'h20) begin + $display("Failed third @ at %0t, expected 8'h20, got %h", + $simtime, result[j]); + pass = 1'b0; + end + + if (pass) $display("PASSED"); + $finish; + end +endmodule diff --git a/ivtest/ivltests/nb_ec_concat.v b/ivtest/ivltests/nb_ec_concat.v new file mode 100644 index 000000000..a27ae3a99 --- /dev/null +++ b/ivtest/ivltests/nb_ec_concat.v @@ -0,0 +1,104 @@ +// Check that non-blocking event control assignments to concatanations work as +// expected. + +module test; + reg failed = 1'b0; + + `define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED. %s: expected %b, got %b.", `"val`", exp, val); \ + failed = 1'b1; \ + end + + reg [3:0] x; + reg [3:0] y; + reg [3:0] z[1:0]; + + integer i = 0; + event e; + + initial begin + // Test all of + // * vector + // * vector part select + // * array element + // * array element part + + // Immediate index + {z[1][1:0],z[0],y[1:0],x} <= @e 12'h5a5; + #1 + // Assignment must not occur until the event is triggered + `check(z[1], 4'bxxxx) + `check(z[0], 4'bxxxx) + `check(y, 4'bxxxx) + `check(x, 4'bxxxx) + + ->e; + `check(z[1], 4'bxx01); + `check(z[0], 4'b0110); + `check(y, 4'bxx10); + `check(x, 4'b0101); + + x = 4'hx; + y = 4'hx; + z[0] = 4'hx; + z[1] = 4'hx; + + // Immediate index reverse order + {x,y[1:0],z[0],z[1][1:0]} <= @e 12'ha5a; + #1 + `check(z[1], 4'bxxxx) + `check(z[0], 4'bxxxx) + `check(y, 4'bxxxx) + `check(x, 4'bxxxx) + + ->e; + `check(z[1], 4'bxx10); + `check(z[0], 4'b0110); + `check(y, 4'bxx01); + `check(x, 4'b1010); + + x = 4'hx; + y = 4'hx; + z[0] = 4'hx; + z[1] = 4'hx; + + // Variable index + {z[i+1][i+:2],z[i],y[i+:2],x} <= @e 12'h5a5; + #1 + `check(z[1], 4'bxxxx) + `check(z[0], 4'bxxxx) + `check(y, 4'bxxxx) + `check(x, 4'bxxxx) + + ->e; + `check(z[1], 4'bxx01); + `check(z[0], 4'b0110); + `check(y, 4'bxx10); + `check(x, 4'b0101); + + x = 4'hx; + y = 4'hx; + z[0] = 4'hx; + z[1] = 4'hx; + + // Variable index reverse order + {x,y[i+:2],z[i],z[i+1][i+:2]} <= @e 12'ha5a; + #1 + `check(z[1], 4'bxxxx) + `check(z[0], 4'bxxxx) + `check(y, 4'bxxxx) + `check(x, 4'bxxxx) + + ->e; + `check(z[1], 4'bxx10); + `check(z[0], 4'b0110); + `check(y, 4'bxx01); + `check(x, 4'b1010); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/regress-ivl1.list b/ivtest/regress-ivl1.list index 649d38043..effab3aac 100644 --- a/ivtest/regress-ivl1.list +++ b/ivtest/regress-ivl1.list @@ -185,6 +185,7 @@ ca_time_smtm normal ivltests gold=ca_time_smtm.gold nb_array_pv normal ivltests nb_ec_array normal ivltests nb_ec_array_pv normal ivltests +nb_ec_array_pv2 normal ivltests nb_ec_pv normal ivltests nb_ec_pv2 normal ivltests nb_ec_real normal ivltests diff --git a/ivtest/regress-vlg.list b/ivtest/regress-vlg.list index 9a15545ac..74b1c5ed1 100644 --- a/ivtest/regress-vlg.list +++ b/ivtest/regress-vlg.list @@ -676,6 +676,7 @@ muxtest normal ivltests # Validates that X sel and inputs same, output not X named_event_no_edges CE ivltests nb_assign normal ivltests nb_delay normal ivltests +nb_ec_concat normal ivltests nblkorder normal ivltests # Validates Non-blocking order determinism negative_genvar normal ivltests negvalue normal ivltests gold=negvalue.gold diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 9c42bcae6..db5e06fdd 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -179,6 +179,8 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix, /* If needed use the global error state. */ if (part_off_ex) { fprintf(vvp_out, " %%flag_mov 4, %d;\n", error_flag); + fprintf(vvp_out, " %%ix/mov 3, %d;\n", word_ix_reg); + clr_word(word_ix_reg); } fprintf(vvp_out, " %%assign/vec4/a/e v%p, %d;\n", lsig, part_off_reg); @@ -203,8 +205,6 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix, clr_word(delay_index); } - if (nevents != 0) fprintf(vvp_out, " %%evctl/c;\n"); - clr_flag(error_flag); if (part_off_reg) clr_word(part_off_reg); @@ -279,7 +279,6 @@ static void assign_to_lvector(ivl_lval_t lval, draw_eval_expr_into_integer(part_off_ex, offset_index); fprintf(vvp_out, " %s/vec4/off/e v%p_%lu, %d;\n", assign_op, sig, use_word, offset_index); - fprintf(vvp_out, " %%evctl/c;\n"); clr_word(offset_index); @@ -312,7 +311,6 @@ static void assign_to_lvector(ivl_lval_t lval, fprintf(vvp_out, " %%flag_set/imm 4, 0;\n"); fprintf(vvp_out, " %s/vec4/off/e v%p_%lu, %d;\n", assign_op, sig, use_word, offset_index); - fprintf(vvp_out, " %%evctl/c;\n"); clr_word(offset_index); } else { @@ -346,8 +344,6 @@ static void assign_to_lvector(ivl_lval_t lval, /* Event control delay... */ fprintf(vvp_out, " %s/vec4/e v%p_%lu;\n", assign_op, sig, use_word); - fprintf(vvp_out, " %%evctl/c;\n"); - } else { /* * The %assign can only take a 32 bit delay. For a larger @@ -593,6 +589,9 @@ static int show_stmt_assign_nb(ivl_statement_t net) } } + if (nevents) + fprintf(vvp_out, " %%evctl/c;\n"); + return 0; } diff --git a/vvp/vthread.cc b/vvp/vthread.cc index c84ec4e1a..439e7529b 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -1349,8 +1349,6 @@ bool of_ASSIGN_VEC4E(vthread_t thr, vvp_code_t cp) schedule_evctl(ptr, value, 0, sig->value_size(), thr->event, thr->ecount); } - thr->event = 0; - thr->ecount = 0; return true; }