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