From 0059fb1ec71f34ba100a1dd0a568236558cf707d Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 14 Oct 2012 16:12:16 -0700 Subject: [PATCH] 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. --- net_expr.cc | 7 +++++++ tgt-stub/expression.c | 16 +++++++++++--- tgt-vvp/eval_object.c | 5 +++++ tgt-vvp/eval_string.c | 19 +++++++++++++++++ tgt-vvp/stmt_assign.c | 11 ++++++++++ vvp/codes.h | 2 ++ vvp/compile.cc | 10 +++++---- vvp/opcodes.txt | 20 ++++++++++++++++-- vvp/vthread.cc | 49 ++++++++++++++++++++++++++++++++++++++++++- vvp/vvp_object.cc | 31 +++++++++++++++++++++++++++ vvp/vvp_object.h | 17 +++++++++++++++ 11 files changed, 177 insertions(+), 10 deletions(-) diff --git a/net_expr.cc b/net_expr.cc index 12713bbe7..ab204a3e1 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -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; diff --git a/tgt-stub/expression.c b/tgt-stub/expression.c index f21684ca0..8cc2cbe21 100644 --- a/tgt-stub/expression.c +++ b/tgt-stub/expression.c @@ -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\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); - show_expression(oper2, 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"; diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index 72d9053e2..a48ca77d6 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -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. diff --git a/tgt-vvp/eval_string.c b/tgt-vvp/eval_string.c index 4ddb42eb2..01d6613fa 100644 --- a/tgt-vvp/eval_string.c +++ b/tgt-vvp/eval_string.c @@ -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; diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index aca4c198d..953690880 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -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); diff --git a/vvp/codes.h b/vvp/codes.h index 0e330e4a8..4d1d59791 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -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); diff --git a/vvp/compile.cc b/vvp/compile.cc index bbe80bf35..2911a8861 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -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} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 9b27187bb..294e99260 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -609,6 +609,17 @@ The dar/r variant reads a real-value into a real-valued register. (See also %set/dar) +* %load/str +* %load/dar/str + +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 , , This instruction loads a vector value from the given functor node into @@ -745,6 +756,7 @@ The supported types are: "b" - unsigned bool -bits "sb" - signed bool -bits "r" - real + "S" - SystemVerilog string * %nor , , @@ -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 +* %store/dar/str -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 , , diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 2a8faddd9..c1346e0de 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -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 (net->fun); + assert(obj); + + vvp_darray*darray = dynamic_cast (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(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 + * In this case, 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 (net->fun); + assert(obj); + + vvp_darray*darray = dynamic_cast(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. */ diff --git a/vvp/vvp_object.cc b/vvp/vvp_object.cc index 5d0bcac08..14562befa 100644 --- a/vvp/vvp_object.cc +++ b/vvp/vvp_object.cc @@ -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 vvp_darray_atom::~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]; +} diff --git a/vvp/vvp_object.h b/vvp/vvp_object.h index 25c612394..b93127857 100644 --- a/vvp/vvp_object.h +++ b/vvp/vvp_object.h @@ -20,6 +20,7 @@ */ # include +# include # include 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 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 array_; +}; + #endif