From 318a4033b823554e9e894435007c978ac0bbd3a3 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 25 Nov 2012 10:13:05 -0800 Subject: [PATCH] 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. --- Makefile.in | 3 +- PExpr.h | 3 ++ design_dump.cc | 8 ++++++ dup_expr.cc | 6 ++++ elab_expr.cc | 44 +++++++++++++++++++++++++++++ elab_lval.cc | 53 ++++++++++++++++++++++++++++++++--- elab_scope.cc | 10 ++++++- elab_type.cc | 64 +++++++++++++++++++++++++++++++++++++++++++ emit.cc | 5 ++++ ivl_target.h | 11 ++++++-- net_assign.cc | 40 +++++++++++++++++++++++++-- net_expr.cc | 9 ++++++ net_nex_input.cc | 5 ++++ netclass.cc | 24 ++++++++++++++++ netclass.h | 11 ++++++++ netlist.cc | 6 ++++ netlist.h | 31 +++++++++++++++++++++ netvector.cc | 11 ++++++-- netvector.h | 12 +++++++- pform_types.h | 7 +++++ t-dll-api.cc | 15 ++++++++++ t-dll-expr.cc | 15 ++++++++++ t-dll-proc.cc | 1 + t-dll.h | 8 +++++- target.cc | 6 ++++ target.h | 1 + tgt-stub/expression.c | 17 ++++++++++++ tgt-stub/statement.c | 44 +++++++++++++++++++++++++---- 28 files changed, 451 insertions(+), 19 deletions(-) create mode 100644 elab_type.cc diff --git a/Makefile.in b/Makefile.in index 0e342d85c..d231f2669 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 \ diff --git a/PExpr.h b/PExpr.h index 1a0d41f5f..25c4bca4a 100644 --- a/PExpr.h +++ b/PExpr.h @@ -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; diff --git a/design_dump.cc b/design_dump.cc index 3e7139472..038f30443 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -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 << ""; } +void NetEProperty::dump(ostream&o) const +{ + o << net_->name() << "." << pname_; +} + void NetEScope::dump(ostream&o) const { o << ""; diff --git a/dup_expr.cc b/dup_expr.cc index 43d43a68c..e3d9cd552 100644 --- a/dup_expr.cc +++ b/dup_expr.cc @@ -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); diff --git a/elab_expr.cc b/elab_expr.cc index b8c9dab7e..d7d58f27a 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -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); + } } } diff --git a/elab_lval.cc b/elab_lval.cc index d5119e0fc..fb1558265 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -24,6 +24,7 @@ # include "netlist.h" # include "netmisc.h" # include "netstruct.h" +# include "netclass.h" # include "compiler.h" # include # include @@ -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 diff --git a/elab_scope.cc b/elab_scope.cc index 6b89ce4c4..1341fb064 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -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::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); } diff --git a/elab_type.cc b/elab_type.cc new file mode 100644 index 000000000..06938b66f --- /dev/null +++ b/elab_type.cc @@ -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 +# 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; + } +} diff --git a/emit.cc b/emit.cc index 9fd251c6d..fee25e0bf 100644 --- a/emit.cc +++ b/emit.cc @@ -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); diff --git a/ivl_target.h b/ivl_target.h index 148fc30e6..6c34ced24 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -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); diff --git a/net_assign.cc b/net_assign.cc index 1ef7cc204..d4fefa69c 100644 --- a/net_assign.cc +++ b/net_assign.cc @@ -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.". If this is "a.b" (no + // member/property reference, then return width==1. If this is + // "a.b.", then get the type of the 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 (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 (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() diff --git a/net_expr.cc b/net_expr.cc index 7e04540c7..5e5c05d76 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -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) diff --git a/net_nex_input.cc b/net_nex_input.cc index 5ca6e2be1..d75b3c7c1 100644 --- a/net_nex_input.cc +++ b/net_nex_input.cc @@ -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; diff --git a/netclass.cc b/netclass.cc index 620954ca5..4a5a78fce 100644 --- a/netclass.cc +++ b/netclass.cc @@ -18,6 +18,9 @@ */ # include "netclass.h" +# include + +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::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::const_iterator cur; + cur = properties_.find(pname); + if (cur == properties_.end()) + return 0; + else + return cur->second; +} diff --git a/netclass.h b/netclass.h index 64dbd51fb..58828c51f 100644 --- a/netclass.h +++ b/netclass.h @@ -22,20 +22,31 @@ # include "LineInfo.h" # include "ivl_target.h" # include "nettypes.h" +# include 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 properties_; }; #endif diff --git a/netlist.cc b/netlist.cc index 3afe6bba9..36bcdd5ce 100644 --- a/netlist.cc +++ b/netlist.cc @@ -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 (net_type_); } +netclass_t* NetNet::class_type(void) const +{ + return dynamic_cast (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: diff --git a/netlist.h b/netlist.h index 4e13d849b..a45b7a08a 100644 --- a/netlist.h +++ b/netlist.h @@ -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 diff --git a/netvector.cc b/netvector.cc index 609e6e986..08c0239e8 100644 --- a/netvector.cc +++ b/netvector.cc @@ -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)); } diff --git a/netvector.h b/netvector.h index ab65678de..3add278fb 100644 --- a/netvector.h +++ b/netvector.h @@ -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 [:]. 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 packed_dims_; ivl_variable_type_t type_; diff --git a/pform_types.h b/pform_types.h index 6193d99c2..8af2d3c6e 100644 --- a/pform_types.h +++ b/pform_types.h @@ -34,7 +34,10 @@ * parse-form types. */ +class Design; +class NetScope; class PExpr; +class ivl_type_s; typedef named named_number_t; typedef named named_pexpr_t; typedef std::pair 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; }; /* diff --git a/t-dll-api.cc b/t-dll-api.cc index 3960831d9..db2b0cc15 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -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); diff --git a/t-dll-expr.cc b/t-dll-expr.cc index 740369e31..4d0f90b28 100644 --- a/t-dll-expr.cc +++ b/t-dll-expr.cc @@ -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); diff --git a/t-dll-proc.cc b/t-dll-proc.cc index e144452e4..e217afe62 100644 --- a/t-dll-proc.cc +++ b/t-dll-proc.cc @@ -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; diff --git a/t-dll.h b/t-dll.h index 8ea42b35e..c3fc32712 100644 --- a/t-dll.h +++ b/t-dll.h @@ -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; diff --git a/target.cc b/target.cc index 7b5403282..056b95286 100644 --- a/target.cc +++ b/target.cc @@ -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() << "): " diff --git a/target.h b/target.h index 69d13092e..9ad290d6a 100644 --- a/target.h +++ b/target.h @@ -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*); diff --git a/tgt-stub/expression.c b/tgt-stub/expression.c index 431793f7c..51688fa20 100644 --- a/tgt-stub/expression.c +++ b/tgt-stub/expression.c @@ -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%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); diff --git a/tgt-stub/statement.c b/tgt-stub/statement.c index 5f9cda357..5b8486c26 100644 --- a/tgt-stub/statement.c +++ b/tgt-stub/statement.c @@ -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%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);