From 61c82d2cb0f68be464d4964199738f03b3b0d9df Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 10 May 2016 22:16:40 +0100 Subject: [PATCH] Handle mixed continuous and non-blocking assignments to same vector. SystemVerilog allows a mixture of procedural and continuous assignments to be applied to different parts of the same vector. The previous attempt to make this work for non-blocking assignments was flawed (see preceding fix for vvp_fun_part_pv::recv_vec4_pv). Instead, handle this case by converting the non-blocking assignment into a delayed force statement, which matches the way mixed continuous and blocking assignments are handled. --- tgt-vvp/vvp_process.c | 40 +++++++++++--------- vvp/codes.h | 3 +- vvp/compile.cc | 1 + vvp/opcodes.txt | 8 ++-- vvp/schedule.cc | 85 +++++++++++++++++++++++++++++++++++++++++++ vvp/schedule.h | 9 +++++ vvp/vthread.cc | 32 ++++++++++++++++ 7 files changed, 156 insertions(+), 22 deletions(-) diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 994709fd1..4b41a4bdf 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -225,6 +225,10 @@ static void assign_to_lvector(ivl_lval_t lval, const unsigned long use_word = 0; + const char*assign_op = "%assign"; + if (ivl_signal_type(sig) == IVL_SIT_UWIRE) + assign_op = "%force"; + // Detect the case that this is actually a non-blocking assign // to an array word. In that case, run off somewhere else to // deal with it. @@ -263,8 +267,8 @@ static void assign_to_lvector(ivl_lval_t lval, to know to skip the assign. */ draw_eval_expr_into_integer(part_off_ex, offset_index); /* If the index expression has XZ bits, skip the assign. */ - fprintf(vvp_out, " %%assign/vec4/off/d v%p_%lu, %d, %d;\n", - sig, use_word, offset_index, delay_index); + fprintf(vvp_out, " %s/vec4/off/d v%p_%lu, %d, %d;\n", + assign_op, sig, use_word, offset_index, delay_index); clr_word(offset_index); clr_word(delay_index); @@ -273,8 +277,8 @@ static void assign_to_lvector(ivl_lval_t lval, int offset_index = allocate_word(); /* Event control delay... */ draw_eval_expr_into_integer(part_off_ex, offset_index); - fprintf(vvp_out, " %%assign/vec4/off/e v%p_%lu, %d;\n", - sig, use_word, 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); @@ -292,8 +296,8 @@ static void assign_to_lvector(ivl_lval_t lval, to know to skip the assign. */ draw_eval_expr_into_integer(part_off_ex, offset_index); /* If the index expression has XZ bits, skip the assign. */ - fprintf(vvp_out, " %%assign/vec4/off/d v%p_%lu, %d, %d;\n", - sig, use_word, offset_index, delay_index); + fprintf(vvp_out, " %s/vec4/off/d v%p_%lu, %d, %d;\n", + assign_op, sig, use_word, offset_index, delay_index); clr_word(offset_index); clr_word(delay_index); } @@ -306,8 +310,8 @@ static void assign_to_lvector(ivl_lval_t lval, fprintf(vvp_out, " %%ix/load %d, %lu, 0;\n", offset_index, part_off); fprintf(vvp_out, " %%flag_set/imm 4, 0;\n"); - fprintf(vvp_out, " %%assign/vec4/off/e v%p_%lu, %d;\n", - sig, use_word, 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); @@ -325,8 +329,8 @@ static void assign_to_lvector(ivl_lval_t lval, delay_index, low_d, hig_d); fprintf(vvp_out, " %%flag_set/imm 4, 0;\n"); } - fprintf(vvp_out, " %%assign/vec4/off/d v%p_%lu, %d, %d;\n", - sig, use_word, offset_index, delay_index); + fprintf(vvp_out, " %s/vec4/off/d v%p_%lu, %d, %d;\n", + assign_op, sig, use_word, offset_index, delay_index); clr_word(offset_index); clr_word(delay_index); } @@ -335,13 +339,13 @@ static void assign_to_lvector(ivl_lval_t lval, /* Calculated delay... */ int delay_index = allocate_word(); draw_eval_expr_into_integer(dexp, delay_index); - fprintf(vvp_out, " %%assign/vec4/d v%p_%lu, %d;\n", - sig, use_word, delay_index); + fprintf(vvp_out, " %s/vec4/d v%p_%lu, %d;\n", + assign_op, sig, use_word, delay_index); clr_word(delay_index); } else if (nevents != 0) { /* Event control delay... */ - fprintf(vvp_out, " %%assign/vec4/e v%p_%lu;\n", - sig, use_word); + fprintf(vvp_out, " %s/vec4/e v%p_%lu;\n", + assign_op, sig, use_word); fprintf(vvp_out, " %%evctl/c;\n"); } else { @@ -353,12 +357,12 @@ static void assign_to_lvector(ivl_lval_t lval, int delay_index = allocate_word(); fprintf(vvp_out, " %%ix/load %d, %lu, %lu;\n", delay_index, low_d, hig_d); - fprintf(vvp_out, " %%assign/vec4/d v%p_%lu, %d;\n", - sig, use_word, delay_index); + fprintf(vvp_out, " %s/vec4/d v%p_%lu, %d;\n", + assign_op, sig, use_word, delay_index); clr_word(delay_index); } else { - fprintf(vvp_out, " %%assign/vec4 v%p_%lu, %lu;\n", - sig, use_word, low_d); + fprintf(vvp_out, " %s/vec4 v%p_%lu, %lu;\n", + assign_op, sig, use_word, low_d); } } } diff --git a/vvp/codes.h b/vvp/codes.h index b8db26ae6..41509a97f 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -1,7 +1,7 @@ #ifndef IVL_codes_H #define IVL_codes_H /* - * Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -118,6 +118,7 @@ extern bool of_FLAG_SET_VEC4(vthread_t thr, vvp_code_t code); extern bool of_FORCE_LINK(vthread_t thr, vvp_code_t code); extern bool of_FORCE_VEC4(vthread_t thr, vvp_code_t code); extern bool of_FORCE_VEC4_OFF(vthread_t thr, vvp_code_t code); +extern bool of_FORCE_VEC4_OFF_D(vthread_t thr, vvp_code_t code); extern bool of_FORCE_WR(vthread_t thr, vvp_code_t code); extern bool of_FORK(vthread_t thr, vvp_code_t code); extern bool of_FREE(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index cf80c9094..5de3f87b6 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -169,6 +169,7 @@ static const struct opcode_table_s opcode_table[] = { { "%force/link", of_FORCE_LINK,2,{OA_FUNC_PTR, OA_FUNC_PTR2, OA_NONE} }, { "%force/vec4", of_FORCE_VEC4, 1,{OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%force/vec4/off",of_FORCE_VEC4_OFF,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} }, + { "%force/vec4/off/d",of_FORCE_VEC4_OFF_D,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%force/wr", of_FORCE_WR, 1,{OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%fork", of_FORK, 2, {OA_CODE_PTR2,OA_VPI_PTR, OA_NONE} }, { "%free", of_FREE, 1, {OA_VPI_PTR, OA_NONE, OA_NONE} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 6df430586..2e489e88e 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) * */ @@ -528,15 +528,17 @@ writes the LSB to the selected flag. * %force/vec4