diff --git a/Makefile.in b/Makefile.in index da1d823f6..0e342d85c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -107,13 +107,13 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \ elab_scope.o elab_sig.o elab_sig_analog.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 netdarray.o \ + net_design.o netclass.o netdarray.o \ netenum.o netparray.o netstruct.o netvector.o net_event.o net_expr.o net_func.o \ net_func_eval.o net_link.o net_modulo.o \ net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \ net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \ pform_disciplines.o pform_dump.o pform_package.o pform_pclass.o \ - pform_string_type.o pform_struct_type.o pform_types.o \ + pform_class_type.o pform_string_type.o pform_struct_type.o pform_types.o \ symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \ Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PGate.o \ PGenerate.o PPackage.o PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \ diff --git a/PClass.h b/PClass.h index 1153fd48c..ec5440468 100644 --- a/PClass.h +++ b/PClass.h @@ -22,6 +22,7 @@ # include "PScope.h" # include "LineInfo.h" # include "StringHeap.h" +# include /* * SystemVerilog supports class declarations with their own lexical @@ -35,6 +36,8 @@ class PClass : public PScopeExtra, public LineInfo { explicit PClass (perm_string name, LexicalScope*parent); ~PClass(); + void dump(std::ostream&out, unsigned indent) const; + public: class_type_t*type; }; diff --git a/PExpr.cc b/PExpr.cc index adbc36c2f..1992c0f28 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -389,6 +389,14 @@ PENew::~PENew() delete size_; } +PENewClass::PENewClass(void) +{ +} + +PENewClass::~PENewClass() +{ +} + PENumber::PENumber(verinum*vp) : value_(vp) { diff --git a/PExpr.h b/PExpr.h index 13c52a3f9..59e64abdb 100644 --- a/PExpr.h +++ b/PExpr.h @@ -467,12 +467,36 @@ class PENew : public PExpr { PExpr*size_; }; +class PENewClass : public PExpr { + + public: + explicit PENewClass (); + ~PENewClass(); + virtual void dump(ostream&) const; + // Class objects don't have a useful width, but the expression + // is IVL_VT_CLASS. + virtual unsigned test_width(Design*des, NetScope*scope, + width_mode_t&mode); + // Note that class (new) expressions only appear in context + // that uses this form of the elaborate_expr method. In fact, + // the type argument is going to be a netclas_t object. + virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, + ivl_type_t type, unsigned flags) const; + + private: +}; + class PENull : public PExpr { public: explicit PENull(); ~PENull(); virtual void dump(ostream&) const; + virtual unsigned test_width(Design*des, NetScope*scope, + width_mode_t&mode); + virtual NetExpr*elaborate_expr(Design*des, NetScope*, + unsigned expr_wid, + unsigned flags) const; }; class PENumber : public PExpr { diff --git a/PScope.h b/PScope.h index f0661d1ee..8fe77cae8 100644 --- a/PScope.h +++ b/PScope.h @@ -30,6 +30,7 @@ class PExpr; class PFunction; class AProcess; class PProcess; +class PClass; class PTask; class PWire; @@ -165,8 +166,13 @@ class PScopeExtra : public PScope { ~PScopeExtra(); /* Task definitions within this module */ - map tasks; - map funcs; + std::map tasks; + std::map funcs; + /* class definitions within this module. */ + std::map classes; + + protected: + void dump_classes_(ostream&out, unsigned indent) const; }; #endif diff --git a/PWire.cc b/PWire.cc index 56cca4731..31e117b48 100644 --- a/PWire.cc +++ b/PWire.cc @@ -253,7 +253,7 @@ void PWire::set_unpacked_idx(const list&ranges) } } -void PWire::set_packed_type(data_type_t*type) +void PWire::set_data_type(data_type_t*type) { assert(set_data_type_ == 0); set_data_type_ = type; diff --git a/PWire.h b/PWire.h index b0a2e0444..464d4d6c6 100644 --- a/PWire.h +++ b/PWire.h @@ -81,7 +81,7 @@ class PWire : public LineInfo { void set_unpacked_idx(const std::list&ranges); - void set_packed_type(data_type_t*type); + void set_data_type(data_type_t*type); void set_discipline(ivl_discipline_t); ivl_discipline_t get_discipline(void) const; @@ -118,6 +118,8 @@ class PWire : public LineInfo { // me the size and address ranges of the memory. std::listunpacked_; + // This is the complex type of the wire. the data_type_ may + // modify how this is interpreted. data_type_t*set_data_type_; ivl_discipline_t discipline_; diff --git a/design_dump.cc b/design_dump.cc index 3e14e52b8..95a8634b9 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -109,6 +109,9 @@ ostream& operator << (ostream&o, ivl_variable_type_t val) case IVL_VT_DARRAY: o << "darray"; break; + case IVL_VT_CLASS: + o << "class"; + break; } return o; } @@ -1506,6 +1509,11 @@ void NetENetenum::dump(ostream&o) const o << ""; } +void NetENull::dump(ostream&o) const +{ + o << ""; +} + void NetEScope::dump(ostream&o) const { o << ""; diff --git a/dup_expr.cc b/dup_expr.cc index e45b6b698..69bdc411a 100644 --- a/dup_expr.cc +++ b/dup_expr.cc @@ -177,6 +177,12 @@ NetENetenum* NetENetenum::dup_expr() const return 0; } +NetENull* NetENull::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 2c0d62639..c4f70c010 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -101,6 +101,12 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, case IVL_VT_NO_TYPE: ivl_assert(*expr, 0); break; + case IVL_VT_CLASS: + cerr << expr->get_fileline() << ": sorry: " + << "I do not know how to elaborate r-value as IVL_VT_CLASS." << endl; + des->errors += 1; + return 0; + break; } return elab_and_eval(des, scope, expr, context_wid, need_const); @@ -1074,7 +1080,7 @@ unsigned PECallFunction::test_width(Design*des, NetScope*scope, } unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope, - width_mode_t&mode) + width_mode_t&) { if (!gn_system_verilog()) return 0; @@ -2396,7 +2402,9 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) signed_flag_ = net->get_signed(); if (debug_elaborate) { cerr << get_fileline() << ": PEIdent::test_width: " - << net->name() << " is a net, width=" << expr_width_ << endl; + << net->name() << " is a net, " + << "type=" << expr_type_ + << ", width=" << expr_width_ << endl; } return expr_width_; } @@ -4021,6 +4029,44 @@ NetExpr* PENew::elaborate_expr(Design*des, NetScope*scope, return tmp; } +unsigned PENewClass::test_width(Design*, NetScope*, width_mode_t&) +{ + expr_type_ = IVL_VT_CLASS; + expr_width_ = 1; + min_width_ = 1; + signed_flag_= false; + return 1; +} + +NetExpr* PENewClass::elaborate_expr(Design*, NetScope*, + ivl_type_t ntype, unsigned) const +{ + NetESFunc*tmp = new NetESFunc("$ivl_class_method$new", ntype, 0); + tmp->set_line(*this); + return tmp; +} + +/* + * A "null" expression represents class objects/handles. This brings + * up a ton of special cases, but we handle it here bu setting the + * expr_type_ and expr_width_ to fixed values. + */ +unsigned PENull::test_width(Design*, NetScope*, width_mode_t&) +{ + expr_type_ = IVL_VT_CLASS; + expr_width_ = 1; + min_width_ = 1; + signed_flag_ = false; + return expr_width_; +} + +NetExpr* PENull::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const +{ + NetENull*tmp = new NetENull; + tmp->set_line(*this); + return tmp; +} + unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode) { expr_type_ = IVL_VT_LOGIC; diff --git a/elab_scope.cc b/elab_scope.cc index de44e8830..6b89ce4c4 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -33,8 +33,10 @@ */ # include "Module.h" -# include "PEvent.h" +# include "PClass.h" # include "PExpr.h" +# include "PEvent.h" +# include "PClass.h" # include "PGate.h" # include "PGenerate.h" # include "PTask.h" @@ -42,6 +44,7 @@ # include "Statement.h" # include "AStatement.h" # include "netlist.h" +# include "netclass.h" # include "netenum.h" # include "util.h" # include @@ -286,6 +289,22 @@ 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); + scope->add_class(use_class); +} + +static void elaborate_scope_classes(Design*des, NetScope*scope, + const map&classes) +{ + for (map::const_iterator cur = classes.begin() + ; cur != classes.end() ; ++ cur) { + elaborate_scope_class(des, scope, cur->second); + } +} + static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc, const Module::replace_t&replacements) { @@ -500,6 +519,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, elaborate_scope_enumerations(des, scope, enum_sets); + elaborate_scope_classes(des, scope, classes); + // Run through the defparams for this module and save the result // in a table for later final override. diff --git a/elab_sig.cc b/elab_sig.cc index 9cc281518..1ca0ad751 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -34,6 +34,7 @@ # include "compiler.h" # include "netlist.h" # include "netmisc.h" +# include "netclass.h" # include "netenum.h" # include "netstruct.h" # include "netvector.h" @@ -864,6 +865,13 @@ static bool evaluate_ranges(Design*des, NetScope*scope, return bad_msb | bad_lsb; } +static netclass_t* locate_class_type(Design*des, NetScope*scope, + class_type_t*class_type) +{ + netclass_t*use_class = scope->find_class(class_type->name); + return use_class; +} + static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope, struct_type_t*struct_type) { @@ -1196,9 +1204,19 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const NetNet*sig = 0; - // If this is a struct type, then build the net with the - // struct type. - if (struct_type_t*struct_type = dynamic_cast(set_data_type_)) { + if (class_type_t*class_type = dynamic_cast(set_data_type_)) { + // If this is a class variable, then the class type + // should already have been elaborated. All we need to + // do right now is locate the netclass_t object for the + // class, and use that to build the net. + netclass_t*use_type = locate_class_type(des, scope, class_type); + // (No arrays of classes) + list use_unpacked; + sig = new NetNet(scope, name_, wtype, use_unpacked, use_type); + + } else if (struct_type_t*struct_type = dynamic_cast(set_data_type_)) { + // If this is a struct type, then build the net with the + // struct type. netstruct_t*use_type = elaborate_struct_type(des, scope, struct_type); if (debug_elaborate) { cerr << get_fileline() << ": debug: Create signal " << wtype; diff --git a/elaborate.cc b/elaborate.cc index 886ae53f9..9a67f6976 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2385,6 +2385,10 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const handle it with this code instead. */ rv = elaborate_rval_(des, scope, lv->sig()->net_type()); + } else if (lv->more==0 && dynamic_cast (rval())) { + + rv = elaborate_rval_(des, scope, lv->sig()->net_type()); + } else { /* Elaborate the r-value expression, then try to evaluate it. */ rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type()); diff --git a/emit.cc b/emit.cc index 94871ac75..57e093aec 100644 --- a/emit.cc +++ b/emit.cc @@ -551,6 +551,11 @@ void NetENetenum::expr_scan(struct expr_scan_t*tgt) const tgt->expr_netenum(this); } +void NetENull::expr_scan(struct expr_scan_t*tgt) const +{ + tgt->expr_null(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 be25028be..005aec748 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -224,6 +224,7 @@ typedef enum ivl_expr_type_e { IVL_EX_ENUMTYPE = 21, IVL_EX_EVENT = 17, IVL_EX_MEMORY = 4, + IVL_EX_NULL = 22, IVL_EX_NUMBER = 5, IVL_EX_REALNUM = 16, IVL_EX_SCOPE = 6, @@ -426,6 +427,7 @@ typedef enum ivl_variable_type_e { IVL_VT_LOGIC = 4, IVL_VT_STRING = 5, IVL_VT_DARRAY = 6, /* Array (esp. dynamic array) */ + IVL_VT_CLASS = 7, /* SystemVerilog class instances */ IVL_VT_VECTOR = IVL_VT_LOGIC /* For compatibility */ } ivl_variable_type_t; diff --git a/net_expr.cc b/net_expr.cc index ab204a3e1..4b9b33822 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -20,6 +20,7 @@ # include "config.h" # include "netlist.h" # include "netenum.h" +# include "netclass.h" # include "netdarray.h" # include "compiler.h" # include "netmisc.h" @@ -320,6 +321,14 @@ netenum_t* NetENetenum::netenum() const return netenum_; } +NetENull::NetENull() +{ +} + +NetENull::~NetENull() +{ +} + NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid, ivl_select_type_t sel_type) : expr_(exp), base_(base), sel_type_(sel_type) @@ -395,8 +404,12 @@ NetESFunc::NetESFunc(const char*n, ivl_type_t rtype, unsigned np) // FIXME: For now, assume that all uses of this constructor // are for the IVL_VT_DARRAY type. Eventually, the type_ // member will go away. - ivl_assert(*this, dynamic_cast(rtype)); - type_ = IVL_VT_DARRAY; + if (dynamic_cast(rtype)) + type_ = IVL_VT_DARRAY; + else if (dynamic_cast(rtype)) + type_ = IVL_VT_CLASS; + else + ivl_assert(*this, 0); } NetESFunc::NetESFunc(const char*n, netenum_t*enum_type, unsigned np) diff --git a/net_nex_input.cc b/net_nex_input.cc index 5e3932bc2..19bad21b0 100644 --- a/net_nex_input.cc +++ b/net_nex_input.cc @@ -96,6 +96,11 @@ NexusSet* NetENetenum::nex_input(bool) return new NexusSet; } +NexusSet* NetENull::nex_input(bool) +{ + return new NexusSet; +} + NexusSet* NetEScope::nex_input(bool) { return new NexusSet; diff --git a/net_scope.cc b/net_scope.cc index af0f86f42..6a5771636 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -21,6 +21,7 @@ # include "compiler.h" # include "netlist.h" +# include "netclass.h" # include "netenum.h" # include # include @@ -551,6 +552,20 @@ netenum_t*NetScope::enumeration_for_name(perm_string name) return tmp->enumeration(); } +void NetScope::add_class(netclass_t*net_class) +{ + classes_[net_class->get_name()] = net_class; +} + +netclass_t*NetScope::find_class(perm_string name) +{ + map::const_iterator cur = classes_.find(name); + if (cur == classes_.end()) + return 0; + else + return cur->second; +} + /* * This method locates a child scope by name. The name is the simple * name of the child, no hierarchy is searched. diff --git a/netclass.cc b/netclass.cc new file mode 100644 index 000000000..620954ca5 --- /dev/null +++ b/netclass.cc @@ -0,0 +1,34 @@ +/* + * 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 "netclass.h" + +netclass_t::netclass_t(perm_string name) +: name_(name) +{ +} + +netclass_t::~netclass_t() +{ +} + +ivl_variable_type_t netclass_t::base_type() const +{ + return IVL_VT_CLASS; +} diff --git a/netclass.h b/netclass.h new file mode 100644 index 000000000..64dbd51fb --- /dev/null +++ b/netclass.h @@ -0,0 +1,41 @@ +#ifndef __netclass_H +#define __netclass_H +/* + * 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 "LineInfo.h" +# include "ivl_target.h" +# include "nettypes.h" + +class netclass_t : public ivl_type_s { + public: + netclass_t(perm_string class_name); + ~netclass_t(); + + // As an ivl_type_s object, the netclass is always an + // ivl_VT_CLASS object. + ivl_variable_type_t base_type() const; + + inline perm_string get_name() const { return name_; } + + private: + perm_string name_; +}; + +#endif diff --git a/netlist.h b/netlist.h index f75a6121c..26265768f 100644 --- a/netlist.h +++ b/netlist.h @@ -76,6 +76,7 @@ class NetEvTrig; class NetEvWait; class PExpr; class PFunction; +class netclass_t; class netdarray_t; class netparray_t; class netenum_t; @@ -835,6 +836,9 @@ class NetScope : public Attrib { netenum_t* enumeration_for_name(perm_string name); + void add_class(netclass_t*class_type); + netclass_t* find_class(perm_string name); + /* The parent and child() methods allow users of NetScope objects to locate nearby scopes. */ NetScope* parent() { return up_; } @@ -1083,6 +1087,8 @@ class NetScope : public Attrib { std::list enum_sets_; std::map enum_names_; + std::map classes_; + NetScope*up_; map children_; @@ -3871,6 +3877,23 @@ class NetENetenum : public NetExpr { netenum_t*netenum_; }; +/* + * The NetENull node represents the SystemVerilog (null) + * expression. This is always a null class handle. + */ +class NetENull : public NetExpr { + + public: + NetENull(); + ~NetENull(); + + virtual void expr_scan(struct expr_scan_t*) const; + virtual NetENull* dup_expr() const; + virtual NexusSet* nex_input(bool rem_out = true); + + virtual void dump(ostream&os) const; +}; + /* * 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/parse.y b/parse.y index 2713333a9..9403c3338 100644 --- a/parse.y +++ b/parse.y @@ -658,7 +658,6 @@ class_declaration /* IEEE1800-2005: A.1.2 */ class_items_opt K_endclass { // Process a class. pform_end_class_declaration(); - yyerror(@2, "sorry: Class declarations not supported yet."); } class_declaration_endname_opt { // Wrap up the class. @@ -819,16 +818,18 @@ class_item_qualifier /* IEEE1800-2005 A.1.8 */ class_new /* IEEE1800-2005 A.2.4 */ : K_new '(' ')' - { yyerror(@1, "sorry: class_new not implemented yet."); - $$ = 0; + { PENewClass*tmp = new PENewClass; + FILE_NAME(tmp, @1); + $$ = tmp; } | K_new '(' expression_list_proper ')' { yyerror(@1, "sorry: class_new not implemented yet."); $$ = 0; } | K_new - { yyerror(@1, "sorry: class_new not implemented yet."); - $$ = 0; + { PENewClass*tmp = new PENewClass; + FILE_NAME(tmp, @1); + $$ = tmp; } ; diff --git a/pform.cc b/pform.cc index c58968782..aacaf0bbf 100644 --- a/pform.cc +++ b/pform.cc @@ -284,11 +284,33 @@ void pform_pop_scope() lexical_scope = lexical_scope->parent_scope(); } +static PScopeExtra* find_nearest_scopex(LexicalScope*scope) +{ + PScopeExtra*scopex = dynamic_cast (scope); + while (scope && !scopex) { + scope = scope->parent_scope(); + scopex = dynamic_cast (scope); + } + return scopex; +} + PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name) { PClass*class_scope = new PClass(name, lexical_scope); FILE_NAME(class_scope, loc); + PScopeExtra*scopex = find_nearest_scopex(lexical_scope); + + assert(!pform_cur_generate); + + if (scopex->classes.find(name) != scopex->classes.end()) { + cerr << class_scope->get_fileline() << ": error: duplicate " + " definition for class '" << name << "' in '" + << scopex->pscope_name() << "'." << endl; + error_count += 1; + } + scopex->classes[name] = class_scope; + lexical_scope = class_scope; return class_scope; } @@ -309,12 +331,7 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto) PTask*task = new PTask(task_name, lexical_scope, is_auto); FILE_NAME(task, loc); - LexicalScope*scope = lexical_scope; - PScopeExtra*scopex = dynamic_cast (scope); - while (scope && !scopex) { - scope = scope->parent_scope(); - scopex = dynamic_cast (scope); - } + PScopeExtra*scopex = find_nearest_scopex(lexical_scope); assert(scopex); if (pform_cur_generate) { @@ -2042,7 +2059,7 @@ void pform_module_define_port(const struct vlltype&li, cur->set_signed(signed_flag); if (struct_type) { - cur->set_packed_type(struct_type); + cur->set_data_type(struct_type); } else if (range == 0) { cur->set_range_scalar((type == NetNet::IMPLICIT) ? SR_PORT : SR_BOTH); @@ -2830,7 +2847,7 @@ template static void pform_set2_data_type(const struct vlltype&li, T*d } PWire*net = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, base_type); - net->set_packed_type(data_type); + net->set_data_type(data_type); pform_bind_attributes(net->attributes, attr, true); } @@ -2855,7 +2872,7 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, assert(enum_type->range.get() != 0); assert(enum_type->range->size() == 1); //XXXXcur->set_range(*enum_type->range, SR_NET); - cur->set_packed_type(enum_type); + cur->set_data_type(enum_type); pform_bind_attributes(cur->attributes, attr, true); } @@ -2925,8 +2942,8 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list (data_type)) { - VLerror(li, "sorry: Class types not supported."); + if (class_type_t*class_type = dynamic_cast (data_type)) { + pform_set_class_type(class_type, names, net_type, attr); return; } diff --git a/pform.h b/pform.h index 287763d85..6a76664b1 100644 --- a/pform.h +++ b/pform.h @@ -311,6 +311,9 @@ extern void pform_set_struct_type(struct_type_t*struct_type, std::list*names, NetNet::Type net_type, std::list*attr); +extern void pform_set_class_type(class_type_t*class_type, std::list*names, NetNet::Type net_type, std::list*addr); + + /* pform_set_attrib and pform_set_type_attrib exist to support the $attribute syntax, which can only set string values to attributes. The functions keep the value strings that are diff --git a/pform_class_type.cc b/pform_class_type.cc new file mode 100644 index 000000000..44f0d3555 --- /dev/null +++ b/pform_class_type.cc @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2012 Picture Elements, Inc. + * 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.h" +# include "parse_misc.h" +# include "ivl_assert.h" + +static void pform_set_class_type(class_type_t*class_type, perm_string name, NetNet::Type net_type, list*attr) +{ + PWire*net = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, IVL_VT_CLASS); + net->set_data_type(class_type); + pform_bind_attributes(net->attributes, attr, true); +} + +void pform_set_class_type(class_type_t*class_type, list*names, NetNet::Type net_type, list*attr) +{ + for (list::iterator cur = names->begin() + ; cur != names->end() ; ++ cur) { + pform_set_class_type(class_type, *cur, net_type, attr); + } +} diff --git a/pform_dump.cc b/pform_dump.cc index fc7668588..bbbbc50d8 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -26,6 +26,7 @@ * module in question. */ # include "pform.h" +# include "PClass.h" # include "PEvent.h" # include "PGenerate.h" # include "PSpec.h" @@ -278,6 +279,11 @@ void PENew::dump(ostream&out) const out << "new [" << *size_ << "]"; } +void PENewClass::dump(ostream&out) const +{ + out << "class_new"; +} + void PENull::dump(ostream&out) const { out << "null"; @@ -1259,6 +1265,23 @@ void LexicalScope::dump_wires_(ostream&out, unsigned indent) const } } +void PScopeExtra::dump_classes_(ostream&out, unsigned indent) const +{ + // Dump the task definitions. + typedef map::const_iterator class_iter_t; + for (class_iter_t cur = classes.begin() + ; cur != classes.end() ; ++ cur ) { + cur->second->dump(out, indent); + } +} + +void PClass::dump(ostream&out, unsigned indent) const +{ + out << setw(indent) << "" << "class " << type->name << ";" << endl; + type->pform_dump(out, indent+2); + out << setw(indent) << "" << "endclass" << endl; +} + void Module::dump_specparams_(ostream&out, unsigned indent) const { typedef map::const_iterator parm_iter_t; @@ -1328,6 +1351,8 @@ void Module::dump(ostream&out) const dump_enumerations_(out, 4); + dump_classes_(out, 4); + typedef map::const_iterator genvar_iter_t; for (genvar_iter_t cur = genvars.begin() ; cur != genvars.end() ; ++ cur ) { diff --git a/pform_pclass.cc b/pform_pclass.cc index 89e4f8115..382d3b44f 100644 --- a/pform_pclass.cc +++ b/pform_pclass.cc @@ -21,6 +21,9 @@ # include "PClass.h" # include "parse_misc.h" +/* + * The functions here help the parser put together class type declarations. + */ static PClass*pform_cur_class = 0; void pform_start_class_declaration(const struct vlltype&loc, class_type_t*type) @@ -47,14 +50,15 @@ void pform_class_property(const struct vlltype&loc, return; } + // Add the non-static properties to the class type + // object. Unwind the list of names to make a map of name to + // type. for (list::iterator cur = decls->begin() ; cur != decls->end() ; ++cur) { decl_assignment_t*curp = *cur; pform_cur_class->type->properties[curp->name] = data_type; } - - VLerror(loc, "sorry: class properties not implemented yet."); } void pform_end_class_declaration(void) diff --git a/pform_struct_type.cc b/pform_struct_type.cc index 248ce7fb7..b03b45554 100644 --- a/pform_struct_type.cc +++ b/pform_struct_type.cc @@ -56,7 +56,7 @@ static void pform_set_packed_struct(struct_type_t*struct_type, perm_string name, ivl_variable_type_t base_type = struct_type->figure_packed_base_type(); PWire*net = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, base_type); - net->set_packed_type(struct_type); + net->set_data_type(struct_type); pform_bind_attributes(net->attributes, attr, true); } @@ -89,7 +89,7 @@ static void pform_makewire(const struct vlltype&li, PWire*cur = pform_get_make_wire_in_scope(name, NetNet::WIRE, ptype, base_type); FILE_NAME(cur, li); - cur->set_packed_type(struct_type); + cur->set_data_type(struct_type); } void pform_makewire(const struct vlltype&li, diff --git a/t-dll-expr.cc b/t-dll-expr.cc index 87164c6a2..dff404f11 100644 --- a/t-dll-expr.cc +++ b/t-dll-expr.cc @@ -316,6 +316,19 @@ void dll_target::expr_creal(const NetECReal*net) expr_->u_.real_.value = net->value().as_double(); } +void dll_target::expr_null(const NetENull*net) +{ + assert(expr_ == 0); + expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); + expr_->width_ = net->expr_width(); + expr_->signed_ = 0; + expr_->sized_ = 1; + expr_->type_ = IVL_EX_NULL; + FILE_NAME(expr_, net); + expr_->value_ = IVL_VT_CLASS; + expr_->net_type= 0; +} + void dll_target::expr_event(const NetEEvent*net) { assert(expr_ == 0); diff --git a/t-dll.h b/t-dll.h index b622c576b..a999547d8 100644 --- a/t-dll.h +++ b/t-dll.h @@ -137,6 +137,7 @@ struct dll_target : public target_t, public expr_scan_t { void expr_concat(const NetEConcat*); void expr_const(const NetEConst*); void expr_creal(const NetECReal*); + void expr_null(const NetENull*); void expr_param(const NetEConstParam*); void expr_rparam(const NetECRealParam*); void expr_event(const NetEEvent*); diff --git a/target.cc b/target.cc index 72751d9e2..a0539ba7b 100644 --- a/target.cc +++ b/target.cc @@ -444,6 +444,12 @@ void expr_scan_t::expr_const(const NetEConst*) "unhandled expr_const." << endl; } +void expr_scan_t::expr_null(const NetENull*) +{ + cerr << "expr_scan_t (" << typeid(*this).name() << "): " + "unhandled expr_null." << endl; +} + void expr_scan_t::expr_param(const NetEConstParam*that) { expr_const(that); diff --git a/target.h b/target.h index 61c35d721..4db422fb6 100644 --- a/target.h +++ b/target.h @@ -150,6 +150,7 @@ struct expr_scan_t { virtual ~expr_scan_t(); virtual void expr_access_func(const NetEAccess*); virtual void expr_const(const NetEConst*); + virtual void expr_null(const NetENull*); virtual void expr_param(const NetEConstParam*); virtual void expr_rparam(const NetECRealParam*); virtual void expr_creal(const NetECReal*); diff --git a/tgt-stub/expression.c b/tgt-stub/expression.c index 8cc2cbe21..669969d6f 100644 --- a/tgt-stub/expression.c +++ b/tgt-stub/expression.c @@ -165,6 +165,16 @@ static void show_memory_expression(ivl_expr_t net, unsigned ind) width); } +static void show_null_expression(ivl_expr_t net, unsigned ind) +{ + fprintf(out, "%*s\n", ind, ""); + if (ivl_expr_value(net) != IVL_VT_CLASS) { + fprintf(out, "%sERROR: null expression must be IVL_VT_CLASS, got %s.\n", + ind+3, "", vt_type_string(net)); + stub_errors += 1; + } +} + static void show_select_expression(ivl_expr_t net, unsigned ind) { unsigned width = ivl_expr_width(net); @@ -351,6 +361,10 @@ void show_expression(ivl_expr_t net, unsigned ind) show_memory_expression(net, ind); break; + case IVL_EX_NULL: + show_null_expression(net, ind); + break; + case IVL_EX_NUMBER: { const char*bits = ivl_expr_bits(net); diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index f87face83..e13cab828 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -172,6 +172,9 @@ const char*data_type_string(ivl_variable_type_t vtype) case IVL_VT_DARRAY: vt = "darray"; break; + case IVL_VT_CLASS: + vt = "class"; + break; } return vt; diff --git a/tgt-stub/types.c b/tgt-stub/types.c index 0a7e143f5..b469d5e46 100644 --- a/tgt-stub/types.c +++ b/tgt-stub/types.c @@ -56,6 +56,9 @@ static void show_net_type(ivl_type_t net_type) case IVL_VT_DARRAY: show_net_type_darray(net_type); break; + case IVL_VT_CLASS: + fprintf(out, "class"); + break; case IVL_VT_VOID: fprintf(out, "void"); break; @@ -114,6 +117,9 @@ void show_type_of_signal(ivl_signal_t net) case IVL_VT_VOID: fprintf(out, "void"); break; + case IVL_VT_CLASS: + fprintf(out, "class"); + break; } for (dim = 0 ; dim < ivl_signal_packed_dimensions(net) ; dim += 1) {