Handle vec4 part selects / vec4 cassign / repeat statements
These features need to be adapted to the vec4 stack.
This commit is contained in:
parent
d55e4c0552
commit
e708a5b59d
|
|
@ -435,10 +435,12 @@ static void draw_select_vec4(ivl_expr_t expr)
|
||||||
ivl_expr_t base = ivl_expr_oper2(expr);
|
ivl_expr_t base = ivl_expr_oper2(expr);
|
||||||
// This is the part select width
|
// This is the part select width
|
||||||
unsigned wid = ivl_expr_width(expr);
|
unsigned wid = ivl_expr_width(expr);
|
||||||
|
// Is the select base expression signed or unsigned?
|
||||||
|
char sign_suff = ivl_expr_signed(base)? 's' : 'u';
|
||||||
|
|
||||||
draw_eval_vec4(subexpr, 0);
|
draw_eval_vec4(subexpr, 0);
|
||||||
draw_eval_vec4(base, 0);
|
draw_eval_vec4(base, 0);
|
||||||
fprintf(vvp_out, " %%part %u;\n", wid);
|
fprintf(vvp_out, " %%part/%c %u;\n", sign_suff, wid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_select_pad_vec4(ivl_expr_t expr, int stuff_ok_flag)
|
static void draw_select_pad_vec4(ivl_expr_t expr, int stuff_ok_flag)
|
||||||
|
|
@ -486,8 +488,19 @@ static void draw_signal_vec4(ivl_expr_t expr)
|
||||||
{
|
{
|
||||||
ivl_signal_t sig = ivl_expr_signal(expr);
|
ivl_signal_t sig = ivl_expr_signal(expr);
|
||||||
|
|
||||||
assert(ivl_signal_dimensions(sig) == 0);
|
/* Handle the simple case, a signal expression that is a
|
||||||
fprintf(vvp_out, " %%load/vec4 v%p_0;\n", sig);
|
simple vector, no array dimensions. */
|
||||||
|
if (ivl_signal_dimensions(sig) == 0) {
|
||||||
|
fprintf(vvp_out, " %%load/vec4 v%p_0;\n", sig);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* calculate the array index... */
|
||||||
|
int addr_index = allocate_word();
|
||||||
|
draw_eval_expr_into_integer(ivl_expr_oper1(expr), addr_index);
|
||||||
|
|
||||||
|
fprintf(vvp_out, " %%load/vec4a v%p, %d;\n", sig, addr_index);
|
||||||
|
clr_word(addr_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_ternary_vec4(ivl_expr_t expr, int stuff_ok_flag)
|
static void draw_ternary_vec4(ivl_expr_t expr, int stuff_ok_flag)
|
||||||
|
|
|
||||||
|
|
@ -551,17 +551,38 @@ static void set_vec_to_lval(ivl_statement_t net, struct vector_info res)
|
||||||
* Store a vector from the vec4 stack to the statement l-values. This
|
* Store a vector from the vec4 stack to the statement l-values. This
|
||||||
* all assumes that the value to be assigned is already on the top of
|
* all assumes that the value to be assigned is already on the top of
|
||||||
* the stack.
|
* the stack.
|
||||||
|
*
|
||||||
|
* NOTE TO SELF: The %store/vec4 takes a width, but the %assign/vec4
|
||||||
|
* instructions do not, instead relying on the expression width. I
|
||||||
|
* think that it the proper way to do it, so soon I should change the
|
||||||
|
* %store/vec4 to not include the width operand.
|
||||||
*/
|
*/
|
||||||
static void store_vec4_to_lval(ivl_statement_t net)
|
static void store_vec4_to_lval(ivl_statement_t net)
|
||||||
{
|
{
|
||||||
assert(ivl_stmt_lvals(net) == 1);
|
for (unsigned lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
|
||||||
|
ivl_lval_t lval = ivl_stmt_lval(net,lidx);
|
||||||
|
ivl_signal_t lsig = ivl_lval_sig(lval);
|
||||||
|
unsigned lwid = ivl_lval_width(lval);
|
||||||
|
|
||||||
ivl_lval_t lval = ivl_stmt_lval(net,0);
|
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
||||||
ivl_signal_t lsig = ivl_lval_sig(lval);
|
|
||||||
|
|
||||||
assert(ivl_lval_width(lval) == ivl_signal_width(lsig));
|
if (lidx+1 < ivl_stmt_lvals(net))
|
||||||
|
fprintf(vvp_out, " %%split/vec4 %u;\n", lwid);
|
||||||
|
|
||||||
fprintf(vvp_out, " %%store/vec4 v%p_0, %u;\n", lsig, ivl_signal_width(lsig));
|
if (part_off_ex) {
|
||||||
|
/* Dynamically calculated part offset */
|
||||||
|
int offset_index = allocate_word();
|
||||||
|
draw_eval_expr_into_integer(part_off_ex, offset_index);
|
||||||
|
fprintf(vvp_out, " %%store/vec4/off v%p_0, %d, %u;\n",
|
||||||
|
lsig, offset_index, lwid);
|
||||||
|
clr_word(offset_index);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* No offset expression, so use simpler store function. */
|
||||||
|
assert(lwid == ivl_signal_width(lsig));
|
||||||
|
fprintf(vvp_out, " %%store/vec4 v%p_0, %u;\n", lsig, lwid);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int show_stmt_assign_vector(ivl_statement_t net)
|
static int show_stmt_assign_vector(ivl_statement_t net)
|
||||||
|
|
|
||||||
|
|
@ -111,8 +111,8 @@ static void assign_to_array_r_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||||
unsigned bit, uint64_t delay, ivl_expr_t dexp,
|
uint64_t delay, ivl_expr_t dexp,
|
||||||
ivl_expr_t part_off_ex, unsigned width,
|
ivl_expr_t part_off_ex,
|
||||||
unsigned nevents)
|
unsigned nevents)
|
||||||
{
|
{
|
||||||
unsigned skip_assign = transient_id++;
|
unsigned skip_assign = transient_id++;
|
||||||
|
|
@ -121,6 +121,10 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||||
int delay_index;
|
int delay_index;
|
||||||
unsigned long part_off = 0;
|
unsigned long part_off = 0;
|
||||||
|
|
||||||
|
/* Figure the constant part offset, if possible. If we can do
|
||||||
|
so, then forget about the expression and use the calculated
|
||||||
|
value. After this block, if the part_off_ex!=0, then the
|
||||||
|
part offset is used, otherwise, use part_off. */
|
||||||
if (part_off_ex == 0) {
|
if (part_off_ex == 0) {
|
||||||
part_off = 0;
|
part_off = 0;
|
||||||
} else if (number_is_immediate(part_off_ex, IMM_WID, 0) &&
|
} else if (number_is_immediate(part_off_ex, IMM_WID, 0) &&
|
||||||
|
|
@ -136,25 +140,16 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||||
word_ix_reg = allocate_word();
|
word_ix_reg = allocate_word();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This code is common to all the different types of array delays. */
|
/* Calculate array word index into word index register */
|
||||||
if (number_is_immediate(word_ix, IMM_WID, 0) &&
|
draw_eval_expr_into_integer(word_ix, word_ix_reg);
|
||||||
!number_is_unknown(word_ix)) {
|
/* Skip assignment if word expression is not defined. */
|
||||||
fprintf(vvp_out, " %%ix/load %d, %lu, 0; address\n", word_ix_reg,
|
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
||||||
get_number_immediate(word_ix));
|
|
||||||
} else {
|
|
||||||
/* Calculate array word index into word index register */
|
|
||||||
draw_eval_expr_into_integer(word_ix, word_ix_reg);
|
|
||||||
/* Skip assignment if word expression is not defined. */
|
|
||||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
|
||||||
}
|
|
||||||
if (part_off_ex) {
|
if (part_off_ex) {
|
||||||
draw_eval_expr_into_integer(part_off_ex, part_off_reg);
|
draw_eval_expr_into_integer(part_off_ex, part_off_reg);
|
||||||
/* If the index expression has XZ bits, skip the assign. */
|
/* If the index expression has XZ bits, skip the assign. */
|
||||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
||||||
if (dexp == 0) {
|
|
||||||
fprintf(vvp_out, " %%ix/mov 3, %u;\n", word_ix_reg);
|
|
||||||
clr_word(word_ix_reg);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* Store word part select into part_off_reg */
|
/* Store word part select into part_off_reg */
|
||||||
fprintf(vvp_out, " %%ix/load %d, %lu, 0; part off\n",
|
fprintf(vvp_out, " %%ix/load %d, %lu, 0; part off\n",
|
||||||
|
|
@ -165,42 +160,34 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||||
/* Calculated delay... */
|
/* Calculated delay... */
|
||||||
delay_index = allocate_word();
|
delay_index = allocate_word();
|
||||||
draw_eval_expr_into_integer(dexp, delay_index);
|
draw_eval_expr_into_integer(dexp, delay_index);
|
||||||
}
|
if (word_ix_reg != 3) {
|
||||||
|
fprintf(vvp_out, " %%ix/mov 3, %u;\n", word_ix_reg);
|
||||||
/* Store expression width into index word 0 */
|
clr_word(word_ix_reg);
|
||||||
fprintf(vvp_out, " %%ix/load 0, %u, 0; word width\n", width);
|
}
|
||||||
|
fprintf(vvp_out, " %%assign/vec4/a/d v%p, %d, %d;\n", lsig,
|
||||||
if (dexp != 0) {
|
delay_index, part_off_reg);
|
||||||
fprintf(vvp_out, " %%ix/mov 1, %u;\n", part_off_reg);
|
|
||||||
fprintf(vvp_out, " %%ix/mov 3, %u;\n", word_ix_reg);
|
|
||||||
fprintf(vvp_out, " %%assign/av/d v%p, %d, %u;\n", lsig,
|
|
||||||
delay_index, bit);
|
|
||||||
clr_word(part_off_reg);
|
clr_word(part_off_reg);
|
||||||
clr_word(word_ix_reg);
|
|
||||||
clr_word(delay_index);
|
clr_word(delay_index);
|
||||||
|
|
||||||
} else if (nevents != 0) {
|
} else if (nevents != 0) {
|
||||||
/* Event control delay... */
|
/* Event control delay... */
|
||||||
fprintf(vvp_out, " %%assign/av/e v%p, %u;\n", lsig, bit);
|
fprintf(vvp_out, " %%assign/vec4/a/e v%p, 0;\n", lsig);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* Constant delay... */
|
/* Constant delay... */
|
||||||
unsigned long low_d = delay % UINT64_C(0x100000000);
|
unsigned long low_d = delay % UINT64_C(0x100000000);
|
||||||
unsigned long hig_d = delay / UINT64_C(0x100000000);
|
unsigned long hig_d = delay / UINT64_C(0x100000000);
|
||||||
|
|
||||||
/*
|
delay_index = allocate_word();
|
||||||
* The %assign can only take a 32 bit delay. For a larger
|
fprintf(vvp_out, " %%ix/load %d, %lu, %lu; Constant delay\n",
|
||||||
* delay we need to put it into an index register.
|
delay_index, low_d, hig_d);
|
||||||
*/
|
if (word_ix_reg != 3) {
|
||||||
if (hig_d != 0) {
|
fprintf(vvp_out, " %%ix/mov 3, %u;\n", word_ix_reg);
|
||||||
delay_index = allocate_word();
|
clr_word(word_ix_reg);
|
||||||
fprintf(vvp_out, " %%ix/load %d, %lu, %lu;\n",
|
|
||||||
delay_index, low_d, hig_d);
|
|
||||||
fprintf(vvp_out, " %%assign/av/d v%p, %d, %u;\n", lsig,
|
|
||||||
delay_index, bit);
|
|
||||||
clr_word(delay_index);
|
|
||||||
} else {
|
|
||||||
fprintf(vvp_out, " %%assign/av v%p, %lu, %u;\n",
|
|
||||||
lsig, low_d, bit);
|
|
||||||
}
|
}
|
||||||
|
fprintf(vvp_out, " %%assign/vec4/a/d v%p, %d, %u;\n", lsig,
|
||||||
|
part_off_reg, delay_index);
|
||||||
|
clr_word(delay_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||||
|
|
@ -209,6 +196,11 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||||
clear_expression_lookaside();
|
clear_expression_lookaside();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The code to generate here assumes that a vec4 vector of the right
|
||||||
|
* width is top of the vec4 stack. Arrange for it to be popped and
|
||||||
|
* assigned to the given l-value.
|
||||||
|
*/
|
||||||
static void assign_to_lvector(ivl_lval_t lval,
|
static void assign_to_lvector(ivl_lval_t lval,
|
||||||
uint64_t delay, ivl_expr_t dexp,
|
uint64_t delay, ivl_expr_t dexp,
|
||||||
unsigned nevents)
|
unsigned nevents)
|
||||||
|
|
@ -217,17 +209,15 @@ static void assign_to_lvector(ivl_lval_t lval,
|
||||||
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
||||||
unsigned long part_off = 0;
|
unsigned long part_off = 0;
|
||||||
|
|
||||||
ivl_expr_t word_ix = ivl_lval_idx(lval);
|
|
||||||
const unsigned long use_word = 0;
|
const unsigned long use_word = 0;
|
||||||
|
|
||||||
|
// 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.
|
||||||
if (ivl_signal_dimensions(sig) > 0) {
|
if (ivl_signal_dimensions(sig) > 0) {
|
||||||
#if 0
|
ivl_expr_t word_ix = ivl_lval_idx(lval);
|
||||||
assert(word_ix);
|
assert(word_ix);
|
||||||
assign_to_array_word(sig, word_ix, bit, delay, dexp, part_off_ex,
|
assign_to_array_word(sig, word_ix, delay, dexp, part_off_ex, nevents);
|
||||||
width, nevents);
|
|
||||||
#else
|
|
||||||
fprintf(stderr, "XXXX %%assign to array word not supported yet.\n");
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -243,6 +233,10 @@ static void assign_to_lvector(ivl_lval_t lval,
|
||||||
unsigned long hig_d = delay / UINT64_C(0x100000000);
|
unsigned long hig_d = delay / UINT64_C(0x100000000);
|
||||||
|
|
||||||
if (part_off_ex) {
|
if (part_off_ex) {
|
||||||
|
// The part select offset is calculated (not constant)
|
||||||
|
// so in these cases we'll need to use
|
||||||
|
// %assign/vec4/off/... variants.
|
||||||
|
|
||||||
unsigned skip_assign = transient_id++;
|
unsigned skip_assign = transient_id++;
|
||||||
if (dexp != 0) {
|
if (dexp != 0) {
|
||||||
/* Calculated delay... */
|
/* Calculated delay... */
|
||||||
|
|
@ -275,32 +269,20 @@ static void assign_to_lvector(ivl_lval_t lval,
|
||||||
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||||
fprintf(vvp_out, " %%evctl/c;\n");
|
fprintf(vvp_out, " %%evctl/c;\n");
|
||||||
} else {
|
} else {
|
||||||
|
int offset_index = allocate_word();
|
||||||
|
int delay_index = allocate_word();
|
||||||
|
|
||||||
/* Constant delay... */
|
/* Constant delay... */
|
||||||
draw_eval_expr_into_integer(part_off_ex, 1);
|
fprintf(vvp_out, " %%ix/load %d, %lu, %lu;\n",
|
||||||
|
delay_index, low_d, hig_d);
|
||||||
|
/* Calculated part offset... */
|
||||||
|
draw_eval_expr_into_integer(part_off_ex, offset_index);
|
||||||
/* If the index expression has XZ bits, skip the assign. */
|
/* If the index expression has XZ bits, skip the assign. */
|
||||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
||||||
#if 0
|
fprintf(vvp_out, " %%assign/vec4/off/d v%p_%lu, %d, %d;\n",
|
||||||
fprintf(vvp_out, " %%ix/load 0, %u, 0;\n", width);
|
sig, use_word, offset_index, delay_index);
|
||||||
/*
|
clr_word(offset_index);
|
||||||
* The %assign can only take a 32 bit delay. For a larger
|
clr_word(delay_index);
|
||||||
* delay we need to put it into an index register.
|
|
||||||
*/
|
|
||||||
if (hig_d != 0) {
|
|
||||||
int delay_index = allocate_word();
|
|
||||||
fprintf(vvp_out, " %%ix/load %d, %lu, %lu;\n",
|
|
||||||
delay_index, low_d, hig_d);
|
|
||||||
fprintf(vvp_out,
|
|
||||||
" %%assign/v0/x1/d v%p_%lu, %d, %u;\n",
|
|
||||||
sig, use_word, delay_index, bit);
|
|
||||||
clr_word(delay_index);
|
|
||||||
} else {
|
|
||||||
fprintf(vvp_out,
|
|
||||||
" %%assign/v0/x1 v%p_%lu, %lu, %u;\n",
|
|
||||||
sig, use_word, low_d, bit);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
assert(0); // XXXX
|
|
||||||
#endif
|
|
||||||
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -356,6 +338,9 @@ static void assign_to_lvector(ivl_lval_t lval,
|
||||||
assert(0); // XXXX
|
assert(0); // XXXX
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
// Constant part offset, non-constant (calculated)
|
||||||
|
// assignment delay. Use the %assign/vec4/off/d
|
||||||
|
// instruction to handle this case.
|
||||||
int offset_index = allocate_word();
|
int offset_index = allocate_word();
|
||||||
int delay_index = allocate_word();
|
int delay_index = allocate_word();
|
||||||
fprintf(vvp_out, " %%ix/load %d, %lu, 0;\n", offset_index, part_off);
|
fprintf(vvp_out, " %%ix/load %d, %lu, 0;\n", offset_index, part_off);
|
||||||
|
|
@ -932,26 +917,21 @@ static void force_real_to_lval(ivl_statement_t net)
|
||||||
fprintf(vvp_out, " %s v%p_%lu;\n", command_name, lsig, use_word);
|
fprintf(vvp_out, " %s v%p_%lu;\n", command_name, lsig, use_word);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
|
static void force_vector_to_lval(ivl_statement_t net)
|
||||||
{
|
{
|
||||||
unsigned lidx;
|
unsigned lidx;
|
||||||
unsigned roff = 0;
|
|
||||||
|
|
||||||
const char*command_name;
|
const char*command_name;
|
||||||
const char*command_name_x0;
|
|
||||||
|
|
||||||
switch (ivl_statement_type(net)) {
|
switch (ivl_statement_type(net)) {
|
||||||
case IVL_ST_CASSIGN:
|
case IVL_ST_CASSIGN:
|
||||||
command_name = "%cassign/v";
|
command_name = "%cassign/vec4";
|
||||||
command_name_x0 = "%cassign/x0";
|
|
||||||
break;
|
break;
|
||||||
case IVL_ST_FORCE:
|
case IVL_ST_FORCE:
|
||||||
command_name = "%force/v";
|
command_name = "%force/vec4";
|
||||||
command_name_x0 = "%force/x0";
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
command_name = "ERROR";
|
command_name = "ERROR";
|
||||||
command_name_x0 = "ERROR";
|
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -960,24 +940,9 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
|
||||||
ivl_lval_t lval = ivl_stmt_lval(net, lidx);
|
ivl_lval_t lval = ivl_stmt_lval(net, lidx);
|
||||||
ivl_signal_t lsig = ivl_lval_sig(lval);
|
ivl_signal_t lsig = ivl_lval_sig(lval);
|
||||||
|
|
||||||
unsigned use_wid = ivl_lval_width(lval);
|
|
||||||
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
|
||||||
unsigned long part_off;
|
|
||||||
ivl_expr_t word_idx = ivl_lval_idx(lval);
|
ivl_expr_t word_idx = ivl_lval_idx(lval);
|
||||||
unsigned long use_word = 0;
|
unsigned long use_word = 0;
|
||||||
|
|
||||||
if (part_off_ex == 0) {
|
|
||||||
part_off = 0;
|
|
||||||
} else {
|
|
||||||
assert(number_is_immediate(part_off_ex, IMM_WID, 0));
|
|
||||||
/* An out-of-range or undefined offset will have been
|
|
||||||
converted to a canonical offset of 1'bx. Skip the
|
|
||||||
assignment in this case. */
|
|
||||||
if (number_is_unknown(part_off_ex))
|
|
||||||
return;
|
|
||||||
part_off = get_number_immediate(part_off_ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (word_idx != 0) {
|
if (word_idx != 0) {
|
||||||
assert(number_is_immediate(word_idx, IMM_WID, 0));
|
assert(number_is_immediate(word_idx, IMM_WID, 0));
|
||||||
/* An out-of-range or undefined index will have been
|
/* An out-of-range or undefined index will have been
|
||||||
|
|
@ -1001,24 +966,13 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
|
||||||
|
|
||||||
/* L-Value must be a signal: reg or wire */
|
/* L-Value must be a signal: reg or wire */
|
||||||
assert(lsig != 0);
|
assert(lsig != 0);
|
||||||
|
/* Do not support bit or part selects of l-values yet. */
|
||||||
|
assert(ivl_lval_width(lval) == ivl_signal_width(lsig));
|
||||||
|
assert(!ivl_lval_part_off(lval));
|
||||||
|
|
||||||
if (part_off != 0 || use_wid != ivl_signal_width(lsig)) {
|
|
||||||
|
|
||||||
command_name = command_name_x0;
|
fprintf(vvp_out, " %s v%p_%lu;\n", command_name, lsig, use_word);
|
||||||
fprintf(vvp_out, " %%ix/load 0, %lu, 0;\n", part_off);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* Do not support bit or part selects of l-values yet. */
|
|
||||||
assert(ivl_lval_width(lval) == ivl_signal_width(lsig));
|
|
||||||
|
|
||||||
assert((roff + use_wid) <= rvec.wid);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(vvp_out, " %s v%p_%lu, %u, %u;\n", command_name,
|
|
||||||
lsig, use_word, rvec.base+roff, use_wid);
|
|
||||||
|
|
||||||
if (rvec.base >= 4)
|
|
||||||
roff += use_wid;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1170,13 +1124,11 @@ static int show_stmt_cassign(ivl_statement_t net)
|
||||||
force_real_to_lval(net);
|
force_real_to_lval(net);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
struct vector_info rvec;
|
|
||||||
|
|
||||||
rvec = draw_eval_expr(rval, STUFF_OK_47);
|
|
||||||
|
|
||||||
|
draw_eval_vec4(rval, STUFF_OK_47);
|
||||||
/* Write out initial continuous assign instructions to assign
|
/* Write out initial continuous assign instructions to assign
|
||||||
the expression value to the l-value. */
|
the expression value to the l-value. */
|
||||||
force_vector_to_lval(net, rvec);
|
force_vector_to_lval(net);
|
||||||
}
|
}
|
||||||
|
|
||||||
force_link_rval(net, rval);
|
force_link_rval(net, rval);
|
||||||
|
|
@ -1474,13 +1426,12 @@ static int show_stmt_force(ivl_statement_t net)
|
||||||
force_real_to_lval(net);
|
force_real_to_lval(net);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
struct vector_info rvec;
|
|
||||||
|
|
||||||
rvec = draw_eval_expr(rval, STUFF_OK_47);
|
draw_eval_vec4(rval, STUFF_OK_47);
|
||||||
|
|
||||||
/* Write out initial continuous assign instructions to assign
|
/* Write out initial continuous assign instructions to assign
|
||||||
the expression value to the l-value. */
|
the expression value to the l-value. */
|
||||||
force_vector_to_lval(net, rvec);
|
force_vector_to_lval(net);
|
||||||
}
|
}
|
||||||
|
|
||||||
force_link_rval(net, rval);
|
force_link_rval(net, rval);
|
||||||
|
|
@ -1686,28 +1637,27 @@ static int show_stmt_repeat(ivl_statement_t net, ivl_scope_t sscope)
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
unsigned lab_top = local_count++, lab_out = local_count++;
|
unsigned lab_top = local_count++, lab_out = local_count++;
|
||||||
ivl_expr_t expr = ivl_stmt_cond_expr(net);
|
ivl_expr_t expr = ivl_stmt_cond_expr(net);
|
||||||
struct vector_info cnt;
|
|
||||||
const char *sign = ivl_expr_signed(expr) ? "s" : "u";
|
const char *sign = ivl_expr_signed(expr) ? "s" : "u";
|
||||||
|
|
||||||
show_stmt_file_line(net, "Repeat statement.");
|
show_stmt_file_line(net, "Repeat statement.");
|
||||||
|
|
||||||
cnt = draw_eval_expr(expr, 0);
|
/* Calculate the repeat count onto the top of the vec4 stack. */
|
||||||
|
draw_eval_vec4(expr, STUFF_OK_XZ);
|
||||||
|
|
||||||
/* Test that 0 < expr */
|
/* Test that 0 < expr */
|
||||||
fprintf(vvp_out, "T_%u.%u %%cmp/%s 0, %u, %u;\n", thread_count,
|
fprintf(vvp_out, "T_%u.%u %%dup/vec4;\n", thread_count, lab_top);
|
||||||
lab_top, sign, cnt.base, cnt.wid);
|
fprintf(vvp_out, " %%pushi/vec4 0, 0, %u;\n", ivl_expr_width(expr));
|
||||||
clear_expression_lookaside();
|
fprintf(vvp_out, " %%cmp/%s;\n", sign);
|
||||||
fprintf(vvp_out, " %%jmp/0xz T_%u.%u, 5;\n", thread_count, lab_out);
|
fprintf(vvp_out, " %%jmp/1xz T_%u.%u, 5;\n", thread_count, lab_out);
|
||||||
/* This adds -1 (all ones in 2's complement) to the count. */
|
/* This adds -1 (all ones in 2's complement) to the count. */
|
||||||
fprintf(vvp_out, " %%add %u, 1, %u;\n", cnt.base, cnt.wid);
|
fprintf(vvp_out, " %%pushi/vec4 1, 0, %u;\n", ivl_expr_width(expr));
|
||||||
|
fprintf(vvp_out, " %%sub;\n");
|
||||||
|
|
||||||
rc += show_statement(ivl_stmt_sub_stmt(net), sscope);
|
rc += show_statement(ivl_stmt_sub_stmt(net), sscope);
|
||||||
|
|
||||||
fprintf(vvp_out, " %%jmp T_%u.%u;\n", thread_count, lab_top);
|
fprintf(vvp_out, " %%jmp T_%u.%u;\n", thread_count, lab_top);
|
||||||
fprintf(vvp_out, "T_%u.%u ;\n", thread_count, lab_out);
|
fprintf(vvp_out, "T_%u.%u ;\n", thread_count, lab_out);
|
||||||
clear_expression_lookaside();
|
fprintf(vvp_out, " %%pop/vec4 1;\n");
|
||||||
|
|
||||||
clr_vector(cnt);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
vvp/codes.h
12
vvp/codes.h
|
|
@ -50,6 +50,7 @@ extern bool of_ASSIGN_MV(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_ASSIGN_VEC4(vthread_t thr, vvp_code_t code);
|
extern bool of_ASSIGN_VEC4(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_ASSIGN_VEC4D(vthread_t thr, vvp_code_t code);
|
extern bool of_ASSIGN_VEC4D(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_ASSIGN_VEC4E(vthread_t thr, vvp_code_t code);
|
extern bool of_ASSIGN_VEC4E(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_ASSIGN_VEC4_A_D(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_ASSIGN_VEC4_OFF_D(vthread_t thr, vvp_code_t code);
|
extern bool of_ASSIGN_VEC4_OFF_D(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_ASSIGN_V0X1(vthread_t thr, vvp_code_t code);
|
extern bool of_ASSIGN_V0X1(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_ASSIGN_V0X1D(vthread_t thr, vvp_code_t code);
|
extern bool of_ASSIGN_V0X1D(vthread_t thr, vvp_code_t code);
|
||||||
|
|
@ -62,7 +63,7 @@ extern bool of_BLEND(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_BLEND_WR(vthread_t thr, vvp_code_t code);
|
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_BREAKPOINT(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_CASSIGN_LINK(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_VEC4(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_CASSIGN_WR(vthread_t thr, vvp_code_t code);
|
extern bool of_CASSIGN_WR(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_CASSIGN_X0(vthread_t thr, vvp_code_t code);
|
extern bool of_CASSIGN_X0(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_CAST2(vthread_t thr, vvp_code_t code);
|
extern bool of_CAST2(vthread_t thr, vvp_code_t code);
|
||||||
|
|
@ -109,7 +110,7 @@ extern bool of_FLAG_GET_VEC4(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_FLAG_SET_IMM(vthread_t thr, vvp_code_t code);
|
extern bool of_FLAG_SET_IMM(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_FLAG_SET_VEC4(vthread_t thr, vvp_code_t code);
|
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_LINK(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_FORCE_V(vthread_t thr, vvp_code_t code);
|
extern bool of_FORCE_VEC4(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_FORCE_WR(vthread_t thr, vvp_code_t code);
|
extern bool of_FORCE_WR(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_FORCE_X0(vthread_t thr, vvp_code_t code);
|
extern bool of_FORCE_X0(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_FORK(vthread_t thr, vvp_code_t code);
|
extern bool of_FORK(vthread_t thr, vvp_code_t code);
|
||||||
|
|
@ -130,6 +131,7 @@ extern bool of_JMP(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_JMP0(vthread_t thr, vvp_code_t code);
|
extern bool of_JMP0(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_JMP0XZ(vthread_t thr, vvp_code_t code);
|
extern bool of_JMP0XZ(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_JMP1(vthread_t thr, vvp_code_t code);
|
extern bool of_JMP1(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_JMP1XZ(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_JOIN(vthread_t thr, vvp_code_t code);
|
extern bool of_JOIN(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_JOIN_DETACH(vthread_t thr, vvp_code_t code);
|
extern bool of_JOIN_DETACH(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_LOAD_AR(vthread_t thr, vvp_code_t code);
|
extern bool of_LOAD_AR(vthread_t thr, vvp_code_t code);
|
||||||
|
|
@ -145,6 +147,7 @@ extern bool of_LOAD_OBJ(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_LOAD_STR(vthread_t thr, vvp_code_t code);
|
extern bool of_LOAD_STR(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_LOAD_STRA(vthread_t thr, vvp_code_t code);
|
extern bool of_LOAD_STRA(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_LOAD_VEC4(vthread_t thr, vvp_code_t code);
|
extern bool of_LOAD_VEC4(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_LOAD_VEC4A(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_LOAD_VP0(vthread_t thr, vvp_code_t code);
|
extern bool of_LOAD_VP0(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_LOAD_VP0_S(vthread_t thr, vvp_code_t code);
|
extern bool of_LOAD_VP0_S(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_LOAD_X1P(vthread_t thr, vvp_code_t code);
|
extern bool of_LOAD_X1P(vthread_t thr, vvp_code_t code);
|
||||||
|
|
@ -171,7 +174,8 @@ extern bool of_OR(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_ORR(vthread_t thr, vvp_code_t code);
|
extern bool of_ORR(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_PAD_S(vthread_t thr, vvp_code_t code);
|
extern bool of_PAD_S(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_PAD_U(vthread_t thr, vvp_code_t code);
|
extern bool of_PAD_U(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_PART(vthread_t thr, vvp_code_t code);
|
extern bool of_PART_S(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_PART_U(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_POP_OBJ(vthread_t thr, vvp_code_t code);
|
extern bool of_POP_OBJ(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_POP_REAL(vthread_t thr, vvp_code_t code);
|
extern bool of_POP_REAL(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_POP_STR(vthread_t thr, vvp_code_t code);
|
extern bool of_POP_STR(vthread_t thr, vvp_code_t code);
|
||||||
|
|
@ -191,6 +195,7 @@ extern bool of_PUTC_STR_V(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_RELEASE_NET(vthread_t thr, vvp_code_t code);
|
extern bool of_RELEASE_NET(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_RELEASE_REG(vthread_t thr, vvp_code_t code);
|
extern bool of_RELEASE_REG(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_RELEASE_WR(vthread_t thr, vvp_code_t code);
|
extern bool of_RELEASE_WR(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_REPLICATE(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_SCOPY(vthread_t thr, vvp_code_t code);
|
extern bool of_SCOPY(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_SET_AV(vthread_t thr, vvp_code_t code);
|
extern bool of_SET_AV(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_SET_DAR(vthread_t thr, vvp_code_t code);
|
extern bool of_SET_DAR(vthread_t thr, vvp_code_t code);
|
||||||
|
|
@ -216,6 +221,7 @@ extern bool of_STORE_REALA(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_STORE_STR(vthread_t thr, vvp_code_t code);
|
extern bool of_STORE_STR(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_STORE_STRA(vthread_t thr, vvp_code_t code);
|
extern bool of_STORE_STRA(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_STORE_VEC4(vthread_t thr, vvp_code_t code);
|
extern bool of_STORE_VEC4(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_STORE_VEC4_OFF(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_SUB(vthread_t thr, vvp_code_t code);
|
extern bool of_SUB(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_SUB_WR(vthread_t thr, vvp_code_t code);
|
extern bool of_SUB_WR(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_SUBI(vthread_t thr, vvp_code_t code);
|
extern bool of_SUBI(vthread_t thr, vvp_code_t code);
|
||||||
|
|
|
||||||
|
|
@ -101,10 +101,11 @@ static const struct opcode_table_s opcode_table[] = {
|
||||||
{ "%assign/v0/x1",of_ASSIGN_V0X1,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
{ "%assign/v0/x1",of_ASSIGN_V0X1,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
||||||
{ "%assign/v0/x1/d",of_ASSIGN_V0X1D,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
{ "%assign/v0/x1/d",of_ASSIGN_V0X1D,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
||||||
{ "%assign/v0/x1/e",of_ASSIGN_V0X1E,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
{ "%assign/v0/x1/e",of_ASSIGN_V0X1E,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
||||||
{ "%assign/vec4", of_ASSIGN_VEC4, 2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
{ "%assign/vec4", of_ASSIGN_VEC4, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%assign/vec4/d",of_ASSIGN_VEC4D,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
{ "%assign/vec4/a/d", of_ASSIGN_VEC4_A_D, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
|
||||||
{ "%assign/vec4/e",of_ASSIGN_VEC4E,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
{ "%assign/vec4/d", of_ASSIGN_VEC4D, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%assign/vec4/off/d",of_ASSIGN_VEC4_OFF_D, 3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
{ "%assign/vec4/e", of_ASSIGN_VEC4E, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||||
|
{ "%assign/vec4/off/d",of_ASSIGN_VEC4_OFF_D, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||||
{ "%assign/wr", of_ASSIGN_WR, 2,{OA_VPI_PTR, OA_BIT1, OA_NONE} },
|
{ "%assign/wr", of_ASSIGN_WR, 2,{OA_VPI_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%assign/wr/d",of_ASSIGN_WRD,2,{OA_VPI_PTR, OA_BIT1, OA_NONE} },
|
{ "%assign/wr/d",of_ASSIGN_WRD,2,{OA_VPI_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%assign/wr/e",of_ASSIGN_WRE,1,{OA_VPI_PTR, OA_NONE, OA_NONE} },
|
{ "%assign/wr/e",of_ASSIGN_WRE,1,{OA_VPI_PTR, OA_NONE, OA_NONE} },
|
||||||
|
|
@ -113,8 +114,8 @@ static const struct opcode_table_s opcode_table[] = {
|
||||||
{ "%blend/wr", of_BLEND_WR,0, {OA_NONE, OA_NONE, OA_NONE} },
|
{ "%blend/wr", of_BLEND_WR,0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||||
{ "%breakpoint", of_BREAKPOINT, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
{ "%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/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/vec4",of_CASSIGN_VEC4,1,{OA_FUNC_PTR,OA_NONE , OA_NONE} },
|
||||||
{ "%cassign/wr",of_CASSIGN_WR,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
{ "%cassign/wr", of_CASSIGN_WR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
||||||
{ "%cassign/x0",of_CASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
{ "%cassign/x0",of_CASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
||||||
{ "%cast2", of_CAST2, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%cast2", of_CAST2, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
{ "%cmp/s", of_CMPS, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
{ "%cmp/s", of_CMPS, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||||
|
|
@ -123,8 +124,8 @@ static const struct opcode_table_s opcode_table[] = {
|
||||||
{ "%cmp/wr", of_CMPWR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
{ "%cmp/wr", of_CMPWR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||||
{ "%cmp/ws", of_CMPWS, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
{ "%cmp/ws", of_CMPWS, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||||
{ "%cmp/wu", of_CMPWU, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
{ "%cmp/wu", of_CMPWU, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||||
{ "%cmp/x", of_CMPX, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%cmp/x", of_CMPX, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||||
{ "%cmp/z", of_CMPZ, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%cmp/z", of_CMPZ, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||||
{ "%cmpi/s", of_CMPIS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%cmpi/s", of_CMPIS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
{ "%cmpi/u", of_CMPIU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%cmpi/u", of_CMPIU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
{ "%concat/str", of_CONCAT_STR, 0,{OA_NONE, OA_NONE, OA_NONE} },
|
{ "%concat/str", of_CONCAT_STR, 0,{OA_NONE, OA_NONE, OA_NONE} },
|
||||||
|
|
@ -157,9 +158,9 @@ static const struct opcode_table_s opcode_table[] = {
|
||||||
{ "%flag_get/vec4", of_FLAG_GET_VEC4, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
{ "%flag_get/vec4", of_FLAG_GET_VEC4, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
{ "%flag_set/imm", of_FLAG_SET_IMM, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
|
{ "%flag_set/imm", of_FLAG_SET_IMM, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
|
||||||
{ "%flag_set/vec4", of_FLAG_SET_VEC4, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
{ "%flag_set/vec4", of_FLAG_SET_VEC4, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
{ "%force/link",of_FORCE_LINK,2,{OA_FUNC_PTR,OA_FUNC_PTR2,OA_NONE} },
|
{ "%force/link",of_FORCE_LINK,2,{OA_FUNC_PTR, OA_FUNC_PTR2, OA_NONE} },
|
||||||
{ "%force/v",of_FORCE_V,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
{ "%force/vec4",of_FORCE_VEC4,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||||
{ "%force/wr",of_FORCE_WR,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
{ "%force/wr", of_FORCE_WR, 1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||||
{ "%force/x0",of_FORCE_X0,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
{ "%force/x0",of_FORCE_X0,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||||
{ "%free", of_FREE, 1, {OA_VPI_PTR, OA_NONE, OA_NONE} },
|
{ "%free", of_FREE, 1, {OA_VPI_PTR, OA_NONE, OA_NONE} },
|
||||||
{ "%inv", of_INV, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
{ "%inv", of_INV, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||||
|
|
@ -178,6 +179,7 @@ static const struct opcode_table_s opcode_table[] = {
|
||||||
{ "%jmp/0", of_JMP0, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
{ "%jmp/0", of_JMP0, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%jmp/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
{ "%jmp/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%jmp/1", of_JMP1, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
{ "%jmp/1", of_JMP1, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||||
|
{ "%jmp/1xz",of_JMP1XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%join", of_JOIN, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
{ "%join", of_JOIN, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||||
{ "%join/detach",of_JOIN_DETACH,1,{OA_NUMBER,OA_NONE, OA_NONE} },
|
{ "%join/detach",of_JOIN_DETACH,1,{OA_NUMBER,OA_NONE, OA_NONE} },
|
||||||
{ "%load/ar",of_LOAD_AR,2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
{ "%load/ar",of_LOAD_AR,2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
||||||
|
|
@ -188,11 +190,12 @@ static const struct opcode_table_s opcode_table[] = {
|
||||||
{ "%load/dar",of_LOAD_DAR,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
|
{ "%load/dar",of_LOAD_DAR,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
|
||||||
{ "%load/dar/r", of_LOAD_DAR_R, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE}},
|
{ "%load/dar/r", of_LOAD_DAR_R, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE}},
|
||||||
{ "%load/dar/str",of_LOAD_DAR_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
{ "%load/dar/str",of_LOAD_DAR_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||||
{ "%load/obj", of_LOAD_OBJ, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
{ "%load/obj", of_LOAD_OBJ, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
||||||
{ "%load/real", of_LOAD_REAL,1,{OA_VPI_PTR, OA_NONE, OA_NONE} },
|
{ "%load/real", of_LOAD_REAL, 1,{OA_VPI_PTR, OA_NONE, OA_NONE} },
|
||||||
{ "%load/str", of_LOAD_STR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
{ "%load/str", of_LOAD_STR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
||||||
{ "%load/stra", of_LOAD_STRA,2,{OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
{ "%load/stra", of_LOAD_STRA, 2,{OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%load/vec4", of_LOAD_VEC4,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
{ "%load/vec4", of_LOAD_VEC4, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
||||||
|
{ "%load/vec4a", of_LOAD_VEC4A,2,{OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%load/vp0",of_LOAD_VP0,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
|
{ "%load/vp0",of_LOAD_VP0,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
|
||||||
{ "%load/vp0/s",of_LOAD_VP0_S,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
|
{ "%load/vp0/s",of_LOAD_VP0_S,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
|
||||||
{ "%load/x1p",of_LOAD_X1P,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
|
{ "%load/x1p",of_LOAD_X1P,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
|
||||||
|
|
@ -219,7 +222,8 @@ static const struct opcode_table_s opcode_table[] = {
|
||||||
{ "%or/r", of_ORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%or/r", of_ORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
{ "%pad/s", of_PAD_S, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
{ "%pad/s", of_PAD_S, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
{ "%pad/u", of_PAD_U, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
{ "%pad/u", of_PAD_U, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
{ "%part", of_PART, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
{ "%part/s", of_PART_S, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
|
{ "%part/u", of_PART_U, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
{ "%pop/obj", of_POP_OBJ, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
{ "%pop/obj", of_POP_OBJ, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||||
{ "%pop/real",of_POP_REAL,1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
{ "%pop/real",of_POP_REAL,1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
{ "%pop/str", of_POP_STR, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
{ "%pop/str", of_POP_STR, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
|
|
@ -238,7 +242,8 @@ static const struct opcode_table_s opcode_table[] = {
|
||||||
{ "%putc/str/v",of_PUTC_STR_V,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
{ "%putc/str/v",of_PUTC_STR_V,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
||||||
{ "%release/net",of_RELEASE_NET,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
{ "%release/net",of_RELEASE_NET,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
||||||
{ "%release/reg",of_RELEASE_REG,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
{ "%release/reg",of_RELEASE_REG,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
||||||
{ "%release/wr",of_RELEASE_WR,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
{ "%release/wr", of_RELEASE_WR, 2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
||||||
|
{ "%replicate", of_REPLICATE, 1,{OA_NUMBER, OA_NONE,OA_NONE} },
|
||||||
{ "%scopy", of_SCOPY, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
{ "%scopy", of_SCOPY, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||||
{ "%set/av", of_SET_AV, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
|
{ "%set/av", of_SET_AV, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
|
||||||
{ "%set/dar",of_SET_DAR,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
{ "%set/dar",of_SET_DAR,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||||
|
|
@ -258,11 +263,12 @@ static const struct opcode_table_s opcode_table[] = {
|
||||||
{ "%store/prop/r", of_STORE_PROP_R, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
{ "%store/prop/r", of_STORE_PROP_R, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
{ "%store/prop/str",of_STORE_PROP_STR,1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
{ "%store/prop/str",of_STORE_PROP_STR,1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
{ "%store/prop/v", of_STORE_PROP_V, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%store/prop/v", of_STORE_PROP_V, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
{ "%store/real", of_STORE_REAL, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
{ "%store/real", of_STORE_REAL, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
||||||
{ "%store/reala", of_STORE_REALA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
{ "%store/reala", of_STORE_REALA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%store/str", of_STORE_STR, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
{ "%store/str", of_STORE_STR, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
||||||
{ "%store/stra", of_STORE_STRA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
{ "%store/stra", of_STORE_STRA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%store/vec4", of_STORE_VEC4, 2, {OA_FUNC_PTR,OA_BIT1, OA_NONE} },
|
{ "%store/vec4", of_STORE_VEC4, 2, {OA_FUNC_PTR,OA_BIT1, OA_NONE} },
|
||||||
|
{ "%store/vec4/off",of_STORE_VEC4_OFF,3, {OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
||||||
{ "%sub", of_SUB, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
{ "%sub", of_SUB, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||||
{ "%sub/wr", of_SUB_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
{ "%sub/wr", of_SUB_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||||
{ "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
|
|
@ -567,6 +573,12 @@ bool vpi_handle_resolv_list_s::resolve(bool mes)
|
||||||
|
|
||||||
val.ptr = vpip_make_vthr_str_stack(base);
|
val.ptr = vpip_make_vthr_str_stack(base);
|
||||||
sym_set_value(sym_vpi, label(), val);
|
sym_set_value(sym_vpi, label(), val);
|
||||||
|
|
||||||
|
} else if (1 == sscanf(label(), "S<%u,vec4>%n", &base, &n)
|
||||||
|
&& n == strlen(label())) {
|
||||||
|
|
||||||
|
val.ptr = vpip_make_vthr_vec4_stack(base);
|
||||||
|
sym_set_value(sym_vpi, label(), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,9 +115,9 @@ The %assign/ar/e variation uses the information in the thread
|
||||||
event control registers to determine when to perform the assign.
|
event control registers to determine when to perform the assign.
|
||||||
%evctl is used to set the event control information.
|
%evctl is used to set the event control information.
|
||||||
|
|
||||||
* %assign/av <array-label>, <delay>, <bit>
|
* %assign/av <array-label>, <delay>, <bit> (XXXX Old definition)
|
||||||
* %assign/av/d <array-label>, <delayx>, <bit>
|
* %assign/av/d <array-label>, <delayx>, <bit> (XXXX Old definition)
|
||||||
* %assign/av/e <array-label>, <bit>
|
* %assign/av/e <array-label>, <bit> (XXXX Old definition)
|
||||||
|
|
||||||
The %assign/av instruction assigns a vector value to a word in the
|
The %assign/av instruction assigns a vector value to a word in the
|
||||||
labeled array. The <delay> is the delay in simulation time to the
|
labeled array. The <delay> is the delay in simulation time to the
|
||||||
|
|
@ -181,6 +181,19 @@ pulled from the vec4 stack.
|
||||||
The %assign/vec4/d instruction is the same, but gets its delay value
|
The %assign/vec4/d instruction is the same, but gets its delay value
|
||||||
from the index register <delayx> instead.
|
from the index register <delayx> instead.
|
||||||
|
|
||||||
|
* %assign/vec4/a/d <var-label>, <off-index>, <delay-index>
|
||||||
|
* %assign/vec4/a/e <var-label>, <off-index>
|
||||||
|
|
||||||
|
This instruction implements delayed assignment to an array word. The
|
||||||
|
value is popped from the vec4 stack; the width is taken from the
|
||||||
|
popped value. The <off-index> index register contains the canonical
|
||||||
|
offset into the memory word for a part select, and the <delay-index>
|
||||||
|
index register contains the delay for the assignment. Index register 3
|
||||||
|
contains the word address.
|
||||||
|
|
||||||
|
The <off-index> and <delay-index> index registers can be 0, which
|
||||||
|
means a zero value instead of the contents of index register 0.
|
||||||
|
|
||||||
* %assign/vec4/off/d <var-label>, <off-index>, <delay-index>
|
* %assign/vec4/off/d <var-label>, <off-index>, <delay-index>
|
||||||
|
|
||||||
This is for writing parts to the target variable. The <var-label> is
|
This is for writing parts to the target variable. The <var-label> is
|
||||||
|
|
@ -250,7 +263,7 @@ debugger commands.
|
||||||
This may not work on all platforms. If run-time debugging is compiled
|
This may not work on all platforms. If run-time debugging is compiled
|
||||||
out, then this function is a no-op.
|
out, then this function is a no-op.
|
||||||
|
|
||||||
* %cassign/v <var-label>, <bit>, <wid>
|
* %cassign/vec4 <var-label>
|
||||||
|
|
||||||
Perform a continuous assign of a constant value to the target
|
Perform a continuous assign of a constant value to the target
|
||||||
variable. This is similar to %set, but it uses the cassign port
|
variable. This is similar to %set, but it uses the cassign port
|
||||||
|
|
@ -342,8 +355,8 @@ popped from the stack first, then (a).
|
||||||
|
|
||||||
[compare signed/unsigned integer words.]
|
[compare signed/unsigned integer words.]
|
||||||
|
|
||||||
* %cmp/z <bit-l>, <bit-r>, <wid>
|
* %cmp/z
|
||||||
* %cmp/x <bit-l>, <bit-r>, <wid>
|
* %cmp/x
|
||||||
|
|
||||||
These instructions are for implementing the casez and casex
|
These instructions are for implementing the casez and casex
|
||||||
comparisons. These work similar to the %cmp/u instructions, except
|
comparisons. These work similar to the %cmp/u instructions, except
|
||||||
|
|
@ -427,6 +440,12 @@ will be deactivated. For a full deactivation the <base> is 0 and
|
||||||
|
|
||||||
The same as %deassign above except this is used for real variables.
|
The same as %deassign above except this is used for real variables.
|
||||||
|
|
||||||
|
* %debug/thr
|
||||||
|
|
||||||
|
These opcodes are aids for debugging the vvp engine. The vvp code
|
||||||
|
generator should not generate these, and they should not alter code
|
||||||
|
flow, data contents, etc.
|
||||||
|
|
||||||
* %delay <low>, <high>
|
* %delay <low>, <high>
|
||||||
|
|
||||||
This opcode pauses the thread, and causes it to be rescheduled for a
|
This opcode pauses the thread, and causes it to be rescheduled for a
|
||||||
|
|
@ -536,7 +555,7 @@ writes the LSB to the selected flag.
|
||||||
* %force/v <label>, <bit>, <wid>
|
* %force/v <label>, <bit>, <wid>
|
||||||
|
|
||||||
Force a constant value to the target variable. This is similar to %set
|
Force a constant value to the target variable. This is similar to %set
|
||||||
and %cassign/v, but it uses the force port (port-2) of the signal
|
and %cassign/vec4, but it uses the force port (port-2) of the signal
|
||||||
functor instead of the normal assign port (port-0), so the signal
|
functor instead of the normal assign port (port-0), so the signal
|
||||||
responds differently. See "VARIABLE STATEMENTS" and "NET STATEMENTS"
|
responds differently. See "VARIABLE STATEMENTS" and "NET STATEMENTS"
|
||||||
in the README.txt file.
|
in the README.txt file.
|
||||||
|
|
@ -753,6 +772,15 @@ more than the width at the functor, the value is padded with X bits.
|
||||||
This instruction loads a vector value from the given functor node and
|
This instruction loads a vector value from the given functor node and
|
||||||
pushes it onto the vec4 stack. See also the %store/vec4 instruction.
|
pushes it onto the vec4 stack. See also the %store/vec4 instruction.
|
||||||
|
|
||||||
|
* %load/vec4a <arr-label>, <addr-index>
|
||||||
|
|
||||||
|
This instruction loads a vec4 value from the array and pushes the
|
||||||
|
value onto the stack. The <addr-index> is the index register that
|
||||||
|
holds the canonical array index.
|
||||||
|
|
||||||
|
The load checks flag bit 4. If it is 1, then the load it cancelled and
|
||||||
|
replaced with a load of all X bits. See %ix/vec4.
|
||||||
|
|
||||||
* %load/vp0 <bit>, <functor-label>, <wid>
|
* %load/vp0 <bit>, <functor-label>, <wid>
|
||||||
* %load/vp0/s <bit>, <functor-label>, <wid>
|
* %load/vp0/s <bit>, <functor-label>, <wid>
|
||||||
|
|
||||||
|
|
@ -1070,6 +1098,12 @@ Release the force on the real signal that is represented by the functor
|
||||||
statement. The <type> is 0 for nets and 1 for registers. See the other
|
statement. The <type> is 0 for nets and 1 for registers. See the other
|
||||||
%release commands above.
|
%release commands above.
|
||||||
|
|
||||||
|
* %replicate <count>
|
||||||
|
|
||||||
|
Pop the vec4 value, replicate it <count> times, then push the
|
||||||
|
result. In other words, push the concatenation of <count> copies.
|
||||||
|
See also the %concat instruction.
|
||||||
|
|
||||||
* %set/dar <var-label>, <bit>, <wid>
|
* %set/dar <var-label>, <bit>, <wid>
|
||||||
* %set/dar/obj <index>, <bit>, <wid>
|
* %set/dar/obj <index>, <bit>, <wid>
|
||||||
|
|
||||||
|
|
@ -1214,12 +1248,18 @@ The %store/dar/str is similar, but the target is a dynamic array of
|
||||||
string string. The index is taken from signed index register 3.
|
string string. The index is taken from signed index register 3.
|
||||||
|
|
||||||
* %store/vec4 <var-label>, <wid>
|
* %store/vec4 <var-label>, <wid>
|
||||||
|
* %store/vec4/off <var-label>, <offset>, <wid>
|
||||||
|
|
||||||
Store a logic vector into the variable. The value (and its width) is
|
Store a logic vector into the variable. The value (and its width) is
|
||||||
popped off the top of the stack and written to the variable. The value
|
popped off the top of the stack and written to the variable. The value
|
||||||
is then optionally truncated to <wid> bits and assigned to the
|
is then optionally truncated to <wid> bits and assigned to the
|
||||||
variable. It is an error for the value to be fewer then <wid> bits.
|
variable. It is an error for the value to be fewer then <wid> bits.
|
||||||
|
|
||||||
|
The %store/vec4/off is similar, but it uses the index register
|
||||||
|
<offset> to get a vector offset into the target vec4 variable.
|
||||||
|
|
||||||
|
NOTE: The <wid> is not necessary, and should be removed.
|
||||||
|
|
||||||
* %sub <bit-l>, <bit-r>, <wid> (XXXX Old version)
|
* %sub <bit-l>, <bit-r>, <wid> (XXXX Old version)
|
||||||
|
|
||||||
This instruction arithmetically subtracts the right vector out of the
|
This instruction arithmetically subtracts the right vector out of the
|
||||||
|
|
|
||||||
|
|
@ -660,6 +660,7 @@ vpiHandle vpip_make_vthr_vector(unsigned base, unsigned wid, bool signed_flag);
|
||||||
|
|
||||||
vpiHandle vpip_make_vthr_word(unsigned base, const char*type);
|
vpiHandle vpip_make_vthr_word(unsigned base, const char*type);
|
||||||
vpiHandle vpip_make_vthr_str_stack(unsigned depth);
|
vpiHandle vpip_make_vthr_str_stack(unsigned depth);
|
||||||
|
vpiHandle vpip_make_vthr_vec4_stack(unsigned depth);
|
||||||
|
|
||||||
vpiHandle vpip_make_vthr_A(char*label, unsigned index);
|
vpiHandle vpip_make_vthr_A(char*label, unsigned index);
|
||||||
vpiHandle vpip_make_vthr_A(char*label, char*symbol);
|
vpiHandle vpip_make_vthr_A(char*label, char*symbol);
|
||||||
|
|
|
||||||
|
|
@ -650,7 +650,6 @@ class __vpiVThrStrStack : public __vpiHandle {
|
||||||
int vpi_get(int code);
|
int vpi_get(int code);
|
||||||
void vpi_get_value(p_vpi_value val);
|
void vpi_get_value(p_vpi_value val);
|
||||||
private:
|
private:
|
||||||
const char* name;
|
|
||||||
unsigned depth_;
|
unsigned depth_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -703,6 +702,57 @@ void __vpiVThrStrStack::vpi_get_value(p_vpi_value vp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class __vpiVThrVec4Stack : public __vpiHandle {
|
||||||
|
public:
|
||||||
|
__vpiVThrVec4Stack(unsigned depth);
|
||||||
|
int get_type_code(void) const;
|
||||||
|
int vpi_get(int code);
|
||||||
|
void vpi_get_value(p_vpi_value val);
|
||||||
|
private:
|
||||||
|
unsigned depth_;
|
||||||
|
};
|
||||||
|
|
||||||
|
__vpiVThrVec4Stack::__vpiVThrVec4Stack(unsigned d)
|
||||||
|
: depth_(d)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int __vpiVThrVec4Stack::get_type_code(void) const
|
||||||
|
{ return vpiConstant; }
|
||||||
|
|
||||||
|
|
||||||
|
int __vpiVThrVec4Stack::vpi_get(int code)
|
||||||
|
{
|
||||||
|
switch (code) {
|
||||||
|
case vpiSigned:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case vpiConstType:
|
||||||
|
return vpiBinaryConst;
|
||||||
|
|
||||||
|
#if defined(CHECK_WITH_VALGRIND) || defined(BR916_STOPGAP_FIX)
|
||||||
|
case _vpiFromThr:
|
||||||
|
return _vpiVThr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __vpiVThrVec4Stack::vpi_get_value(p_vpi_value vp)
|
||||||
|
{
|
||||||
|
assert(vpip_current_vthread);
|
||||||
|
vvp_vector4_t val = vthread_get_vec4_stack(vpip_current_vthread, depth_);
|
||||||
|
|
||||||
|
switch (vp->format) {
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "internal error: vpi_get_value(<format=%d>)"
|
||||||
|
" not implemented for __vpiVThrVec4Stack.\n", vp->format);
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
vpiHandle vpip_make_vthr_str_stack(unsigned depth)
|
vpiHandle vpip_make_vthr_str_stack(unsigned depth)
|
||||||
{
|
{
|
||||||
|
|
@ -710,6 +760,12 @@ vpiHandle vpip_make_vthr_str_stack(unsigned depth)
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vpiHandle vpip_make_vthr_vec4_stack(unsigned depth)
|
||||||
|
{
|
||||||
|
class __vpiVThrVec4Stack*obj = new __vpiVThrVec4Stack(depth);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CHECK_WITH_VALGRIND
|
#ifdef CHECK_WITH_VALGRIND
|
||||||
static map<vpiHandle, bool> stack_map;
|
static map<vpiHandle, bool> stack_map;
|
||||||
|
|
||||||
|
|
|
||||||
210
vvp/vthread.cc
210
vvp/vthread.cc
|
|
@ -379,6 +379,11 @@ double vthread_get_real_stack(struct vthread_s*thr, unsigned depth)
|
||||||
return thr->peek_real(depth);
|
return thr->peek_real(depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const vvp_vector4_t& vthread_get_vec4_stack(struct vthread_s*thr, unsigned depth)
|
||||||
|
{
|
||||||
|
return thr->peek_vec4(depth);
|
||||||
|
}
|
||||||
|
|
||||||
template <class T> T coerce_to_width(const T&that, unsigned width)
|
template <class T> T coerce_to_width(const T&that, unsigned width)
|
||||||
{
|
{
|
||||||
if (that.size() == width)
|
if (that.size() == width)
|
||||||
|
|
@ -1242,6 +1247,25 @@ bool of_ASSIGN_VEC4(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* %assign/vec4/a/d <arr>, <offx>, <delx>
|
||||||
|
*/
|
||||||
|
bool of_ASSIGN_VEC4_A_D(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
int off_idx = cp->bit_idx[0];
|
||||||
|
int del_idx = cp->bit_idx[1];
|
||||||
|
int adr_idx = 3;
|
||||||
|
|
||||||
|
long off = off_idx? thr->words[off_idx].w_int : 0;
|
||||||
|
unsigned del = del_idx? thr->words[del_idx].w_uint : 0;
|
||||||
|
long adr = thr->words[adr_idx].w_int;
|
||||||
|
|
||||||
|
vvp_vector4_t value = thr->pop_vec4();
|
||||||
|
|
||||||
|
schedule_assign_array_word(cp->array, adr, off, value, del);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* %assign/vec4/off/d <var>, <off>, <del>
|
* %assign/vec4/off/d <var>, <off>, <del>
|
||||||
*/
|
*/
|
||||||
|
|
@ -1617,10 +1641,10 @@ bool of_CASSIGN_LINK(vthread_t, vvp_code_t cp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the %cassign/v instruction invokes a continuous assign of a
|
* the %cassign/vec4 instruction invokes a continuous assign of a
|
||||||
* constant value to a signal. The instruction arguments are:
|
* constant value to a signal. The instruction arguments are:
|
||||||
*
|
*
|
||||||
* %cassign/v <net>, <base>, <wid> ;
|
* %cassign/vec4 <net>;
|
||||||
*
|
*
|
||||||
* Where the <net> is the net label assembled into a vvp_net pointer,
|
* Where the <net> is the net label assembled into a vvp_net pointer,
|
||||||
* and the <base> and <wid> are stashed in the bit_idx array.
|
* and the <base> and <wid> are stashed in the bit_idx array.
|
||||||
|
|
@ -1628,22 +1652,15 @@ bool of_CASSIGN_LINK(vthread_t, vvp_code_t cp)
|
||||||
* This instruction writes vvp_vector4_t values to port-1 of the
|
* This instruction writes vvp_vector4_t values to port-1 of the
|
||||||
* target signal.
|
* target signal.
|
||||||
*/
|
*/
|
||||||
bool of_CASSIGN_V(vthread_t thr, vvp_code_t cp)
|
bool of_CASSIGN_VEC4(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
#if 0
|
vvp_net_t*net = cp->net;
|
||||||
vvp_net_t*net = cp->net;
|
vvp_vector4_t value = thr->pop_vec4();
|
||||||
unsigned base = cp->bit_idx[0];
|
|
||||||
unsigned wid = cp->bit_idx[1];
|
|
||||||
|
|
||||||
/* Collect the thread bits into a vector4 item. */
|
|
||||||
vvp_vector4_t value = vthread_bits_to_vector(thr, base, wid);
|
|
||||||
|
|
||||||
/* set the value into port 1 of the destination. */
|
/* set the value into port 1 of the destination. */
|
||||||
vvp_net_ptr_t ptr (net, 1);
|
vvp_net_ptr_t ptr (net, 1);
|
||||||
vvp_send_vec4(ptr, value, 0);
|
vvp_send_vec4(ptr, value, 0);
|
||||||
#else
|
|
||||||
fprintf(stderr, "XXXX NOT IMPLEMENTED: %%cassign/v ...\n");
|
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2026,30 +2043,28 @@ bool of_CMPU(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* %cmp/x
|
||||||
|
*/
|
||||||
bool of_CMPX(vthread_t thr, vvp_code_t cp)
|
bool of_CMPX(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
vvp_bit4_t eq = BIT4_1;
|
vvp_bit4_t eq = BIT4_1;
|
||||||
#if 0
|
vvp_vector4_t rval = thr->pop_vec4();
|
||||||
unsigned idx1 = cp->bit_idx[0];
|
vvp_vector4_t lval = thr->pop_vec4();
|
||||||
unsigned idx2 = cp->bit_idx[1];
|
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
|
assert(rval.size() == lval.size());
|
||||||
vvp_bit4_t lv = thr_get_bit(thr, idx1);
|
unsigned wid = lval.size();
|
||||||
vvp_bit4_t rv = thr_get_bit(thr, idx2);
|
|
||||||
|
|
||||||
|
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||||
|
vvp_bit4_t lv = lval.value(idx);
|
||||||
|
vvp_bit4_t rv = rval.value(idx);
|
||||||
if ((lv != rv) && !bit4_is_xz(lv) && !bit4_is_xz(rv)) {
|
if ((lv != rv) && !bit4_is_xz(lv) && !bit4_is_xz(rv)) {
|
||||||
eq = BIT4_0;
|
eq = BIT4_0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idx1 >= 4) idx1 += 1;
|
|
||||||
if (idx2 >= 4) idx2 += 1;
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
fprintf(stderr, "XXXX NOT IMLEMENTED: %%cmpx ...\n");
|
|
||||||
#endif
|
|
||||||
thr->flags[4] = eq;
|
|
||||||
|
|
||||||
|
thr->flags[4] = eq;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2095,30 +2110,28 @@ bool of_CMPWU(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* %cmp/z
|
||||||
|
*/
|
||||||
bool of_CMPZ(vthread_t thr, vvp_code_t cp)
|
bool of_CMPZ(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
vvp_bit4_t eq = BIT4_1;
|
vvp_bit4_t eq = BIT4_1;
|
||||||
#if 0
|
vvp_vector4_t rval = thr->pop_vec4();
|
||||||
unsigned idx1 = cp->bit_idx[0];
|
vvp_vector4_t lval = thr->pop_vec4();
|
||||||
unsigned idx2 = cp->bit_idx[1];
|
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
|
assert(rval.size() == lval.size());
|
||||||
vvp_bit4_t lv = thr_get_bit(thr, idx1);
|
unsigned wid = lval.size();
|
||||||
vvp_bit4_t rv = thr_get_bit(thr, idx2);
|
|
||||||
|
|
||||||
if ((lv != BIT4_Z) && (rv != BIT4_Z) && (lv != rv)) {
|
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||||
|
vvp_bit4_t lv = lval.value(idx);
|
||||||
|
vvp_bit4_t rv = rval.value(idx);
|
||||||
|
if ((lv != rv) && (rv != BIT4_Z) && (lv != BIT4_Z)) {
|
||||||
eq = BIT4_0;
|
eq = BIT4_0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idx1 >= 4) idx1 += 1;
|
|
||||||
if (idx2 >= 4) idx2 += 1;
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
fprintf(stderr, "XXXX NOT IMPLEMENTED: %%cmpz ...\n");
|
|
||||||
#endif
|
|
||||||
thr->flags[4] = eq;
|
|
||||||
|
|
||||||
|
thr->flags[4] = eq;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2941,26 +2954,22 @@ bool of_FORCE_LINK(vthread_t, vvp_code_t cp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The %force/v instruction invokes a force assign of a constant value
|
* The %force/vec4 instruction invokes a force assign of a constant value
|
||||||
* to a signal. The instruction arguments are:
|
* to a signal. The instruction arguments are:
|
||||||
*
|
*
|
||||||
* %force/v <net>, <base>, <wid> ;
|
* %force/vec4 <net> ;
|
||||||
*
|
*
|
||||||
* where the <net> is the net label assembled into a vvp_net pointer,
|
* where the <net> is the net label assembled into a vvp_net pointer,
|
||||||
* and the <base> and <wid> are stashed in the bit_idx array.
|
* and the value to be forced is popped from the vec4 stack.\.
|
||||||
*
|
*
|
||||||
* The instruction writes a vvp_vector4_t value to port-2 of the
|
* The instruction writes a vvp_vector4_t value to port-2 of the
|
||||||
* target signal.
|
* target signal.
|
||||||
*/
|
*/
|
||||||
bool of_FORCE_V(vthread_t thr, vvp_code_t cp)
|
bool of_FORCE_VEC4(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
#if 0
|
vvp_net_t*net = cp->net;
|
||||||
vvp_net_t*net = cp->net;
|
|
||||||
unsigned base = cp->bit_idx[0];
|
|
||||||
unsigned wid = cp->bit_idx[1];
|
|
||||||
|
|
||||||
/* Collect the thread bits into a vector4 item. */
|
vvp_vector4_t value = thr->pop_vec4();
|
||||||
vvp_vector4_t value = vthread_bits_to_vector(thr, base, wid);
|
|
||||||
|
|
||||||
/* Send the force value to the filter on the node. */
|
/* Send the force value to the filter on the node. */
|
||||||
|
|
||||||
|
|
@ -2969,9 +2978,7 @@ bool of_FORCE_V(vthread_t thr, vvp_code_t cp)
|
||||||
value = coerce_to_width(value, net->fil->filter_size());
|
value = coerce_to_width(value, net->fil->filter_size());
|
||||||
|
|
||||||
net->force_vec4(value, vvp_vector2_t(vvp_vector2_t::FILL1, net->fil->filter_size()));
|
net->force_vec4(value, vvp_vector2_t(vvp_vector2_t::FILL1, net->fil->filter_size()));
|
||||||
#else
|
|
||||||
fprintf(stderr, "XXXX NOT IMPLEMENTED: %%force/v ...\n");
|
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3401,6 +3408,26 @@ bool of_JMP1(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* %jmp/1xz <pc>, <flag>
|
||||||
|
*/
|
||||||
|
bool of_JMP1XZ(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
if (thr->flags[cp->bit_idx[0]] != BIT4_0)
|
||||||
|
thr->pc = cp->cptr;
|
||||||
|
|
||||||
|
/* Normally, this returns true so that the processor just
|
||||||
|
keeps going to the next instruction. However, if there was
|
||||||
|
a $stop or vpiStop, returning false here can break the
|
||||||
|
simulation out of a hung loop. */
|
||||||
|
if (schedule_stopped()) {
|
||||||
|
schedule_vthread(thr, 0, false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The %join instruction causes the thread to wait for one child
|
* The %join instruction causes the thread to wait for one child
|
||||||
* to die. If a child is already dead (and a zombie) then I reap
|
* to die. If a child is already dead (and a zombie) then I reap
|
||||||
|
|
@ -3921,6 +3948,29 @@ bool of_LOAD_VEC4(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* %load/vec4a <arr>, <adrx>
|
||||||
|
*/
|
||||||
|
bool of_LOAD_VEC4A(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
int adr_index = cp->bit_idx[0];
|
||||||
|
|
||||||
|
long adr = thr->words[adr_index].w_int;
|
||||||
|
|
||||||
|
// If flag[3] is set, then the calculation of the address
|
||||||
|
// failed, and this load should return X instead of the actual
|
||||||
|
// value.
|
||||||
|
if (thr->flags[4] == BIT4_1) {
|
||||||
|
vvp_vector4_t tmp (get_array_word_size(cp->array), BIT4_X);
|
||||||
|
thr->push_vec4(tmp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
vvp_vector4_t tmp (array_get_word(cp->array, adr));
|
||||||
|
thr->push_vec4(tmp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is like of_LOAD_VEC, but includes an add of an integer value from
|
* This is like of_LOAD_VEC, but includes an add of an integer value from
|
||||||
* index 0. The <wid> is the expected result width not the vector width.
|
* index 0. The <wid> is the expected result width not the vector width.
|
||||||
|
|
@ -4368,12 +4418,13 @@ bool of_PAD_U(vthread_t thr, vvp_code_t cp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* %part <wid>
|
* %part/s <wid>
|
||||||
|
* %part/u <wid>
|
||||||
* Two values are popped from the stack. First, pop the canonical
|
* Two values are popped from the stack. First, pop the canonical
|
||||||
* index of the part select, and second is the value to be
|
* index of the part select, and second is the value to be
|
||||||
* selected. The result is pushed back to the stack.
|
* selected. The result is pushed back to the stack.
|
||||||
*/
|
*/
|
||||||
bool of_PART(vthread_t thr, vvp_code_t cp)
|
static bool of_PART_base(vthread_t thr, vvp_code_t cp, bool signed_flag)
|
||||||
{
|
{
|
||||||
unsigned wid = cp->number;
|
unsigned wid = cp->number;
|
||||||
|
|
||||||
|
|
@ -4384,7 +4435,7 @@ bool of_PART(vthread_t thr, vvp_code_t cp)
|
||||||
|
|
||||||
// NOTE: This is treating the vector as signed. Is that correct?
|
// NOTE: This is treating the vector as signed. Is that correct?
|
||||||
int32_t base;
|
int32_t base;
|
||||||
bool value_ok = vector4_to_value(base4, base, true);
|
bool value_ok = vector4_to_value(base4, base, signed_flag);
|
||||||
if (! value_ok) {
|
if (! value_ok) {
|
||||||
thr->push_vec4(res);
|
thr->push_vec4(res);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -4417,6 +4468,16 @@ bool of_PART(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool of_PART_S(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
return of_PART_base(thr, cp, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool of_PART_U(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
return of_PART_base(thr, cp, false);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* %mov/wu <dst>, <src>
|
* %mov/wu <dst>, <src>
|
||||||
*/
|
*/
|
||||||
|
|
@ -5359,6 +5420,21 @@ bool of_RELEASE_WR(vthread_t, vvp_code_t cp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool of_REPLICATE(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
int rept = cp->number;
|
||||||
|
vvp_vector4_t val = thr->pop_vec4();
|
||||||
|
vvp_vector4_t res (val.size() * rept, BIT4_X);
|
||||||
|
|
||||||
|
for (int idx = 0 ; idx < rept ; idx += 1) {
|
||||||
|
res.set_vec(idx * val.size(), val);
|
||||||
|
}
|
||||||
|
|
||||||
|
thr->push_vec4(res);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool of_SCOPY(vthread_t thr, vvp_code_t)
|
bool of_SCOPY(vthread_t thr, vvp_code_t)
|
||||||
{
|
{
|
||||||
vvp_object_t tmp;
|
vvp_object_t tmp;
|
||||||
|
|
@ -6037,6 +6113,28 @@ bool of_STORE_VEC4(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* %storevec4/off <var-label>, <offset>, <wid>
|
||||||
|
*/
|
||||||
|
bool of_STORE_VEC4_OFF(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
vvp_net_ptr_t ptr(cp->net, 0);
|
||||||
|
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (cp->net->fil);
|
||||||
|
unsigned off_index = cp->bit_idx[0];
|
||||||
|
unsigned wid = cp->bit_idx[1];
|
||||||
|
|
||||||
|
int off = thr->words[off_index].w_int;
|
||||||
|
|
||||||
|
vvp_vector4_t val = thr->pop_vec4();
|
||||||
|
assert(val.size() >= wid);
|
||||||
|
if (val.size() > wid)
|
||||||
|
val.resize(wid);
|
||||||
|
|
||||||
|
vvp_send_vec4_pv(ptr, val, off, wid, sig->value_size(), thr->wt_context);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool of_SUB(vthread_t thr, vvp_code_t cp)
|
bool of_SUB(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
vvp_vector4_t r = thr->pop_vec4();
|
vvp_vector4_t r = thr->pop_vec4();
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,7 @@ extern void vthread_pop_real(struct vthread_s*thr, unsigned count);
|
||||||
depth==1, etc. */
|
depth==1, etc. */
|
||||||
extern const std::string&vthread_get_str_stack(struct vthread_s*thr, unsigned depth);
|
extern const std::string&vthread_get_str_stack(struct vthread_s*thr, unsigned depth);
|
||||||
extern double vthread_get_real_stack(struct vthread_s*thr, unsigned depth);
|
extern double vthread_get_real_stack(struct vthread_s*thr, unsigned depth);
|
||||||
|
extern const vvp_vector4_t& vthread_get_vec4_stack(struct vthread_s*thr, unsigned depth);
|
||||||
|
|
||||||
/* This is used to actually delete a thread once we are done with it. */
|
/* This is used to actually delete a thread once we are done with it. */
|
||||||
extern void vthread_delete(vthread_t thr);
|
extern void vthread_delete(vthread_t thr);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue