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,
|
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||||
width_mode_t&mode);
|
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*,
|
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||||
unsigned expr_wid, unsigned) const;
|
unsigned expr_wid, unsigned) const;
|
||||||
virtual NetAssign_* elaborate_lval(Design*des,
|
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;
|
<< " elaborate (ivl_type_t) this expression. " << endl;
|
||||||
cerr << get_fileline() << ": : Expression is: " << *this
|
cerr << get_fileline() << ": : Expression is: " << *this
|
||||||
<< endl;
|
<< endl;
|
||||||
|
cerr << get_fileline() << ": : Expression type: " << typeid(*this).name() << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1091,11 +1092,13 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
|
||||||
if (path_.size() < 2)
|
if (path_.size() < 2)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
perm_string member_name;
|
||||||
|
ivl_type_t member_type = 0;
|
||||||
pform_name_t use_path = path_;
|
pform_name_t use_path = path_;
|
||||||
perm_string method_name = peek_tail_name(use_path);
|
perm_string method_name = peek_tail_name(use_path);
|
||||||
use_path.pop_back();
|
use_path.pop_back();
|
||||||
|
|
||||||
NetNet *net;
|
NetNet *net = 0;
|
||||||
const NetExpr *par;
|
const NetExpr *par;
|
||||||
NetEvent *eve;
|
NetEvent *eve;
|
||||||
const NetExpr *ex1, *ex2;
|
const NetExpr *ex1, *ex2;
|
||||||
|
|
@ -1103,13 +1106,54 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
|
||||||
symbol_search(this, des, scope, use_path,
|
symbol_search(this, des, scope, use_path,
|
||||||
net, par, eve, ex1, ex2);
|
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)
|
if (net == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
netdarray_t*darray = net->darray_type();
|
|
||||||
|
|
||||||
// function int size()
|
// 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_type_ = IVL_VT_BOOL;
|
||||||
expr_width_ = 32;
|
expr_width_ = 32;
|
||||||
min_width_ = expr_width_;
|
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);
|
perm_string method_name = peek_tail_name(use_path);
|
||||||
use_path.pop_back();
|
use_path.pop_back();
|
||||||
|
|
||||||
NetNet *net;
|
NetNet *net = 0;
|
||||||
const NetExpr *par;
|
const NetExpr *par;
|
||||||
NetEvent *eve;
|
NetEvent *eve;
|
||||||
const NetExpr *ex1, *ex2;
|
const NetExpr *ex1, *ex2;
|
||||||
|
|
@ -2570,9 +2614,37 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
net, par, eve,
|
net, par, eve,
|
||||||
ex1, ex2);
|
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) {
|
if (net == 0) {
|
||||||
cerr << get_fileline() << ": internal error: "
|
cerr << get_fileline() << ": internal error: "
|
||||||
<< "Expecting idents wtih ntype to be signals." << endl;
|
<< "Expecting idents with ntype to be signals." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -4192,6 +4264,27 @@ unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode)
|
||||||
return expr_width_;
|
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*,
|
NetEConst* PENumber::elaborate_expr(Design*, NetScope*,
|
||||||
unsigned expr_wid, unsigned) const
|
unsigned expr_wid, unsigned) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
15
elab_lval.cc
15
elab_lval.cc
|
|
@ -25,6 +25,7 @@
|
||||||
# include "netmisc.h"
|
# include "netmisc.h"
|
||||||
# include "netstruct.h"
|
# include "netstruct.h"
|
||||||
# include "netclass.h"
|
# include "netclass.h"
|
||||||
|
# include "netdarray.h"
|
||||||
# include "compiler.h"
|
# include "compiler.h"
|
||||||
# include <cstdlib>
|
# include <cstdlib>
|
||||||
# include <iostream>
|
# include <iostream>
|
||||||
|
|
@ -716,7 +717,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
||||||
return true;
|
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,
|
NetAssign_*lv,
|
||||||
const perm_string&method_name) const
|
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);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -865,7 +865,7 @@ static bool evaluate_ranges(Design*des, NetScope*scope,
|
||||||
return bad_msb | bad_lsb;
|
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)
|
class_type_t*class_type)
|
||||||
{
|
{
|
||||||
netclass_t*use_class = scope->find_class(class_type->name);
|
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;
|
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_assert(*data_type, !bad_range);
|
||||||
|
|
||||||
ivl_type_s*element_type = elaborate_type(des, scope, data_type->base_type);
|
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 "pform_types.h"
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
|
# include "netdarray.h"
|
||||||
# include "netscalar.h"
|
# include "netscalar.h"
|
||||||
# include "netvector.h"
|
# include "netvector.h"
|
||||||
# include <typeinfo>
|
# include <typeinfo>
|
||||||
|
|
@ -85,3 +86,15 @@ ivl_type_s* string_type_t::elaborate_type(Design*, NetScope*) const
|
||||||
{
|
{
|
||||||
return &netstring_t::type_string;
|
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;
|
NetExpr*rv;
|
||||||
const ivl_type_s*lv_net_type = lv->net_type();
|
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
|
/* If the l-value is a compound type of some sort, then use
|
||||||
the newer net_type form of the elaborate_rval_ method to
|
the newer net_type form of the elaborate_rval_ method to
|
||||||
handle the new types. */
|
handle the new types. */
|
||||||
|
|
@ -2388,9 +2396,21 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
||||||
ivl_assert(*this, lv->more==0);
|
ivl_assert(*this, lv->more==0);
|
||||||
rv = elaborate_rval_(des, scope, lv_net_type);
|
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);
|
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 {
|
} else {
|
||||||
/* Elaborate the r-value expression, then try to evaluate it. */
|
/* 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);
|
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
|
void struct_type_t::pform_dump(ostream&out, unsigned indent) const
|
||||||
{
|
{
|
||||||
out << setw(indent) << "" << "Struct " << (packed_flag?"packed":"unpacked")
|
out << setw(indent) << "" << "Struct " << (packed_flag?"packed":"unpacked")
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,18 @@ void pform_class_property(const struct vlltype&loc,
|
||||||
; cur != decls->end() ; ++cur) {
|
; cur != decls->end() ; ++cur) {
|
||||||
|
|
||||||
decl_assignment_t*curp = *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;
|
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
|
* 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
|
* must also be packed (as this is a packed array) but that may be
|
||||||
* worked out during elaboration.
|
* 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)
|
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 ivl_variable_type_t figure_packed_base_type(void)const;
|
||||||
virtual void pform_dump(std::ostream&out, unsigned indent) 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 {
|
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:
|
case IVL_VT_LOGIC:
|
||||||
show_prop_type_vector(ptype);
|
show_prop_type_vector(ptype);
|
||||||
break;
|
break;
|
||||||
|
case IVL_VT_DARRAY:
|
||||||
|
case IVL_VT_CLASS:
|
||||||
|
fprintf(vvp_out, "\"o\"");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
|
||||||
fprintf(vvp_out, "\"<ERROR-no-type>\"");
|
fprintf(vvp_out, "\"<ERROR-no-type>\"");
|
||||||
|
assert(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,16 @@ static int eval_object_null(ivl_expr_t ex)
|
||||||
return 0;
|
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)
|
static int eval_object_signal(ivl_expr_t ex)
|
||||||
{
|
{
|
||||||
ivl_signal_t sig = ivl_expr_signal(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:
|
case IVL_EX_NULL:
|
||||||
return eval_object_null(ex);
|
return eval_object_null(ex);
|
||||||
|
|
||||||
|
case IVL_EX_PROPERTY:
|
||||||
|
return eval_object_property(ex);
|
||||||
|
|
||||||
case IVL_EX_SIGNAL:
|
case IVL_EX_SIGNAL:
|
||||||
return eval_object_signal(ex);
|
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) {
|
} 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
|
stack. The %store/prop/r will pop the stack
|
||||||
value. */
|
value. */
|
||||||
draw_eval_string(rval);
|
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, " %%store/prop/str %d;\n", prop_idx);
|
||||||
fprintf(vvp_out, " %%pop/obj 1;\n");
|
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 {
|
} else {
|
||||||
|
fprintf(vvp_out, " ; ERROR: ivl_type_base(prop_type) = %d\n",
|
||||||
|
ivl_type_base(prop_type));
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,9 @@ 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 get_object(char*buf, vvp_object_t&val);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t offset_;
|
size_t offset_;
|
||||||
};
|
};
|
||||||
|
|
@ -104,6 +107,16 @@ string class_property_t::get_string(char*)
|
||||||
return "";
|
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 {
|
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);
|
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)
|
template <class T> void property_atom<T>::set_vec4(char*buf, const vvp_vector4_t&val)
|
||||||
{
|
{
|
||||||
T*tmp = reinterpret_cast<T*> (buf+offset_);
|
T*tmp = reinterpret_cast<T*> (buf+offset_);
|
||||||
|
|
@ -204,6 +237,19 @@ string property_string::get_string(char*buf)
|
||||||
return *tmp;
|
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)
|
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>;
|
properties_[idx].type = new property_real<double>;
|
||||||
else if (type == "S")
|
else if (type == "S")
|
||||||
properties_[idx].type = new property_string;
|
properties_[idx].type = new property_string;
|
||||||
|
else if (type == "o")
|
||||||
|
properties_[idx].type = new property_object;
|
||||||
else
|
else
|
||||||
properties_[idx].type = 0;
|
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);
|
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
|
int class_type::get_type_code(void) const
|
||||||
{
|
{
|
||||||
return vpiClassDefn;
|
return vpiClassDefn;
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,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 get_object(inst_t inst, size_t pid, vvp_object_t&val) const;
|
||||||
|
|
||||||
public: // VPI related methods
|
public: // VPI related methods
|
||||||
int get_type_code(void) const;
|
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(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_POW_S(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_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_R(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_PROP_STR(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_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_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_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_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_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_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_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", 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/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} },
|
||||||
|
|
@ -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/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/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/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/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} },
|
||||||
|
|
|
||||||
|
|
@ -889,12 +889,13 @@ 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/r <pid>
|
* %prop/r <pid>
|
||||||
* %prop/str <pid>
|
* %prop/str <pid>
|
||||||
|
|
||||||
Write the vector (/v) or real value (/r) or string (/str) into
|
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
|
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.
|
The class object stack is NOT popped.
|
||||||
|
|
||||||
|
|
@ -1016,6 +1017,7 @@ variable given by the label.
|
||||||
|
|
||||||
See also %load/obj.
|
See also %load/obj.
|
||||||
|
|
||||||
|
* %store/prop/obj <index>
|
||||||
* %store/prop/r <index>
|
* %store/prop/r <index>
|
||||||
* %store/prop/str <index>
|
* %store/prop/str <index>
|
||||||
* %store/prop/v <index>, <bit>, <wid>
|
* %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
|
into the the property number <index> 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,
|
||||||
|
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/real <var-label>
|
||||||
* %store/reala <var-label>, <index>
|
* %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);
|
darray->get_word(adr, word);
|
||||||
assert(word.size() == wid);
|
assert(word.size() == wid);
|
||||||
|
|
||||||
|
thr_check_addr(thr, bit+word.size());
|
||||||
thr->bits4.set_vec(bit, word);
|
thr->bits4.set_vec(bit, word);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -4533,6 +4534,26 @@ bool of_POW_WR(vthread_t thr, vvp_code_t)
|
||||||
return true;
|
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>
|
* %prop/r <pid>
|
||||||
*
|
*
|
||||||
|
|
@ -5112,6 +5133,28 @@ bool of_STORE_OBJ(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
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>
|
* %store/prop/r <id>
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -64,3 +64,13 @@ 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)
|
||||||
|
{
|
||||||
|
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);
|
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 get_object(size_t pid, vvp_object_t&val);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const class_type* defn_;
|
const class_type* defn_;
|
||||||
// For now, only support 32bit bool signed properties.
|
// For now, only support 32bit bool signed properties.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue