Fix some vec4 handling of putc, len, and other string methods.
This commit is contained in:
parent
0eca210722
commit
1805598eae
12
elab_expr.cc
12
elab_expr.cc
|
|
@ -1271,6 +1271,18 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
|
|||
if (net == 0)
|
||||
return 0;
|
||||
|
||||
// Look fonr built in string attributes.
|
||||
if (net->data_type()==IVL_VT_STRING) {
|
||||
|
||||
if (method_name == "len") {
|
||||
expr_type_ = IVL_VT_BOOL;
|
||||
expr_width_ = 32;
|
||||
min_width_ = 32;
|
||||
signed_flag_= true;
|
||||
return expr_width_;
|
||||
}
|
||||
}
|
||||
|
||||
// function int size()
|
||||
if (use_darray && method_name == "size") {
|
||||
if (debug_elaborate) {
|
||||
|
|
|
|||
|
|
@ -135,6 +135,9 @@ ivl_variable_type_t NetAssign_::expr_type() const
|
|||
return darray->element_base_type();
|
||||
}
|
||||
|
||||
if (sig_->data_type()==IVL_VT_STRING && base_!=0)
|
||||
return IVL_VT_BOOL;
|
||||
|
||||
if (ntype) return ntype->base_type();
|
||||
|
||||
ivl_assert(*this, sig_);
|
||||
|
|
|
|||
|
|
@ -604,6 +604,20 @@ static void draw_select_vec4(ivl_expr_t expr)
|
|||
// Is the select base expression signed or unsigned?
|
||||
char sign_suff = ivl_expr_signed(base)? 's' : 'u';
|
||||
|
||||
// Special Case: If the sub-expression is a STRING, then this
|
||||
// is a select from that string.
|
||||
if (ivl_expr_value(subexpr)==IVL_VT_STRING) {
|
||||
assert(base);
|
||||
assert(wid==8);
|
||||
draw_eval_string(subexpr);
|
||||
int base_idx = allocate_word();
|
||||
draw_eval_expr_into_integer(base, base_idx);
|
||||
fprintf(vvp_out, " %%substr/vec4 %d, %u;\n", base_idx, wid);
|
||||
fprintf(vvp_out, " %%pop/str 1;\n");
|
||||
clr_word(base_idx);
|
||||
return;
|
||||
}
|
||||
|
||||
draw_eval_vec4(subexpr, 0);
|
||||
draw_eval_vec4(base, 0);
|
||||
fprintf(vvp_out, " %%part/%c %u;\n", sign_suff, wid);
|
||||
|
|
|
|||
|
|
@ -884,17 +884,15 @@ static int show_stmt_assign_sig_string(ivl_statement_t net)
|
|||
return 0;
|
||||
}
|
||||
|
||||
assert(ivl_expr_width(rval)==8);
|
||||
draw_eval_vec4(rval, STUFF_OK_XZ);
|
||||
|
||||
/* Calculate the character select for the word. */
|
||||
int mux_word = allocate_word();
|
||||
draw_eval_expr_into_integer(part, mux_word);
|
||||
|
||||
/* Evaluate the r-value as a vector. */
|
||||
struct vector_info rvec = draw_eval_expr_wid(rval, 8, STUFF_OK_XZ);
|
||||
fprintf(vvp_out, " %%putc/str/vec4 v%p_0, %d;\n", var, mux_word);
|
||||
|
||||
assert(rvec.wid == 8);
|
||||
fprintf(vvp_out, " %%putc/str/v v%p_0, %d, %u;\n", var, mux_word, rvec.base);
|
||||
|
||||
clr_vector(rvec);
|
||||
clr_word(mux_word);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ extern bool of_PUSHI_STR(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_PUSHI_REAL(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_PUSHI_VEC4(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_PUSHV_STR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_PUTC_STR_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_PUTC_STR_VEC4(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_WR(vthread_t thr, vvp_code_t code);
|
||||
|
|
@ -227,7 +227,7 @@ 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_SUBI(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SUBSTR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SUBSTR_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SUBSTR_VEC4(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_TEST_NUL(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);
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ static const struct opcode_table_s opcode_table[] = {
|
|||
{ "%pushi/str", of_PUSHI_STR, 1,{OA_STRING, OA_NONE, OA_NONE} },
|
||||
{ "%pushi/vec4",of_PUSHI_VEC4,3,{OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%pushv/str", of_PUSHV_STR, 2, {OA_BIT1,OA_BIT2, OA_NONE} },
|
||||
{ "%putc/str/v",of_PUTC_STR_V,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%putc/str/vec4",of_PUTC_STR_VEC4,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
||||
{ "%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/wr", of_RELEASE_WR, 2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
||||
|
|
@ -274,7 +274,7 @@ static const struct opcode_table_s opcode_table[] = {
|
|||
{ "%sub/wr", of_SUB_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%substr", of_SUBSTR, 2,{OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%substr/v",of_SUBSTR_V,3,{OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%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} },
|
||||
{ "%wait", of_WAIT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||
{ "%wait/fork",of_WAIT_FORK,0,{OA_NONE, OA_NONE, OA_NONE} },
|
||||
|
|
|
|||
|
|
@ -1087,12 +1087,12 @@ This opcode is limited to 32bit numbers.
|
|||
|
||||
Convert a vector to a string and push the string to the string stack.
|
||||
|
||||
* %putc/str/v <functor-label>, <muxr>, <base>
|
||||
* %putc/str/v <functor-label>, <muxr>
|
||||
|
||||
Extract a vector byte from the thread vector space and write it to a
|
||||
Pop a vector byte from the thread vec4 stack and write it to a
|
||||
character of the string variable at <functtor-label>. This is
|
||||
basically an implementation of <string>.putc(<muxr>, <val>) where
|
||||
<val> is the 8bit vector at <base> in the thread space.
|
||||
<val> is the 8bit vector popped from the stack.
|
||||
|
||||
* %release/net <functor-label>, <base>, <width>
|
||||
* %release/reg <functor-label>, <base>, <width>
|
||||
|
|
@ -1317,13 +1317,14 @@ This instruction takes the substring of the top string in the string
|
|||
stack. This implements the SystemVerilog style substring. The string
|
||||
stack is popped and replaced with the result.
|
||||
|
||||
* %substr/v <bit-l>, <sel>, <wid>
|
||||
* %substr/vec4 <sel>, <wid>
|
||||
|
||||
This instruction extracts the substring of the top string in the string
|
||||
stack and delivers the result to vector space. The <bit>,<wid> part is
|
||||
the location where the result goes, and <sel> is the index register
|
||||
that holds the index. This is the general method for getting string
|
||||
values into the vector space. The string value is NOT popped.
|
||||
This instruction extracts the substring of the top string in the
|
||||
string stack and pushes the result to the vec4 stack. The <sel> is the
|
||||
index register that holds the select base, and the <wid> is the width,
|
||||
in bits, of the result. Note that <wid> must be a multiple of 8.
|
||||
|
||||
The string value is NOT popped.
|
||||
|
||||
|
||||
* %test_nul <var-label>
|
||||
|
|
|
|||
|
|
@ -4003,7 +4003,7 @@ static void load_base(vvp_code_t cp, vvp_vector4_t&dst)
|
|||
signal functor. Only signals save their vector value. */
|
||||
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (net->fil);
|
||||
if (sig == 0) {
|
||||
cerr << "%%load/v error: Net arg not a signal? "
|
||||
cerr << "%load/v error: Net arg not a signal? "
|
||||
<< (net->fil ? typeid(*net->fil).name() : typeid(*net->fun).name()) << endl;
|
||||
assert(sig);
|
||||
}
|
||||
|
|
@ -5329,56 +5329,47 @@ bool of_PUSHV_STR(vthread_t thr, vvp_code_t cp)
|
|||
}
|
||||
|
||||
/*
|
||||
* %putc/str/v <var>, <muxr>, <base>
|
||||
* %putc/str/vec4 <var>, <mux>
|
||||
*/
|
||||
bool of_PUTC_STR_V(vthread_t thr, vvp_code_t cp)
|
||||
bool of_PUTC_STR_VEC4(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
#if 0
|
||||
unsigned muxr = cp->bit_idx[0];
|
||||
unsigned base = cp->bit_idx[1];
|
||||
int32_t mux = muxr? thr->words[muxr].w_int : 0;
|
||||
|
||||
vvp_vector4_t val = thr->pop_vec4();
|
||||
assert(val.size() == 8);
|
||||
|
||||
/* The mux is the index into the string. If it is <0, then
|
||||
this operation cannot possible effect the string, so we are
|
||||
done. */
|
||||
assert(muxr < 16);
|
||||
int32_t mux = thr->words[muxr].w_int;
|
||||
if (mux < 0)
|
||||
return true;
|
||||
|
||||
/* Extract the character from the vector space. If that byte
|
||||
is null (8'h00) then the standard says it is to be skipped. */
|
||||
unsigned long*tmp = vector_to_array(thr, base, 8);
|
||||
assert(tmp);
|
||||
char tmp_val = tmp[0] & 0xff;
|
||||
delete [] tmp;
|
||||
if (tmp_val == 0)
|
||||
return true;
|
||||
|
||||
/* Get the existing value of the string. If we find that the
|
||||
index is too big for the string, then give up. */
|
||||
vvp_net_t*net = cp->net;
|
||||
vvp_fun_signal_string*fun = dynamic_cast<vvp_fun_signal_string*> (net->fun);
|
||||
assert(fun);
|
||||
|
||||
string val = fun->get_string();
|
||||
if (val.size() <= (size_t)mux)
|
||||
string tmp = fun->get_string();
|
||||
if (tmp.size() <= (size_t)mux)
|
||||
return true;
|
||||
|
||||
/* If the value to write is the same as the destination, then
|
||||
stop now. */
|
||||
if (val[mux] == tmp_val)
|
||||
char val_str = 0;
|
||||
for (size_t idx = 0 ; idx < 8 ; idx += 1) {
|
||||
if (val.value(idx)==BIT4_1)
|
||||
val_str |= 1<<idx;
|
||||
}
|
||||
|
||||
// It is a quirk of the Verilog standard that putc(..., 'h00)
|
||||
// has no effect. Test for that case here.
|
||||
if (val_str == 0)
|
||||
return true;
|
||||
|
||||
/* Finally, modify the string and write the new string to the
|
||||
variable so that the new value propagates. */
|
||||
val[mux] = tmp_val;
|
||||
vvp_send_string(vvp_net_ptr_t(cp->net, 0), val, thr->wt_context);
|
||||
#else
|
||||
fprintf(stderr, "XXXX NOT IMPLEMENTED: %%putc/str/v ...\n");
|
||||
#endif
|
||||
tmp[mux] = val_str;
|
||||
|
||||
vvp_send_string(vvp_net_ptr_t(cp->net, 0), tmp, thr->wt_context);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* These implement the %release/net and %release/reg instructions. The
|
||||
* %release/net instruction applies to a net kind of functor by
|
||||
|
|
@ -6168,6 +6159,39 @@ bool of_SUBSTR(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* %substr/vec4 <index>, <wid>
|
||||
*/
|
||||
bool of_SUBSTR_VEC4(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned sel_idx = cp->bit_idx[0];
|
||||
unsigned wid = cp->bit_idx[1];
|
||||
|
||||
int32_t sel = thr->words[sel_idx].w_int;
|
||||
string&val = thr->peek_str(0);
|
||||
|
||||
assert(wid%8 == 0);
|
||||
|
||||
if (sel < 0 || sel >= (int32_t)val.size()) {
|
||||
vvp_vector4_t res (wid, BIT4_0);
|
||||
thr->push_vec4(res);
|
||||
return true;
|
||||
}
|
||||
|
||||
vvp_vector4_t res (wid, BIT4_0);
|
||||
|
||||
assert(wid==8);
|
||||
unsigned char tmp = val[sel];
|
||||
for (int idx = 0 ; idx < 8 ; idx += 1) {
|
||||
if (tmp & (1<<idx))
|
||||
res.set_bit(idx, BIT4_1);
|
||||
}
|
||||
|
||||
thr->push_vec4(res);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* %substr/v <bitl>, <index>, <wid>
|
||||
*/
|
||||
|
|
@ -6177,7 +6201,7 @@ bool of_SUBSTR_V(vthread_t thr, vvp_code_t cp)
|
|||
uint32_t bitl = cp->bit_idx[0];
|
||||
uint32_t sel = cp->bit_idx[1];
|
||||
unsigned wid = cp->number;
|
||||
#if 0
|
||||
|
||||
thr_check_addr(thr, bitl+wid);
|
||||
assert(bitl >= 4);
|
||||
|
||||
|
|
@ -6198,11 +6222,10 @@ bool of_SUBSTR_V(vthread_t thr, vvp_code_t cp)
|
|||
bitl += 8;
|
||||
use_sel += 1;
|
||||
}
|
||||
#else
|
||||
fprintf(stderr, "XXXX NOT IMPLEMENTED : %%substr/v %u, %u, %u\n", bitl, sel, wid);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool of_FILE_LINE(vthread_t, vvp_code_t cp)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue