diff --git a/elab_type.cc b/elab_type.cc index 319603fae..313c358a8 100644 --- a/elab_type.cc +++ b/elab_type.cc @@ -80,3 +80,8 @@ ivl_type_s* real_type_t::elaborate_type(Design*, NetScope*) const } return 0; } + +ivl_type_s* string_type_t::elaborate_type(Design*, NetScope*) const +{ + return &netstring_t::type_string; +} diff --git a/netscalar.cc b/netscalar.cc index 0c0873da8..6ab52d167 100644 --- a/netscalar.cc +++ b/netscalar.cc @@ -23,6 +23,7 @@ using namespace std; netreal_t netreal_t::type_real; netreal_t netreal_t::type_shortreal; +netstring_t netstring_t::type_string; netreal_t::~netreal_t() { @@ -32,3 +33,12 @@ ivl_variable_type_t netreal_t::base_type() const { return IVL_VT_REAL; } + +netstring_t::~netstring_t() +{ +} + +ivl_variable_type_t netstring_t::base_type() const +{ + return IVL_VT_STRING; +} diff --git a/netscalar.h b/netscalar.h index b3aeec137..9559b7841 100644 --- a/netscalar.h +++ b/netscalar.h @@ -34,4 +34,16 @@ class netreal_t : public ivl_type_s { static netreal_t type_shortreal; }; +class netstring_t : public ivl_type_s { + + public: + inline explicit netstring_t() { } + ~netstring_t(); + + ivl_variable_type_t base_type() const; + + public: + static netstring_t type_string; +}; + #endif diff --git a/pform_types.h b/pform_types.h index 10a80e188..d191738d7 100644 --- a/pform_types.h +++ b/pform_types.h @@ -181,6 +181,8 @@ struct real_type_t : public data_type_t { struct string_type_t : public data_type_t { inline explicit string_type_t() { } ~string_type_t(); + + ivl_type_s* elaborate_type(Design*des, NetScope*scope) const; }; struct class_type_t : public data_type_t { diff --git a/tgt-stub/expression.c b/tgt-stub/expression.c index 5d5eebfcc..1bff24c82 100644 --- a/tgt-stub/expression.c +++ b/tgt-stub/expression.c @@ -214,6 +214,9 @@ static void show_property_expression(ivl_expr_t net, unsigned ind) if (ivl_expr_value(net) == IVL_VT_REAL) { fprintf(out, "%*s\n", ind, "", ivl_signal_basename(sig), pnam); + } else if (ivl_expr_value(net) == IVL_VT_STRING) { + fprintf(out, "%*s\n", ind, "", + ivl_signal_basename(sig), pnam); } else { fprintf(out, "%*s\n", ind, "", ivl_signal_basename(sig), pnam, ivl_expr_width(net), signed_flag); diff --git a/tgt-vvp/eval_string.c b/tgt-vvp/eval_string.c index 981901972..d7964ceb1 100644 --- a/tgt-vvp/eval_string.c +++ b/tgt-vvp/eval_string.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Stephen Williams (steve@icarus.com) + * Copyright (c) 2012-2013 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -60,6 +60,15 @@ static void string_ex_concat(ivl_expr_t expr) } } +static void string_ex_property(ivl_expr_t expr) +{ + ivl_signal_t sig = ivl_expr_signal(expr); + unsigned pidx = ivl_expr_property_idx(expr); + + fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); + fprintf(vvp_out, " %%prop/str %u;\n", pidx); +} + static void string_ex_signal(ivl_expr_t expr) { ivl_signal_t sig = ivl_expr_signal(expr); @@ -100,6 +109,22 @@ static void string_ex_select(ivl_expr_t expr) fprintf(vvp_out, " %%load/dar/str v%p_0;\n", sig); } +static void string_ex_string(ivl_expr_t expr) +{ + const char*val = ivl_expr_string(expr); + + /* Special case: The elaborator converts the string "" to an + 8-bit zero, which is in turn escaped to the 4-character + string \000. Detect this special case and convert it back + to an empty string. [Perhaps elaboration should be fixed?] */ + if (ivl_expr_width(expr)==8 && (strcmp(val,"\\000") == 0)) { + fprintf(vvp_out, " %%pushi/str \"\";\n"); + return; + } + + fprintf(vvp_out, " %%pushi/str \"%s\";\n", val); +} + static void string_ex_substr(ivl_expr_t expr) { ivl_expr_t arg; @@ -129,7 +154,7 @@ void draw_eval_string(ivl_expr_t expr) switch (ivl_expr_type(expr)) { case IVL_EX_STRING: - fprintf(vvp_out, " %%pushi/str \"%s\";\n", ivl_expr_string(expr)); + string_ex_string(expr); break; case IVL_EX_SIGNAL: @@ -140,6 +165,10 @@ void draw_eval_string(ivl_expr_t expr) string_ex_concat(expr); break; + case IVL_EX_PROPERTY: + string_ex_property(expr); + break; + case IVL_EX_SELECT: string_ex_select(expr); break; diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 04c1f5d25..72167043e 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -869,6 +869,16 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net) fprintf(vvp_out, " %%store/prop/r %d;\n", prop_idx); fprintf(vvp_out, " %%pop/obj 1;\n"); + } else if (ivl_type_base(prop_type) == IVL_VT_STRING) { + + /* Calculate the real value into the real value + stack. The %store/prop/r will pop the stack + value. */ + draw_eval_string(rval); + fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); + fprintf(vvp_out, " %%store/prop/str %d;\n", prop_idx); + fprintf(vvp_out, " %%pop/obj 1;\n"); + } else { assert(0); } diff --git a/vvp/class_type.cc b/vvp/class_type.cc index 12336d349..1c931a912 100644 --- a/vvp/class_type.cc +++ b/vvp/class_type.cc @@ -53,6 +53,9 @@ class class_property_t { virtual void set_real(char*buf, double val); virtual double get_real(char*buf); + virtual void set_string(char*buf, const std::string&val); + virtual string get_string(char*buf); + protected: size_t offset_; }; @@ -90,6 +93,17 @@ double class_property_t::get_real(char*) return 0.0; } +void class_property_t::set_string(char*, const string&) +{ + assert(0); +} + +string class_property_t::get_string(char*) +{ + assert(0); + return ""; +} + /* */ template class property_atom : public class_property_t { @@ -126,6 +140,26 @@ template class property_real : public class_property_t { double get_real(char*buf); }; +class property_string : public class_property_t { + public: + inline explicit property_string(void) { } + ~property_string() { } + + size_t instance_size() const { return sizeof(std::string); } + + public: + void construct(char*buf) const + { /* string*tmp = */ new (buf+offset_) string; } + + void destruct(char*buf) const + { string*tmp = reinterpret_cast (buf+offset_); + tmp->~string(); + } + + void set_string(char*buf, const string&); + string get_string(char*buf); +}; + template void property_atom::set_vec4(char*buf, const vvp_vector4_t&val) { T*tmp = reinterpret_cast (buf+offset_); @@ -158,6 +192,18 @@ template double property_real::get_real(char*buf) return *tmp; } +void property_string::set_string(char*buf, const string&val) +{ + string*tmp = reinterpret_cast(buf+offset_); + *tmp = val; +} + +string property_string::get_string(char*buf) +{ + string*tmp = reinterpret_cast(buf+offset_); + return *tmp; +} + /* **** */ class_type::class_type(const string&nam, size_t nprop) @@ -189,6 +235,8 @@ void class_type::set_property(size_t idx, const string&name, const string&type) properties_[idx].type = new property_atom; else if (type == "r") properties_[idx].type = new property_real; + else if (type == "S") + properties_[idx].type = new property_string; else properties_[idx].type = 0; } @@ -275,6 +323,21 @@ double class_type::get_real(class_type::inst_t obj, size_t pid) const return properties_[pid].type->get_real(buf); } +void class_type::set_string(class_type::inst_t obj, size_t pid, + const string&val) const +{ + char*buf = reinterpret_cast (obj); + assert(pid < properties_.size()); + properties_[pid].type->set_string(buf, val); +} + +string class_type::get_string(class_type::inst_t obj, size_t pid) const +{ + char*buf = reinterpret_cast (obj); + assert(pid < properties_.size()); + return properties_[pid].type->get_string(buf); +} + int class_type::get_type_code(void) const { return vpiClassDefn; diff --git a/vvp/class_type.h b/vvp/class_type.h index d435d91c9..1c617117b 100644 --- a/vvp/class_type.h +++ b/vvp/class_type.h @@ -63,6 +63,8 @@ class class_type : public __vpiHandle { void get_vec4(inst_t inst, size_t pid, vvp_vector4_t&val) const; void set_real(inst_t inst, size_t pid, double val) const; double get_real(inst_t inst, size_t pid) const; + void set_string(inst_t inst, size_t pid, const std::string&val) const; + std::string get_string(inst_t inst, size_t pid) const; public: // VPI related methods int get_type_code(void) const; diff --git a/vvp/codes.h b/vvp/codes.h index c50b51ed2..51f050b33 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -166,6 +166,7 @@ extern bool of_POW(vthread_t thr, vvp_code_t code); extern bool of_POW_S(vthread_t thr, vvp_code_t code); extern bool of_POW_WR(vthread_t thr, vvp_code_t code); extern bool of_PROP_R(vthread_t thr, vvp_code_t code); +extern bool of_PROP_STR(vthread_t thr, vvp_code_t code); extern bool of_PROP_V(vthread_t thr, vvp_code_t code); extern bool of_PUSHI_STR(vthread_t thr, vvp_code_t code); extern bool of_PUSHI_REAL(vthread_t thr, vvp_code_t code); @@ -186,6 +187,7 @@ extern bool of_STORE_DAR_R(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_PROP_R(vthread_t thr, vvp_code_t code); +extern bool of_STORE_PROP_STR(vthread_t thr, vvp_code_t code); extern bool of_STORE_PROP_V(vthread_t thr, vvp_code_t code); extern bool of_STORE_REAL(vthread_t thr, vvp_code_t code); extern bool of_STORE_REALA(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index e71b3ce95..b7c66d1e6 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -213,8 +213,9 @@ static const struct opcode_table_s opcode_table[] = { { "%pow", of_POW, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%pow/s", of_POW_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%pow/wr", of_POW_WR, 0, {OA_NONE, OA_NONE, OA_NONE} }, - { "%prop/r", of_PROP_R, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, - { "%prop/v", of_PROP_V, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, + { "%prop/r", of_PROP_R, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, + { "%prop/str",of_PROP_STR,1, {OA_NUMBER, OA_NONE, OA_NONE} }, + { "%prop/v", of_PROP_V, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%pushi/real",of_PUSHI_REAL,2,{OA_BIT1, OA_BIT2, OA_NONE} }, { "%pushi/str", of_PUSHI_STR, 1,{OA_STRING, OA_NONE, OA_NONE} }, { "%pushv/str", of_PUSHV_STR, 2, {OA_BIT1,OA_BIT2, OA_NONE} }, @@ -232,8 +233,9 @@ static const struct opcode_table_s opcode_table[] = { { "%store/dar/r", of_STORE_DAR_R, 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/prop/r",of_STORE_PROP_R,1, {OA_NUMBER, OA_NONE, OA_NONE} }, - { "%store/prop/v",of_STORE_PROP_V,3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, + { "%store/prop/r", of_STORE_PROP_R, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, + { "%store/prop/str",of_STORE_PROP_STR,1, {OA_NUMBER, OA_NONE, OA_NONE} }, + { "%store/prop/v", of_STORE_PROP_V, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%store/real", of_STORE_REAL, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%store/reala", of_STORE_REALA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} }, { "%store/str", of_STORE_STR, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 27daabbf0..571c67256 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -890,9 +890,11 @@ the result. * %prop/v , , * %prop/r +* %prop/str -Write the vector (/v) or real value (/r) into property number of -the class object on the top of the object stack. The real value is popped. +Write the vector (/v) or real value (/r) or string (/str) into +property number of the class object on the top of the object +stack. The real value is popped. The class object stack is NOT popped. @@ -1015,6 +1017,7 @@ variable given by the label. See also %load/obj. * %store/prop/r +* %store/prop/str * %store/prop/v , , The %store/prop/r pops a real value from the real stack and stores it diff --git a/vvp/vthread.cc b/vvp/vthread.cc index f36123a25..dfe0edcbd 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -4552,6 +4552,25 @@ bool of_PROP_R(vthread_t thr, vvp_code_t cp) return true; } +/* + * %prop/str + * + * Load a string value from the cobject and push it onto the real value + * stack. + */ +bool of_PROP_STR(vthread_t thr, vvp_code_t cp) +{ + unsigned pid = cp->number; + + vvp_object_t&obj = thr->peek_object(); + vvp_cobject*cobj = obj.peek(); + + string val = cobj->get_string(pid); + thr->push_str(val); + + return true; +} + /* * %prop/v * @@ -5114,6 +5133,27 @@ bool of_STORE_PROP_R(vthread_t thr, vvp_code_t cp) return true; } +/* + * %store/prop/str + * + * Pop a string value from the string stack, and store the value into + * the property of the object references by the top of the stack. Do NOT + * pop the object stack. + */ +bool of_STORE_PROP_STR(vthread_t thr, vvp_code_t cp) +{ + size_t pid = cp->number; + string val = thr->pop_str(); + + vvp_object_t&obj = thr->peek_object(); + vvp_cobject*cobj = obj.peek(); + assert(cobj); + + cobj->set_string(pid, val); + + return true; +} + /* * %store/prop/v * diff --git a/vvp/vvp_cobject.cc b/vvp/vvp_cobject.cc index 212d42f5c..1c563626f 100644 --- a/vvp/vvp_cobject.cc +++ b/vvp/vvp_cobject.cc @@ -54,3 +54,13 @@ double vvp_cobject::get_real(size_t pid) { return defn_->get_real(properties_, pid); } + +void vvp_cobject::set_string(size_t pid, const string&val) +{ + defn_->set_string(properties_, pid, val); +} + +string vvp_cobject::get_string(size_t pid) +{ + return defn_->get_string(properties_, pid); +} diff --git a/vvp/vvp_cobject.h b/vvp/vvp_cobject.h index b463eca22..93ef16fa8 100644 --- a/vvp/vvp_cobject.h +++ b/vvp/vvp_cobject.h @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +# include # include # include "vvp_object.h" # include "class_type.h" @@ -37,6 +38,9 @@ class vvp_cobject : public vvp_object { void set_real(size_t pid, double val); double get_real(size_t pid); + void set_string(size_t pid, const std::string&val); + std::string get_string(size_t pid); + private: const class_type* defn_; // For now, only support 32bit bool signed properties.