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)
|
if (net == 0)
|
||||||
return 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()
|
// function int size()
|
||||||
if (use_darray && method_name == "size") {
|
if (use_darray && method_name == "size") {
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,9 @@ ivl_variable_type_t NetAssign_::expr_type() const
|
||||||
return darray->element_base_type();
|
return darray->element_base_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sig_->data_type()==IVL_VT_STRING && base_!=0)
|
||||||
|
return IVL_VT_BOOL;
|
||||||
|
|
||||||
if (ntype) return ntype->base_type();
|
if (ntype) return ntype->base_type();
|
||||||
|
|
||||||
ivl_assert(*this, sig_);
|
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?
|
// Is the select base expression signed or unsigned?
|
||||||
char sign_suff = ivl_expr_signed(base)? 's' : 'u';
|
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(subexpr, 0);
|
||||||
draw_eval_vec4(base, 0);
|
draw_eval_vec4(base, 0);
|
||||||
fprintf(vvp_out, " %%part/%c %u;\n", sign_suff, wid);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(ivl_expr_width(rval)==8);
|
||||||
|
draw_eval_vec4(rval, STUFF_OK_XZ);
|
||||||
|
|
||||||
/* Calculate the character select for the word. */
|
/* Calculate the character select for the word. */
|
||||||
int mux_word = allocate_word();
|
int mux_word = allocate_word();
|
||||||
draw_eval_expr_into_integer(part, mux_word);
|
draw_eval_expr_into_integer(part, mux_word);
|
||||||
|
|
||||||
/* Evaluate the r-value as a vector. */
|
fprintf(vvp_out, " %%putc/str/vec4 v%p_0, %d;\n", var, mux_word);
|
||||||
struct vector_info rvec = draw_eval_expr_wid(rval, 8, STUFF_OK_XZ);
|
|
||||||
|
|
||||||
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);
|
clr_word(mux_word);
|
||||||
return 0;
|
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_REAL(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_PUSHI_VEC4(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_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_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);
|
||||||
|
|
@ -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_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);
|
||||||
extern bool of_SUBSTR(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_TEST_NUL(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_VPI_CALL(vthread_t thr, vvp_code_t code);
|
extern bool of_VPI_CALL(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_WAIT(vthread_t thr, vvp_code_t code);
|
extern bool of_WAIT(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/str", of_PUSHI_STR, 1,{OA_STRING, OA_NONE, OA_NONE} },
|
||||||
{ "%pushi/vec4",of_PUSHI_VEC4,3,{OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%pushi/vec4",of_PUSHI_VEC4,3,{OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
{ "%pushv/str", of_PUSHV_STR, 2, {OA_BIT1,OA_BIT2, OA_NONE} },
|
{ "%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/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} },
|
||||||
|
|
@ -274,7 +274,7 @@ static const struct opcode_table_s opcode_table[] = {
|
||||||
{ "%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} },
|
||||||
{ "%substr", of_SUBSTR, 2,{OA_BIT1, OA_BIT2, OA_NONE} },
|
{ "%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} },
|
{ "%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", of_WAIT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||||
{ "%wait/fork",of_WAIT_FORK,0,{OA_NONE, 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.
|
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
|
character of the string variable at <functtor-label>. This is
|
||||||
basically an implementation of <string>.putc(<muxr>, <val>) where
|
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/net <functor-label>, <base>, <width>
|
||||||
* %release/reg <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. This implements the SystemVerilog style substring. The string
|
||||||
stack is popped and replaced with the result.
|
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
|
This instruction extracts the substring of the top string in the
|
||||||
stack and delivers the result to vector space. The <bit>,<wid> part is
|
string stack and pushes the result to the vec4 stack. The <sel> is the
|
||||||
the location where the result goes, and <sel> is the index register
|
index register that holds the select base, and the <wid> is the width,
|
||||||
that holds the index. This is the general method for getting string
|
in bits, of the result. Note that <wid> must be a multiple of 8.
|
||||||
values into the vector space. The string value is NOT popped.
|
|
||||||
|
The string value is NOT popped.
|
||||||
|
|
||||||
|
|
||||||
* %test_nul <var-label>
|
* %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. */
|
signal functor. Only signals save their vector value. */
|
||||||
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (net->fil);
|
vvp_signal_value*sig = dynamic_cast<vvp_signal_value*> (net->fil);
|
||||||
if (sig == 0) {
|
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;
|
<< (net->fil ? typeid(*net->fil).name() : typeid(*net->fun).name()) << endl;
|
||||||
assert(sig);
|
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 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)
|
if (mux < 0)
|
||||||
return true;
|
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
|
/* Get the existing value of the string. If we find that the
|
||||||
index is too big for the string, then give up. */
|
index is too big for the string, then give up. */
|
||||||
vvp_net_t*net = cp->net;
|
vvp_net_t*net = cp->net;
|
||||||
vvp_fun_signal_string*fun = dynamic_cast<vvp_fun_signal_string*> (net->fun);
|
vvp_fun_signal_string*fun = dynamic_cast<vvp_fun_signal_string*> (net->fun);
|
||||||
assert(fun);
|
assert(fun);
|
||||||
|
|
||||||
string val = fun->get_string();
|
string tmp = fun->get_string();
|
||||||
if (val.size() <= (size_t)mux)
|
if (tmp.size() <= (size_t)mux)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* If the value to write is the same as the destination, then
|
char val_str = 0;
|
||||||
stop now. */
|
for (size_t idx = 0 ; idx < 8 ; idx += 1) {
|
||||||
if (val[mux] == tmp_val)
|
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;
|
return true;
|
||||||
|
|
||||||
/* Finally, modify the string and write the new string to the
|
tmp[mux] = val_str;
|
||||||
variable so that the new value propagates. */
|
|
||||||
val[mux] = tmp_val;
|
vvp_send_string(vvp_net_ptr_t(cp->net, 0), tmp, thr->wt_context);
|
||||||
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
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These implement the %release/net and %release/reg instructions. The
|
* These implement the %release/net and %release/reg instructions. The
|
||||||
* %release/net instruction applies to a net kind of functor by
|
* %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;
|
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>
|
* %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 bitl = cp->bit_idx[0];
|
||||||
uint32_t sel = cp->bit_idx[1];
|
uint32_t sel = cp->bit_idx[1];
|
||||||
unsigned wid = cp->number;
|
unsigned wid = cp->number;
|
||||||
#if 0
|
|
||||||
thr_check_addr(thr, bitl+wid);
|
thr_check_addr(thr, bitl+wid);
|
||||||
assert(bitl >= 4);
|
assert(bitl >= 4);
|
||||||
|
|
||||||
|
|
@ -6198,11 +6222,10 @@ bool of_SUBSTR_V(vthread_t thr, vvp_code_t cp)
|
||||||
bitl += 8;
|
bitl += 8;
|
||||||
use_sel += 1;
|
use_sel += 1;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
fprintf(stderr, "XXXX NOT IMPLEMENTED : %%substr/v %u, %u, %u\n", bitl, sel, wid);
|
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool of_FILE_LINE(vthread_t, vvp_code_t cp)
|
bool of_FILE_LINE(vthread_t, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue