Support for dynamic arrays of strings.

Strings, when put into dynamic arrays, are treated as first class
types much line reals. Add the code generator and vvp support for
this situation. Also fix a bug distinguishing between character
selects from strings and select form arrays of strings.
This commit is contained in:
Stephen Williams 2012-10-14 16:12:16 -07:00
parent d6efece5dd
commit 0059fb1ec7
11 changed files with 177 additions and 10 deletions

View File

@ -351,6 +351,13 @@ ivl_select_type_t NetESelect::select_type() const
ivl_variable_type_t NetESelect::expr_type() const
{
ivl_variable_type_t type = expr_->expr_type();
// Special case: If the sub-expression is an IVL_VT_STRING,
// then this node is representing a character select. The
// width is the width of a byte, and the data type is BOOL.
if (type == IVL_VT_STRING && expr_width()==8)
return IVL_VT_BOOL;
if (type != IVL_VT_DARRAY)
return type;

View File

@ -178,10 +178,19 @@ static void show_select_expression(ivl_expr_t net, unsigned ind)
substring and the code generator will handle it
differently. */
fprintf(out, "%*s<substring: width=%u bits, %u bytes>\n", ind, "", width, width/8);
if (width%8 != 0)
if (width%8 != 0) {
fprintf(out, "%*sERROR: Width should be a multiple of 8 bits.\n", ind, "");
stub_errors += 1;
}
assert(oper1);
show_expression(oper1, ind+3);
if (oper2) {
show_expression(oper2, ind+3);
} else {
fprintf(out, "%*sERROR: oper2 missing! Pad makes no sense for IVL_VT_STRING expressions.\n", ind+3, "");
stub_errors += 1;
}
} else if (oper2) {
/* If oper2 is present, then it is the base of a part
@ -303,9 +312,10 @@ void show_unary_expression(ivl_expr_t net, unsigned ind)
void show_expression(ivl_expr_t net, unsigned ind)
{
assert(net);
unsigned idx;
const ivl_expr_type_t code = ivl_expr_type(net);
ivl_parameter_t par = ivl_expr_parameter(net);
const ivl_expr_type_t code = ivl_expr_type(net);
unsigned width = ivl_expr_width(net);
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
const char*sized = ivl_expr_sized(net)? "sized" : "unsized";

View File

@ -42,6 +42,11 @@ static int eval_darray_new(ivl_expr_t ex)
assert(ivl_type_packed_dimensions(element_type) == 0);
fprintf(vvp_out, " %%new/darray %u, \"r\";\n", size_reg);
break;
case IVL_VT_STRING:
// STRING objects are not packable.
assert(ivl_type_packed_dimensions(element_type) == 0);
fprintf(vvp_out, " %%new/darray %u, \"S\";\n", size_reg);
break;
case IVL_VT_BOOL:
// bool objects are vectorable, but for now only support
// a single dimensions.

View File

@ -71,6 +71,21 @@ static void string_ex_signal(ivl_expr_t expr)
fallback_eval(expr);
}
static void string_ex_select(ivl_expr_t expr)
{
/* The sube references the expression to be selected from. */
ivl_expr_t sube = ivl_expr_oper1(expr);
/* This is the select expression */
ivl_expr_t shift= ivl_expr_oper2(expr);
/* Assume the sub-expression is a signal */
ivl_signal_t sig = ivl_expr_signal(sube);
assert(ivl_signal_data_type(sig) == IVL_VT_DARRAY);
draw_eval_expr_into_integer(shift, 3);
fprintf(vvp_out, " %%load/dar/str v%p_0;\n", sig);
}
void draw_eval_string(ivl_expr_t expr)
{
@ -87,6 +102,10 @@ void draw_eval_string(ivl_expr_t expr)
string_ex_concat(expr);
break;
case IVL_EX_SELECT:
string_ex_select(expr);
break;
default:
fallback_eval(expr);
break;

View File

@ -794,6 +794,17 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net)
fprintf(vvp_out, " %%set/dar/r v%p_0, %u;\n", var, dst);
clr_word(dst);
} else if (mux && ivl_type_base(element_type)==IVL_VT_STRING) {
/* Evaluate the rval into the top of the string stack. */
draw_eval_string(rval);
/* The %store/dar/s expects the array index to me in index
register 3. Calculate the index in place. */
draw_eval_expr_into_integer(mux, 3);
fprintf(vvp_out, " %%store/dar/str v%p_0;\n", var);
} else if (mux) {
struct vector_info rvec = draw_eval_expr_wid(rval, ivl_lval_width(lval),
STUFF_OK_XZ);

View File

@ -127,6 +127,7 @@ extern bool of_LOAD_AVP0_S(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_AVX_P(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_DAR(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_DAR_R(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_DAR_STR(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_STR(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_VP0(vthread_t thr, vvp_code_t code);
@ -174,6 +175,7 @@ extern bool of_SET_X0_X(vthread_t thr, vvp_code_t code);
extern bool of_SHIFTL_I0(vthread_t thr, vvp_code_t code);
extern bool of_SHIFTR_I0(vthread_t thr, vvp_code_t code);
extern bool of_SHIFTR_S_I0(vthread_t thr, vvp_code_t code);
extern bool of_STORE_DAR_STR(vthread_t thr, vvp_code_t code);
extern bool of_STORE_OBJ(vthread_t thr, vvp_code_t code);
extern bool of_STORE_STR(vthread_t thr, vvp_code_t code);
extern bool of_SUB(vthread_t thr, vvp_code_t code);

View File

@ -174,8 +174,9 @@ static const struct opcode_table_s opcode_table[] = {
{ "%load/avp0/s",of_LOAD_AVP0_S,3,{OA_BIT1,OA_ARR_PTR, OA_BIT2} },
{ "%load/avx.p",of_LOAD_AVX_P,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} },
{ "%load/dar",of_LOAD_DAR,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%load/dar/r",of_LOAD_DAR_R,2,{OA_BIT1, OA_FUNC_PTR, OA_NONE} },
{ "%load/str",of_LOAD_STR,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%load/dar/r", of_LOAD_DAR_R, 2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
{ "%load/dar/str",of_LOAD_DAR_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%load/str", of_LOAD_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%load/v", of_LOAD_VEC,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} },
@ -221,8 +222,9 @@ static const struct opcode_table_s opcode_table[] = {
{ "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
{ "%shiftr/i0", of_SHIFTR_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
{ "%shiftr/s/i0", of_SHIFTR_S_I0,2,{OA_BIT1,OA_NUMBER, OA_NONE} },
{ "%store/obj",of_STORE_OBJ,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%store/str",of_STORE_STR,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%store/dar/str",of_STORE_DAR_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%store/obj", of_STORE_OBJ, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%store/str", of_STORE_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%sub", of_SUB, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%sub/wr", of_SUB_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },

View File

@ -609,6 +609,17 @@ The dar/r variant reads a real-value into a real-valued register.
(See also %set/dar)
* %load/str <var-label>
* %load/dar/str <var-label>
The %load/str instruction gets the string from the string variable and
pushes in to the string stack. (See also %store/str)
The %load/dar/str is similar, but the variable is a dynamic array of
strings, and there is an index value in index register 3.
(See also %store/dar/str)
* %load/v <bit>, <functor-label>, <wid>
This instruction loads a vector value from the given functor node into
@ -745,6 +756,7 @@ The supported types are:
"b<N>" - unsigned bool <N>-bits
"sb<N>" - signed bool <N>-bits
"r" - real
"S" - SystemVerilog string
* %nor <dst>, <src>, <wid>
@ -936,9 +948,13 @@ This pops the top of the object stack and writes it to the object
variable given by the label.
* %store/str <var-label>
* %store/dar/str <var-label>
This pops the top of the string stack and writes it to the string
varible.
The %store/str instruction pops the top of the string stack and writes
it to the string variable.
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.
* %sub <bit-l>, <bit-r>, <wid>

View File

@ -3147,9 +3147,28 @@ bool of_LOAD_DAR_R(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_LOAD_DAR_STR(vthread_t thr, vvp_code_t cp)
{
unsigned adr = thr->words[3].w_int;
vvp_net_t*net = cp->net;
assert(net);
vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun);
assert(obj);
vvp_darray*darray = dynamic_cast<vvp_darray*> (obj->get_object());
assert(darray);
string word;
darray->get_word(adr, word);
thr->stack_str.push_back(word);
return true;
}
/*
* %load/vp0, %load/vp0/s, %load/avp0 and %load/avp0/s share this function.
*/
*/
#if (SIZEOF_UNSIGNED_LONG >= 8)
# define CPU_WORD_STRIDE CPU_WORD_BITS - 1 // avoid a warning
#else
@ -3998,6 +4017,8 @@ bool of_NEW_DARRAY(vthread_t thr, vvp_code_t cp)
obj = new vvp_darray_atom<int64_t>(size);
} else if (strcmp(text,"r") == 0) {
obj = new vvp_darray_real(size);
} else if (strcmp(text,"S") == 0) {
obj = new vvp_darray_string(size);
} else {
obj = new vvp_darray (size);
}
@ -4809,6 +4830,32 @@ bool of_SHIFTR_S_I0(vthread_t thr, vvp_code_t cp)
return true;
}
/*
* %store/dar/str <var>
* In this case, <var> is the name of a dynamic array. Signed index
* register 3 contains the index into the dynamic array.
*/
bool of_STORE_DAR_STR(vthread_t thr, vvp_code_t cp)
{
long adr = thr->words[3].w_int;
// Pop the string to be stored...
assert(!thr->stack_str.empty());
string value = thr->stack_str.back();
thr->stack_str.pop_back();
vvp_net_t*net = cp->net;
vvp_fun_signal_object*obj = dynamic_cast<vvp_fun_signal_object*> (net->fun);
assert(obj);
vvp_darray*darray = dynamic_cast<vvp_darray*>(obj->get_object());
assert(darray);
darray->set_word(adr, value);
return true;
}
bool of_STORE_OBJ(vthread_t thr, vvp_code_t cp)
{
/* set the value into port 0 of the destination. */

View File

@ -42,6 +42,11 @@ void vvp_darray::set_word(unsigned, double)
cerr << "XXXX set_word(double) not implemented for " << typeid(*this).name() << endl;
}
void vvp_darray::set_word(unsigned, const string&)
{
cerr << "XXXX set_word(string) not implemented for " << typeid(*this).name() << endl;
}
void vvp_darray::get_word(unsigned, vvp_vector4_t&)
{
cerr << "XXXX get_word(vvp_vector4_t) not implemented for " << typeid(*this).name() << endl;
@ -52,6 +57,11 @@ void vvp_darray::get_word(unsigned, double&)
cerr << "XXXX get_word(double) not implemented for " << typeid(*this).name() << endl;
}
void vvp_darray::get_word(unsigned, string&)
{
cerr << "XXXX get_word(string) not implemented for " << typeid(*this).name() << endl;
}
template <class TYPE> vvp_darray_atom<TYPE>::~vvp_darray_atom()
{
}
@ -110,3 +120,24 @@ void vvp_darray_real::get_word(unsigned adr, double&value)
value = array_[adr];
}
vvp_darray_string::~vvp_darray_string()
{
}
void vvp_darray_string::set_word(unsigned adr, const string&value)
{
if (adr >= array_.size())
return;
array_[adr] = value;
}
void vvp_darray_string::get_word(unsigned adr, string&value)
{
if (adr >= array_.size()) {
value = 0.0;
return;
}
value = array_[adr];
}

View File

@ -20,6 +20,7 @@
*/
# include <stdlib.h>
# include <string>
# include <vector>
typedef class vvp_object*vvp_object_t;
@ -45,6 +46,9 @@ class vvp_darray : public vvp_object {
virtual void set_word(unsigned adr, double value);
virtual void get_word(unsigned adr, double&value);
virtual void set_word(unsigned adr, const std::string&value);
virtual void get_word(unsigned adr, std::string&value);
private:
size_t size_;
};
@ -75,4 +79,17 @@ class vvp_darray_real : public vvp_darray {
std::vector<double> array_;
};
class vvp_darray_string : public vvp_darray {
public:
inline vvp_darray_string(size_t siz) : vvp_darray(siz), array_(siz) { }
~vvp_darray_string();
void set_word(unsigned adr, const std::string&value);
void get_word(unsigned adr, std::string&value);
private:
std::vector<std::string> array_;
};
#endif