Add support for darrays as class properties.
This commit is contained in:
parent
c49b21115a
commit
4568766cff
2
PExpr.h
2
PExpr.h
|
|
@ -518,6 +518,8 @@ class PENumber : public PExpr {
|
|||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid, unsigned) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
|
|
|
|||
105
elab_expr.cc
105
elab_expr.cc
|
|
@ -144,6 +144,7 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, ivl_type_t, unsigned) cons
|
|||
<< " elaborate (ivl_type_t) this expression. " << endl;
|
||||
cerr << get_fileline() << ": : Expression is: " << *this
|
||||
<< endl;
|
||||
cerr << get_fileline() << ": : Expression type: " << typeid(*this).name() << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1091,11 +1092,13 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
|
|||
if (path_.size() < 2)
|
||||
return 0;
|
||||
|
||||
perm_string member_name;
|
||||
ivl_type_t member_type = 0;
|
||||
pform_name_t use_path = path_;
|
||||
perm_string method_name = peek_tail_name(use_path);
|
||||
use_path.pop_back();
|
||||
|
||||
NetNet *net;
|
||||
NetNet *net = 0;
|
||||
const NetExpr *par;
|
||||
NetEvent *eve;
|
||||
const NetExpr *ex1, *ex2;
|
||||
|
|
@ -1103,13 +1106,54 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
|
|||
symbol_search(this, des, scope, use_path,
|
||||
net, par, eve, ex1, ex2);
|
||||
|
||||
const netdarray_t*use_darray = 0;
|
||||
|
||||
if (net != 0)
|
||||
use_darray = net->darray_type();
|
||||
|
||||
// Net is not found, but maybe it is a member of a
|
||||
// struct or class. Try to locate net without the member
|
||||
// name and test if it is a type that has members.
|
||||
if (net == 0 && use_path.size() >= 2) {
|
||||
pform_name_t tmp_path = use_path;
|
||||
member_name = peek_tail_name(tmp_path);
|
||||
tmp_path.pop_back();
|
||||
|
||||
net = 0;
|
||||
symbol_search(this, des, scope, tmp_path,
|
||||
net, par, eve, ex1, ex2);
|
||||
if (net && net->class_type()) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PECallFunction::test_width_method_: "
|
||||
<< "Found net=" << tmp_path
|
||||
<< ", member_name=" << member_name
|
||||
<< ", method_name=" << method_name
|
||||
<< endl;
|
||||
}
|
||||
|
||||
netclass_t* class_type = net->class_type();
|
||||
member_type = class_type->get_property(member_name);
|
||||
use_path = tmp_path;
|
||||
|
||||
use_darray = dynamic_cast<const netdarray_t*> (member_type);
|
||||
|
||||
} else {
|
||||
member_name = perm_string();
|
||||
net = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// After all, no sign of a net match. Give up.
|
||||
if (net == 0)
|
||||
return 0;
|
||||
|
||||
netdarray_t*darray = net->darray_type();
|
||||
|
||||
// function int size()
|
||||
if (darray && method_name == "size") {
|
||||
if (use_darray && method_name == "size") {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PECallFunction::test_width_method_: "
|
||||
<< "Match darray size() method." << endl;
|
||||
}
|
||||
|
||||
expr_type_ = IVL_VT_BOOL;
|
||||
expr_width_ = 32;
|
||||
min_width_ = expr_width_;
|
||||
|
|
@ -1866,7 +1910,7 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
|||
perm_string method_name = peek_tail_name(use_path);
|
||||
use_path.pop_back();
|
||||
|
||||
NetNet *net;
|
||||
NetNet *net = 0;
|
||||
const NetExpr *par;
|
||||
NetEvent *eve;
|
||||
const NetExpr *ex1, *ex2;
|
||||
|
|
@ -2570,9 +2614,37 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
net, par, eve,
|
||||
ex1, ex2);
|
||||
|
||||
if (net == 0 && gn_system_verilog() && path_.size() >= 2) {
|
||||
pform_name_t use_path = path_;
|
||||
name_component_t member_comp = use_path.back();
|
||||
use_path.pop_back();
|
||||
|
||||
ivl_assert(*this, net == 0);
|
||||
symbol_search(this, des, scope, use_path, net, par, eve, ex1, ex2);
|
||||
|
||||
if (net == 0) {
|
||||
// Nope, no struct/class with member.
|
||||
|
||||
} else if (net->struct_type() != 0) {
|
||||
return check_for_struct_members(this, des, scope,
|
||||
net, use_path.back().index,
|
||||
member_comp);
|
||||
|
||||
} else if (net->class_type()!=0) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
|
||||
<< "Ident " << use_path
|
||||
<< " look for property " << member_comp << endl;
|
||||
}
|
||||
|
||||
return check_for_class_property(this, des, scope,
|
||||
net, member_comp);
|
||||
}
|
||||
}
|
||||
|
||||
if (net == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Expecting idents wtih ntype to be signals." << endl;
|
||||
<< "Expecting idents with ntype to be signals." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -4192,6 +4264,27 @@ unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode)
|
|||
return expr_width_;
|
||||
}
|
||||
|
||||
NetEConst* PENumber::elaborate_expr(Design*des, NetScope*, ivl_type_t ntype, unsigned) const
|
||||
{
|
||||
const netvector_t*use_type = dynamic_cast<const netvector_t*> (ntype);
|
||||
if (use_type == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "I don't know how cast numbers to this type."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
verinum use_val = value();
|
||||
use_val .has_sign( use_type->get_signed() );
|
||||
use_val = cast_to_width(use_val, use_type->packed_width());
|
||||
|
||||
NetEConst*tmp = new NetEConst(use_val);
|
||||
tmp->set_line(*this);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEConst* PENumber::elaborate_expr(Design*, NetScope*,
|
||||
unsigned expr_wid, unsigned) const
|
||||
{
|
||||
|
|
|
|||
15
elab_lval.cc
15
elab_lval.cc
|
|
@ -25,6 +25,7 @@
|
|||
# include "netmisc.h"
|
||||
# include "netstruct.h"
|
||||
# include "netclass.h"
|
||||
# include "netdarray.h"
|
||||
# include "compiler.h"
|
||||
# include <cstdlib>
|
||||
# include <iostream>
|
||||
|
|
@ -716,7 +717,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*,
|
||||
bool PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope,
|
||||
NetAssign_*lv,
|
||||
const perm_string&method_name) const
|
||||
{
|
||||
|
|
@ -740,6 +741,18 @@ bool PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*,
|
|||
}
|
||||
|
||||
lv->set_property(method_name);
|
||||
|
||||
const netdarray_t*mtype = dynamic_cast<const netdarray_t*> (ptype);
|
||||
if (mtype) {
|
||||
const name_component_t&name_tail = path_.back();
|
||||
if (name_tail.index.size() > 0) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "Array index of array properties not supported."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -865,7 +865,7 @@ static bool evaluate_ranges(Design*des, NetScope*scope,
|
|||
return bad_msb | bad_lsb;
|
||||
}
|
||||
|
||||
static netclass_t* locate_class_type(Design*des, NetScope*scope,
|
||||
static netclass_t* locate_class_type(Design*, NetScope*scope,
|
||||
class_type_t*class_type)
|
||||
{
|
||||
netclass_t*use_class = scope->find_class(class_type->name);
|
||||
|
|
@ -928,7 +928,7 @@ static netparray_t* elaborate_parray_type(Design*des, NetScope*scope,
|
|||
{
|
||||
|
||||
vector<netrange_t>packed_dimensions;
|
||||
bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->packed_dims);
|
||||
bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->dims);
|
||||
ivl_assert(*data_type, !bad_range);
|
||||
|
||||
ivl_type_s*element_type = elaborate_type(des, scope, data_type->base_type);
|
||||
|
|
|
|||
13
elab_type.cc
13
elab_type.cc
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
# include "pform_types.h"
|
||||
# include "netlist.h"
|
||||
# include "netdarray.h"
|
||||
# include "netscalar.h"
|
||||
# include "netvector.h"
|
||||
# include <typeinfo>
|
||||
|
|
@ -85,3 +86,15 @@ ivl_type_s* string_type_t::elaborate_type(Design*, NetScope*) const
|
|||
{
|
||||
return &netstring_t::type_string;
|
||||
}
|
||||
|
||||
ivl_type_s* uarray_type_t::elaborate_type(Design*des, NetScope*scope) const
|
||||
{
|
||||
|
||||
ivl_type_t btype = base_type->elaborate_type(des, scope);
|
||||
|
||||
assert(dims->size() == 1);
|
||||
list<pform_range_t>::const_iterator cur = dims->begin();
|
||||
assert(cur->first == 0 && cur->second==0);
|
||||
ivl_type_s*res = new netdarray_t(btype);
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
24
elaborate.cc
24
elaborate.cc
|
|
@ -2381,6 +2381,14 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
|||
NetExpr*rv;
|
||||
const ivl_type_s*lv_net_type = lv->net_type();
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PAssign::elaborate: ";
|
||||
if (lv_net_type)
|
||||
cerr << "lv_net_type=" << *lv_net_type << endl;
|
||||
else
|
||||
cerr << "lv_net_type=<nil>" << endl;
|
||||
}
|
||||
|
||||
/* If the l-value is a compound type of some sort, then use
|
||||
the newer net_type form of the elaborate_rval_ method to
|
||||
handle the new types. */
|
||||
|
|
@ -2388,9 +2396,21 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
|||
ivl_assert(*this, lv->more==0);
|
||||
rv = elaborate_rval_(des, scope, lv_net_type);
|
||||
|
||||
} else if (dynamic_cast<const netdarray_t*> (lv_net_type)) {
|
||||
} else if (const netdarray_t*dtype = dynamic_cast<const netdarray_t*> (lv_net_type)) {
|
||||
ivl_assert(*this, lv->more==0);
|
||||
rv = elaborate_rval_(des, scope, lv_net_type);
|
||||
if (debug_elaborate) {
|
||||
if (lv->word())
|
||||
cerr << get_fileline() << ": PAssign::elaborate: "
|
||||
<< "lv->word() = " << *lv->word() << endl;
|
||||
else
|
||||
cerr << get_fileline() << ": PAssign::elaborate: "
|
||||
<< "lv->word() = <nil>" << endl;
|
||||
}
|
||||
ivl_type_t use_lv_type = lv_net_type;
|
||||
if (lv->word())
|
||||
use_lv_type = dtype->element_type();
|
||||
|
||||
rv = elaborate_rval_(des, scope, use_lv_type);
|
||||
|
||||
} else {
|
||||
/* Elaborate the r-value expression, then try to evaluate it. */
|
||||
|
|
|
|||
|
|
@ -154,6 +154,13 @@ void parray_type_t::pform_dump(ostream&out, unsigned indent) const
|
|||
base_type->pform_dump(out, indent+4);
|
||||
}
|
||||
|
||||
void uarray_type_t::pform_dump(ostream&out, unsigned indent) const
|
||||
{
|
||||
out << setw(indent) << "" << "Unpacked array " << "[...]"
|
||||
<< " of:" << endl;
|
||||
base_type->pform_dump(out, indent+4);
|
||||
}
|
||||
|
||||
void struct_type_t::pform_dump(ostream&out, unsigned indent) const
|
||||
{
|
||||
out << setw(indent) << "" << "Struct " << (packed_flag?"packed":"unpacked")
|
||||
|
|
|
|||
|
|
@ -57,7 +57,18 @@ void pform_class_property(const struct vlltype&loc,
|
|||
; cur != decls->end() ; ++cur) {
|
||||
|
||||
decl_assignment_t*curp = *cur;
|
||||
pform_cur_class->type->properties[curp->name] = data_type;
|
||||
data_type_t*use_type = data_type;
|
||||
|
||||
if (curp->index.size() > 0) {
|
||||
list<pform_range_t>*pd = new list<pform_range_t> (curp->index);
|
||||
use_type = new uarray_type_t(use_type, pd);
|
||||
}
|
||||
|
||||
if (curp->expr.get()) {
|
||||
VLerror(loc, "sorry: Initialization expressions for properties not implemented.");
|
||||
}
|
||||
|
||||
pform_cur_class->type->properties[curp->name] = use_type;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -154,20 +154,39 @@ struct vector_type_t : public data_type_t {
|
|||
std::auto_ptr< list<pform_range_t> > pdims;
|
||||
};
|
||||
|
||||
struct array_base_t : public data_type_t {
|
||||
public:
|
||||
inline explicit array_base_t(data_type_t*btype, std::list<pform_range_t>*pd)
|
||||
: base_type(btype), dims(pd) { }
|
||||
|
||||
data_type_t*base_type;
|
||||
std::auto_ptr< list<pform_range_t> > dims;
|
||||
};
|
||||
|
||||
/*
|
||||
* The array_type_t is a generalization of the vector_type_t in that
|
||||
* The parray_type_t is a generalization of the vector_type_t in that
|
||||
* the base type is another general data type. Ultimately, the subtype
|
||||
* must also be packed (as this is a packed array) but that may be
|
||||
* worked out during elaboration.
|
||||
*/
|
||||
struct parray_type_t : public data_type_t {
|
||||
struct parray_type_t : public array_base_t {
|
||||
inline explicit parray_type_t(data_type_t*btype, std::list<pform_range_t>*pd)
|
||||
: base_type(btype), packed_dims(pd) { }
|
||||
: array_base_t(btype, pd) { }
|
||||
|
||||
virtual ivl_variable_type_t figure_packed_base_type(void)const;
|
||||
virtual void pform_dump(std::ostream&out, unsigned indent) const;
|
||||
};
|
||||
|
||||
data_type_t*base_type;
|
||||
std::auto_ptr< list<pform_range_t> > packed_dims;
|
||||
/*
|
||||
* The uarray_type_t represents unpacked array types.
|
||||
*/
|
||||
struct uarray_type_t : public array_base_t {
|
||||
inline explicit uarray_type_t(data_type_t*btype, std::list<pform_range_t>*pd)
|
||||
: array_base_t(btype, pd) { }
|
||||
|
||||
public:
|
||||
virtual void pform_dump(std::ostream&out, unsigned indent) const;
|
||||
virtual ivl_type_s* elaborate_type(Design*des, NetScope*scope) const;
|
||||
};
|
||||
|
||||
struct real_type_t : public data_type_t {
|
||||
|
|
|
|||
|
|
@ -61,9 +61,13 @@ static void show_prop_type(ivl_type_t ptype)
|
|||
case IVL_VT_LOGIC:
|
||||
show_prop_type_vector(ptype);
|
||||
break;
|
||||
case IVL_VT_DARRAY:
|
||||
case IVL_VT_CLASS:
|
||||
fprintf(vvp_out, "\"o\"");
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
fprintf(vvp_out, "\"<ERROR-no-type>\"");
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,6 +80,16 @@ static int eval_object_null(ivl_expr_t ex)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int eval_object_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/obj %u;\n", pidx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eval_object_signal(ivl_expr_t ex)
|
||||
{
|
||||
ivl_signal_t sig = ivl_expr_signal(ex);
|
||||
|
|
@ -106,6 +116,9 @@ int draw_eval_object(ivl_expr_t ex)
|
|||
case IVL_EX_NULL:
|
||||
return eval_object_null(ex);
|
||||
|
||||
case IVL_EX_PROPERTY:
|
||||
return eval_object_property(ex);
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
return eval_object_signal(ex);
|
||||
|
||||
|
|
|
|||
|
|
@ -871,7 +871,7 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
|||
|
||||
} else if (ivl_type_base(prop_type) == IVL_VT_STRING) {
|
||||
|
||||
/* Calculate the real value into the real value
|
||||
/* Calculate the string value into the string value
|
||||
stack. The %store/prop/r will pop the stack
|
||||
value. */
|
||||
draw_eval_string(rval);
|
||||
|
|
@ -879,7 +879,19 @@ static int show_stmt_assign_sig_cobject(ivl_statement_t net)
|
|||
fprintf(vvp_out, " %%store/prop/str %d;\n", prop_idx);
|
||||
fprintf(vvp_out, " %%pop/obj 1;\n");
|
||||
|
||||
} else if (ivl_type_base(prop_type) == IVL_VT_DARRAY) {
|
||||
|
||||
/* The property is a darray, and there is no mux
|
||||
expression to the assignment is of an entire
|
||||
array object. */
|
||||
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
|
||||
draw_eval_object(rval);
|
||||
fprintf(vvp_out, " %%store/prop/obj %d;\n", prop_idx);
|
||||
fprintf(vvp_out, " %%pop/obj 1;\n");
|
||||
|
||||
} else {
|
||||
fprintf(vvp_out, " ; ERROR: ivl_type_base(prop_type) = %d\n",
|
||||
ivl_type_base(prop_type));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ class class_property_t {
|
|||
virtual void set_string(char*buf, const std::string&val);
|
||||
virtual string get_string(char*buf);
|
||||
|
||||
virtual void set_object(char*buf, const vvp_object_t&val);
|
||||
virtual void get_object(char*buf, vvp_object_t&val);
|
||||
|
||||
protected:
|
||||
size_t offset_;
|
||||
};
|
||||
|
|
@ -104,6 +107,16 @@ string class_property_t::get_string(char*)
|
|||
return "";
|
||||
}
|
||||
|
||||
void class_property_t::set_object(char*, const vvp_object_t&)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void class_property_t::get_object(char*, vvp_object_t&)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
template <class T> class property_atom : public class_property_t {
|
||||
|
|
@ -160,6 +173,26 @@ class property_string : public class_property_t {
|
|||
string get_string(char*buf);
|
||||
};
|
||||
|
||||
class property_object : public class_property_t {
|
||||
public:
|
||||
inline explicit property_object(void) { }
|
||||
~property_object() { }
|
||||
|
||||
size_t instance_size() const { return sizeof(vvp_object_t); }
|
||||
|
||||
public:
|
||||
void construct(char*buf) const
|
||||
{ /* vvp_object_t*tmp = */ new (buf+offset_) vvp_object_t; }
|
||||
|
||||
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 get_object(char*buf, vvp_object_t&);
|
||||
};
|
||||
|
||||
template <class T> void property_atom<T>::set_vec4(char*buf, const vvp_vector4_t&val)
|
||||
{
|
||||
T*tmp = reinterpret_cast<T*> (buf+offset_);
|
||||
|
|
@ -204,6 +237,19 @@ string property_string::get_string(char*buf)
|
|||
return *tmp;
|
||||
}
|
||||
|
||||
void property_object::set_object(char*buf, const vvp_object_t&val)
|
||||
{
|
||||
vvp_object_t*tmp = reinterpret_cast<vvp_object_t*>(buf+offset_);
|
||||
*tmp = val;
|
||||
}
|
||||
|
||||
void property_object::get_object(char*buf, vvp_object_t&val)
|
||||
{
|
||||
vvp_object_t*tmp = reinterpret_cast<vvp_object_t*>(buf+offset_);
|
||||
val = *tmp;
|
||||
}
|
||||
|
||||
|
||||
/* **** */
|
||||
|
||||
class_type::class_type(const string&nam, size_t nprop)
|
||||
|
|
@ -237,6 +283,8 @@ void class_type::set_property(size_t idx, const string&name, const string&type)
|
|||
properties_[idx].type = new property_real<double>;
|
||||
else if (type == "S")
|
||||
properties_[idx].type = new property_string;
|
||||
else if (type == "o")
|
||||
properties_[idx].type = new property_object;
|
||||
else
|
||||
properties_[idx].type = 0;
|
||||
}
|
||||
|
|
@ -338,6 +386,21 @@ string class_type::get_string(class_type::inst_t obj, size_t pid) const
|
|||
return properties_[pid].type->get_string(buf);
|
||||
}
|
||||
|
||||
void class_type::set_object(class_type::inst_t obj, size_t pid,
|
||||
const vvp_object_t&val) const
|
||||
{
|
||||
char*buf = reinterpret_cast<char*> (obj);
|
||||
assert(pid < properties_.size());
|
||||
properties_[pid].type->set_object(buf, val);
|
||||
}
|
||||
|
||||
void class_type::get_object(class_type::inst_t obj, size_t pid, vvp_object_t&val) const
|
||||
{
|
||||
char*buf = reinterpret_cast<char*> (obj);
|
||||
assert(pid < properties_.size());
|
||||
properties_[pid].type->get_object(buf, val);
|
||||
}
|
||||
|
||||
int class_type::get_type_code(void) const
|
||||
{
|
||||
return vpiClassDefn;
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@ class class_type : public __vpiHandle {
|
|||
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;
|
||||
void set_object(inst_t inst, size_t pid, const vvp_object_t&val) const;
|
||||
void get_object(inst_t inst, size_t pid, vvp_object_t&val) const;
|
||||
|
||||
public: // VPI related methods
|
||||
int get_type_code(void) const;
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ extern bool of_POP_STR(vthread_t thr, vvp_code_t code);
|
|||
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_OBJ(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);
|
||||
|
|
@ -186,6 +187,7 @@ extern bool of_SHIFTR_S_I0(vthread_t thr, vvp_code_t code);
|
|||
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_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);
|
||||
|
|
|
|||
|
|
@ -213,6 +213,7 @@ 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/obj",of_PROP_OBJ,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/v", of_PROP_V, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
|
|
@ -233,6 +234,7 @@ 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/obj",of_STORE_PROP_OBJ,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/v", of_STORE_PROP_V, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
|
|
|
|||
|
|
@ -889,12 +889,13 @@ This opcode raises the left operand by the right operand, and pushes
|
|||
the result.
|
||||
|
||||
* %prop/v <pid>, <base>, <wid>
|
||||
* %prop/obj <pid>
|
||||
* %prop/r <pid>
|
||||
* %prop/str <pid>
|
||||
|
||||
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.
|
||||
stack.
|
||||
|
||||
The class object stack is NOT popped.
|
||||
|
||||
|
|
@ -1016,6 +1017,7 @@ variable given by the label.
|
|||
|
||||
See also %load/obj.
|
||||
|
||||
* %store/prop/obj <index>
|
||||
* %store/prop/r <index>
|
||||
* %store/prop/str <index>
|
||||
* %store/prop/v <index>, <bit>, <wid>
|
||||
|
|
@ -1024,6 +1026,10 @@ 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
|
||||
object stack. The cobject is NOT popped.
|
||||
|
||||
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
|
||||
top of the object stack. The cobject is NOT popped.
|
||||
|
||||
* %store/real <var-label>
|
||||
* %store/reala <var-label>, <index>
|
||||
|
||||
|
|
|
|||
|
|
@ -3226,6 +3226,7 @@ bool of_LOAD_DAR(vthread_t thr, vvp_code_t cp)
|
|||
darray->get_word(adr, word);
|
||||
assert(word.size() == wid);
|
||||
|
||||
thr_check_addr(thr, bit+word.size());
|
||||
thr->bits4.set_vec(bit, word);
|
||||
|
||||
return true;
|
||||
|
|
@ -4533,6 +4534,26 @@ bool of_POW_WR(vthread_t thr, vvp_code_t)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* %prop/obj <pid>
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
unsigned pid = cp->number;
|
||||
|
||||
vvp_object_t&obj = thr->peek_object();
|
||||
vvp_cobject*cobj = obj.peek<vvp_cobject>();
|
||||
|
||||
vvp_object_t val;
|
||||
cobj->get_object(pid, val);
|
||||
|
||||
thr->push_object(val);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* %prop/r <pid>
|
||||
*
|
||||
|
|
@ -5112,6 +5133,28 @@ bool of_STORE_OBJ(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* %store/prop/obj <id>
|
||||
*
|
||||
* 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
|
||||
* pop the object stack.
|
||||
*/
|
||||
bool of_STORE_PROP_OBJ(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
size_t pid = cp->number;
|
||||
vvp_object_t val;
|
||||
thr->pop_object(val);
|
||||
|
||||
vvp_object_t&obj = thr->peek_object();
|
||||
vvp_cobject*cobj = obj.peek<vvp_cobject>();
|
||||
assert(cobj);
|
||||
|
||||
cobj->set_object(pid, val);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* %store/prop/r <id>
|
||||
*
|
||||
|
|
|
|||
|
|
@ -64,3 +64,13 @@ string vvp_cobject::get_string(size_t pid)
|
|||
{
|
||||
return defn_->get_string(properties_, pid);
|
||||
}
|
||||
|
||||
void vvp_cobject::set_object(size_t pid, const vvp_object_t&val)
|
||||
{
|
||||
defn_->set_object(properties_, pid, val);
|
||||
}
|
||||
|
||||
void vvp_cobject::get_object(size_t pid, vvp_object_t&val)
|
||||
{
|
||||
return defn_->get_object(properties_, pid, val);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,9 @@ class vvp_cobject : public vvp_object {
|
|||
void set_string(size_t pid, const std::string&val);
|
||||
std::string get_string(size_t pid);
|
||||
|
||||
void set_object(size_t pid, const vvp_object_t&val);
|
||||
void get_object(size_t pid, vvp_object_t&val);
|
||||
|
||||
private:
|
||||
const class_type* defn_;
|
||||
// For now, only support 32bit bool signed properties.
|
||||
|
|
|
|||
Loading…
Reference in New Issue