Support testing nul for property that is an object.

This commit is contained in:
Stephen Williams 2014-10-22 12:58:50 -07:00
parent 87c019c65c
commit 35f5d51028
5 changed files with 70 additions and 6 deletions

View File

@ -192,6 +192,9 @@ static void draw_binary_vec4_compare_class(ivl_expr_t expr)
return;
}
/* A signal/variable is compared to null. Implement this with
the %test_nul statement, which peeks at the variable
contents directly. */
if (ivl_expr_type(re)==IVL_EX_NULL && ivl_expr_type(le)==IVL_EX_SIGNAL) {
ivl_signal_t sig= ivl_expr_signal(le);
@ -210,8 +213,33 @@ static void draw_binary_vec4_compare_class(ivl_expr_t expr)
return;
}
if (ivl_expr_type(re)==IVL_EX_NULL && ivl_expr_type(le)==IVL_EX_PROPERTY) {
ivl_signal_t sig = ivl_expr_signal(le);
unsigned pidx = ivl_expr_property_idx(le);
ivl_expr_t idx_expr = ivl_expr_oper1(le);
int idx = 0;
/* If the property has an array index, then evaluate it
into an index register. */
if ( idx_expr ) {
idx = allocate_word();
draw_eval_expr_into_integer(idx_expr, idx);
}
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
fprintf(vvp_out, " %%test_nul/prop %u, %d;\n", pidx, idx);
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
fprintf(vvp_out, " %%flag_get/vec4 4;\n");
if (ivl_expr_opcode(expr) == 'n')
fprintf(vvp_out, " %%inv;\n");
if (idx != 0) clr_word(idx);
return;
}
fprintf(stderr, "SORRY: Compare class handles not implemented\n");
fprintf(vvp_out, " ; XXXX compare class handles.\n");
fprintf(vvp_out, " ; XXXX compare class handles. re-type=%d, le-type=%d\n",
ivl_expr_type(re), ivl_expr_type(le));
vvp_errors += 1;
}

View File

@ -245,6 +245,7 @@ extern bool of_SUBSTR_VEC4(vthread_t thr, vvp_code_t code);
extern bool of_TEST_NUL(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_TEST_NUL_PROP(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);

View File

@ -234,7 +234,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%pow", of_POW, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%pow/s", of_POW_S, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%pow/wr", of_POW_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%prop/obj",of_PROP_OBJ,1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%prop/obj",of_PROP_OBJ,2, {OA_NUMBER, OA_BIT1, OA_NONE} },
{ "%prop/r", of_PROP_R, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%prop/str",of_PROP_STR,1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%prop/v", of_PROP_V, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
@ -289,9 +289,10 @@ 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/vec4",of_SUBSTR_VEC4,2,{OA_BIT1, OA_BIT2, 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} },
{ "%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} },
{ "%test_nul/prop",of_TEST_NUL_PROP,2,{OA_NUMBER, OA_BIT1, 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, 0, {OA_NONE, OA_NONE, OA_NONE} },

View File

@ -1046,7 +1046,7 @@ This opcode raises the left operand by the right operand, and pushes
the result.
* %prop/v <pid>
* %prop/obj <pid>
* %prop/obj <pid>, <idx>
* %prop/r <pid>
* %prop/str <pid>
@ -1362,6 +1362,7 @@ The string value is NOT popped.
* %test_nul <var-label>
* %test_nul/obj
* %test_nul/prop <pid>, <idx>
This instruction tests the contents of the addressed variable to see
if it is null. If it is, set flag bit 4 to 1. Otherwise, set flag bit
@ -1370,6 +1371,10 @@ if it is null. If it is, set flag bit 4 to 1. Otherwise, set flag bit
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.
The %test_nul/prop instruction tests an object property for nul. The
object with the property is peeked from the top of the object stack,
and the <idx> is the array index if the property is an array of objects.
This is intended to implement the SystemVerilog expression
(<var>==null), where <var> is a class variable.

View File

@ -288,6 +288,8 @@ void vthread_s::debug_dump(ostream&fd, const char*label)
fd << "**** vec4 stack..." << endl;
for (size_t idx = stack_vec4_.size() ; idx > 0 ; idx -= 1)
fd << " " << (stack_vec4_.size()-idx) << ": " << stack_vec4_[idx-1] << endl;
fd << "**** str stack (" << stack_str_.size() << ")..." << endl;
fd << "**** obj stack (" << stack_obj_size_ << ")..." << endl;
fd << "**** Done ****" << endl;
}
@ -6642,6 +6644,33 @@ bool of_TEST_NUL_OBJ(vthread_t thr, vvp_code_t)
return true;
}
/*
* %test_nul/prop <pid>, <idx>
*/
bool of_TEST_NUL_PROP(vthread_t thr, vvp_code_t cp)
{
unsigned pid = cp->number;
unsigned idx = cp->bit_idx[0];
if (idx != 0) {
assert(idx < vthread_s::WORDS_COUNT);
idx = thr->words[idx].w_uint;
}
vvp_object_t&obj = thr->peek_object();
vvp_cobject*cobj = obj.peek<vvp_cobject>();
vvp_object_t val;
cobj->get_object(pid, val, idx);
if (val.test_nil())
thr->flags[4] = BIT4_1;
else
thr->flags[4] = BIT4_0;
return true;
}
bool of_VPI_CALL(vthread_t thr, vvp_code_t cp)
{
vpip_execute_vpi_call(thr, cp->handle);