diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index d4028dddf..82c4bd428 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -527,7 +527,7 @@ static struct vector_info draw_binary_expr_eq_class(ivl_expr_t expr) ivl_expr_t word_ex = ivl_expr_oper1(le); int word_ix = allocate_word(); draw_eval_expr_into_integer(word_ex, word_ix); - fprintf(vvp_out, " %%test_nula v%p, %d;\n", sig, word_ix); + fprintf(vvp_out, " %%test_nul/a v%p, %d;\n", sig, word_ix); clr_word(word_ix); } fprintf(vvp_out, " %%mov %u, 4, 1;\n", res.base); @@ -536,6 +536,16 @@ static struct vector_info draw_binary_expr_eq_class(ivl_expr_t expr) return res; } + if (ivl_expr_type(re) == IVL_EX_NULL && ivl_expr_value(le)==IVL_VT_CLASS) { + draw_eval_object(le); + fprintf(vvp_out, " %%test_nul/obj;\n"); + fprintf(vvp_out, " %%pop/obj 1, 0;\n"); + fprintf(vvp_out, " %%mov %u, 4, 1;\n", res.base); + if (ivl_expr_opcode(expr) == 'n') + fprintf(vvp_out, " %%inv %u, 1;\n", res.base); + return res; + } + fprintf(stderr, "SORRY: Compare class handles not implemented\n"); fprintf(vvp_out, " ; XXXX compare class handles.\n"); vvp_errors += 1; diff --git a/vvp/codes.h b/vvp/codes.h index bbb555c7d..05e4af45d 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -219,7 +219,8 @@ extern bool of_SUBI(vthread_t thr, vvp_code_t code); extern bool of_SUBSTR(vthread_t thr, vvp_code_t code); extern bool of_SUBSTR_V(vthread_t thr, vvp_code_t code); extern bool of_TEST_NUL(vthread_t thr, vvp_code_t code); -extern bool of_TEST_NULA(vthread_t thr, vvp_code_t code); +extern bool of_TEST_NUL_A(vthread_t thr, vvp_code_t code); +extern bool of_TEST_NUL_OBJ(vthread_t thr, vvp_code_t code); extern bool of_VPI_CALL(vthread_t thr, vvp_code_t code); extern bool of_WAIT(vthread_t thr, vvp_code_t code); extern bool of_WAIT_FORK(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index 0ab23b841..697c58064 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -265,8 +265,9 @@ static const struct opcode_table_s opcode_table[] = { { "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%substr", of_SUBSTR, 2,{OA_BIT1, OA_BIT2, OA_NONE} }, { "%substr/v",of_SUBSTR_V,3,{OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%test_nul", of_TEST_NUL, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, - { "%test_nula", of_TEST_NULA,2,{OA_ARR_PTR, OA_BIT1, OA_NONE} }, + { "%test_nul", of_TEST_NUL, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, + { "%test_nul/a", of_TEST_NUL_A, 2,{OA_ARR_PTR, OA_BIT1, OA_NONE} }, + { "%test_nul/obj",of_TEST_NUL_OBJ,0,{OA_NONE, OA_NONE, OA_NONE} }, { "%wait", of_WAIT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%wait/fork",of_WAIT_FORK,0,{OA_NONE, OA_NONE, OA_NONE} }, { "%xnor", of_XNOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 6924f7f65..f3361f67b 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -1134,10 +1134,14 @@ values into the vector space. The string value is NOT popped. * %test_nul +* %test_nul/obj This instruction tests the contents of the addressed variable to see if it is null. If it is, set bit 4 to 1. Otherwise, set bit 4 to 0. +The %test_null/obj tests the object on the top of the stack, instead +of any variable. The value in the stack is NOT popped. + This is intended to implement the SystemVerilog expression (==null), where is a class variable. diff --git a/vvp/vthread.cc b/vvp/vthread.cc index db1d9e08a..ae2986364 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -5832,7 +5832,7 @@ bool of_TEST_NUL(vthread_t thr, vvp_code_t cp) return true; } -bool of_TEST_NULA(vthread_t thr, vvp_code_t cp) +bool of_TEST_NUL_A(vthread_t thr, vvp_code_t cp) { unsigned idx = cp->bit_idx[0]; unsigned adr = thr->words[idx].w_int; @@ -5853,6 +5853,15 @@ bool of_TEST_NULA(vthread_t thr, vvp_code_t cp) return true; } +bool of_TEST_NUL_OBJ(vthread_t thr, vvp_code_t) +{ + if (thr->peek_object().test_nil()) + thr_put_bit(thr, 4, BIT4_1); + else + thr_put_bit(thr, 4, BIT4_0); + return true; +} + bool of_VPI_CALL(vthread_t thr, vvp_code_t cp) { vpip_execute_vpi_call(thr, cp->handle);