Allow class properties to be arrayed.
This adds the runtime support for class properties that are classes to be arrayed. Add a means to define the dimensions of a property in the vvp format, and add functions for setting/extracting elements of a property.
This commit is contained in:
parent
ea4b000be6
commit
98799ff7fa
|
|
@ -203,6 +203,21 @@ ostream& ivl_type_s::debug_dump(ostream&o) const
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ostream& netclass_t::debug_dump(ostream&fd) const
|
||||||
|
{
|
||||||
|
fd << "class " << name_ << "{";
|
||||||
|
for (size_t idx = 0 ; idx < property_table_.size() ; idx += 1) {
|
||||||
|
if (idx != 0) fd << "; ";
|
||||||
|
if (property_table_[idx].type)
|
||||||
|
property_table_[idx].type->debug_dump(fd);
|
||||||
|
else
|
||||||
|
fd << "NO_TYPE";
|
||||||
|
fd << " " << property_table_[idx].name;
|
||||||
|
}
|
||||||
|
fd << "}";
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
ostream& netdarray_t::debug_dump(ostream&o) const
|
ostream& netdarray_t::debug_dump(ostream&o) const
|
||||||
{
|
{
|
||||||
o << "dynamic array of " << *element_type();
|
o << "dynamic array of " << *element_type();
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ class netclass_t : public ivl_type_s {
|
||||||
void emit_scope(struct target_t*tgt) const;
|
void emit_scope(struct target_t*tgt) const;
|
||||||
bool emit_defs(struct target_t*tgt) const;
|
bool emit_defs(struct target_t*tgt) const;
|
||||||
|
|
||||||
|
std::ostream& debug_dump(std::ostream&fd) const;
|
||||||
void dump_scope(ostream&fd) const;
|
void dump_scope(ostream&fd) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -65,3 +65,8 @@ vector<netrange_t> netparray_t::slice_dimensions() const
|
||||||
netuarray_t::~netuarray_t()
|
netuarray_t::~netuarray_t()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<netrange_t> netuarray_t::slice_dimensions() const
|
||||||
|
{
|
||||||
|
return static_dimensions();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,10 @@ class netuarray_t : public netsarray_t {
|
||||||
explicit netuarray_t(const std::vector<netrange_t>&packed,
|
explicit netuarray_t(const std::vector<netrange_t>&packed,
|
||||||
ivl_type_t etype);
|
ivl_type_t etype);
|
||||||
~netuarray_t();
|
~netuarray_t();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Virtual methods from the ivl_type_s type...
|
||||||
|
std::vector<netrange_t> slice_dimensions() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline netuarray_t::netuarray_t(const std::vector<netrange_t>&pd,
|
inline netuarray_t::netuarray_t(const std::vector<netrange_t>&pd,
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,8 @@ class netarray_t : public ivl_type_s {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Some virtual methods have a common implementation for arrays.
|
// Some virtual methods have a common implementation for arrays.
|
||||||
|
|
||||||
|
// The base_type() for arrays is the base_Typeof the element.
|
||||||
ivl_variable_type_t base_type() const;
|
ivl_variable_type_t base_type() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ static void show_prop_type_vector(ivl_type_t ptype)
|
||||||
static void show_prop_type(ivl_type_t ptype)
|
static void show_prop_type(ivl_type_t ptype)
|
||||||
{
|
{
|
||||||
ivl_variable_type_t data_type = ivl_type_base(ptype);
|
ivl_variable_type_t data_type = ivl_type_base(ptype);
|
||||||
|
unsigned packed_dimensions = ivl_type_packed_dimensions(ptype);
|
||||||
|
|
||||||
switch (data_type) {
|
switch (data_type) {
|
||||||
case IVL_VT_REAL:
|
case IVL_VT_REAL:
|
||||||
|
|
@ -64,6 +65,15 @@ static void show_prop_type(ivl_type_t ptype)
|
||||||
case IVL_VT_DARRAY:
|
case IVL_VT_DARRAY:
|
||||||
case IVL_VT_CLASS:
|
case IVL_VT_CLASS:
|
||||||
fprintf(vvp_out, "\"o\"");
|
fprintf(vvp_out, "\"o\"");
|
||||||
|
if (packed_dimensions > 0) {
|
||||||
|
unsigned idx;
|
||||||
|
fprintf(vvp_out, " ");
|
||||||
|
for (idx = 0 ; idx < packed_dimensions ; idx += 1) {
|
||||||
|
fprintf(vvp_out, "[%d:%d]",
|
||||||
|
ivl_type_packed_msb(ptype,idx),
|
||||||
|
ivl_type_packed_lsb(ptype,idx));
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(vvp_out, "\"<ERROR-no-type>\"");
|
fprintf(vvp_out, "\"<ERROR-no-type>\"");
|
||||||
|
|
|
||||||
|
|
@ -172,9 +172,22 @@ static int eval_object_property(ivl_expr_t expr)
|
||||||
ivl_signal_t sig = ivl_expr_signal(expr);
|
ivl_signal_t sig = ivl_expr_signal(expr);
|
||||||
unsigned pidx = ivl_expr_property_idx(expr);
|
unsigned pidx = ivl_expr_property_idx(expr);
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
ivl_expr_t idx_expr = 0;
|
||||||
|
|
||||||
|
/* If there is an array index expression, then this is an
|
||||||
|
array'ed property, and we need to calculate the index for
|
||||||
|
the expression. */
|
||||||
|
if ( (idx_expr = ivl_expr_oper1(expr)) ) {
|
||||||
|
idx = allocate_word();
|
||||||
|
draw_eval_expr_into_integer(idx_expr, idx);
|
||||||
|
}
|
||||||
|
|
||||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
||||||
fprintf(vvp_out, " %%prop/obj %u;\n", pidx);
|
fprintf(vvp_out, " %%prop/obj %u, %d; eval_object_property\n", pidx, idx);
|
||||||
fprintf(vvp_out, " %%pop/obj 1, 1;\n");
|
fprintf(vvp_out, " %%pop/obj 1, 1;\n");
|
||||||
|
|
||||||
|
if (idx != 0) clr_word(idx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -334,7 +334,11 @@ static ivl_type_t draw_lval_expr(ivl_lval_t lval)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(ivl_type_base(sub_type) == IVL_VT_CLASS);
|
assert(ivl_type_base(sub_type) == IVL_VT_CLASS);
|
||||||
fprintf(vvp_out, " %%prop/obj %d;\n", ivl_lval_property_idx(lval));
|
if (ivl_lval_idx(lval)) {
|
||||||
|
fprintf(vvp_out, " ; XXXX Don't know how to handle ivl_lval_idx values here.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(vvp_out, " %%prop/obj %d, 0; draw_lval_expr\n", ivl_lval_property_idx(lval));
|
||||||
fprintf(vvp_out, " %%pop/obj 1, 1;\n");
|
fprintf(vvp_out, " %%pop/obj 1, 1;\n");
|
||||||
return ivl_type_prop_type(sub_type, ivl_lval_property_idx(lval));
|
return ivl_type_prop_type(sub_type, ivl_lval_property_idx(lval));
|
||||||
}
|
}
|
||||||
|
|
@ -1063,22 +1067,33 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
||||||
|
|
||||||
} else if (ivl_type_base(prop_type) == IVL_VT_DARRAY) {
|
} else if (ivl_type_base(prop_type) == IVL_VT_DARRAY) {
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
/* The property is a darray, and there is no mux
|
/* The property is a darray, and there is no mux
|
||||||
expression to the assignment is of an entire
|
expression to the assignment is of an entire
|
||||||
array object. */
|
array object. */
|
||||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
||||||
draw_eval_object(rval);
|
draw_eval_object(rval);
|
||||||
fprintf(vvp_out, " %%store/prop/obj %d;\n", prop_idx);
|
fprintf(vvp_out, " %%store/prop/obj %d, %d; IVL_VT_DARRAY\n", prop_idx, idx);
|
||||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||||
|
|
||||||
} else if (ivl_type_base(prop_type) == IVL_VT_CLASS) {
|
} else if (ivl_type_base(prop_type) == IVL_VT_CLASS) {
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
ivl_expr_t idx_expr;
|
||||||
|
if ( (idx_expr = ivl_lval_idx(lval)) ) {
|
||||||
|
idx = allocate_word();
|
||||||
|
}
|
||||||
|
|
||||||
/* The property is a class object. */
|
/* The property is a class object. */
|
||||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
||||||
draw_eval_object(rval);
|
draw_eval_object(rval);
|
||||||
fprintf(vvp_out, " %%store/prop/obj %d;\n", prop_idx);
|
if (idx_expr) draw_eval_expr_into_integer(idx_expr, idx);
|
||||||
|
fprintf(vvp_out, " %%store/prop/obj %d, %d; IVL_VT_CLASS\n", prop_idx, idx);
|
||||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||||
|
|
||||||
|
if (idx_expr) clr_word(idx);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(vvp_out, " ; ERROR: ivl_type_base(prop_type) = %d\n",
|
fprintf(vvp_out, " ; ERROR: ivl_type_base(prop_type) = %d\n",
|
||||||
ivl_type_base(prop_type));
|
ivl_type_base(prop_type));
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,8 @@ class class_property_t {
|
||||||
virtual void set_string(char*buf, const std::string&val);
|
virtual void set_string(char*buf, const std::string&val);
|
||||||
virtual string get_string(char*buf);
|
virtual string get_string(char*buf);
|
||||||
|
|
||||||
virtual void set_object(char*buf, const vvp_object_t&val);
|
virtual void set_object(char*buf, const vvp_object_t&val, uint64_t element);
|
||||||
virtual void get_object(char*buf, vvp_object_t&val);
|
virtual void get_object(char*buf, vvp_object_t&val, uint64_t element);
|
||||||
|
|
||||||
// Implement polymorphic shallow copy.
|
// Implement polymorphic shallow copy.
|
||||||
virtual void copy(char*buf, char*src) = 0;
|
virtual void copy(char*buf, char*src) = 0;
|
||||||
|
|
@ -110,12 +110,12 @@ string class_property_t::get_string(char*)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void class_property_t::set_object(char*, const vvp_object_t&)
|
void class_property_t::set_object(char*, const vvp_object_t&, uint64_t)
|
||||||
{
|
{
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void class_property_t::get_object(char*, vvp_object_t&)
|
void class_property_t::get_object(char*, vvp_object_t&, uint64_t)
|
||||||
{
|
{
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
@ -234,24 +234,23 @@ class property_string : public class_property_t {
|
||||||
|
|
||||||
class property_object : public class_property_t {
|
class property_object : public class_property_t {
|
||||||
public:
|
public:
|
||||||
inline explicit property_object(void) { }
|
inline explicit property_object(uint64_t as): array_size_(as==0? 1 : as) { }
|
||||||
~property_object() { }
|
~property_object() { }
|
||||||
|
|
||||||
size_t instance_size() const { return sizeof(vvp_object_t); }
|
size_t instance_size() const { return array_size_ * sizeof(vvp_object_t); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void construct(char*buf) const
|
void construct(char*buf) const;
|
||||||
{ /* vvp_object_t*tmp = */ new (buf+offset_) vvp_object_t; }
|
|
||||||
|
|
||||||
void destruct(char*buf) const
|
void destruct(char*buf) const;
|
||||||
{ vvp_object_t*tmp = reinterpret_cast<vvp_object_t*> (buf+offset_);
|
|
||||||
tmp->~vvp_object_t();
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_object(char*buf, const vvp_object_t&);
|
void set_object(char*buf, const vvp_object_t&, uint64_t);
|
||||||
void get_object(char*buf, vvp_object_t&);
|
void get_object(char*buf, vvp_object_t&, uint64_t);
|
||||||
|
|
||||||
void copy(char*dst, char*src);
|
void copy(char*dst, char*src);
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t array_size_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T> void property_atom<T>::set_vec4(char*buf, const vvp_vector4_t&val)
|
template <class T> void property_atom<T>::set_vec4(char*buf, const vvp_vector4_t&val)
|
||||||
|
|
@ -360,23 +359,39 @@ void property_string::copy(char*dst, char*src)
|
||||||
*dst_obj = *src_obj;
|
*dst_obj = *src_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
void property_object::set_object(char*buf, const vvp_object_t&val)
|
void property_object::construct(char*buf) const
|
||||||
{
|
{
|
||||||
vvp_object_t*tmp = reinterpret_cast<vvp_object_t*>(buf+offset_);
|
for (size_t idx = 0 ; idx < array_size_ ; idx += 1)
|
||||||
*tmp = val;
|
new (buf+offset_ + idx*sizeof(vvp_object_t)) vvp_object_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
void property_object::get_object(char*buf, vvp_object_t&val)
|
void property_object::destruct(char*buf) const
|
||||||
{
|
{
|
||||||
|
vvp_object_t*tmp = reinterpret_cast<vvp_object_t*> (buf+offset_);
|
||||||
|
for (size_t idx = 0 ; idx < array_size_ ; idx += 1)
|
||||||
|
(tmp+idx)->~vvp_object_t();
|
||||||
|
}
|
||||||
|
|
||||||
|
void property_object::set_object(char*buf, const vvp_object_t&val, uint64_t idx)
|
||||||
|
{
|
||||||
|
assert(idx < array_size_);
|
||||||
vvp_object_t*tmp = reinterpret_cast<vvp_object_t*>(buf+offset_);
|
vvp_object_t*tmp = reinterpret_cast<vvp_object_t*>(buf+offset_);
|
||||||
val = *tmp;
|
tmp[idx] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void property_object::get_object(char*buf, vvp_object_t&val, uint64_t idx)
|
||||||
|
{
|
||||||
|
assert(idx < array_size_);
|
||||||
|
vvp_object_t*tmp = reinterpret_cast<vvp_object_t*>(buf+offset_);
|
||||||
|
val = tmp[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
void property_object::copy(char*dst, char*src)
|
void property_object::copy(char*dst, char*src)
|
||||||
{
|
{
|
||||||
vvp_object_t*dst_obj = reinterpret_cast<vvp_object_t*>(dst);
|
vvp_object_t*dst_obj = reinterpret_cast<vvp_object_t*>(dst);
|
||||||
vvp_object_t*src_obj = reinterpret_cast<vvp_object_t*>(src);
|
vvp_object_t*src_obj = reinterpret_cast<vvp_object_t*>(src);
|
||||||
*dst_obj = *src_obj;
|
for (size_t idx = 0 ; idx < array_size_ ; idx += 1)
|
||||||
|
dst_obj[idx] = src_obj[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* **** */
|
/* **** */
|
||||||
|
|
@ -393,7 +408,7 @@ class_type::~class_type()
|
||||||
delete properties_[idx].type;
|
delete properties_[idx].type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void class_type::set_property(size_t idx, const string&name, const string&type)
|
void class_type::set_property(size_t idx, const string&name, const string&type, uint64_t array_size)
|
||||||
{
|
{
|
||||||
assert(idx < properties_.size());
|
assert(idx < properties_.size());
|
||||||
properties_[idx].name = name;
|
properties_[idx].name = name;
|
||||||
|
|
@ -419,7 +434,7 @@ void class_type::set_property(size_t idx, const string&name, const string&type)
|
||||||
else if (type == "S")
|
else if (type == "S")
|
||||||
properties_[idx].type = new property_string;
|
properties_[idx].type = new property_string;
|
||||||
else if (type == "o")
|
else if (type == "o")
|
||||||
properties_[idx].type = new property_object;
|
properties_[idx].type = new property_object(array_size);
|
||||||
else if (type[0] == 'b') {
|
else if (type[0] == 'b') {
|
||||||
size_t wid = strtoul(type.c_str()+1, 0, 0);
|
size_t wid = strtoul(type.c_str()+1, 0, 0);
|
||||||
properties_[idx].type = new property_bit(wid);
|
properties_[idx].type = new property_bit(wid);
|
||||||
|
|
@ -529,18 +544,19 @@ string class_type::get_string(class_type::inst_t obj, size_t pid) const
|
||||||
}
|
}
|
||||||
|
|
||||||
void class_type::set_object(class_type::inst_t obj, size_t pid,
|
void class_type::set_object(class_type::inst_t obj, size_t pid,
|
||||||
const vvp_object_t&val) const
|
const vvp_object_t&val, size_t idx) const
|
||||||
{
|
{
|
||||||
char*buf = reinterpret_cast<char*> (obj);
|
char*buf = reinterpret_cast<char*> (obj);
|
||||||
assert(pid < properties_.size());
|
assert(pid < properties_.size());
|
||||||
properties_[pid].type->set_object(buf, val);
|
properties_[pid].type->set_object(buf, val, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void class_type::get_object(class_type::inst_t obj, size_t pid, vvp_object_t&val) const
|
void class_type::get_object(class_type::inst_t obj, size_t pid,
|
||||||
|
vvp_object_t&val, size_t idx) const
|
||||||
{
|
{
|
||||||
char*buf = reinterpret_cast<char*> (obj);
|
char*buf = reinterpret_cast<char*> (obj);
|
||||||
assert(pid < properties_.size());
|
assert(pid < properties_.size());
|
||||||
properties_[pid].type->get_object(buf, val);
|
properties_[pid].type->get_object(buf, val, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void class_type::copy_property(class_type::inst_t dst, size_t pid, class_type::inst_t src) const
|
void class_type::copy_property(class_type::inst_t dst, size_t pid, class_type::inst_t src) const
|
||||||
|
|
@ -569,10 +585,10 @@ void compile_class_start(char*lab, char*nam, unsigned ntype)
|
||||||
delete[]nam;
|
delete[]nam;
|
||||||
}
|
}
|
||||||
|
|
||||||
void compile_class_property(unsigned idx, char*nam, char*typ)
|
void compile_class_property(unsigned idx, char*nam, char*typ, uint64_t array_size)
|
||||||
{
|
{
|
||||||
assert(compile_class);
|
assert(compile_class);
|
||||||
compile_class->set_property(idx, nam, typ);
|
compile_class->set_property(idx, nam, typ, array_size);
|
||||||
delete[]nam;
|
delete[]nam;
|
||||||
delete[]typ;
|
delete[]typ;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ class class_type : public __vpiHandle {
|
||||||
// Set the details about the property. This is used during
|
// Set the details about the property. This is used during
|
||||||
// parse of the .vvp file to fill in the details of the
|
// parse of the .vvp file to fill in the details of the
|
||||||
// property for the class definition.
|
// property for the class definition.
|
||||||
void set_property(size_t idx, const std::string&name, const std::string&type);
|
void set_property(size_t idx, const std::string&name, const std::string&type, uint64_t array_size);
|
||||||
|
|
||||||
// This method is called after all the properties are
|
// This method is called after all the properties are
|
||||||
// defined. This calculates information about the definition.
|
// defined. This calculates information about the definition.
|
||||||
|
|
@ -66,8 +66,8 @@ class class_type : public __vpiHandle {
|
||||||
double get_real(inst_t inst, size_t pid) 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;
|
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;
|
std::string get_string(inst_t inst, size_t pid) const;
|
||||||
void set_object(inst_t inst, size_t pid, const vvp_object_t&val) const;
|
void set_object(inst_t inst, size_t pid, const vvp_object_t&val, size_t idx) const;
|
||||||
void get_object(inst_t inst, size_t pid, vvp_object_t&val) const;
|
void get_object(inst_t inst, size_t pid, vvp_object_t&val, size_t idx) const;
|
||||||
|
|
||||||
void copy_property(inst_t dst, size_t idx, inst_t src) const;
|
void copy_property(inst_t dst, size_t idx, inst_t src) const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,7 @@ static const struct opcode_table_s opcode_table[] = {
|
||||||
{ "%pow", of_POW, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%pow", of_POW, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
{ "%pow/s", of_POW_S, 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} },
|
{ "%pow/wr", of_POW_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||||
{ "%prop/obj",of_PROP_OBJ,1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
{ "%prop/obj",of_PROP_OBJ,2, {OA_NUMBER, OA_BIT1, OA_NONE} },
|
||||||
{ "%prop/r", of_PROP_R, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
{ "%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/str",of_PROP_STR,1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
{ "%prop/v", of_PROP_V, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
{ "%prop/v", of_PROP_V, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
|
|
@ -248,7 +248,7 @@ static const struct opcode_table_s opcode_table[] = {
|
||||||
{ "%store/dar/str",of_STORE_DAR_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/obj", of_STORE_OBJ, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
||||||
{ "%store/obja", of_STORE_OBJA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
{ "%store/obja", of_STORE_OBJA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
|
||||||
{ "%store/prop/obj",of_STORE_PROP_OBJ,1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
{ "%store/prop/obj",of_STORE_PROP_OBJ,2, {OA_NUMBER, OA_BIT1, OA_NONE} },
|
||||||
{ "%store/prop/r", of_STORE_PROP_R, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
{ "%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/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/prop/v", of_STORE_PROP_V, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
|
|
|
||||||
|
|
@ -552,7 +552,7 @@ extern void compile_island_tranvp(char*island, char*ba, char*bb,
|
||||||
extern void delete_udp_symbols(void);
|
extern void delete_udp_symbols(void);
|
||||||
|
|
||||||
extern void compile_class_start(char*lab, char*nam, unsigned nprop);
|
extern void compile_class_start(char*lab, char*nam, unsigned nprop);
|
||||||
extern void compile_class_property(unsigned idx, char*nam, char*typ);
|
extern void compile_class_property(unsigned idx, char*nam, char*typ, uint64_t array_size);
|
||||||
extern void compile_class_done(void);
|
extern void compile_class_done(void);
|
||||||
|
|
||||||
#endif /* IVL_compile_H */
|
#endif /* IVL_compile_H */
|
||||||
|
|
|
||||||
|
|
@ -892,7 +892,7 @@ This opcode raises the left operand by the right operand, and pushes
|
||||||
the result.
|
the result.
|
||||||
|
|
||||||
* %prop/v <pid>, <base>, <wid>
|
* %prop/v <pid>, <base>, <wid>
|
||||||
* %prop/obj <pid>
|
* %prop/obj <pid>, <idx>
|
||||||
* %prop/r <pid>
|
* %prop/r <pid>
|
||||||
* %prop/str <pid>
|
* %prop/str <pid>
|
||||||
|
|
||||||
|
|
@ -901,6 +901,11 @@ the property number <pid> of the class object on the top of the
|
||||||
object stack. Push the resulting value to the appropriate stack. The
|
object stack. Push the resulting value to the appropriate stack. The
|
||||||
class object that is the source is NOT popped from the object stack.
|
class object that is the source is NOT popped from the object stack.
|
||||||
|
|
||||||
|
The <idx> is the address of an index variable that selects the word of
|
||||||
|
an arrayed property. If the <idx> value is 0, then use index value
|
||||||
|
zero instead of reading index register zero. Use this form for
|
||||||
|
non-arrayed properties.
|
||||||
|
|
||||||
* %pushi/real <mant>, <exp>
|
* %pushi/real <mant>, <exp>
|
||||||
|
|
||||||
This opcode loads an immediate value, floating point, into the real
|
This opcode loads an immediate value, floating point, into the real
|
||||||
|
|
@ -1048,18 +1053,21 @@ variable given by the label.
|
||||||
|
|
||||||
See also %load/obj.
|
See also %load/obj.
|
||||||
|
|
||||||
* %store/prop/obj <index>
|
* %store/prop/obj <pid>, <idx>
|
||||||
* %store/prop/r <index>
|
* %store/prop/r <pid>
|
||||||
* %store/prop/str <index>
|
* %store/prop/str <pid>
|
||||||
* %store/prop/v <index>, <bit>, <wid>
|
* %store/prop/v <pid>, <bit>, <wid>
|
||||||
|
|
||||||
The %store/prop/r pops a real value from the real stack and stores it
|
The %store/prop/r pops a real value from the real stack and stores it
|
||||||
into the the property number <index> of a cobject in the top of the
|
into the the property number <pid> of a cobject in the top of the
|
||||||
object stack. The cobject is NOT popped.
|
object stack. The cobject is NOT popped.
|
||||||
|
|
||||||
The %store/prop/obj pops an object from the top of the object stack,
|
The %store/prop/obj pops an object from the top of the object stack,
|
||||||
then writes it to the property number <index> of the cobject now on
|
then writes it to the property number <pid> of the cobject now on
|
||||||
top of the object stack. The cobject is NOT popped.
|
top of the object stack. The cobject is NOT popped. The <idx> argument
|
||||||
|
is the index register to select an element. If the property is an
|
||||||
|
array, this selects the element. If <idx> is 0, then use the value 0
|
||||||
|
instead of index register zero. Use 0 for non-array properties.
|
||||||
|
|
||||||
* %store/real <var-label>
|
* %store/real <var-label>
|
||||||
* %store/reala <var-label>, <index>
|
* %store/reala <var-label>, <index>
|
||||||
|
|
|
||||||
29
vvp/parse.y
29
vvp/parse.y
|
|
@ -115,6 +115,7 @@ static struct __vpiModPath*modpath_dst = 0;
|
||||||
%type <flag> local_flag
|
%type <flag> local_flag
|
||||||
%type <vpi_enum> port_type
|
%type <vpi_enum> port_type
|
||||||
%type <numb> signed_t_number
|
%type <numb> signed_t_number
|
||||||
|
%type <numb> dimension dimensions dimensions_opt
|
||||||
%type <symb> symbol symbol_opt
|
%type <symb> symbol symbol_opt
|
||||||
%type <symbv> symbols symbols_net
|
%type <symbv> symbols symbols_net
|
||||||
%type <numbv> numbers
|
%type <numbv> numbers
|
||||||
|
|
@ -898,8 +899,32 @@ class_properties
|
||||||
;
|
;
|
||||||
|
|
||||||
class_property
|
class_property
|
||||||
: T_NUMBER ':' T_STRING ',' T_STRING
|
: T_NUMBER ':' T_STRING ',' T_STRING dimensions_opt
|
||||||
{ compile_class_property($1, $3, $5); }
|
{ compile_class_property($1, $3, $5, $6); }
|
||||||
|
;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The syntax for dimensions allows the code generator to give the
|
||||||
|
* accurate dimensions for for the property, but for now we are only
|
||||||
|
* interested in the total number of elements. So reduce the ranges
|
||||||
|
* to a simple number, and scale the number.
|
||||||
|
*/
|
||||||
|
dimensions_opt
|
||||||
|
: dimensions
|
||||||
|
{ $$ = $1; }
|
||||||
|
| { $$ = 0; }
|
||||||
|
;
|
||||||
|
|
||||||
|
dimensions
|
||||||
|
: dimensions dimension
|
||||||
|
{ $$ = $1 * $2; }
|
||||||
|
| dimension
|
||||||
|
{ $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
dimension
|
||||||
|
: '[' T_NUMBER ':' T_NUMBER ']'
|
||||||
|
{ $$ = ($2 > $4? $2 - $4 : $4 - $2) + 1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
/* Enumeration types */
|
/* Enumeration types */
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,8 @@ using namespace std;
|
||||||
* to reap the child immediately.
|
* to reap the child immediately.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const size_t THR_MAX_WORDS = 16;
|
||||||
|
|
||||||
struct vthread_s {
|
struct vthread_s {
|
||||||
vthread_s();
|
vthread_s();
|
||||||
|
|
||||||
|
|
@ -106,7 +108,7 @@ struct vthread_s {
|
||||||
union {
|
union {
|
||||||
int64_t w_int;
|
int64_t w_int;
|
||||||
uint64_t w_uint;
|
uint64_t w_uint;
|
||||||
} words[16];
|
} words[THR_MAX_WORDS];
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vector<double> stack_real_;
|
vector<double> stack_real_;
|
||||||
|
|
@ -4657,19 +4659,25 @@ bool of_POW_WR(vthread_t thr, vvp_code_t)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* %prop/obj <pid>
|
* %prop/obj <pid>, <idx>
|
||||||
*
|
*
|
||||||
* Load an object value from the cobject and push it onto the object stack.
|
* Load an object value from the cobject and push it onto the object stack.
|
||||||
*/
|
*/
|
||||||
bool of_PROP_OBJ(vthread_t thr, vvp_code_t cp)
|
bool of_PROP_OBJ(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
unsigned pid = cp->number;
|
unsigned pid = cp->number;
|
||||||
|
unsigned idx = cp->bit_idx[0];
|
||||||
|
|
||||||
|
if (idx != 0) {
|
||||||
|
assert(idx < THR_MAX_WORDS);
|
||||||
|
idx = thr->words[idx].w_uint;
|
||||||
|
}
|
||||||
|
|
||||||
vvp_object_t&obj = thr->peek_object();
|
vvp_object_t&obj = thr->peek_object();
|
||||||
vvp_cobject*cobj = obj.peek<vvp_cobject>();
|
vvp_cobject*cobj = obj.peek<vvp_cobject>();
|
||||||
|
|
||||||
vvp_object_t val;
|
vvp_object_t val;
|
||||||
cobj->get_object(pid, val);
|
cobj->get_object(pid, val, idx);
|
||||||
|
|
||||||
thr->push_object(val);
|
thr->push_object(val);
|
||||||
|
|
||||||
|
|
@ -5479,7 +5487,7 @@ bool of_STORE_OBJA(vthread_t thr, vvp_code_t cp)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* %store/prop/obj <id>
|
* %store/prop/obj <pid>, <idx>
|
||||||
*
|
*
|
||||||
* Pop an object value from the object stack, and store the value into
|
* Pop an object value from the object stack, and store the value into
|
||||||
* the property of the object references by the top of the stack. Do NOT
|
* the property of the object references by the top of the stack. Do NOT
|
||||||
|
|
@ -5488,6 +5496,13 @@ bool of_STORE_OBJA(vthread_t thr, vvp_code_t cp)
|
||||||
bool of_STORE_PROP_OBJ(vthread_t thr, vvp_code_t cp)
|
bool of_STORE_PROP_OBJ(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
size_t pid = cp->number;
|
size_t pid = cp->number;
|
||||||
|
unsigned idx = cp->bit_idx[0];
|
||||||
|
|
||||||
|
if (idx != 0) {
|
||||||
|
assert(idx < THR_MAX_WORDS);
|
||||||
|
idx = thr->words[idx].w_uint;
|
||||||
|
}
|
||||||
|
|
||||||
vvp_object_t val;
|
vvp_object_t val;
|
||||||
thr->pop_object(val);
|
thr->pop_object(val);
|
||||||
|
|
||||||
|
|
@ -5495,7 +5510,7 @@ bool of_STORE_PROP_OBJ(vthread_t thr, vvp_code_t cp)
|
||||||
vvp_cobject*cobj = obj.peek<vvp_cobject>();
|
vvp_cobject*cobj = obj.peek<vvp_cobject>();
|
||||||
assert(cobj);
|
assert(cobj);
|
||||||
|
|
||||||
cobj->set_object(pid, val);
|
cobj->set_object(pid, val, idx);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,14 +65,14 @@ string vvp_cobject::get_string(size_t pid)
|
||||||
return defn_->get_string(properties_, pid);
|
return defn_->get_string(properties_, pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vvp_cobject::set_object(size_t pid, const vvp_object_t&val)
|
void vvp_cobject::set_object(size_t pid, const vvp_object_t&val, size_t idx)
|
||||||
{
|
{
|
||||||
defn_->set_object(properties_, pid, val);
|
defn_->set_object(properties_, pid, val, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vvp_cobject::get_object(size_t pid, vvp_object_t&val)
|
void vvp_cobject::get_object(size_t pid, vvp_object_t&val, size_t idx)
|
||||||
{
|
{
|
||||||
return defn_->get_object(properties_, pid, val);
|
return defn_->get_object(properties_, pid, val, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vvp_cobject::shallow_copy(const vvp_object*obj)
|
void vvp_cobject::shallow_copy(const vvp_object*obj)
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,8 @@ class vvp_cobject : public vvp_object {
|
||||||
void set_string(size_t pid, const std::string&val);
|
void set_string(size_t pid, const std::string&val);
|
||||||
std::string get_string(size_t pid);
|
std::string get_string(size_t pid);
|
||||||
|
|
||||||
void set_object(size_t pid, const vvp_object_t&val);
|
void set_object(size_t pid, const vvp_object_t&val, size_t idx);
|
||||||
void get_object(size_t pid, vvp_object_t&val);
|
void get_object(size_t pid, vvp_object_t&val, size_t idx);
|
||||||
|
|
||||||
void shallow_copy(const vvp_object*that);
|
void shallow_copy(const vvp_object*that);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue