tgt-vvp: Support assignment operators on object properties
Currently assignment operators on object properties are silently ignored. Make sure that they are handled. To enable this refactor the code a bit so that the assignment operator handling can be shared between object property assignments and scalar value assignments. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
parent
d0327c5eda
commit
867c7d18b4
|
|
@ -541,13 +541,77 @@ static unsigned int draw_array_pattern(ivl_signal_t var, ivl_expr_t rval,
|
||||||
return array_idx;
|
return array_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void draw_stmt_assign_vector_opcode(unsigned char opcode, bool is_signed)
|
||||||
|
{
|
||||||
|
int idx_reg;
|
||||||
|
|
||||||
|
switch (opcode) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '+':
|
||||||
|
fprintf(vvp_out, " %%add;\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '-':
|
||||||
|
fprintf(vvp_out, " %%sub;\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '*':
|
||||||
|
fprintf(vvp_out, " %%mul;\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '/':
|
||||||
|
fprintf(vvp_out, " %%div%s;\n", is_signed ? "/s":"");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '%':
|
||||||
|
fprintf(vvp_out, " %%mod%s;\n", is_signed ? "/s":"");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '&':
|
||||||
|
fprintf(vvp_out, " %%and;\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '|':
|
||||||
|
fprintf(vvp_out, " %%or;\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '^':
|
||||||
|
fprintf(vvp_out, " %%xor;\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'l': /* lval <<= expr */
|
||||||
|
idx_reg = allocate_word();
|
||||||
|
fprintf(vvp_out, " %%ix/vec4 %d;\n", idx_reg);
|
||||||
|
fprintf(vvp_out, " %%shiftl %d;\n", idx_reg);
|
||||||
|
clr_word(idx_reg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r': /* lval >>= expr */
|
||||||
|
idx_reg = allocate_word();
|
||||||
|
fprintf(vvp_out, " %%ix/vec4 %d;\n", idx_reg);
|
||||||
|
fprintf(vvp_out, " %%shiftr %d;\n", idx_reg);
|
||||||
|
clr_word(idx_reg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'R': /* lval >>>= expr */
|
||||||
|
idx_reg = allocate_word();
|
||||||
|
fprintf(vvp_out, " %%ix/vec4 %d;\n", idx_reg);
|
||||||
|
fprintf(vvp_out, " %%shiftr/s %d;\n", idx_reg);
|
||||||
|
clr_word(idx_reg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf(vvp_out, "; UNSUPPORTED ASSIGNMENT OPCODE: %c\n", opcode);
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int show_stmt_assign_vector(ivl_statement_t net)
|
static int show_stmt_assign_vector(ivl_statement_t net)
|
||||||
{
|
{
|
||||||
ivl_expr_t rval = ivl_stmt_rval(net);
|
ivl_expr_t rval = ivl_stmt_rval(net);
|
||||||
//struct vector_info res;
|
|
||||||
//struct vector_info lres = {0, 0};
|
|
||||||
struct vec_slice_info*slices = 0;
|
|
||||||
int idx_reg;
|
|
||||||
|
|
||||||
if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) {
|
if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) {
|
||||||
ivl_lval_t lval = ivl_stmt_lval(net, 0);
|
ivl_lval_t lval = ivl_stmt_lval(net, 0);
|
||||||
|
|
@ -556,96 +620,30 @@ static int show_stmt_assign_vector(ivl_statement_t net)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned wid = ivl_stmt_lwidth(net);
|
||||||
|
|
||||||
/* If this is a compressed assignment, then get the contents
|
/* If this is a compressed assignment, then get the contents
|
||||||
of the l-value. We need these values as part of the r-value
|
of the l-value. We need these values as part of the r-value
|
||||||
calculation. */
|
calculation. */
|
||||||
if (ivl_stmt_opcode(net) != 0) {
|
if (ivl_stmt_opcode(net) != 0) {
|
||||||
|
struct vec_slice_info *slices;
|
||||||
|
|
||||||
|
slices = calloc(ivl_stmt_lvals(net), sizeof(struct vec_slice_info));
|
||||||
|
|
||||||
fprintf(vvp_out, " ; show_stmt_assign_vector: Get l-value for compressed %c= operand\n", ivl_stmt_opcode(net));
|
fprintf(vvp_out, " ; show_stmt_assign_vector: Get l-value for compressed %c= operand\n", ivl_stmt_opcode(net));
|
||||||
slices = calloc(ivl_stmt_lvals(net), sizeof(struct vec_slice_info));
|
|
||||||
get_vec_from_lval(net, slices);
|
get_vec_from_lval(net, slices);
|
||||||
}
|
draw_eval_vec4(rval);
|
||||||
|
resize_vec4_wid(rval, wid);
|
||||||
unsigned wid = ivl_stmt_lwidth(net);
|
draw_stmt_assign_vector_opcode(ivl_stmt_opcode(net),
|
||||||
draw_eval_vec4(rval);
|
ivl_expr_signed(rval));
|
||||||
resize_vec4_wid(rval, wid);
|
put_vec_to_lval(net, slices);
|
||||||
|
free(slices);
|
||||||
switch (ivl_stmt_opcode(net)) {
|
} else {
|
||||||
case 0:
|
draw_eval_vec4(rval);
|
||||||
|
resize_vec4_wid(rval, wid);
|
||||||
store_vec4_to_lval(net);
|
store_vec4_to_lval(net);
|
||||||
break;
|
|
||||||
|
|
||||||
case '+':
|
|
||||||
fprintf(vvp_out, " %%add;\n");
|
|
||||||
put_vec_to_lval(net, slices);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '-':
|
|
||||||
fprintf(vvp_out, " %%sub;\n");
|
|
||||||
put_vec_to_lval(net, slices);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '*':
|
|
||||||
fprintf(vvp_out, " %%mul;\n");
|
|
||||||
put_vec_to_lval(net, slices);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '/':
|
|
||||||
fprintf(vvp_out, " %%div%s;\n", ivl_expr_signed(rval)? "/s":"");
|
|
||||||
put_vec_to_lval(net, slices);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '%':
|
|
||||||
fprintf(vvp_out, " %%mod%s;\n", ivl_expr_signed(rval)? "/s":"");
|
|
||||||
put_vec_to_lval(net, slices);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '&':
|
|
||||||
fprintf(vvp_out, " %%and;\n");
|
|
||||||
put_vec_to_lval(net, slices);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '|':
|
|
||||||
fprintf(vvp_out, " %%or;\n");
|
|
||||||
put_vec_to_lval(net, slices);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '^':
|
|
||||||
fprintf(vvp_out, " %%xor;\n");
|
|
||||||
put_vec_to_lval(net, slices);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'l': /* lval <<= expr */
|
|
||||||
idx_reg = allocate_word();
|
|
||||||
fprintf(vvp_out, " %%ix/vec4 %d;\n", idx_reg);
|
|
||||||
fprintf(vvp_out, " %%shiftl %d;\n", idx_reg);
|
|
||||||
clr_word(idx_reg);
|
|
||||||
put_vec_to_lval(net, slices);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'r': /* lval >>= expr */
|
|
||||||
idx_reg = allocate_word();
|
|
||||||
fprintf(vvp_out, " %%ix/vec4 %d;\n", idx_reg);
|
|
||||||
fprintf(vvp_out, " %%shiftr %d;\n", idx_reg);
|
|
||||||
clr_word(idx_reg);
|
|
||||||
put_vec_to_lval(net, slices);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'R': /* lval >>>= expr */
|
|
||||||
idx_reg = allocate_word();
|
|
||||||
fprintf(vvp_out, " %%ix/vec4 %d;\n", idx_reg);
|
|
||||||
fprintf(vvp_out, " %%shiftr/s %d;\n", idx_reg);
|
|
||||||
clr_word(idx_reg);
|
|
||||||
put_vec_to_lval(net, slices);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
fprintf(vvp_out, "; UNSUPPORTED ASSIGNMENT OPCODE: %c\n", ivl_stmt_opcode(net));
|
|
||||||
assert(0);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slices) free(slices);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -817,42 +815,11 @@ static void store_real_to_lval(ivl_lval_t lval)
|
||||||
clr_word(word_ix);
|
clr_word(word_ix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void draw_stmt_assign_real_opcode(unsigned char opcode)
|
||||||
* This function assigns a value to a real variable. This is destined
|
|
||||||
* for /dev/null when typed ivl_signal_t takes over all the real
|
|
||||||
* variable support.
|
|
||||||
*/
|
|
||||||
static int show_stmt_assign_sig_real(ivl_statement_t net)
|
|
||||||
{
|
{
|
||||||
struct real_lval_info*slice = 0;
|
switch (opcode) {
|
||||||
ivl_lval_t lval;
|
|
||||||
|
|
||||||
assert(ivl_stmt_lvals(net) == 1);
|
|
||||||
lval = ivl_stmt_lval(net, 0);
|
|
||||||
|
|
||||||
ivl_expr_t rval = ivl_stmt_rval(net);
|
|
||||||
if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) {
|
|
||||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
|
||||||
draw_array_pattern(sig, rval, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If this is a compressed assignment, then get the contents
|
|
||||||
of the l-value. We need this value as part of the r-value
|
|
||||||
calculation. */
|
|
||||||
if (ivl_stmt_opcode(net) != 0) {
|
|
||||||
fprintf(vvp_out, " ; show_stmt_assign_real: Get l-value for compressed %c= operand\n", ivl_stmt_opcode(net));
|
|
||||||
slice = calloc(1, sizeof(struct real_lval_info));
|
|
||||||
get_real_from_lval(lval, slice);
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_eval_real(rval);
|
|
||||||
|
|
||||||
switch (ivl_stmt_opcode(net)) {
|
|
||||||
case 0:
|
case 0:
|
||||||
store_real_to_lval(lval);
|
break;
|
||||||
if (slice) free(slice);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case '+':
|
case '+':
|
||||||
fprintf(vvp_out, " %%add/wr;\n");
|
fprintf(vvp_out, " %%add/wr;\n");
|
||||||
|
|
@ -875,13 +842,47 @@ static int show_stmt_assign_sig_real(ivl_statement_t net)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(vvp_out, "; UNSUPPORTED ASSIGNMENT OPCODE: %c\n", ivl_stmt_opcode(net));
|
fprintf(vvp_out, "; UNSUPPORTED ASSIGNMENT OPCODE: %c\n", opcode);
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function assigns a value to a real variable. This is destined
|
||||||
|
* for /dev/null when typed ivl_signal_t takes over all the real
|
||||||
|
* variable support.
|
||||||
|
*/
|
||||||
|
static int show_stmt_assign_sig_real(ivl_statement_t net)
|
||||||
|
{
|
||||||
|
ivl_lval_t lval;
|
||||||
|
|
||||||
|
assert(ivl_stmt_lvals(net) == 1);
|
||||||
|
lval = ivl_stmt_lval(net, 0);
|
||||||
|
|
||||||
|
ivl_expr_t rval = ivl_stmt_rval(net);
|
||||||
|
if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) {
|
||||||
|
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||||
|
draw_array_pattern(sig, rval, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this is a compressed assignment, then get the contents
|
||||||
|
of the l-value. We need this value as part of the r-value
|
||||||
|
calculation. */
|
||||||
|
if (ivl_stmt_opcode(net) != 0) {
|
||||||
|
struct real_lval_info slice;
|
||||||
|
|
||||||
|
fprintf(vvp_out, " ; show_stmt_assign_real: Get l-value for compressed %c= operand\n", ivl_stmt_opcode(net));
|
||||||
|
get_real_from_lval(lval, &slice);
|
||||||
|
draw_eval_real(rval);
|
||||||
|
draw_stmt_assign_real_opcode(ivl_stmt_opcode(net));
|
||||||
|
put_real_to_lval(lval, &slice);
|
||||||
|
} else {
|
||||||
|
draw_eval_real(rval);
|
||||||
|
store_real_to_lval(lval);
|
||||||
|
}
|
||||||
|
|
||||||
put_real_to_lval(lval, slice);
|
|
||||||
free(slice);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1260,39 +1261,43 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
||||||
ivl_type_t sig_type = ivl_signal_net_type(sig);
|
ivl_type_t sig_type = ivl_signal_net_type(sig);
|
||||||
ivl_type_t prop_type = ivl_type_prop_type(sig_type, prop_idx);
|
ivl_type_t prop_type = ivl_type_prop_type(sig_type, prop_idx);
|
||||||
|
|
||||||
if (ivl_type_base(prop_type) == IVL_VT_BOOL) {
|
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
||||||
|
|
||||||
|
if (ivl_type_base(prop_type) == IVL_VT_BOOL ||
|
||||||
|
ivl_type_base(prop_type) == IVL_VT_LOGIC) {
|
||||||
assert(ivl_type_packed_dimensions(prop_type) == 0 ||
|
assert(ivl_type_packed_dimensions(prop_type) == 0 ||
|
||||||
(ivl_type_packed_dimensions(prop_type) == 1 &&
|
(ivl_type_packed_dimensions(prop_type) == 1 &&
|
||||||
ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)));
|
ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)));
|
||||||
|
|
||||||
|
if (ivl_stmt_opcode(net) != 0) {
|
||||||
|
fprintf(vvp_out, " %%prop/v %d;\n", prop_idx);
|
||||||
|
}
|
||||||
|
|
||||||
draw_eval_vec4(rval);
|
draw_eval_vec4(rval);
|
||||||
if (ivl_expr_value(rval)!=IVL_VT_BOOL)
|
if (ivl_type_base(prop_type) == IVL_VT_BOOL &&
|
||||||
|
ivl_expr_value(rval) != IVL_VT_BOOL)
|
||||||
fprintf(vvp_out, " %%cast2;\n");
|
fprintf(vvp_out, " %%cast2;\n");
|
||||||
|
|
||||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
draw_stmt_assign_vector_opcode(ivl_stmt_opcode(net),
|
||||||
fprintf(vvp_out, " %%store/prop/v %d, %u; Store in bool property %s\n",
|
ivl_expr_signed(rval));
|
||||||
prop_idx, lwid, ivl_type_prop_name(sig_type, prop_idx));
|
|
||||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
|
||||||
|
|
||||||
} else if (ivl_type_base(prop_type) == IVL_VT_LOGIC) {
|
|
||||||
assert(ivl_type_packed_dimensions(prop_type) == 0 ||
|
|
||||||
(ivl_type_packed_dimensions(prop_type) == 1 &&
|
|
||||||
ivl_type_packed_msb(prop_type,0) >= ivl_type_packed_lsb(prop_type, 0)));
|
|
||||||
|
|
||||||
draw_eval_vec4(rval);
|
|
||||||
|
|
||||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
|
||||||
fprintf(vvp_out, " %%store/prop/v %d, %u; Store in logic property %s\n",
|
fprintf(vvp_out, " %%store/prop/v %d, %u; Store in logic property %s\n",
|
||||||
prop_idx, lwid, ivl_type_prop_name(sig_type, prop_idx));
|
prop_idx, lwid, ivl_type_prop_name(sig_type, prop_idx));
|
||||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||||
|
|
||||||
} else if (ivl_type_base(prop_type) == IVL_VT_REAL) {
|
} else if (ivl_type_base(prop_type) == IVL_VT_REAL) {
|
||||||
|
|
||||||
|
if (ivl_stmt_opcode(net) != 0) {
|
||||||
|
fprintf(vvp_out, " %%prop/r %d;\n", prop_idx);
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate the real value into the real value
|
/* Calculate the real value into the real value
|
||||||
stack. The %store/prop/r will pop the stack
|
stack. The %store/prop/r will pop the stack
|
||||||
value. */
|
value. */
|
||||||
draw_eval_real(rval);
|
draw_eval_real(rval);
|
||||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
|
||||||
|
draw_stmt_assign_real_opcode(ivl_stmt_opcode(net));
|
||||||
|
|
||||||
fprintf(vvp_out, " %%store/prop/r %d;\n", prop_idx);
|
fprintf(vvp_out, " %%store/prop/r %d;\n", prop_idx);
|
||||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||||
|
|
||||||
|
|
@ -1302,7 +1307,6 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
||||||
stack. The %store/prop/r will pop the stack
|
stack. The %store/prop/r will pop the stack
|
||||||
value. */
|
value. */
|
||||||
draw_eval_string(rval);
|
draw_eval_string(rval);
|
||||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
|
||||||
fprintf(vvp_out, " %%store/prop/str %d;\n", prop_idx);
|
fprintf(vvp_out, " %%store/prop/str %d;\n", prop_idx);
|
||||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||||
|
|
||||||
|
|
@ -1313,7 +1317,6 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
||||||
/* The property is a darray, and there is no mux
|
/* The property is a darray, and there is no mux
|
||||||
expression to the assignment is of an entire
|
expression to the assignment is of an entire
|
||||||
array object. */
|
array object. */
|
||||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
|
||||||
errors += draw_eval_object(rval);
|
errors += draw_eval_object(rval);
|
||||||
fprintf(vvp_out, " %%store/prop/obj %d, %d; IVL_VT_DARRAY\n", prop_idx, idx);
|
fprintf(vvp_out, " %%store/prop/obj %d, %d; IVL_VT_DARRAY\n", prop_idx, idx);
|
||||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||||
|
|
@ -1327,7 +1330,6 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The property is a class object. */
|
/* The property is a class object. */
|
||||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
|
||||||
errors += draw_eval_object(rval);
|
errors += draw_eval_object(rval);
|
||||||
if (idx_expr) draw_eval_expr_into_integer(idx_expr, idx);
|
if (idx_expr) draw_eval_expr_into_integer(idx_expr, idx);
|
||||||
fprintf(vvp_out, " %%store/prop/obj %d, %d; IVL_VT_CLASS\n", prop_idx, idx);
|
fprintf(vvp_out, " %%store/prop/obj %d, %d; IVL_VT_CLASS\n", prop_idx, idx);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue