Handle strings as class object properties.

While we are at it, fix a handling of null strings in
string expressions.
This commit is contained in:
Stephen Williams 2013-01-13 17:14:40 -08:00
parent 106850ca7d
commit c49b21115a
15 changed files with 205 additions and 8 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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<property base=%s, prop=%s, real>\n", ind, "",
ivl_signal_basename(sig), pnam);
} else if (ivl_expr_value(net) == IVL_VT_STRING) {
fprintf(out, "%*s<property base=%s, prop=%s, string>\n", ind, "",
ivl_signal_basename(sig), pnam);
} else {
fprintf(out, "%*s<property base=%s, prop=%s, width=%u, %s>\n", ind, "",
ivl_signal_basename(sig), pnam, ivl_expr_width(net), signed_flag);

View File

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

View File

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

View File

@ -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 T> class property_atom : public class_property_t {
@ -126,6 +140,26 @@ template <class T> 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<string*> (buf+offset_);
tmp->~string();
}
void set_string(char*buf, const string&);
string get_string(char*buf);
};
template <class T> void property_atom<T>::set_vec4(char*buf, const vvp_vector4_t&val)
{
T*tmp = reinterpret_cast<T*> (buf+offset_);
@ -158,6 +192,18 @@ template <class T> double property_real<T>::get_real(char*buf)
return *tmp;
}
void property_string::set_string(char*buf, const string&val)
{
string*tmp = reinterpret_cast<string*>(buf+offset_);
*tmp = val;
}
string property_string::get_string(char*buf)
{
string*tmp = reinterpret_cast<string*>(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<int64_t>;
else if (type == "r")
properties_[idx].type = new property_real<double>;
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<char*> (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<char*> (obj);
assert(pid < properties_.size());
return properties_[pid].type->get_string(buf);
}
int class_type::get_type_code(void) const
{
return vpiClassDefn;

View File

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

View File

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

View File

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

View File

@ -890,9 +890,11 @@ the result.
* %prop/v <pid>, <base>, <wid>
* %prop/r <pid>
* %prop/str <pid>
Write the vector (/v) or real value (/r) into property number <pid> 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 <pid> 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 <index>
* %store/prop/str <index>
* %store/prop/v <index>, <bit>, <wid>
The %store/prop/r pops a real value from the real stack and stores it

View File

@ -4552,6 +4552,25 @@ bool of_PROP_R(vthread_t thr, vvp_code_t cp)
return true;
}
/*
* %prop/str <pid>
*
* 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<vvp_cobject>();
string val = cobj->get_string(pid);
thr->push_str(val);
return true;
}
/*
* %prop/v <pid> <base> <wid>
*
@ -5114,6 +5133,27 @@ bool of_STORE_PROP_R(vthread_t thr, vvp_code_t cp)
return true;
}
/*
* %store/prop/str <id>
*
* 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<vvp_cobject>();
assert(cobj);
cobj->set_string(pid, val);
return true;
}
/*
* %store/prop/v <id> <base> <wid>
*

View File

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

View File

@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include <string>
# include <stdint.h>
# 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.