diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index cac098fd3..8fa8830dc 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -802,7 +802,7 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec) switch (ivl_statement_type(net)) { case IVL_ST_CASSIGN: command_name = "%cassign/v"; - command_name_x0 = "ERROR"; + command_name_x0 = "%cassign/x0"; break; case IVL_ST_FORCE: command_name = "%force/v"; @@ -842,12 +842,6 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec) if (part_off != 0 || use_wid != ivl_signal_width(lsig)) { - if (ivl_statement_type(net) == IVL_ST_CASSIGN) { - fprintf(stderr, "%s:%u: vvp-tgt sorry: cannot assign " - "signal to a bit/part select.\n", - ivl_stmt_file(net), ivl_stmt_lineno(net)); - exit(1); - } command_name = command_name_x0; fprintf(vvp_out, " %%ix/load 0, %u;\n", part_off); @@ -967,15 +961,12 @@ static int show_stmt_deassign(ivl_statement_t net) assert(lsig != 0); assert(ivl_lval_mux(lval) == 0); - /* We do not currently support deassigning a bit or - * part select. */ + unsigned use_wid = ivl_lval_width(lval); ivl_expr_t part_off_ex = ivl_lval_part_off(lval); - if (ivl_signal_width(lsig) > ivl_lval_width(lval) || - (part_off_ex && get_number_immediate(part_off_ex) != 0)) { - fprintf(stderr, "%s:%u: vvp-tgt sorry: cannot deassign " - "a bit/part select.\n", ivl_stmt_file(net), - ivl_stmt_lineno(net)); - exit(1); + unsigned part_off = 0; + if (part_off_ex != 0) { + assert(number_is_immediate(part_off_ex, 64)); + part_off = get_number_immediate(part_off_ex); } if (word_idx != 0) { @@ -984,7 +975,8 @@ static int show_stmt_deassign(ivl_statement_t net) } - fprintf(vvp_out, " %%deassign v%p_%lu;\n", lsig, use_word); + fprintf(vvp_out, " %%deassign v%p_%lu, %u, %u;\n", + lsig, use_word, part_off, use_wid); } return 0; diff --git a/vvp/codes.h b/vvp/codes.h index 0b0f7dad7..6cb5c3852 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -52,6 +52,7 @@ extern bool of_BLEND_WR(vthread_t thr, vvp_code_t code); extern bool of_BREAKPOINT(vthread_t thr, vvp_code_t code); extern bool of_CASSIGN_LINK(vthread_t thr, vvp_code_t code); extern bool of_CASSIGN_V(vthread_t thr, vvp_code_t code); +extern bool of_CASSIGN_X0(vthread_t thr, vvp_code_t code); extern bool of_CMPIS(vthread_t thr, vvp_code_t code); extern bool of_CMPIU(vthread_t thr, vvp_code_t code); extern bool of_CMPS(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index ff073ab2f..608232b95 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -101,6 +101,7 @@ const static struct opcode_table_s opcode_table[] = { { "%breakpoint", of_BREAKPOINT, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%cassign/link",of_CASSIGN_LINK,2,{OA_FUNC_PTR,OA_FUNC_PTR2,OA_NONE} }, { "%cassign/v",of_CASSIGN_V,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} }, + { "%cassign/x0",of_CASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} }, { "%cmp/s", of_CMPS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%cmp/u", of_CMPU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%cmp/wr", of_CMPWR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, @@ -113,7 +114,7 @@ const static struct opcode_table_s opcode_table[] = { { "%cvt/ir", of_CVT_IR, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%cvt/ri", of_CVT_RI, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%cvt/vr", of_CVT_VR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%deassign",of_DEASSIGN,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} }, + { "%deassign",of_DEASSIGN,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%delay", of_DELAY, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%delayx", of_DELAYX, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, { "%div", of_DIV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 05156a6ae..6d7c6afa7 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -168,6 +168,13 @@ variable. This is similar to %set, but it uses the cassign port signal responds differently. See "VARIABLE STATEMENTS" in the README.txt file. +* %cassign/x0