Flesh out class type elaboration

Add properties to the classes, and elaborate expressions that
have class properties. Describe class object property references
all the way down to the stub target.
This commit is contained in:
Stephen Williams 2012-11-25 10:13:05 -08:00
parent f7033ca19a
commit 318a4033b8
28 changed files with 451 additions and 19 deletions

View File

@ -104,7 +104,8 @@ FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o
O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
elab_expr.o elaborate_analog.o elab_lval.o elab_net.o \
elab_scope.o elab_sig.o elab_sig_analog.o emit.o eval.o eval_attrib.o \
elab_scope.o elab_sig.o elab_sig_analog.o elab_type.o \
emit.o eval.o eval_attrib.o \
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \
net_design.o netclass.o netdarray.o \

View File

@ -373,6 +373,9 @@ class PEIdent : public PExpr {
bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
bool elaborate_lval_net_idx_(Design*, NetScope*, NetAssign_*,
index_component_t::ctype_t) const;
bool elaborate_lval_net_class_member_(Design*, NetScope*,
NetAssign_*,
const perm_string&) const;
bool elaborate_lval_net_packed_member_(Design*, NetScope*,
NetAssign_*,
const perm_string&) const;

View File

@ -857,6 +857,9 @@ void NetAssign_::dump_lval(ostream&o) const
{
if (sig_) {
o << sig_->name();
if (! member_.nil()) {
o << "." << member_;
}
if (word_) {
o << "[word=" << *word_ << "]";
}
@ -1519,6 +1522,11 @@ void NetENull::dump(ostream&o) const
o << "<null>";
}
void NetEProperty::dump(ostream&o) const
{
o << net_->name() << "." << pname_;
}
void NetEScope::dump(ostream&o) const
{
o << "<scope=" << scope_path(scope_) << ">";

View File

@ -189,6 +189,12 @@ NetENull* NetENull::dup_expr() const
return 0;
}
NetEProperty* NetEProperty::dup_expr() const
{
ivl_assert(*this, 0);
return 0;
}
NetEScope* NetEScope::dup_expr() const
{
ivl_assert(*this, 0);

View File

@ -26,6 +26,7 @@
# include "pform.h"
# include "netlist.h"
# include "netclass.h"
# include "netenum.h"
# include "netvector.h"
# include "discipline.h"
@ -1673,6 +1674,28 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
return sel;
}
static NetExpr* check_for_class_property(const LineInfo*li,
Design*des, NetScope*scope,
NetNet*net,
const name_component_t&comp)
{
netclass_t*class_type = net->class_type();
const ivl_type_s*ptype = class_type->get_property(comp.name);
if (ptype == 0) {
cerr << li->get_fileline() << ": error: "
<< "Class " << class_type->get_name()
<< " has no property " << comp.name << "." << endl;
des->errors += 1;
return 0;
}
NetEProperty*tmp = new NetEProperty(net, comp.name);
tmp->set_line(*li);
return tmp;
}
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, unsigned flags) const
{
@ -2488,6 +2511,17 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
return expr_width_;
}
}
if (netclass_t*class_type = net->class_type()) {
const ivl_type_s*ptype = class_type->get_property(method_name);
if (ptype) {
expr_type_ = ptype->base_type();
expr_width_ = ptype->packed_width();
min_width_ = expr_width_;
signed_flag_ = ptype->get_signed();
return expr_width_;
}
}
}
}
@ -2736,6 +2770,16 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
member_comp);
}
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);
}
}
}

View File

@ -24,6 +24,7 @@
# include "netlist.h"
# include "netmisc.h"
# include "netstruct.h"
# include "netclass.h"
# include "compiler.h"
# include <cstdlib>
# include <iostream>
@ -164,12 +165,17 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
the search with "a.b". */
if (reg == 0 && path_.size() >= 2) {
pform_name_t use_path = path_;
method_name = peek_tail_name(use_path);
perm_string tmp_name = peek_tail_name(use_path);
use_path.pop_back();
symbol_search(this, des, scope, use_path, reg, par, eve);
if (reg && reg->struct_type() == 0) {
method_name = perm_string();
if (reg && reg->struct_type()) {
method_name = tmp_name;
} else if (reg && reg->class_type()) {
method_name = tmp_name;
} else {
reg = 0;
}
}
@ -186,7 +192,8 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
ivl_assert(*this, reg);
// We are processing the tail of a string of names. For
// example, the verilog may be "a.b.c", so we are processing
// "c" at this point.
// "c" at this point. (Note that if method_name is not nil,
// then this is "a.b.c.method" and "a.b.c" is a struct or class.)
const name_component_t&name_tail = path_.back();
// Use the last index to determine what kind of select
@ -229,6 +236,16 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
return lv;
}
if (reg->class_type() && !method_name.nil() && gn_system_verilog()) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_class_member_(des, scope, lv, method_name);
return lv;
}
// Past this point, we should have taken care of the cases
// where the name is a member/method of a struct/class.
ivl_assert(*this, method_name.nil());
if (reg->unpacked_dimensions() > 0)
return elaborate_lval_net_word_(des, scope, reg);
@ -673,6 +690,34 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
return true;
}
bool PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*,
NetAssign_*lv,
const perm_string&method_name) const
{
if (debug_elaborate) {
cerr << get_fileline() << ": elaborate_lval_net_class_member_: "
<< "l-value is property " << method_name
<< " of " << lv->sig()->name() << "." << endl;
}
netclass_t*class_type = lv->sig()->class_type();
ivl_assert(*this, class_type);
/* Make sure the property is really present in the class. If
not, then generate an error message and return an error. */
const ivl_type_s*ptype = class_type->get_property(method_name);
if (ptype == 0) {
cerr << get_fileline() << ": error: Class " << class_type->get_name()
<< " does not have a property " << method_name << "." << endl;
des->errors += 1;
return false;
}
lv->set_property(method_name);
return true;
}
bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
NetAssign_*lv,
const perm_string&member_name) const

View File

@ -292,7 +292,15 @@ static void elaborate_scope_enumerations(Design*des, NetScope*scope,
static void elaborate_scope_class(Design*des, NetScope*scope,
PClass*pclass)
{
netclass_t*use_class = new netclass_t(pclass->type->name);
class_type_t*use_type = pclass->type;
netclass_t*use_class = new netclass_t(use_type->name);
for (map<perm_string, data_type_t*>::iterator cur = use_type->properties.begin()
; cur != use_type->properties.end() ; ++ cur) {
ivl_type_s*tmp = cur->second->elaborate_type(des, scope);
use_class->set_property(cur->first, tmp);
}
scope->add_class(use_class);
}

64
elab_type.cc Normal file
View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2012 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
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "pform_types.h"
# include "netlist.h"
# include "netvector.h"
# include <typeinfo>
# include "ivl_assert.h"
using namespace std;
ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*) const
{
cerr << get_fileline() << ": internal error: "
<< "Elaborate method not implemented for " << typeid(*this).name()
<< "." << endl;
des->errors += 1;
return 0;
}
ivl_type_s* atom2_type_t::elaborate_type(Design*des, NetScope*) const
{
switch (type_code) {
case 32:
if (signed_flag)
return &netvector_t::atom2s32;
else
return &netvector_t::atom2u32;
case 16:
if (signed_flag)
return &netvector_t::atom2s16;
else
return &netvector_t::atom2u16;
case 8:
if (signed_flag)
return &netvector_t::atom2s8;
else
return &netvector_t::atom2u8;
default:
cerr << get_fileline() << ": internal error: "
<< "atom2_type_t type_code=" << type_code << "." << endl;
des->errors += 1;
return 0;
}
}

View File

@ -561,6 +561,11 @@ void NetENull::expr_scan(struct expr_scan_t*tgt) const
tgt->expr_null(this);
}
void NetEProperty::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_property(this);
}
void NetEScope::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_scope(this);

View File

@ -227,6 +227,7 @@ typedef enum ivl_expr_type_e {
IVL_EX_NEW = 23,
IVL_EX_NULL = 22,
IVL_EX_NUMBER = 5,
IVL_EX_PROPERTY = 24,
IVL_EX_REALNUM = 16,
IVL_EX_SCOPE = 6,
IVL_EX_SELECT = 7,
@ -866,7 +867,7 @@ extern uint64_t ivl_expr_delay_val(ivl_expr_t net);
extern double ivl_expr_dvalue(ivl_expr_t net);
/* IVL_EX_ENUMTYPE */
extern ivl_enumtype_t ivl_expr_enumtype(ivl_expr_t net);
/* IVL_EX_SIGNAL, IVL_EX_SFUNC, IVL_EX_VARIABLE */
/* IVL_EX_PROPERTY IVL_EX_SIGNAL IVL_EX_SFUNC IVL_EX_VARIABLE */
extern const char* ivl_expr_name(ivl_expr_t net);
/* IVL_EX_BACCESS */
extern ivl_nature_t ivl_expr_nature(ivl_expr_t net);
@ -892,7 +893,7 @@ extern ivl_select_type_t ivl_expr_sel_type(ivl_expr_t net);
extern ivl_event_t ivl_expr_event(ivl_expr_t net);
/* IVL_EX_SCOPE */
extern ivl_scope_t ivl_expr_scope(ivl_expr_t net);
/* IVL_EX_SIGNAL */
/* IVL_EX_PROPERTY IVL_EX_SIGNAL */
extern ivl_signal_t ivl_expr_signal(ivl_expr_t net);
/* any expression */
extern int ivl_expr_signed(ivl_expr_t net);
@ -1430,6 +1431,11 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
* ivl_expr_t that represents the index expression. Otherwise, it
* returns 0.
*
* ivl_lval_property
* If the l-value is a class object, this is the name of a property
* to select from the object. If this property is not present, then
* the l-value represents the class object itself.
*
* SEMANTIC NOTES
* The ivl_lval_width is not necessarily the same as the width of the
* signal or memory word it represents. It is the width of the vector
@ -1455,6 +1461,7 @@ extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); /* XXXX Obsolete? */
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
extern ivl_expr_t ivl_lval_part_off(ivl_lval_t net);
extern ivl_select_type_t ivl_lval_sel_type(ivl_lval_t net);
extern const char* ivl_lval_property(ivl_lval_t net);
extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);

View File

@ -22,6 +22,7 @@
# include "netlist.h"
# include "netclass.h"
# include "netdarray.h"
# include "ivl_assert.h"
/*
* NetAssign
@ -86,6 +87,21 @@ ivl_select_type_t NetAssign_::select_type() const
unsigned NetAssign_::lwidth() const
{
// If the signal is a class type, then the situation is either
// "a.b" or "a.b.<member>". If this is "a.b" (no
// member/property reference, then return width==1. If this is
// "a.b.<member>", then get the type of the <member> property
// and return the width of that.
if (const netclass_t*class_type = sig_->class_type()) {
if (member_.nil())
return 1;
const ivl_type_s*ptype = class_type->get_property(member_);
ivl_assert(*sig_, ptype);
return ptype->packed_width();
}
if (netdarray_t*darray = sig_->darray_type()) {
if (word_ == 0)
return 1;
@ -98,6 +114,14 @@ unsigned NetAssign_::lwidth() const
ivl_variable_type_t NetAssign_::expr_type() const
{
if (const netclass_t*class_type = sig_->class_type()) {
if (member_.nil())
return sig_->data_type();
const ivl_type_s*tmp = class_type->get_property(member_);
return tmp->base_type();
}
if (netdarray_t*darray = sig_->darray_type()) {
if (word_ == 0)
return IVL_VT_DARRAY;
@ -110,8 +134,14 @@ ivl_variable_type_t NetAssign_::expr_type() const
const ivl_type_s* NetAssign_::net_type() const
{
if (dynamic_cast<const netclass_t*> (sig_->net_type()))
return sig_->net_type();
if (const netclass_t*class_type = sig_->class_type()) {
if (member_.nil())
return sig_->net_type();
const ivl_type_s*tmp = class_type->get_property(member_);
ivl_assert(*sig_, tmp);
return tmp;
}
if (dynamic_cast<const netdarray_t*> (sig_->net_type())) {
if (word_ == 0)
@ -164,6 +194,12 @@ void NetAssign_::set_part(NetExpr*base, unsigned wid,
sel_type_ = sel_type;
}
void NetAssign_::set_property(const perm_string&mname)
{
ivl_assert(*sig_, sig_->class_type());
member_ = mname;
}
/*
*/
void NetAssign_::turn_sig_to_wire_on_release()

View File

@ -348,6 +348,15 @@ NetENull::~NetENull()
{
}
NetEProperty::NetEProperty(NetNet*net, perm_string pnam)
: net_(net), pname_(pnam)
{
}
NetEProperty::~NetEProperty()
{
}
NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid,
ivl_select_type_t sel_type)
: expr_(exp), base_(base), sel_type_(sel_type)

View File

@ -106,6 +106,11 @@ NexusSet* NetENull::nex_input(bool)
return new NexusSet;
}
NexusSet* NetEProperty::nex_input(bool)
{
return new NexusSet;
}
NexusSet* NetEScope::nex_input(bool)
{
return new NexusSet;

View File

@ -18,6 +18,9 @@
*/
# include "netclass.h"
# include <iostream>
using namespace std;
netclass_t::netclass_t(perm_string name)
: name_(name)
@ -28,7 +31,28 @@ netclass_t::~netclass_t()
{
}
bool netclass_t::set_property(perm_string pname, ivl_type_s*ptype)
{
map<perm_string,ivl_type_s*>::const_iterator cur;
cur = properties_.find(pname);
if (cur != properties_.end())
return false;
properties_[pname] = ptype;
return true;
}
ivl_variable_type_t netclass_t::base_type() const
{
return IVL_VT_CLASS;
}
const ivl_type_s* netclass_t::get_property(perm_string pname) const
{
map<perm_string,ivl_type_s*>::const_iterator cur;
cur = properties_.find(pname);
if (cur == properties_.end())
return 0;
else
return cur->second;
}

View File

@ -22,20 +22,31 @@
# include "LineInfo.h"
# include "ivl_target.h"
# include "nettypes.h"
# include <map>
class netclass_t : public ivl_type_s {
public:
netclass_t(perm_string class_name);
~netclass_t();
// Set the property of the class during elaboration. Set the
// name and type, and return true. If the name is already
// present, then return false.
bool set_property(perm_string pname, ivl_type_s*ptype);
// As an ivl_type_s object, the netclass is always an
// ivl_VT_CLASS object.
ivl_variable_type_t base_type() const;
// This is the name of the class type
inline perm_string get_name() const { return name_; }
const ivl_type_s* get_property(perm_string pname) const;
private:
perm_string name_;
// Bind properties to their types.
std::map<perm_string,ivl_type_s*> properties_;
};
#endif

View File

@ -27,6 +27,7 @@
# include "compiler.h"
# include "netlist.h"
# include "netmisc.h"
# include "netclass.h"
# include "netdarray.h"
# include "netenum.h"
# include "netparray.h"
@ -807,6 +808,11 @@ netdarray_t* NetNet::darray_type(void) const
return dynamic_cast<netdarray_t*> (net_type_);
}
netclass_t* NetNet::class_type(void) const
{
return dynamic_cast<netclass_t*> (net_type_);
}
/*
* "depth" is the number of index expressions that the user is using
* to index this identifer. So consider if Net was declared like so:

View File

@ -640,6 +640,7 @@ class NetNet : public NetObj, public PortType {
netenum_t*enumeration(void) const;
const netstruct_t*struct_type(void) const;
netdarray_t*darray_type(void) const;
netclass_t*class_type(void) const;
/* Attach a discipline to the net. */
ivl_discipline_t get_discipline() const;
@ -2446,6 +2447,10 @@ class NetAssign_ {
// that the expression calculates a CANONICAL bit address.
void set_part(NetExpr* loff, unsigned wid,
ivl_select_type_t = IVL_SEL_OTHER);
// Set the member or property name if the signal type is a
// class.
void set_property(const perm_string&name);
inline perm_string get_property(void) const { return member_; }
// Get the width of the r-value that this node expects. This
// method accounts for the presence of the mux, so it is not
@ -2487,6 +2492,8 @@ class NetAssign_ {
NetNet *sig_;
// Memory word index
NetExpr*word_;
// member/property if signal is a class.
perm_string member_;
bool turn_sig_to_wire_on_release_;
// indexed part select base
@ -3923,6 +3930,30 @@ class NetENull : public NetExpr {
virtual void dump(ostream&os) const;
};
/*
* The NetEProperty represents a SystemVerilog properrty select of a
* class object. In SV, the expression would look like "a.b", where
* the "a" is the signal (the NetNet) and "b" is the property name.
*/
class NetEProperty : public NetExpr {
public:
NetEProperty(NetNet*n, perm_string pname);
~NetEProperty();
inline const NetNet* get_sig() const { return net_; }
inline const char* get_pname() const { return pname_.str(); }
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEProperty* dup_expr() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual void dump(ostream&os) const;
private:
NetNet*net_;
perm_string pname_;
};
/*
* This class is a special (and magical) expression node type that
* represents scope names. These can only be found as parameters to

View File

@ -21,8 +21,15 @@
using namespace std;
netvector_t::netvector_t(ivl_variable_type_t type, long msb, long lsb)
: type_(type), signed_(false), isint_(false), is_scalar_(false)
netvector_t netvector_t::atom2s32 (IVL_VT_BOOL, 31, 0, true);
netvector_t netvector_t::atom2u32 (IVL_VT_BOOL, 31, 0, false);
netvector_t netvector_t::atom2s16 (IVL_VT_BOOL, 16, 0, true);
netvector_t netvector_t::atom2u16 (IVL_VT_BOOL, 16, 0, false);
netvector_t netvector_t::atom2s8 (IVL_VT_BOOL, 8, 0, true);
netvector_t netvector_t::atom2u8 (IVL_VT_BOOL, 8, 0, false);
netvector_t::netvector_t(ivl_variable_type_t type, long msb, long lsb, bool flag)
: type_(type), signed_(flag)
{
packed_dims_.push_back(netrange_t(msb,lsb));
}

View File

@ -38,7 +38,8 @@ class netvector_t : public ivl_type_s {
// special case: there is a single packed dimension and we
// know it in the form [<msb>:<lsb>]. This step saves me
// creating a netrange_t for this single item.
explicit netvector_t(ivl_variable_type_t type, long msb, long lsb);
explicit netvector_t(ivl_variable_type_t type, long msb, long lsb,
bool signed_flag =false);
// Special case: scaler object--no packed dimenions at all.
explicit netvector_t(ivl_variable_type_t type);
@ -64,6 +65,15 @@ class netvector_t : public ivl_type_s {
std::ostream& debug_dump(std::ostream&) const;
public:
// Some commonly used predefined types
static netvector_t atom2s32;
static netvector_t atom2u32;
static netvector_t atom2s16;
static netvector_t atom2u16;
static netvector_t atom2s8;
static netvector_t atom2u8;
private:
std::vector<netrange_t> packed_dims_;
ivl_variable_type_t type_;

View File

@ -34,7 +34,10 @@
* parse-form types.
*/
class Design;
class NetScope;
class PExpr;
class ivl_type_s;
typedef named<verinum> named_number_t;
typedef named<PExpr*> named_pexpr_t;
typedef std::pair<PExpr*,PExpr*> pform_range_t;
@ -77,6 +80,8 @@ class data_type_t : public LineInfo {
virtual ivl_variable_type_t figure_packed_base_type(void)const;
// This method is used by the pform dumper to diagnostic dump.
virtual void pform_dump(std::ostream&out, unsigned indent) const;
// Elaborate the type to an ivl_type_s type.
virtual ivl_type_s* elaborate_type(Design*des, NetScope*scope) const;
};
/*
@ -113,6 +118,8 @@ struct atom2_type_t : public data_type_t {
: type_code(tc), signed_flag(flag) { }
int type_code;
bool signed_flag;
ivl_type_s* elaborate_type(Design*des, NetScope*scope) const;
};
/*

View File

@ -428,6 +428,9 @@ extern "C" const char* ivl_expr_name(ivl_expr_t net)
case IVL_EX_SIGNAL:
return net->u_.signal_.sig->name_;
case IVL_EX_PROPERTY:
return net->u_.property_.pname;
default:
assert(0);
}
@ -617,6 +620,9 @@ extern "C" ivl_signal_t ivl_expr_signal(ivl_expr_t net)
case IVL_EX_ARRAY:
return net->u_.signal_.sig;
case IVL_EX_PROPERTY:
return net->u_.property_.sig;
default:
assert(0);
return 0;
@ -1554,6 +1560,15 @@ extern "C" unsigned ivl_lval_width(ivl_lval_t net)
return net->width_;
}
extern "C" const char* ivl_lval_property(ivl_lval_t net)
{
assert(net);
if (net->property.nil())
return 0;
else
return net->property.str();
}
extern "C" ivl_signal_t ivl_lval_sig(ivl_lval_t net)
{
assert(net);

View File

@ -350,6 +350,21 @@ void dll_target::expr_null(const NetENull*net)
expr_->net_type= 0;
}
void dll_target::expr_property(const NetEProperty*net)
{
assert(expr_ == 0);
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
expr_->width_ = net->expr_width();
expr_->signed_ = net->has_sign();
expr_->sized_ = 1;
expr_->type_ = IVL_EX_PROPERTY;
FILE_NAME(expr_, net);
expr_->value_ = net->expr_type();
expr_->net_type= net->net_type();
expr_->u_.property_.sig = find_signal(des_, net->get_sig());
expr_->u_.property_.pname = net->get_pname();
}
void dll_target::expr_event(const NetEEvent*net)
{
assert(expr_ == 0);

View File

@ -162,6 +162,7 @@ void dll_target::make_assign_lvals_(const NetAssignBase*net)
}
cur->width_ = asn->lwidth();
cur->property = asn->get_property();
if (asn->sig()) {
cur->type_ = IVL_LVAL_REG;

View File

@ -140,6 +140,7 @@ struct dll_target : public target_t, public expr_scan_t {
void expr_new(const NetENew*);
void expr_null(const NetENull*);
void expr_param(const NetEConstParam*);
void expr_property(const NetEProperty*);
void expr_rparam(const NetECRealParam*);
void expr_event(const NetEEvent*);
void expr_scope(const NetEScope*);
@ -324,6 +325,10 @@ struct ivl_expr_s {
ivl_expr_t size;
} new_;
struct {
ivl_signal_t sig;
const char*pname;
} property_;
} u_;
};
@ -441,10 +446,11 @@ enum ivl_lval_type_t {
struct ivl_lval_s {
ivl_expr_t loff;
ivl_select_type_t sel_type;
ivl_select_type_t sel_type :3;
ivl_expr_t idx;
unsigned width_;
unsigned type_ : 8;
perm_string property;
union {
ivl_signal_t sig;
ivl_memory_t mem;

View File

@ -461,6 +461,12 @@ void expr_scan_t::expr_param(const NetEConstParam*that)
expr_const(that);
}
void expr_scan_t::expr_property(const NetEProperty*)
{
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
"unhandled expr_property." << endl;
}
void expr_scan_t::expr_creal(const NetECReal*)
{
cerr << "expr_scan_t (" << typeid(*this).name() << "): "

View File

@ -153,6 +153,7 @@ struct expr_scan_t {
virtual void expr_new(const NetENew*);
virtual void expr_null(const NetENull*);
virtual void expr_param(const NetEConstParam*);
virtual void expr_property(const NetEProperty*);
virtual void expr_rparam(const NetECRealParam*);
virtual void expr_creal(const NetECReal*);
virtual void expr_concat(const NetEConcat*);

View File

@ -205,6 +205,19 @@ static void show_null_expression(ivl_expr_t net, unsigned ind)
}
}
static void show_property_expression(ivl_expr_t net, unsigned ind)
{
ivl_signal_t sig = ivl_expr_signal(net);
const char* pnam = ivl_expr_name(net);
fprintf(out, "%*s%s<property>%s\n", ind, "",
ivl_signal_basename(sig), pnam);
if (ivl_signal_data_type(sig) != IVL_VT_CLASS) {
fprintf(out, "%*sERROR: Property signal must be IVL_VT_CLASS, got %s.\n",
ind+3, "", data_type_string(ivl_signal_data_type(sig)));
}
}
static void show_select_expression(ivl_expr_t net, unsigned ind)
{
unsigned width = ivl_expr_width(net);
@ -399,6 +412,10 @@ void show_expression(ivl_expr_t net, unsigned ind)
show_null_expression(net, ind);
break;
case IVL_EX_PROPERTY:
show_property_expression(net, ind);
break;
case IVL_EX_NUMBER: {
const char*bits = ivl_expr_bits(net);

View File

@ -30,6 +30,12 @@ static unsigned show_assign_lval_darray(ivl_lval_t lval, unsigned ind)
ivl_signal_t sig = ivl_lval_sig(lval);
assert(sig);
fprintf(out, "%*s{name=%s darray width=%u l-value width=%u}\n",
ind, "",
ivl_signal_name(sig),
ivl_signal_width(sig),
ivl_lval_width(lval));
if (ivl_lval_idx(lval)) {
fprintf(out, "%*sAddress-0 select of ", ind+4, "");
show_type_of_signal(sig);
@ -51,21 +57,49 @@ static unsigned show_assign_lval_darray(ivl_lval_t lval, unsigned ind)
return ivl_lval_width(lval);
}
static unsigned show_assign_lval_class(ivl_lval_t lval, unsigned ind)
{
ivl_signal_t sig = ivl_lval_sig(lval);
const char*sig_prop = ivl_lval_property(lval);
assert(sig);
/* If there is no property select, then this l-value is for
the class handle itself. */
if (sig_prop == 0) {
fprintf(out, "%*s{name=%s class object}\n", ind, "", ivl_signal_name(sig));
if (ivl_lval_width(lval) != 1) {
fprintf(out, "%*sERROR: ivl_lval_width should be 1 for class objects\n",
ind+4, "");
stub_errors += 1;
}
return ivl_lval_width(lval);
}
fprintf(out, "%*s{name=%s<property>%s l-value width=%u}\n",
ind, "", ivl_signal_name(sig), sig_prop, ivl_lval_width(lval));
return ivl_lval_width(lval);
}
static unsigned show_assign_lval(ivl_lval_t lval, unsigned ind)
{
ivl_signal_t sig = ivl_lval_sig(lval);
assert(sig);
fprintf(out, "%*s{name=%s width=%u lvwidth=%u}\n",
/* Special case: target signal is a darray. */
if (ivl_signal_data_type(sig) == IVL_VT_DARRAY)
return show_assign_lval_darray(lval, ind);
/* Special case: target signal is a class. */
if (ivl_signal_data_type(sig) == IVL_VT_CLASS)
return show_assign_lval_class(lval, ind);
fprintf(out, "%*s{name=%s signal width=%u l-value width=%u}\n",
ind, "",
ivl_signal_name(sig),
ivl_signal_width(sig),
ivl_lval_width(lval));
/* Special case: target signal is a darray. */
if (ivl_signal_data_type(sig) == IVL_VT_DARRAY)
return show_assign_lval_darray(lval, ind);
if (ivl_lval_idx(lval)) {
fprintf(out, "%*sAddress-0 select expression:\n", ind+4, "");
show_expression(ivl_lval_idx(lval), ind+6);