Fix some vec4 handling of putc, len, and other string methods.

This commit is contained in:
Stephen Williams 2014-01-31 19:01:28 -08:00
parent 0eca210722
commit 1805598eae
8 changed files with 107 additions and 56 deletions

View File

@ -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) {

View File

@ -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_);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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} },

View File

@ -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>

View File

@ -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)
{