diff --git a/Makefile.in b/Makefile.in index 3fd3bf9108..e0cb5ab586 100644 --- a/Makefile.in +++ b/Makefile.in @@ -16,7 +16,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.180 2007/02/06 05:07:31 steve Exp $" +#ident "$Id: Makefile.in,v 1.181 2007/05/24 04:07:11 steve Exp $" # # SHELL = /bin/sh @@ -108,7 +108,7 @@ load_module.o netlist.o netmisc.o net_assign.o \ net_design.o net_event.o net_expr.o net_force.o net_func.o \ net_link.o net_modulo.o net_nex_input.o net_nex_output.o \ net_proc.o net_scope.o net_udp.o pad_to_width.o \ -parse.o parse_misc.o pform.o pform_dump.o \ +parse.o parse_misc.o pform.o pform_dump.o pform_types.o \ set_width.o symbol_search.o sync.o sys_funcs.o \ verinum.o verireal.o target.o targets.o \ Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \ diff --git a/Module.cc b/Module.cc index a5bd756d01..f828b9e148 100644 --- a/Module.cc +++ b/Module.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: Module.cc,v 1.26 2007/04/19 02:52:53 steve Exp $" +#ident "$Id: Module.cc,v 1.27 2007/05/24 04:07:11 steve Exp $" #endif # include "config.h" @@ -111,9 +111,9 @@ unsigned Module::find_port(const char*name) const } -PWire* Module::get_wire(const hname_t&name) const +PWire* Module::get_wire(const pform_name_t&name) const { - map::const_iterator obj = wires_.find(name); + map::const_iterator obj = wires_.find(name); if (obj == wires_.end()) return 0; else @@ -133,11 +133,6 @@ PGate* Module::get_gate(perm_string name) return 0; } -const map& Module::get_wires() const -{ - return wires_; -} - const list& Module::get_gates() const { return gates_; @@ -151,6 +146,10 @@ const list& Module::get_behaviors() const /* * $Log: Module.cc,v $ + * Revision 1.27 2007/05/24 04:07:11 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.26 2007/04/19 02:52:53 steve * Add support for -v flag in command file. * diff --git a/Module.h b/Module.h index 5aa125bfbd..8133c21d3a 100644 --- a/Module.h +++ b/Module.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: Module.h,v 1.42 2007/04/19 02:52:53 steve Exp $" +#ident "$Id: Module.h,v 1.43 2007/05/24 04:07:11 steve Exp $" #endif # include @@ -30,6 +30,7 @@ # include "named.h" # include "LineInfo.h" # include "netlist.h" +# include "pform_types.h" class PEvent; class PExpr; class PEIdent; @@ -98,7 +99,7 @@ class Module : public LineInfo { new parameters within the module, but may be used to set values within this module (when instantiated) or in other instantiated modules. */ - mapdefparms; + mapdefparms; /* Parameters may be overridden at instantiation time; the overrides do not contain explicit parameter names, @@ -150,10 +151,9 @@ class Module : public LineInfo { // Find a wire by name. This is used for connecting gates to // existing wires, etc. - PWire* get_wire(const hname_t&name) const; + PWire* get_wire(const pform_name_t&name) const; PGate* get_gate(perm_string name); - const map& get_wires() const; const list& get_gates() const; const list& get_behaviors() const; @@ -168,7 +168,7 @@ class Module : public LineInfo { private: perm_string name_; - map wires_; + map wires_; list gates_; list behaviors_; map tasks_; @@ -182,6 +182,10 @@ class Module : public LineInfo { /* * $Log: Module.h,v $ + * Revision 1.43 2007/05/24 04:07:11 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.42 2007/04/19 02:52:53 steve * Add support for -v flag in command file. * diff --git a/PExpr.cc b/PExpr.cc index ec08c76c51..4866bf3d36 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: PExpr.cc,v 1.38 2006/10/30 05:44:49 steve Exp $" +#ident "$Id: PExpr.cc,v 1.39 2007/05/24 04:07:11 steve Exp $" #endif # include "config.h" @@ -93,13 +93,26 @@ PEBShift::~PEBShift() { } -PECallFunction::PECallFunction(const hname_t&n, const svector &parms) +PECallFunction::PECallFunction(const pform_name_t&n, const svector &parms) : path_(n), parms_(parms) { } -PECallFunction::PECallFunction(const hname_t&n) -: path_(n) +static pform_name_t pn_from_ps(perm_string n) +{ + name_component_t tmp_name (n); + pform_name_t tmp; + tmp.push_back(tmp_name); + return tmp; +} + +PECallFunction::PECallFunction(perm_string n, const svector&parms) +: path_(pn_from_ps(n)), parms_(parms) +{ +} + +PECallFunction::PECallFunction(perm_string n) +: path_(pn_from_ps(n)) { } @@ -165,33 +178,32 @@ bool PEFNumber::is_constant(Module*) const return true; } -PEIdent::PEIdent(const hname_t&s) -: path_(s), msb_(0), lsb_(0), sel_(SEL_NONE), idx_(0) +PEIdent::PEIdent(const pform_name_t&that) +: path_(that) { } -PEIdent::~PEIdent() +PEIdent::PEIdent(perm_string s) { + path_.push_back(name_component_t(s)); } -const hname_t& PEIdent::path() const +PEIdent::~PEIdent() { - return path_; } /* * An identifier can be in a constant expression if (and only if) it is * a parameter. + * + * NOTE: This test does not work if the name is hierarchical! */ bool PEIdent::is_constant(Module*mod) const { if (mod == 0) return false; - /* This is a work-around for map not matching < even when - there is a perm_string operator that can do the comprare. - - The real fix is to make the path_ carry perm_strings. */ - perm_string tmp = perm_string::literal(path_.peek_name(0)); + /* */ + perm_string tmp = path_.back().name; { map::const_iterator cur; cur = mod->parameters.find(tmp); @@ -288,6 +300,10 @@ bool PEUnary::is_constant(Module*m) const /* * $Log: PExpr.cc,v $ + * Revision 1.39 2007/05/24 04:07:11 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.38 2006/10/30 05:44:49 steve * Expression widths with unsized literals are pseudo-infinite width. * diff --git a/PExpr.h b/PExpr.h index fc203d8339..c1ad148409 100644 --- a/PExpr.h +++ b/PExpr.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: PExpr.h,v 1.87 2007/01/16 05:44:14 steve Exp $" +#ident "$Id: PExpr.h,v 1.88 2007/05/24 04:07:11 steve Exp $" #endif # include @@ -27,6 +27,7 @@ # include "netlist.h" # include "verinum.h" # include "LineInfo.h" +# include "pform_types.h" class Design; class Module; @@ -247,9 +248,14 @@ class PEFNumber : public PExpr { class PEIdent : public PExpr { public: - explicit PEIdent(const hname_t&s); + explicit PEIdent(perm_string); + explicit PEIdent(const pform_name_t&); ~PEIdent(); + // Add another name to the string of heirarchy that is the + // current identifier. + void append_name(perm_string); + virtual void dump(ostream&) const; virtual unsigned test_width(Design*des, NetScope*scope, unsigned min, unsigned lval, @@ -286,7 +292,10 @@ class PEIdent : public PExpr { virtual bool is_constant(Module*) const; verinum* eval_const(const Design*des, NetScope*sc) const; - const hname_t& path() const; + const pform_name_t& path() const { return path_; } + + private: + pform_name_t path_; private: // Common functions to calculate parts of part/bit selects. @@ -332,9 +341,9 @@ class PEIdent : public PExpr { NetScope*scope, NetESignal*net, NetScope*found) const; - hname_t path_; public: +#if 0 // Use these to support part-select operators. PExpr*msb_; PExpr*lsb_; @@ -345,6 +354,8 @@ class PEIdent : public PExpr { // expression. If this is a reference to a vector, this is a // bit select. std::vector idx_; +#endif + NetNet* elaborate_net_array_(Design*des, NetScope*scope, NetNet*sig, unsigned lwidth, const NetExpr* rise, @@ -621,8 +632,10 @@ class PETernary : public PExpr { */ class PECallFunction : public PExpr { public: - explicit PECallFunction(const hname_t&n, const svector &parms); - explicit PECallFunction(const hname_t&n); + explicit PECallFunction(const pform_name_t&n, const svector &parms); + // Call of system function (name is not heirarchical) + explicit PECallFunction(perm_string n, const svector &parms); + explicit PECallFunction(perm_string n); ~PECallFunction(); virtual void dump(ostream &) const; @@ -638,7 +651,7 @@ class PECallFunction : public PExpr { int expr_wid, bool sys_task_arg) const; private: - hname_t path_; + pform_name_t path_; svector parms_; bool check_call_matches_definition_(Design*des, NetScope*dscope) const; @@ -655,6 +668,10 @@ class PECallFunction : public PExpr { /* * $Log: PExpr.h,v $ + * Revision 1.88 2007/05/24 04:07:11 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.87 2007/01/16 05:44:14 steve * Major rework of array handling. Memories are replaced with the * more general concept of arrays. The NetMemory and NetEMemory diff --git a/PGenerate.cc b/PGenerate.cc index ff3171a322..26b7dbff43 100644 --- a/PGenerate.cc +++ b/PGenerate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: PGenerate.cc,v 1.2 2007/03/05 05:59:10 steve Exp $" +#ident "$Id: PGenerate.cc,v 1.3 2007/05/24 04:07:11 steve Exp $" #endif # include "PGenerate.h" @@ -42,9 +42,9 @@ PWire* PGenerate::add_wire(PWire*wire) return wire; } -PWire* PGenerate::get_wire(const hname_t&name) const +PWire* PGenerate::get_wire(const pform_name_t&name) const { - map::const_iterator obj = wires.find(name); + map::const_iterator obj = wires.find(name); if (obj == wires.end()) return 0; else diff --git a/PGenerate.h b/PGenerate.h index c913f87f5f..13232b6ea6 100644 --- a/PGenerate.h +++ b/PGenerate.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: PGenerate.h,v 1.2 2007/03/05 05:59:10 steve Exp $" +#ident "$Id: PGenerate.h,v 1.3 2007/05/24 04:07:11 steve Exp $" #endif # include "LineInfo.h" @@ -27,6 +27,7 @@ # include "HName.h" # include # include +# include "pform_types.h" class Design; class NetScope; @@ -59,9 +60,9 @@ class PGenerate : public LineInfo { PExpr*loop_test; PExpr*loop_step; - mapwires; + mapwires; PWire* add_wire(PWire*); - PWire* get_wire(const hname_t&name) const; + PWire* get_wire(const pform_name_t&name) const; list gates; void add_gate(PGate*); diff --git a/PWire.cc b/PWire.cc index e5e1a845c0..a81b89e684 100644 --- a/PWire.cc +++ b/PWire.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2007 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 @@ -17,29 +17,14 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: PWire.cc,v 1.13 2007/04/26 03:06:21 steve Exp $" +#ident "$Id: PWire.cc,v 1.14 2007/05/24 04:07:11 steve Exp $" #endif # include "config.h" # include "PWire.h" # include -PWire::PWire(const hname_t&n, - NetNet::Type t, - NetNet::PortType pt, - ivl_variable_type_t dt) -: hname_(n), type_(t), port_type_(pt), data_type_(dt), - signed_(false), isint_(false), -lidx_(0), ridx_(0) -{ - if (t == NetNet::INTEGER) { - type_ = NetNet::REG; - signed_ = true; - isint_ = true; - } -} - -PWire::PWire(perm_string n, +PWire::PWire(const pform_name_t&n, NetNet::Type t, NetNet::PortType pt, ivl_variable_type_t dt) @@ -59,7 +44,7 @@ NetNet::Type PWire::get_wire_type() const return type_; } -const hname_t& PWire::path() const +const pform_name_t& PWire::path() const { return hname_; } @@ -160,6 +145,10 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx) /* * $Log: PWire.cc,v $ + * Revision 1.14 2007/05/24 04:07:11 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.13 2007/04/26 03:06:21 steve * Rework hname_t to use perm_strings. * diff --git a/PWire.h b/PWire.h index d471625a64..8f304be7b3 100644 --- a/PWire.h +++ b/PWire.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: PWire.h,v 1.20 2007/04/26 03:06:22 steve Exp $" +#ident "$Id: PWire.h,v 1.21 2007/05/24 04:07:11 steve Exp $" #endif # include "netlist.h" @@ -43,24 +43,21 @@ class Design; * identifies a port by keeping it in its port list. * * The hname parameter to the constructor is a hierarchical name. It - * is an array of strings starting with the root, running towards - * the base name, and terminated by a null pointer. The environment - * allocates the memory for me. + * is the name of the wire within a module, so does not include the + * current scope or any instances. Modules contain all the wires, so + * from that perspective, sub-scopes within the module are a part of + * the wire name. */ class PWire : public LineInfo { public: - PWire(const hname_t&hname, - NetNet::Type t, - NetNet::PortType pt, - ivl_variable_type_t dt); - PWire(perm_string name, + PWire(const pform_name_t&hname, NetNet::Type t, NetNet::PortType pt, ivl_variable_type_t dt); // Return a hierarchical name. - const hname_t&path() const; + const pform_name_t&path() const; NetNet::Type get_wire_type() const; bool set_wire_type(NetNet::Type); @@ -84,10 +81,10 @@ class PWire : public LineInfo { // Write myself to the specified stream. void dump(ostream&out, unsigned ind=4) const; - void elaborate_sig(Design*, NetScope*scope) const; + NetNet* elaborate_sig(Design*, NetScope*scope) const; private: - hname_t hname_; + pform_name_t hname_; NetNet::Type type_; NetNet::PortType port_type_; ivl_variable_type_t data_type_; @@ -111,6 +108,10 @@ class PWire : public LineInfo { /* * $Log: PWire.h,v $ + * Revision 1.21 2007/05/24 04:07:11 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.20 2007/04/26 03:06:22 steve * Rework hname_t to use perm_strings. * diff --git a/Statement.cc b/Statement.cc index 02929198f9..f6f14fa654 100644 --- a/Statement.cc +++ b/Statement.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: Statement.cc,v 1.29 2004/02/18 17:11:54 steve Exp $" +#ident "$Id: Statement.cc,v 1.30 2007/05/24 04:07:11 steve Exp $" #endif # include "config.h" @@ -107,16 +107,22 @@ PBlock::~PBlock() delete list_[idx]; } -PCallTask::PCallTask(const hname_t&n, const svector&p) +PCallTask::PCallTask(const pform_name_t&n, const svector&p) : path_(n), parms_(p) { } +PCallTask::PCallTask(perm_string n, const svector&p) +: parms_(p) +{ + path_.push_back(name_component_t(n)); +} + PCallTask::~PCallTask() { } -const hname_t& PCallTask::path() const +const pform_name_t& PCallTask::path() const { return path_; } @@ -178,7 +184,7 @@ PDelayStatement::~PDelayStatement() { } -PDisable::PDisable(const hname_t&sc) +PDisable::PDisable(const pform_name_t&sc) : scope_(sc) { } @@ -273,7 +279,7 @@ PRepeat::~PRepeat() delete statement_; } -PTrigger::PTrigger(const hname_t&e) +PTrigger::PTrigger(const pform_name_t&e) : event_(e) { } @@ -295,6 +301,10 @@ PWhile::~PWhile() /* * $Log: Statement.cc,v $ + * Revision 1.30 2007/05/24 04:07:11 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.29 2004/02/18 17:11:54 steve * Use perm_strings for named langiage items. * diff --git a/Statement.h b/Statement.h index e29d89d591..21864a8315 100644 --- a/Statement.h +++ b/Statement.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: Statement.h,v 1.43 2007/03/05 05:59:10 steve Exp $" +#ident "$Id: Statement.h,v 1.44 2007/05/24 04:07:11 steve Exp $" #endif # include @@ -173,10 +173,11 @@ class PBlock : public Statement { class PCallTask : public Statement { public: - explicit PCallTask(const hname_t&n, const svector&parms); + explicit PCallTask(const pform_name_t&n, const svector&parms); + explicit PCallTask(perm_string n, const svector&parms); ~PCallTask(); - const hname_t& path() const; + const pform_name_t& path() const; unsigned nparms() const { return parms_.count(); } @@ -197,7 +198,7 @@ class PCallTask : public Statement { NetProc* elaborate_sys(Design*des, NetScope*scope) const; NetProc* elaborate_usr(Design*des, NetScope*scope) const; - hname_t path_; + pform_name_t path_; svector parms_; }; @@ -296,14 +297,14 @@ class PDelayStatement : public Statement { class PDisable : public Statement { public: - explicit PDisable(const hname_t&sc); + explicit PDisable(const pform_name_t&sc); ~PDisable(); virtual void dump(ostream&out, unsigned ind) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const; private: - hname_t scope_; + pform_name_t scope_; }; /* @@ -433,14 +434,14 @@ class PRelease : public Statement { class PTrigger : public Statement { public: - explicit PTrigger(const hname_t&ev); + explicit PTrigger(const pform_name_t&ev); ~PTrigger(); virtual NetProc* elaborate(Design*des, NetScope*scope) const; virtual void dump(ostream&out, unsigned ind) const; private: - hname_t event_; + pform_name_t event_; }; class PWhile : public Statement { @@ -460,6 +461,10 @@ class PWhile : public Statement { /* * $Log: Statement.h,v $ + * Revision 1.44 2007/05/24 04:07:11 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.43 2007/03/05 05:59:10 steve * Handle processes within generate loops. * diff --git a/design_dump.cc b/design_dump.cc index af0f396fbd..0286031f12 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: design_dump.cc,v 1.174 2007/03/02 06:13:22 steve Exp $" +#ident "$Id: design_dump.cc,v 1.175 2007/05/24 04:07:11 steve Exp $" #endif # include "config.h" @@ -871,7 +871,7 @@ void NetScope::dump(ostream&o) const /* Dump the saved defparam assignments here. */ { - map::const_iterator pp; + map::const_iterator pp; for (pp = defparams.begin() ; pp != defparams.end() ; pp ++ ) { o << " defparam " << (*pp).first << " = " << @@ -1205,6 +1205,10 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.175 2007/05/24 04:07:11 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.174 2007/03/02 06:13:22 steve * Add support for edge sensitive spec paths. * diff --git a/elab_expr.cc b/elab_expr.cc index b37efebafb..f320730e43 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elab_expr.cc,v 1.124 2007/04/01 05:28:26 steve Exp $" +#ident "$Id: elab_expr.cc,v 1.125 2007/05/24 04:07:11 steve Exp $" #endif # include "config.h" @@ -322,7 +322,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const not lead to executable code but takes the single parameter and makes it into a signed expression. No bits are changed, it just changes the interpretation. */ - if (strcmp(path_.peek_name(0), "$signed") == 0) { + if (strcmp(peek_tail_name(path_), "$signed") == 0) { if ((parms_.count() != 1) || (parms_[0] == 0)) { cerr << get_line() << ": error: The $signed() function " << "takes exactly one(1) argument." << endl; @@ -336,7 +336,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const return sub; } /* add $unsigned to match $signed */ - if (strcmp(path_.peek_name(0), "$unsigned") == 0) { + if (strcmp(peek_tail_name(path_), "$unsigned") == 0) { if ((parms_.count() != 1) || (parms_[0] == 0)) { cerr << get_line() << ": error: The $unsigned() function " << "takes exactly one(1) argument." << endl; @@ -354,8 +354,8 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const the bit width of the sub-expression. The value of the sub-expression is not used, so the expression itself can be deleted. */ - if ((strcmp(path_.peek_name(0), "$sizeof") == 0) - || (strcmp(path_.peek_name(0), "$bits") == 0)) { + if ((strcmp(peek_tail_name(path_), "$sizeof") == 0) + || (strcmp(peek_tail_name(path_), "$bits") == 0)) { if ((parms_.count() != 1) || (parms_[0] == 0)) { cerr << get_line() << ": error: The $bits() function " << "takes exactly one(1) argument." << endl; @@ -363,7 +363,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const return 0; } - if (strcmp(path_.peek_name(0), "$sizeof") == 0) + if (strcmp(peek_tail_name(path_), "$sizeof") == 0) cerr << get_line() << ": warning: $sizeof is deprecated." << " Use $bits() instead." << endl; @@ -382,7 +382,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const a single bit flag -- 1 if the expression is signed, 0 otherwise. The subexpression is elaborated but not evaluated. */ - if (strcmp(path_.peek_name(0), "$is_signed") == 0) { + if (strcmp(peek_tail_name(path_), "$is_signed") == 0) { if ((parms_.count() != 1) || (parms_[0] == 0)) { cerr << get_line() << ": error: The $is_signed() function " << "takes exactly one(1) argument." << endl; @@ -405,7 +405,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const /* Get the return type of the system function by looking it up in the sfunc_table. */ const struct sfunc_return_type*sfunc_info - = lookup_sys_func(path_.peek_name(0)); + = lookup_sys_func(peek_tail_name(path_)); ivl_variable_type_t sfunc_type = sfunc_info->type; unsigned wid = sfunc_info->wid; @@ -423,7 +423,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const if ((nparms == 1) && (parms_[0] == 0)) nparms = 0; - NetESFunc*fun = new NetESFunc(path_.peek_name(0), sfunc_type, + NetESFunc*fun = new NetESFunc(peek_tail_name(path_), sfunc_type, wid, nparms); if (sfunc_info->signed_flag) fun->cast_signed(true); @@ -455,7 +455,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const if (missing_parms > 0) { cerr << get_line() << ": error: The function " - << path_.peek_name(0) + << peek_tail_name(path_) << " has been called with empty parameters." << endl; cerr << get_line() << ": : Verilog doesn't allow " << "passing empty parameters to functions." << endl; @@ -468,7 +468,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope, int expr_wid, bool) const { - if (path_.peek_name(0)[0] == '$') + if (peek_tail_name(path_)[0] == '$') return elaborate_sfunc_(des, scope); NetFuncDef*def = des->find_function(scope, path_); @@ -620,33 +620,38 @@ NetExpr* PEFNumber::elaborate_expr(Design*des, NetScope*scope, int, bool) const bool PEIdent::calculate_parts_(Design*des, NetScope*scope, long&msb, long&lsb) const { - assert(lsb_ != 0); - assert(msb_ != 0); + const name_component_t&name_tail = path_.back(); + ivl_assert(*this, !name_tail.index.empty()); + + const index_component_t&index_tail = name_tail.index.back(); + ivl_assert(*this, index_tail.sel == index_component_t::SEL_PART); + ivl_assert(*this, index_tail.msb && index_tail.lsb); /* This handles part selects. In this case, there are two bit select expressions, and both must be constant. Evaluate them and pass the results back to the caller. */ - NetExpr*lsb_ex = elab_and_eval(des, scope, lsb_, -1); + NetExpr*lsb_ex = elab_and_eval(des, scope, index_tail.lsb, -1); NetEConst*lsb_c = dynamic_cast(lsb_ex); if (lsb_c == 0) { - cerr << lsb_->get_line() << ": error: " + cerr << index_tail.lsb->get_line() << ": error: " "Part select expressions must be constant." << endl; - cerr << lsb_->get_line() << ": : This lsb expression " - "violates the rule: " << *lsb_ << endl; + cerr << index_tail.lsb->get_line() << ": : " + "This lsb expression violates the rule: " + << *index_tail.lsb << endl; des->errors += 1; return false; } - NetExpr*msb_ex = elab_and_eval(des, scope, msb_, -1); + NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, -1); NetEConst*msb_c = dynamic_cast(msb_ex); if (msb_c == 0) { - cerr << msb_->get_line() << ": error: " + cerr << index_tail.msb->get_line() << ": error: " "Part select expressions must be constant." << endl; - cerr << msb_->get_line() << ": : This msb expression " - "violates the rule: " << *msb_ << endl; + cerr << index_tail.msb->get_line() << ": : This msb expression " + "violates the rule: " << *index_tail.msb << endl; des->errors += 1; return false; } @@ -662,13 +667,18 @@ bool PEIdent::calculate_parts_(Design*des, NetScope*scope, bool PEIdent::calculate_up_do_width_(Design*des, NetScope*scope, unsigned long&wid) const { - assert(lsb_); + const name_component_t&name_tail = path_.back(); + ivl_assert(*this, !name_tail.index.empty()); + + const index_component_t&index_tail = name_tail.index.back(); + ivl_assert(*this, index_tail.lsb && index_tail.msb); + bool flag = true; /* Calculate the width expression (in the lsb_ position) first. If the expression is not constant, error but guess 1 so we can keep going and find more errors. */ - NetExpr*wid_ex = elab_and_eval(des, scope, lsb_, -1); + NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1); NetEConst*wid_c = dynamic_cast(wid_ex); if (wid_c == 0) { @@ -695,30 +705,36 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, const NetExpr*ex1, *ex2; - symbol_search(des, scope, path_, - net, par, eve, - ex1, ex2); + symbol_search(des, scope, path_, net, par, eve, ex1, ex2); if (net != 0) { + const name_component_t&name_tail = path_.back(); + index_component_t::ctype_t use_sel = index_component_t::SEL_NONE; + if (!name_tail.index.empty()) + use_sel = name_tail.index.back().sel; + unsigned use_width = net->vector_width(); - switch (sel_) { - case SEL_NONE: + switch (use_sel) { + case index_component_t::SEL_NONE: break; - case SEL_PART: + case index_component_t::SEL_PART: { long msb, lsb; calculate_parts_(des, scope, msb, lsb); use_width = 1 + ((msb>lsb)? (msb-lsb) : (lsb-msb)); break; } - case SEL_IDX_UP: - case SEL_IDX_DO: + case index_component_t::SEL_IDX_UP: + case index_component_t::SEL_IDX_DO: { unsigned long tmp = 0; calculate_up_do_width_(des, scope, tmp); use_width = tmp; break; } + case index_component_t::SEL_BIT: + use_width = 1; + break; default: - assert(0); + ivl_assert(*this, 0); } return use_width; } @@ -774,9 +790,9 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, // Hmm... maybe this is a genvar? This is only possible while // processing generate blocks, but then the genvar_tmp will be // set in the scope. - if (path_.component_count() == 1 + if (path_.size() == 1 && scope->genvar_tmp.str() - && strcmp(path_.peek_name(0), scope->genvar_tmp) == 0) { + && strcmp(peek_tail_name(path_), scope->genvar_tmp) == 0) { verinum val (scope->genvar_tmp_val); NetEConst*tmp = new NetEConst(val); tmp->set_line(*this); @@ -790,8 +806,8 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, if (gn_specify_blocks_flag) { map::const_iterator specp; - perm_string key = perm_string::literal(path_.peek_name(0)); - if (path_.component_count() == 1 + perm_string key = peek_tail_name(path_); + if (path_.size() == 1 && ((specp = scope->specparams.find(key)) != scope->specparams.end())) { NetScope::spec_val_t value = (*specp).second; NetExpr*tmp = 0; @@ -814,8 +830,8 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, // Finally, if this is a scope name, then return that. Look // first to see if this is a name of a local scope. Failing // that, search globally for a hierarchical name. - if ((path_.peek_name(1) == 0)) - if (NetScope*nsc = scope->child(path_.peek_name(0))) { + if ((path_.size() == 1)) + if (NetScope*nsc = scope->child(peek_tail_name(path_))) { NetEScope*tmp = new NetEScope(nsc); tmp->set_line(*this); return tmp; @@ -854,13 +870,18 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des, const NetExpr*par_msb, const NetExpr*par_lsb) const { - NetExpr*tmp; + NetExpr*tmp = par->dup_expr(); - tmp = par->dup_expr(); + const name_component_t&name_tail = path_.back(); + index_component_t::ctype_t use_sel = index_component_t::SEL_NONE; + if (!name_tail.index.empty()) + use_sel = name_tail.index.back().sel; - if (sel_ == SEL_PART) { - assert(msb_ && lsb_); - assert(idx_.empty()); + if (use_sel == index_component_t::SEL_PART) { + ivl_assert(*this, !name_tail.index.empty()); + const index_component_t&index_tail = name_tail.index.back(); + ivl_assert(*this, index_tail.msb); + ivl_assert(*this, index_tail.lsb); /* If the identifier has a part select, we support it by pulling the right bits out and making a @@ -868,8 +889,8 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des, lsb of a parameter is 0 and the msb is the width of the parameter. */ - verinum*lsn = lsb_->eval_const(des, scope); - verinum*msn = msb_->eval_const(des, scope); + verinum*lsn = index_tail.lsb->eval_const(des, scope); + verinum*msn = index_tail.msb->eval_const(des, scope); if ((lsn == 0) || (msn == 0)) { cerr << get_line() << ": error: " "Part select expressions must be " @@ -926,17 +947,19 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des, delete tmp; tmp = new NetEConst(result); - } else if (sel_ == SEL_IDX_UP || sel_ == SEL_IDX_DO) { - assert(msb_); - assert(lsb_); - assert(idx_.empty()); + } else if (use_sel == index_component_t::SEL_IDX_UP || use_sel == index_component_t::SEL_IDX_DO) { + + ivl_assert(*this, !name_tail.index.empty()); + const index_component_t&index_tail = name_tail.index.back(); + ivl_assert(*this, index_tail.msb); + ivl_assert(*this, index_tail.lsb); /* Get and evaluate the width of the index select. This must be constant. */ - NetExpr*wid_ex = elab_and_eval(des, scope, lsb_, -1); + NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1); NetEConst*wid_ec = dynamic_cast (wid_ex); if (wid_ec == 0) { - cerr << lsb_->get_line() << ": error: " + cerr << index_tail.lsb->get_line() << ": error: " << "Second expression of indexed part select " << "most be constant." << endl; des->errors += 1; @@ -945,12 +968,12 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des, unsigned wid = wid_ec->value().as_ulong(); - NetExpr*idx_ex = elab_and_eval(des, scope, msb_, -1); + NetExpr*idx_ex = elab_and_eval(des, scope, index_tail.msb, -1); if (idx_ex == 0) { return 0; } - if (sel_ == SEL_IDX_DO && wid > 1) { + if (use_sel == index_component_t::SEL_IDX_DO && wid > 1) { idx_ex = make_add_expr(idx_ex, 1-(long)wid); } @@ -959,16 +982,16 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des, tmp = new NetESelect(tmp, idx_ex, wid); - } else if (!idx_.empty()) { - assert(!msb_); - assert(!lsb_); - assert(idx_.size() == 1); - assert(sel_ == SEL_NONE); + } else if (use_sel == index_component_t::SEL_BIT) { + ivl_assert(*this, !name_tail.index.empty()); + const index_component_t&index_tail = name_tail.index.back(); + ivl_assert(*this, index_tail.msb); + ivl_assert(*this, !index_tail.lsb); /* Handle the case where a parameter has a bit select attached to it. Generate a NetESelect object to select the bit as desired. */ - NetExpr*mtmp = idx_[0]->elaborate_expr(des, scope, -1,false); + NetExpr*mtmp = index_tail.msb->elaborate_expr(des, scope, -1,false); if (! dynamic_cast(mtmp)) { NetExpr*re = mtmp->eval_tree(); if (re) { @@ -1045,8 +1068,7 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des, NetEConstParam if possible. */ NetEConst*ctmp = dynamic_cast(tmp); if (ctmp != 0) { - perm_string name - = lex_strings.make(path_.peek_tail_name()); + perm_string name = peek_tail_name(path_); NetEConstParam*ptmp = new NetEConstParam(found_in, name, ctmp->value()); delete tmp; @@ -1065,17 +1087,32 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope, NetNet*net, NetScope*found_in, bool sys_task_arg) const { - if (idx_.empty() && !sys_task_arg) { + const name_component_t&name_tail = path_.back(); + + if (name_tail.index.empty() && !sys_task_arg) { cerr << get_line() << ": error: Array " << path() << " Needs an array index here." << endl; des->errors += 1; return 0; } - ivl_assert(*this, sys_task_arg || !idx_.empty()); - NetExpr*word_index = idx_.empty() + index_component_t index_front; + if (! name_tail.index.empty()) { + index_front = name_tail.index.front(); + ivl_assert(*this, index_front.sel != index_component_t::SEL_NONE); + if (index_front.sel != index_component_t::SEL_BIT) { + cerr << get_line() << ": error: Array " << path_ + << " cannot be indexed by a range." << endl; + des->errors += 1; + return 0; + } + ivl_assert(*this, index_front.msb); + ivl_assert(*this, !index_front.lsb); + } + + NetExpr*word_index = index_front.sel == index_component_t::SEL_NONE ? 0 - : elab_and_eval(des, scope, idx_[0], -1); + : elab_and_eval(des, scope, index_front.msb, -1); if (word_index == 0 && !sys_task_arg) return 0; @@ -1106,15 +1143,22 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope, NetESignal*res = new NetESignal(net, word_index); res->set_line(*this); - if (sel_ == SEL_PART) + // Detect that the word has a part select as well. + + index_component_t::ctype_t word_sel = index_component_t::SEL_NONE; + if (name_tail.index.size() > 1) + word_sel = name_tail.index.back().sel; + + if (word_sel == index_component_t::SEL_PART) return elaborate_expr_net_part_(des, scope, res, found_in); - if (sel_ == SEL_IDX_UP) + if (word_sel == index_component_t::SEL_IDX_UP) return elaborate_expr_net_idx_up_(des, scope, res, found_in); - if (sel_ == SEL_IDX_DO) + if (word_sel == index_component_t::SEL_IDX_DO) return elaborate_expr_net_idx_do_(des, scope, res, found_in); + ivl_assert(*this, word_sel == index_component_t::SEL_NONE); return res; } @@ -1125,7 +1169,6 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope, NetESignal*net, NetScope*found_in) const { long msv, lsv; - ivl_assert(*this, (idx_.empty()&& !net->word_index()) || (!idx_.empty()&& net->word_index())); bool flag = calculate_parts_(des, scope, msv, lsv); if (!flag) return 0; @@ -1183,12 +1226,14 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope, NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope, NetESignal*net, NetScope*found_in) const { - assert(lsb_ != 0); - assert(msb_ != 0); + const name_component_t&name_tail = path_.back(); + ivl_assert(*this, !name_tail.index.empty()); - ivl_assert(*this, (idx_.empty()&& !net->word_index()) || (!idx_.empty()&& net->word_index())); + const index_component_t&index_tail = name_tail.index.back(); + ivl_assert(*this, index_tail.lsb != 0); + ivl_assert(*this, index_tail.msb != 0); - NetExpr*base = elab_and_eval(des, scope, msb_, -1); + NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1); unsigned long wid = 0; calculate_up_do_width_(des, scope, wid); @@ -1235,12 +1280,14 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope, NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope, NetESignal*net, NetScope*found_in)const { - assert(lsb_ != 0); - assert(msb_ != 0); + const name_component_t&name_tail = path_.back(); + ivl_assert(*this, ! name_tail.index.empty()); - ivl_assert(*this, (idx_.empty()&& !net->word_index()) || (!idx_.empty()&& net->word_index())); + const index_component_t&index_tail = name_tail.index.back(); + ivl_assert(*this, index_tail.lsb != 0); + ivl_assert(*this, index_tail.msb != 0); - NetExpr*base = elab_and_eval(des, scope, msb_, -1); + NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1); unsigned long wid = 0; calculate_up_do_width_(des, scope, wid); @@ -1284,11 +1331,14 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope, NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope, NetESignal*net, NetScope*found_in) const { - assert(msb_ == 0); - assert(lsb_ == 0); - assert(idx_.size() == 1); + const name_component_t&name_tail = path_.back(); + ivl_assert(*this, !name_tail.index.empty()); + + const index_component_t&index_tail = name_tail.index.back(); + ivl_assert(*this, index_tail.msb != 0); + ivl_assert(*this, index_tail.lsb == 0); - NetExpr*ex = elab_and_eval(des, scope, idx_[0], -1); + NetExpr*ex = elab_and_eval(des, scope, index_tail.msb, -1); // If the bit select is constant, then treat it similar // to the part select, so that I save the effort of @@ -1358,29 +1408,30 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope, NetESignal*node = new NetESignal(net); node->set_line(*this); + index_component_t::ctype_t use_sel = index_component_t::SEL_NONE; + if (! path_.back().index.empty()) + use_sel = path_.back().index.back().sel; + // If this is a part select of a signal, then make a new // temporary signal that is connected to just the // selected bits. The lsb_ and msb_ expressions are from // the foo[msb:lsb] expression in the original. - if (sel_ == SEL_PART) + if (use_sel == index_component_t::SEL_PART) return elaborate_expr_net_part_(des, scope, node, found_in); - if (sel_ == SEL_IDX_UP) + if (use_sel == index_component_t::SEL_IDX_UP) return elaborate_expr_net_idx_up_(des, scope, node, found_in); - if (sel_ == SEL_IDX_DO) + if (use_sel == index_component_t::SEL_IDX_DO) return elaborate_expr_net_idx_do_(des, scope, node, found_in); - if (!idx_.empty()) + if (use_sel == index_component_t::SEL_BIT) return elaborate_expr_net_bit_(des, scope, node, found_in); // It's not anything else, so this must be a simple identifier // expression with no part or bit select. Return the signal // itself as the expression. - assert(sel_ == SEL_NONE); - assert(msb_ == 0); - assert(lsb_ == 0); - assert(idx_.empty()); + assert(use_sel == index_component_t::SEL_NONE); return node; } @@ -1633,6 +1684,10 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, /* * $Log: elab_expr.cc,v $ + * Revision 1.125 2007/05/24 04:07:11 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.124 2007/04/01 05:28:26 steve * Get offsets into indexed part selects correct. * diff --git a/elab_lval.cc b/elab_lval.cc index 9abbfcc3ba..2225c14ba4 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elab_lval.cc,v 1.42 2007/03/14 05:06:49 steve Exp $" +#ident "$Id: elab_lval.cc,v 1.43 2007/05/24 04:07:11 steve Exp $" #endif # include "config.h" @@ -163,11 +163,17 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, return 0; } - assert(reg); + ivl_assert(*this, reg); + + const name_component_t&name_tail = path_.back(); + + index_component_t::ctype_t use_sel = index_component_t::SEL_NONE; + if (!name_tail.index.empty()) + use_sel = name_tail.index.back().sel; // This is the special case that the l-value is an entire // memory. This is, in fact, an error. - if (reg->array_dimensions() > 0 && idx_.size() == 0) { + if (reg->array_dimensions() > 0 && name_tail.index.empty()) { cerr << get_line() << ": error: Cannot assign to array " << path_ << ". Did you forget a word index?" << endl; des->errors += 1; @@ -177,19 +183,19 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, if (reg->array_dimensions() > 0) return elaborate_lval_net_word_(des, scope, reg); - if (sel_ == SEL_PART) { + if (use_sel == index_component_t::SEL_PART) { NetAssign_*lv = new NetAssign_(reg); elaborate_lval_net_part_(des, scope, lv); return lv; } - if (sel_ == SEL_IDX_UP) { + if (use_sel == index_component_t::SEL_IDX_UP) { NetAssign_*lv = new NetAssign_(reg); elaborate_lval_net_idx_up_(des, scope, lv); return lv; } - if (sel_ == SEL_IDX_DO) { + if (use_sel == index_component_t::SEL_IDX_DO) { NetAssign_*lv = new NetAssign_(reg); elaborate_lval_net_idx_do_(des, scope, lv); return lv; @@ -208,12 +214,14 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, return 0; } - ivl_assert(*this, msb_ == 0); - ivl_assert(*this, lsb_ == 0); long msb, lsb; NetExpr*mux; - if (! idx_.empty()) { + if (use_sel == index_component_t::SEL_BIT) { + + const index_component_t&index_tail = name_tail.index.back(); + ivl_assert(*this, index_tail.msb != 0); + ivl_assert(*this, index_tail.lsb == 0); /* If there is only a single select expression, it is a bit select. Evaluate the constant value and treat it @@ -221,9 +229,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, expression it not constant, then return the expression as a mux. */ - ivl_assert(*this, idx_.size() == 1); - - NetExpr*index_expr = elab_and_eval(des, scope, idx_[0], -1); + NetExpr*index_expr = elab_and_eval(des, scope, index_tail.msb, -1); if (NetEConst*index_con = dynamic_cast (index_expr)) { msb = index_con->value().as_long(); @@ -311,9 +317,15 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des, NetScope*scope, NetNet*reg) const { - assert(idx_.size() == 1); + const name_component_t&name_tail = path_.back(); + ivl_assert(*this, !name_tail.index.empty()); + + const index_component_t&index_head = name_tail.index.front(); + ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT); + ivl_assert(*this, index_head.msb != 0); + ivl_assert(*this, index_head.lsb == 0); - NetExpr*word = elab_and_eval(des, scope, idx_[0], -1); + NetExpr*word = elab_and_eval(des, scope, index_head.msb, -1); // If there is a non-zero base to the memory, then build an // expression to calculate the canonical address. @@ -348,13 +360,17 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des, /* An array word may also have part selects applied to them. */ - if (sel_ == SEL_PART) + index_component_t::ctype_t use_sel = index_component_t::SEL_NONE; + if (name_tail.index.size() > 1) + use_sel = name_tail.index.back().sel; + + if (use_sel == index_component_t::SEL_PART) elaborate_lval_net_part_(des, scope, lv); - if (sel_ == SEL_IDX_UP) + if (use_sel == index_component_t::SEL_IDX_UP) elaborate_lval_net_idx_up_(des, scope, lv); - if (sel_ == SEL_IDX_DO) + if (use_sel == index_component_t::SEL_IDX_DO) elaborate_lval_net_idx_do_(des, scope, lv); return lv; @@ -417,8 +433,12 @@ bool PEIdent::elaborate_lval_net_idx_up_(Design*des, NetScope*scope, NetAssign_*lv) const { - assert(lsb_); - assert(msb_); + const name_component_t&name_tail = path_.back();; + ivl_assert(*this, !name_tail.index.empty()); + + const index_component_t&index_tail = name_tail.index.back(); + ivl_assert(*this, index_tail.msb != 0); + ivl_assert(*this, index_tail.lsb != 0); NetNet*reg = lv->sig(); assert(reg); @@ -436,7 +456,7 @@ bool PEIdent::elaborate_lval_net_idx_up_(Design*des, unsigned long wid; calculate_up_do_width_(des, scope, wid); - NetExpr*base = elab_and_eval(des, scope, msb_, -1); + NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1); /* Correct the mux for the range of the vector. */ if (reg->msb() < reg->lsb()) @@ -457,8 +477,13 @@ bool PEIdent::elaborate_lval_net_idx_do_(Design*des, NetScope*scope, NetAssign_*lv) const { - assert(lsb_); - assert(msb_); + const name_component_t&name_tail = path_.back();; + ivl_assert(*this, !name_tail.index.empty()); + + const index_component_t&index_tail = name_tail.index.back(); + ivl_assert(*this, index_tail.msb != 0); + ivl_assert(*this, index_tail.lsb != 0); + cerr << get_line() << ": internal error: don't know how to " "deal with SEL_IDX_DO in lval?" << endl; des->errors += 1; @@ -475,6 +500,10 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const /* * $Log: elab_lval.cc,v $ + * Revision 1.43 2007/05/24 04:07:11 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.42 2007/03/14 05:06:49 steve * Replace some asserts with ivl_asserts. * diff --git a/elab_net.cc b/elab_net.cc index 6d3c44626c..0a8d3247d2 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elab_net.cc,v 1.203 2007/04/18 01:40:49 steve Exp $" +#ident "$Id: elab_net.cc,v 1.204 2007/05/24 04:07:11 steve Exp $" #endif # include "config.h" @@ -1230,7 +1230,7 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope, unsigned errors = 0; unsigned func_pins = 0; - if (path_.peek_name(0)[0] == '$') + if (path_.front().name[0] == '$') return elaborate_net_sfunc_(des, scope, width, rise, fall, decay, drive0, drive1); @@ -1320,11 +1320,13 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope, Link::strength_t drive0, Link::strength_t drive1) const { + perm_string name = peek_tail_name(path_); + /* Handle the special case that the function call is to $signed. This takes a single expression argument, and forces it to be a signed result. Otherwise, it is as if the $signed did not exist. */ - if (strcmp(path_.peek_name(0), "$signed") == 0) { + if (strcmp(name, "$signed") == 0) { if ((parms_.count() != 1) || (parms_[0] == 0)) { cerr << get_line() << ": error: The $signed() function " << "takes exactly one(1) argument." << endl; @@ -1340,7 +1342,7 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope, } /* handle $unsigned like $signed */ - if (strcmp(path_.peek_name(0), "$unsigned") == 0) { + if (strcmp(name, "$unsigned") == 0) { if ((parms_.count() != 1) || (parms_[0] == 0)) { cerr << get_line() << ": error: The $unsigned() function " << "takes exactly one(1) argument." << endl; @@ -1355,11 +1357,11 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope, return sub; } - const struct sfunc_return_type*def = lookup_sys_func(path_.peek_name(0)); + const struct sfunc_return_type*def = lookup_sys_func(name); if (def == 0) { cerr << get_line() << ": error: System function " - << path_.peek_name(0) << " not defined." << endl; + << peek_tail_name(path_) << " not defined." << endl; des->errors += 1; return 0; } @@ -1545,15 +1547,19 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope, Link::strength_t drive0, Link::strength_t drive1) const { - assert(msb_ == 0); - assert(lsb_ == 0); - assert(idx_.size() == 1); + const name_component_t&name_tail = path_.back(); + ivl_assert(*this, !name_tail.index.empty()); + + const index_component_t&index_tail = name_tail.index.back(); + ivl_assert(*this, index_tail.sel == index_component_t::SEL_BIT); + ivl_assert(*this, index_tail.msb != 0); + ivl_assert(*this, index_tail.lsb == 0); /* Elaborate the selector. */ NetNet*sel; if (sig->msb() < sig->lsb()) { - NetExpr*sel_expr = idx_[0]->elaborate_expr(des, scope, -1, false); + NetExpr*sel_expr = index_tail.msb->elaborate_expr(des, scope, -1, false); sel_expr = make_sub_expr(sig->lsb(), sel_expr); if (NetExpr*tmp = sel_expr->eval_tree()) { delete sel_expr; @@ -1563,7 +1569,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope, sel = sel_expr->synthesize(des); } else if (sig->lsb() != 0) { - NetExpr*sel_expr = idx_[0]->elaborate_expr(des, scope, -1,false); + NetExpr*sel_expr = index_tail.msb->elaborate_expr(des, scope, -1,false); sel_expr = make_add_expr(sel_expr, - sig->lsb()); if (NetExpr*tmp = sel_expr->eval_tree()) { delete sel_expr; @@ -1573,7 +1579,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope, sel = sel_expr->synthesize(des); } else { - sel = idx_[0]->elaborate_net(des, scope, 0, 0, 0, 0); + sel = index_tail.msb->elaborate_net(des, scope, 0, 0, 0, 0); } if (debug_elaborate) { @@ -1604,10 +1610,12 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope, Link::strength_t drive0, Link::strength_t drive1) const { - assert(scope); + ivl_assert(*this, scope); + + const name_component_t&name_tail = path_.back(); NetNet* sig = 0; - const NetExpr*par = 0; + const NetExpr*par = 0; NetEvent* eve = 0; symbol_search(des, scope, path_, sig, par, eve); @@ -1646,13 +1654,13 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope, /* Check for the error case that the name is not found, and it is hierarchical. We can't just create a name in another scope, it's just not allowed. */ - if (sig == 0 && path_.component_count() != 1) { + if (sig == 0 && path_.size() != 1) { cerr << get_line() << ": error: The hierarchical name " << path_ << " is undefined in " << scope->name() << "." << endl; - hname_t tmp_path = path_; - delete[] tmp_path.remove_tail_name(); + pform_name_t tmp_path = path_; + tmp_path.pop_back(); NetScope*tmp_scope = des->find_scope(scope, tmp_path); if (tmp_scope == 0) { @@ -1667,28 +1675,28 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope, /* Fallback, this may be an implicitly declared net. */ if (sig == 0) { NetNet::Type nettype = scope->default_nettype(); - sig = new NetNet(scope, lex_strings.make(path_.peek_name(0)), + sig = new NetNet(scope, name_tail.name, nettype, 1); sig->data_type(IVL_VT_LOGIC); if (error_implicit || (nettype == NetNet::NONE)) { cerr << get_line() << ": error: " - << scope->name() << "." << path_.peek_name(0) + << scope->name() << "." << name_tail.name << " not defined in this scope." << endl; des->errors += 1; } else if (warn_implicit) { cerr << get_line() << ": warning: implicit " "definition of wire " << scope->name() - << "." << path_.peek_name(0) << "." << endl; + << "." << name_tail.name << "." << endl; } } - assert(sig); + ivl_assert(*this, sig); /* Handle the case that this is an array elsewhere. */ if (sig->array_dimensions() > 0) { - if (idx_.size() == 0) { + if (name_tail.index.size() == 0) { cerr << get_line() << ": error: Array " << sig->name() << " cannot be used here without an index." << endl; des->errors += 1; @@ -1700,14 +1708,16 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope, drive0, drive1); } + index_component_t::ctype_t use_sel = index_component_t::SEL_NONE; + if (!name_tail.index.empty()) + use_sel = name_tail.index.back().sel; + /* Catch the case of a non-constant bit select. That should be handled elsewhere. */ - if (! idx_.empty()) { - assert(msb_ == 0); - assert(lsb_ == 0); - assert(idx_.size() == 1); + if (use_sel == index_component_t::SEL_BIT) { + const index_component_t&index_tail = name_tail.index.back(); - verinum*mval = idx_[0]->eval_const(des, scope); + verinum*mval = index_tail.msb->eval_const(des, scope); if (mval == 0) { return elaborate_net_bitmux_(des, scope, sig, rise, fall, decay, drive0, drive1); @@ -1755,9 +1765,14 @@ NetNet* PEIdent::elaborate_net_array_(Design*des, NetScope*scope, Link::strength_t drive0, Link::strength_t drive1) const { - ivl_assert(*this, idx_.size() >= 1); - - NetExpr*index_ex = elab_and_eval(des, scope, idx_[0], -1); + const name_component_t&name_tail = path_.back(); + ivl_assert(*this, name_tail.index.size() >= 1); + const index_component_t&index_head = name_tail.index.front(); + ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT); + ivl_assert(*this, index_head.msb != 0); + ivl_assert(*this, index_head.lsb == 0); + + NetExpr*index_ex = elab_and_eval(des, scope, index_head.msb, -1); if (index_ex == 0) return 0; @@ -1821,6 +1836,10 @@ NetNet* PEIdent::elaborate_net_array_(Design*des, NetScope*scope, tmp->data_type(sig->data_type()); connect(tmp->pin(0), mux->pin_Result()); + // If there are more index items then there are array + // dimensions, then treat them as word part selects. For + // example, if this is a memory array, then array dimensions + // is 1 and unsigned midx, lidx; if (eval_part_select_(des, scope, sig, midx, lidx)) do { @@ -2006,7 +2025,7 @@ NetNet* PEIdent::make_implicit_net_(Design*des, NetScope*scope) const NetNet*sig = 0; if (!error_implicit && nettype!=NetNet::NONE) { - sig = new NetNet(scope, lex_strings.make(path_.peek_name(0)), + sig = new NetNet(scope, peek_tail_name(path_), NetNet::IMPLICIT, 1); /* Implicit nets are always scalar logic. */ sig->data_type(IVL_VT_LOGIC); @@ -2014,7 +2033,7 @@ NetNet* PEIdent::make_implicit_net_(Design*des, NetScope*scope) const if (warn_implicit) { cerr << get_line() << ": warning: implicit " "definition of wire logic " << scope->name() - << "." << path_.peek_name(0) << "." << endl; + << "." << peek_tail_name(path_) << "." << endl; } } else { @@ -2037,20 +2056,30 @@ NetNet* PEIdent::make_implicit_net_(Design*des, NetScope*scope) const bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig, unsigned&midx, unsigned&lidx) const { - switch (sel_) { + const name_component_t&name_tail = path_.back(); + // Only treat as part/bit selects any index that is beyond the + // word selects for an array. This is not an array, then + // dimensions==0 and any index is treated as a select. + if (name_tail.index.size() <= sig->array_dimensions()) { + midx = sig->vector_width()-1; + lidx = 0; + return true; + } + + ivl_assert(*this, !name_tail.index.empty()); + + const index_component_t&index_tail = name_tail.index.back(); + + switch (index_tail.sel) { default: cerr << get_line() << ": internal error: " - << "Unexpected sel_ value = " << sel_ << endl; - assert(0); + << "Unexpected sel_ value = " << index_tail.sel << endl; + ivl_assert(*this, 0); break; - case PEIdent::SEL_IDX_DO: - case PEIdent::SEL_IDX_UP: { - assert(msb_); - assert(lsb_); - assert(idx_.size() == sig->array_dimensions()); - - NetExpr*tmp_ex = elab_and_eval(des, scope, msb_, -1); + case index_component_t::SEL_IDX_DO: + case index_component_t::SEL_IDX_UP: { + NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1); NetEConst*tmp = dynamic_cast(tmp_ex); assert(tmp); @@ -2058,14 +2087,14 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig, midx = sig->sb_to_idx(midx_val); delete tmp_ex; - tmp_ex = elab_and_eval(des, scope, lsb_, -1); + tmp_ex = elab_and_eval(des, scope, index_tail.lsb, -1); tmp = dynamic_cast(tmp_ex); assert(tmp); long wid = tmp->value().as_long(); delete tmp_ex; - if (sel_ == PEIdent::SEL_IDX_UP) + if (index_tail.sel == index_component_t::SEL_IDX_UP) lidx = sig->sb_to_idx(midx_val+wid-1); else lidx = sig->sb_to_idx(midx_val-wid+1); @@ -2079,12 +2108,9 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig, break; } - case PEIdent::SEL_PART: { - assert(msb_); - assert(lsb_); - assert(idx_.size() == sig->array_dimensions()); + case index_component_t::SEL_PART: { - NetExpr*tmp_ex = elab_and_eval(des, scope, msb_, -1); + NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1); NetEConst*tmp = dynamic_cast(tmp_ex); assert(tmp); @@ -2092,12 +2118,12 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig, midx = sig->sb_to_idx(midx_val); delete tmp_ex; - tmp_ex = elab_and_eval(des, scope, lsb_, -1); + tmp_ex = elab_and_eval(des, scope, index_tail.lsb, -1); tmp = dynamic_cast(tmp_ex); if (tmp == 0) { cerr << get_line() << ": internal error: " << "lsb expression is not constant?: " - << *tmp_ex << ", " << *lsb_ << endl; + << *tmp_ex << ", " << *index_tail.lsb << endl; } assert(tmp); @@ -2131,19 +2157,16 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig, break; } - case PEIdent::SEL_NONE: - if (idx_.size() > sig->array_dimensions()) { - unsigned a_dims = sig->array_dimensions(); - assert(msb_ == 0); - assert(lsb_ == 0); - assert(idx_.size() == a_dims+1); - verinum*mval = idx_[a_dims]->eval_const(des, scope); + case index_component_t::SEL_BIT: + if (name_tail.index.size() > sig->array_dimensions()) { + const index_component_t&index_head = name_tail.index.front(); + verinum*mval = index_head.msb->eval_const(des, scope); if (mval == 0) { cerr << get_line() << ": error: Index of " << path_ << " needs to be constant in this context." << endl; cerr << get_line() << ": : Index expression is: " - << *(idx_[0]) << endl; + << *index_head.msb << endl; des->errors += 1; return false; } @@ -2160,17 +2183,9 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig, lidx = midx; } else { - if (msb_ || lsb_) { - cerr << get_line() << ": internal error: " - << "Unexpected msb_/lsb_ values?" << endl; - if (msb_) - cerr << get_line() << " : " - << *msb_ << endl; - if (lsb_) - cerr << get_line() << " : " - << *lsb_ << endl; - } - assert(msb_ == 0 && lsb_ == 0); + cerr << get_line() << ": internal error: " + << "Bit select " << path_ << endl; + ivl_assert(*this, 0); midx = sig->vector_width() - 1; lidx = 0; } @@ -2245,10 +2260,16 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, // The default word select is the first. unsigned widx = 0; + const name_component_t&name_tail = path_.back(); + if (sig->array_dimensions() > 0) { - assert(!idx_.empty()); - NetExpr*tmp_ex = elab_and_eval(des, scope, idx_[0], -1); + ivl_assert(*this, !name_tail.index.empty()); + + const index_component_t&index_head = name_tail.index.front(); + ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT); + + NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1); NetEConst*tmp = dynamic_cast(tmp_ex); assert(tmp); @@ -2260,7 +2281,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, cerr << get_line() << ": debug: Use [" << widx << "]" << " to index l-value array." << endl; - } else { + } else if (!name_tail.index.empty()) { if (! eval_part_select_(des, scope, sig, midx, lidx)) return 0; } @@ -2941,6 +2962,10 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope, /* * $Log: elab_net.cc,v $ + * Revision 1.204 2007/05/24 04:07:11 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.203 2007/04/18 01:40:49 steve * Fix elaboration of multiply of two constants. * diff --git a/elab_pexpr.cc b/elab_pexpr.cc index 55b89202a5..8f71778ecd 100644 --- a/elab_pexpr.cc +++ b/elab_pexpr.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elab_pexpr.cc,v 1.26 2007/04/26 03:06:22 steve Exp $" +#ident "$Id: elab_pexpr.cc,v 1.27 2007/05/24 04:07:11 steve Exp $" #endif # include "config.h" @@ -130,44 +130,51 @@ NetExpr*PEFNumber::elaborate_pexpr(Design*des, NetScope*scope) const */ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const { - hname_t path = path_; - perm_string name = path.remove_tail_name(); + pform_name_t path = path_; + name_component_t name_tail = path_.back(); + path.pop_back(); NetScope*pscope = scope; - if (path.peek_name(0)) + if (path_.size() > 0) pscope = des->find_scope(scope, path); const NetExpr*ex_msb; const NetExpr*ex_lsb; - const NetExpr*ex = pscope->get_parameter(name, ex_msb, ex_lsb); + const NetExpr*ex = pscope->get_parameter(name_tail.name, ex_msb, ex_lsb); if (ex == 0) { - cerr << get_line() << ": error: identifier ``" << path_ << + cerr << get_line() << ": error: identifier ``" << name_tail.name << "'' is not a parameter in " << scope->name() << "." << endl; des->errors += 1; return 0; } - NetExpr*res = new NetEParam(des, pscope, name); + NetExpr*res = new NetEParam(des, pscope, name_tail.name); res->set_line(*this); assert(res); - if (msb_ && lsb_) { - assert(idx_.empty()); + index_component_t::ctype_t use_sel = index_component_t::SEL_NONE; + if (!name_tail.index.empty()) + use_sel = name_tail.index.back().sel; + + switch (use_sel) { + case index_component_t::SEL_NONE: + break; + default: + case index_component_t::SEL_PART: cerr << get_line() << ": sorry: Cannot part select " "bits of parameters." << endl; des->errors += 1; + break; - } else if (!idx_.empty()) { - assert(msb_==0); - assert(lsb_==0); - assert(idx_.size() == 1); + case index_component_t::SEL_BIT: /* We have here a bit select. Insert a NetESelect node to handle it. */ - NetExpr*tmp = idx_[0]->elaborate_pexpr(des, scope); + NetExpr*tmp = name_tail.index.back().msb->elaborate_pexpr(des, scope); if (tmp != 0) { res = new NetESelect(res, tmp, 1); } + break; } return res; @@ -233,6 +240,10 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const /* * $Log: elab_pexpr.cc,v $ + * Revision 1.27 2007/05/24 04:07:11 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.26 2007/04/26 03:06:22 steve * Rework hname_t to use perm_strings. * diff --git a/elab_scope.cc b/elab_scope.cc index 2b324c3390..a31bc495ea 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elab_scope.cc,v 1.44 2007/03/22 16:08:15 steve Exp $" +#ident "$Id: elab_scope.cc,v 1.45 2007/05/24 04:07:11 steve Exp $" #endif # include "config.h" @@ -66,7 +66,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, // place of the elaborated expression. typedef map::const_iterator mparm_it_t; - typedef map::const_iterator hparm_it_t; + typedef map::const_iterator pform_parm_it_t; // This loop scans the parameters in the module, and creates @@ -200,7 +200,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, // here because the parameter receiving the assignment may be // in a scope not discovered by this pass. - for (hparm_it_t cur = defparms.begin() + for (pform_parm_it_t cur = defparms.begin() ; cur != defparms.end() ; cur ++ ) { PExpr*ex = (*cur).second; @@ -761,6 +761,10 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const /* * $Log: elab_scope.cc,v $ + * Revision 1.45 2007/05/24 04:07:11 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.44 2007/03/22 16:08:15 steve * Spelling fixes from Larry * diff --git a/elab_sig.cc b/elab_sig.cc index 0d0abf8fa4..fc1a07297e 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elab_sig.cc,v 1.50 2007/04/26 03:06:22 steve Exp $" +#ident "$Id: elab_sig.cc,v 1.51 2007/05/24 04:07:11 steve Exp $" #endif # include "config.h" @@ -34,6 +34,7 @@ # include "netlist.h" # include "netmisc.h" # include "util.h" +# include "ivl_assert.h" /* * This local function checks if a named signal is connected to a @@ -41,8 +42,10 @@ * within the port_t that have a matching name. */ static bool signal_is_in_port(const svector&ports, - const hname_t&name) + NetNet*sig) { + perm_string name = sig->name(); + for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) { Module::port_t*pp = ports[idx]; @@ -53,9 +56,15 @@ static bool signal_is_in_port(const svector&ports, // This port has an internal connection. In this case, // the port has 0 or more NetEIdent objects concatenated // together that form the port. + + // Note that module ports should not have any heirarchy + // in their names: they are in the root of the module + // scope by definition. + for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) { + perm_string pname = peek_tail_name(pp->expr[cc]->path()); assert(pp->expr[cc]); - if (pp->expr[cc]->path() == name) + if (pname == name) return true; } } @@ -63,6 +72,7 @@ static bool signal_is_in_port(const svector&ports, return false; } +#if 0 static NetNet*find_signal_in_scope(NetScope*scope, const hname_t&path) { NetScope*cur = scope; @@ -78,15 +88,12 @@ static NetNet*find_signal_in_scope(NetScope*scope, const hname_t&path) return cur->find_signal(path.peek_name(idx)); } +#endif bool Module::elaborate_sig(Design*des, NetScope*scope) const { bool flag = true; - // Get all the explicitly declared wires of the module and - // start the signals list with them. - const map&wl = get_wires(); - // Scan all the ports of the module, and make sure that each // is connected to wires that have port declarations. for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) { @@ -94,12 +101,12 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const if (pp == 0) continue; - map::const_iterator wt; + map::const_iterator wt; for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) { - hname_t port_path (pp->expr[cc]->path()); - wt = wl.find(port_path); + pform_name_t port_path (pp->expr[cc]->path()); + wt = wires_.find(port_path); - if (wt == wl.end()) { + if (wt == wires_.end()) { cerr << get_line() << ": error: " << "Port " << pp->expr[cc]->path() << " (" << (idx+1) << ") of module " << name_ @@ -119,14 +126,11 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const } } - for (map::const_iterator wt = wl.begin() - ; wt != wl.end() - ; wt ++ ) { + for (map::const_iterator wt = wires_.begin() + ; wt != wires_.end() ; wt ++ ) { PWire*cur = (*wt).second; - cur->elaborate_sig(des, scope); - - NetNet*sig = find_signal_in_scope(scope, cur->path()); + NetNet*sig = cur->elaborate_sig(des, scope); // If this wire is a signal of the module (as opposed to // a port of a function) and is a port, then check that @@ -138,12 +142,10 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const if (sig && (sig->scope() == scope) && (cur->get_port_type() != NetNet::NOT_A_PORT)) { - hname_t name = (*wt).first; - - if (! signal_is_in_port(ports, name)) { + if (! signal_is_in_port(ports, sig)) { cerr << cur->get_line() << ": error: Signal " - << name << " has a declared direction " + << sig->name() << " has a declared direction " << "but is not a port." << endl; des->errors += 1; } @@ -286,7 +288,7 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const { // Scan the declared PWires to elaborate the obvious signals // in the current scope. - typedef map::const_iterator wires_it_t; + typedef map::const_iterator wires_it_t; for (wires_it_t wt = wires.begin() ; wt != wires.end() ; wt ++ ) { @@ -420,9 +422,11 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const name. We know by design that the port name is given as two components: .. */ - hname_t path = (*ports_)[idx]->path(); - perm_string pname = lex_strings.make(path.peek_name(1)); - perm_string ppath = lex_strings.make(path.peek_name(0)); + pform_name_t path = (*ports_)[idx]->path(); + ivl_assert(*this, path.size() == 2); + + perm_string pname = peek_tail_name(path); + perm_string ppath = peek_head_name(path); if (ppath != scope->basename()) { cerr << get_line() << ": internal error: function " @@ -473,28 +477,26 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const name. We know by design that the port name is given as two components: .. */ - hname_t path = (*ports_)[idx]->path(); - assert(path.peek_name(0) && path.peek_name(1)); + pform_name_t path = (*ports_)[idx]->path(); + ivl_assert(*this, path.size() == 2); + + perm_string scope_name = peek_head_name(path); + perm_string port_name = peek_tail_name(path); /* check that the current scope really does have the name of the first component of the task port name. Do this by looking up the task scope in the parent of the current scope. */ - if (scope->parent()->child(path.peek_name(0)) != scope) { - cerr << "internal error: task scope " << path - << " not the same as scope " << scope->name() - << "?!" << endl; - return; - } + ivl_assert(*this, scope->basename() == scope_name); /* Find the signal for the port. We know by definition that it is in the scope of the task, so look only in the scope. */ - NetNet*tmp = scope->find_signal(path.peek_name(1)); + NetNet*tmp = scope->find_signal(port_name); if (tmp == 0) { cerr << get_line() << ": internal error: " - << "Could not find port " << path.peek_name(1) + << "Could not find port " << port_name << " in scope " << scope->name() << endl; scope->dump(cerr); } @@ -518,16 +520,19 @@ bool PGate::elaborate_sig(Design*des, NetScope*scope) const * elaboration this creates an object in the design that represent the * defined item. */ -void PWire::elaborate_sig(Design*des, NetScope*scope) const +NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const { /* The parser may produce hierarchical names for wires. I here follow the scopes down to the base where I actually want to elaborate the NetNet object. */ - { hname_t tmp_path = hname_; - tmp_path.remove_tail_name(); - for (unsigned idx = 0 ; tmp_path.peek_name(idx) ; idx += 1) { - scope = scope->child(tmp_path.peek_name(idx)); + { pform_name_t tmp_path = hname_; + tmp_path.pop_back(); + while (! tmp_path.empty()) { + name_component_t cur = tmp_path.front(); + tmp_path.pop_front(); + + scope = scope->child(cur.name); if (scope == 0) { cerr << get_line() << ": internal error: " @@ -580,7 +585,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const "Unable to evaluate constant expression ``" << *msb_[idx] << "''." << endl; des->errors += 1; - return; + return 0; } mnum[idx] = tmp->value().as_long(); @@ -593,7 +598,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const "Unable to evaluate constant expression ``" << *lsb_[idx] << "''." << endl; des->errors += 1; - return; + return 0; } lnum[idx] = tmp->value().as_long(); @@ -609,7 +614,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const << "'' declared both as a vector and a scalar." << endl; des->errors += 1; - return; + return 0; } @@ -622,7 +627,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const " vs. [" << mnum[0] << ":" << lnum[0] << "]" " for signal ``" << hname_ << "''" << endl; des->errors += 1; - return; + return 0; } } @@ -657,9 +662,9 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const if ((lexp == 0) || (rexp == 0)) { cerr << get_line() << ": internal error: There is " << "a problem evaluating indices for ``" - << hname_.peek_tail_name() << "''." << endl; + << hname_ << "''." << endl; des->errors += 1; - return; + return 0; } NetEConst*lcon = dynamic_cast (lexp); @@ -668,9 +673,9 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const if ((lcon == 0) || (rcon == 0)) { cerr << get_line() << ": internal error: The indices " << "are not constant for array ``" - << hname_.peek_tail_name() << "''." << endl; + << hname_ << "''." << endl; des->errors += 1; - return; + return 0; } verinum lval = lcon->value(); @@ -679,8 +684,6 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const delete lexp; delete rexp; - perm_string name = lex_strings.make(hname_.peek_tail_name()); - array_dimensions = 1; array_s0 = lval.as_long(); array_e0 = rval.as_long(); @@ -720,7 +723,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const } } - perm_string name = lex_strings.make(hname_.peek_tail_name()); + perm_string name = peek_tail_name(hname_); if (debug_elaborate) { cerr << get_line() << ": debug: Create signal " << wtype << " ["<attribute(attrib_list[idx].key, attrib_list[idx].val); + + return sig; } /* * $Log: elab_sig.cc,v $ + * Revision 1.51 2007/05/24 04:07:11 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.50 2007/04/26 03:06:22 steve * Rework hname_t to use perm_strings. * diff --git a/elaborate.cc b/elaborate.cc index 6bbde023d2..b55bb91dbb 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elaborate.cc,v 1.370 2007/04/16 01:10:07 steve Exp $" +#ident "$Id: elaborate.cc,v 1.371 2007/05/24 04:07:11 steve Exp $" #endif # include "config.h" @@ -770,8 +770,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const if (mport.count() == 0) continue; - NetNet*tmp = des->find_signal(instance[0], - mport[0]->path()); + perm_string pname = peek_tail_name(mport[0]->path()); + + NetNet*tmp = instance[0]->find_signal(pname); assert(tmp); if (tmp->port_type() == NetNet::PINPUT) { @@ -1833,7 +1834,7 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const NetProc* PCallTask::elaborate(Design*des, NetScope*scope) const { - if (path_.peek_name(0)[0] == '$') + if (peek_tail_name(path_)[0] == '$') return elaborate_sys(des, scope); else return elaborate_usr(des, scope); @@ -1877,7 +1878,7 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const } } - NetSTask*cur = new NetSTask(path_.peek_name(0), eparms); + NetSTask*cur = new NetSTask(peek_tail_name(path_), eparms); return cur; } @@ -3416,6 +3417,10 @@ Design* elaborate(listroots) /* * $Log: elaborate.cc,v $ + * Revision 1.371 2007/05/24 04:07:11 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.370 2007/04/16 01:10:07 steve * Properly ignore unsupported ifnone. * diff --git a/eval.cc b/eval.cc index 1e9f159874..550b209693 100644 --- a/eval.cc +++ b/eval.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: eval.cc,v 1.45 2007/03/07 00:38:15 steve Exp $" +#ident "$Id: eval.cc,v 1.46 2007/05/24 04:07:12 steve Exp $" #endif # include "config.h" @@ -177,16 +177,17 @@ verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const NetEvent*eve; const NetExpr*expr; + const name_component_t&name_tail = path_.back(); + // Handle the special case that this ident is a genvar // variable name. In that case, the genvar meaning preempts // everything and we just return that value immediately. if (scope->genvar_tmp - && strcmp(path_.peek_tail_name(),scope->genvar_tmp) == 0) { + && strcmp(name_tail.name,scope->genvar_tmp) == 0) { return new verinum(scope->genvar_tmp_val); } - symbol_search(des, scope, path_, - net, expr, eve); + symbol_search(des, scope, path_, net, expr, eve); if (expr == 0) return 0; @@ -201,7 +202,7 @@ verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const assert(eval); - if (msb_ || lsb_) + if (!name_tail.index.empty()) return 0; @@ -275,6 +276,10 @@ verinum* PEUnary::eval_const(const Design*des, NetScope*scope) const /* * $Log: eval.cc,v $ + * Revision 1.46 2007/05/24 04:07:12 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.45 2007/03/07 00:38:15 steve * Lint fixes. * diff --git a/net_design.cc b/net_design.cc index b9bdb1d32e..e2b865386f 100644 --- a/net_design.cc +++ b/net_design.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: net_design.cc,v 1.51 2007/04/26 03:06:22 steve Exp $" +#ident "$Id: net_design.cc,v 1.52 2007/05/24 04:07:12 steve Exp $" #endif # include "config.h" @@ -114,26 +114,28 @@ const list Design::find_root_scopes() const * more step down the tree until the name runs out or the search * fails. */ -NetScope* Design::find_scope(const hname_t&path) const +NetScope* Design::find_scope(const pform_name_t&path) const { - if (path.peek_name(0) == 0) + if (path.empty()) return 0; for (list::const_iterator scope = root_scopes_.begin() ; scope != root_scopes_.end(); scope++) { NetScope*cur = *scope; - if (strcmp(path.peek_name(0), cur->basename()) != 0) + if (strcmp(peek_head_name(path), cur->basename()) != 0) continue; - unsigned hidx = 1; + pform_name_t tmp = path; + tmp.pop_front(); + while (cur) { - const char*name = path.peek_name(hidx); - if (name == 0) - return cur; + if (tmp.empty()) return cur; + perm_string name = peek_head_name(tmp); cur = cur->child(name); - hidx += 1; + + tmp.pop_front(); } } @@ -143,27 +145,30 @@ NetScope* Design::find_scope(const hname_t&path) const /* * This is a relative lookup of a scope by name. The starting point is - * the scope parameter is the place within which I start looking for - * the scope. If I do not find the scope within the passed scope, - * start looking in parent scopes until I find it, or I run out of - * parent scopes. + * the scope parameter within which I start looking for the scope. If + * I do not find the scope within the passed scope, start looking in + * parent scopes until I find it, or I run out of parent scopes. */ -NetScope* Design::find_scope(NetScope*scope, const hname_t&path) const +NetScope* Design::find_scope(NetScope*scope, const pform_name_t&path) const { assert(scope); - if (path.peek_name(0) == 0) + if (path.empty()) return scope; for ( ; scope ; scope = scope->parent()) { - unsigned hidx = 0; - const char*key = path.peek_name(hidx); + + pform_name_t tmp = path; + name_component_t name_front = tmp.front(); + perm_string key = name_front.name; NetScope*cur = scope; do { cur = cur->child(key); if (cur == 0) break; - hidx += 1; - key = path.peek_name(hidx); + tmp.pop_front(); + if (tmp.empty()) break; + name_front = tmp.front(); + key = name_front.name; } while (key); if (cur) return cur; @@ -196,12 +201,13 @@ void NetScope::run_defparams(Design*des) } } - map::const_iterator pp; + map::const_iterator pp; for (pp = defparams.begin() ; pp != defparams.end() ; pp ++ ) { NetExpr*val = (*pp).second; - hname_t path = (*pp).first; + pform_name_t path = (*pp).first; - perm_string perm_name = path.remove_tail_name(); + perm_string perm_name = peek_tail_name(path); + path.pop_back(); /* If there is no path on the name, then the targ_scope is the current scope. */ @@ -423,12 +429,13 @@ const char* Design::get_flag(const string&key) const * It is the job of this function to properly implement Verilog scope * rules as signals are concerned. */ -NetNet* Design::find_signal(NetScope*scope, hname_t path) +NetNet* Design::find_signal(NetScope*scope, pform_name_t path) { assert(scope); - perm_string key = path.remove_tail_name(); - if (path.peek_name(0)) + perm_string key = peek_tail_name(path); + path.pop_back(); + if (! path.empty()) scope = find_scope(scope, path); while (scope) { @@ -444,7 +451,7 @@ NetNet* Design::find_signal(NetScope*scope, hname_t path) return 0; } -NetFuncDef* Design::find_function(NetScope*scope, const hname_t&name) +NetFuncDef* Design::find_function(NetScope*scope, const pform_name_t&name) { assert(scope); NetScope*func = find_scope(scope, name); @@ -454,7 +461,7 @@ NetFuncDef* Design::find_function(NetScope*scope, const hname_t&name) return 0; } -NetFuncDef* Design::find_function(const hname_t&key) +NetFuncDef* Design::find_function(const pform_name_t&key) { NetScope*func = find_scope(key); if (func && (func->type() == NetScope::FUNC)) @@ -463,7 +470,7 @@ NetFuncDef* Design::find_function(const hname_t&key) return 0; } -NetScope* Design::find_task(NetScope*scope, const hname_t&name) +NetScope* Design::find_task(NetScope*scope, const pform_name_t&name) { NetScope*task = find_scope(scope, name); if (task && (task->type() == NetScope::TASK)) @@ -472,7 +479,7 @@ NetScope* Design::find_task(NetScope*scope, const hname_t&name) return 0; } -NetScope* Design::find_task(const hname_t&key) +NetScope* Design::find_task(const pform_name_t&key) { NetScope*task = find_scope(key); if (task && (task->type() == NetScope::TASK)) @@ -558,6 +565,10 @@ void Design::delete_process(NetProcTop*top) /* * $Log: net_design.cc,v $ + * Revision 1.52 2007/05/24 04:07:12 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.51 2007/04/26 03:06:22 steve * Rework hname_t to use perm_strings. * diff --git a/netlist.h b/netlist.h index 57961bf4d1..e635e1494b 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: netlist.h,v 1.378 2007/04/26 03:06:22 steve Exp $" +#ident "$Id: netlist.h,v 1.379 2007/05/24 04:07:12 steve Exp $" #endif /* @@ -33,6 +33,7 @@ # include # include # include "ivl_target.h" +# include "pform_types.h" # include "config.h" # include "verinum.h" # include "verireal.h" @@ -3291,7 +3292,7 @@ class NetScope : public Attrib { assignments from the scope pass to the parameter evaluation step. After that, it is not used. */ - mapdefparams; + mapdefparams; public: /* After everything is all set up, the code generators like @@ -3391,8 +3392,8 @@ class Design { path is taken as an absolute scope name. Otherwise, the scope is located starting at the passed scope and working up if needed. */ - NetScope* find_scope(const hname_t&path) const; - NetScope* find_scope(NetScope*, const hname_t&path) const; + NetScope* find_scope(const pform_name_t&path) const; + NetScope* find_scope(NetScope*, const pform_name_t&path) const; // PARAMETERS @@ -3404,15 +3405,15 @@ class Design { this method, unlike the NetScope::find_signal method, handles global name binding. */ - NetNet*find_signal(NetScope*scope, hname_t path); + NetNet*find_signal(NetScope*scope, pform_name_t path); // Functions - NetFuncDef* find_function(NetScope*scope, const hname_t&key); - NetFuncDef* find_function(const hname_t&path); + NetFuncDef* find_function(NetScope*scope, const pform_name_t&key); + NetFuncDef* find_function(const pform_name_t&path); // Tasks - NetScope* find_task(NetScope*scope, const hname_t&name); - NetScope* find_task(const hname_t&key); + NetScope* find_task(NetScope*scope, const pform_name_t&name); + NetScope* find_task(const pform_name_t&key); // NODES void add_node(NetNode*); @@ -3500,6 +3501,10 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.379 2007/05/24 04:07:12 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.378 2007/04/26 03:06:22 steve * Rework hname_t to use perm_strings. * diff --git a/netmisc.h b/netmisc.h index b20e1f8225..416f8de391 100644 --- a/netmisc.h +++ b/netmisc.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: netmisc.h,v 1.29 2007/03/08 05:30:03 steve Exp $" +#ident "$Id: netmisc.h,v 1.30 2007/05/24 04:07:12 steve Exp $" #endif # include "netlist.h" @@ -40,20 +40,20 @@ * these values are set to 0. */ extern NetScope* symbol_search(const Design*des, - NetScope*start, hname_t path, + NetScope*start, pform_name_t path, NetNet*&net, /* net/reg */ const NetExpr*&par,/* parameter */ NetEvent*&eve, /* named event */ const NetExpr*&ex1, const NetExpr*&ex2); inline NetScope* symbol_search(const Design*des, - NetScope*start, const hname_t&path, + NetScope*start, const pform_name_t&path, NetNet*&net, /* net/reg */ const NetExpr*&par,/* parameter */ NetEvent*&eve /* named event */) { const NetExpr*ex1, *ex2; - return symbol_search(des, start, path, net, /*mem,*/ par, eve, ex1, ex2); + return symbol_search(des, start, path, net, par, eve, ex1, ex2); } /* @@ -125,6 +125,10 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope, /* * $Log: netmisc.h,v $ + * Revision 1.30 2007/05/24 04:07:12 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.29 2007/03/08 05:30:03 steve * Limit the calculated widths of constants. * diff --git a/parse.y b/parse.y index 83cabfa424..e025fec992 100644 --- a/parse.y +++ b/parse.y @@ -1,7 +1,7 @@ %{ /* - * Copyright (c) 1998-2006 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2007 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 @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: parse.y,v 1.236 2007/04/26 03:06:22 steve Exp $" +#ident "$Id: parse.y,v 1.237 2007/05/24 04:07:12 steve Exp $" #endif # include "config.h" @@ -98,6 +98,7 @@ static list* list_from_identifier(list*tmp, char*id) strdup. They can be put into lists with the texts type. */ char*text; list*perm_strings; + pform_name_t*pform_name; hname_t*hier; @@ -123,8 +124,6 @@ static list* list_from_identifier(list*tmp, char*id) svector*event_expr; - PEIdent*indexed_identifier; - NetNet::Type nettype; PGBuiltin::Type gatetype; NetNet::PortType porttype; @@ -191,7 +190,6 @@ static list* list_from_identifier(list*tmp, char*id) %type udp_initial udp_init_opt %type udp_initial_expr_opt -%type identifier %type register_variable net_variable %type register_variable_list net_variable_list list_of_identifiers @@ -217,13 +215,13 @@ static list* list_from_identifier(list*tmp, char*id) %type gate_instance %type gate_instance_list +%type heirarchy_identifier %type expression expr_primary %type lpvalue %type delay_value delay_value_simple %type delay1 delay3 delay3_opt delay_value_list %type expression_list_with_nuls expression_list_proper %type cont_assign cont_assign_list -%type indexed_identifier %type range range_opt %type net_type var_type net_type_opt @@ -492,7 +490,7 @@ charge_strength_opt ; defparam_assign - : identifier '=' expression + : heirarchy_identifier '=' expression { PExpr*tmp = $3; if (!pform_expression_is_constant(tmp)) { yyerror(@3, "error: parameter value " @@ -605,7 +603,7 @@ delay_value_simple } } | IDENTIFIER - { PEIdent*tmp = new PEIdent(hname_t(lex_strings.make($1))); + { PEIdent*tmp = new PEIdent(lex_strings.make($1)); tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); $$ = tmp; @@ -671,16 +669,14 @@ dr_strength1 ; event_control - : '@' identifier + : '@' heirarchy_identifier { PEIdent*tmpi = new PEIdent(*$2); - tmpi->set_file(@2.text); - tmpi->set_lineno(@2.first_line); - delete $2; PEEvent*tmpe = new PEEvent(PEEvent::ANYEDGE, tmpi); PEventStatement*tmps = new PEventStatement(tmpe); tmps->set_file(@1.text); tmps->set_lineno(@1.first_line); $$ = tmps; + delete $2; } | '@' '(' event_expression_list ')' { PEventStatement*tmp = new PEventStatement(*$3); @@ -1034,53 +1030,29 @@ expr_primary } | SYSTEM_IDENTIFIER { perm_string tn = lex_strings.make($1); - PECallFunction*tmp = new PECallFunction(hname_t(tn)); + PECallFunction*tmp = new PECallFunction(tn); tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); $$ = tmp; delete $1; } - /* The indexed_identifier rule matches simple identifiers as well as - indexed arrays. Part selects are handled below. */ - - | indexed_identifier - { PEIdent*tmp = $1; - $$ = tmp; - } + /* The heirarchy_identifier rule matches simple identifiers as well as + indexed arrays and part selects */ - /* There are 3 kinds of part selects. The basic part select has the - usual [M:L] syntax. The indexed part selects use +: or -: in - place of the : in the basic part select, and the first expression - is not limited to constant values. */ - - | indexed_identifier '[' expression ':' expression ']' - { PEIdent*tmp = $1; - tmp->msb_ = $3; - tmp->lsb_ = $5; - tmp->sel_ = PEIdent::SEL_PART; - $$ = tmp; - } - | indexed_identifier '[' expression K_PO_POS expression ']' - { PEIdent*tmp = $1; - tmp->msb_ = $3; - tmp->lsb_ = $5; - tmp->sel_ = PEIdent::SEL_IDX_UP; - $$ = tmp; - } - | indexed_identifier '[' expression K_PO_NEG expression ']' - { PEIdent*tmp = $1; - tmp->msb_ = $3; - tmp->lsb_ = $5; - tmp->sel_ = PEIdent::SEL_IDX_DO; - $$ = tmp; - } + | heirarchy_identifier + { PEIdent*tmp = new PEIdent(*$1); + tmp->set_file(@1.text); + tmp->set_lineno(@1.first_line); + $$ = tmp; + delete $1; + } /* An identifer followed by an expression list in parentheses is a function call. If a system identifier, then a system function call. */ - | identifier '(' expression_list_proper ')' + | heirarchy_identifier '(' expression_list_proper ')' { PECallFunction*tmp = new PECallFunction(*$1, *$3); tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); @@ -1089,7 +1061,7 @@ expr_primary } | SYSTEM_IDENTIFIER '(' expression_list_proper ')' { perm_string tn = lex_strings.make($1); - PECallFunction*tmp = new PECallFunction(hname_t(tn), *$3); + PECallFunction*tmp = new PECallFunction(tn, *$3); tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); $$ = tmp; @@ -1345,39 +1317,61 @@ gatetype /* A general identifier is a hierarchical name, with the right most name the base of the identifier. This rule builds up a - hierarchical name from left to right, forming a list of names. */ -identifier - : IDENTIFIER - { $$ = new hname_t(lex_strings.make($1)); - delete $1; - } - | identifier '.' IDENTIFIER - { hname_t * tmp = $1; - tmp->append(lex_strings.make($3)); - delete $3; - $$ = tmp; - } - ; - - /* An indexed_identifier is an identifier with a bit-select - expression. This bit select may be an array index or bit index, - to be sorted out later. */ -indexed_identifier - : identifier - { PEIdent*tmp = new PEIdent(*$1); - tmp->sel_ = PEIdent::SEL_NONE; - tmp->set_file(@1.text); - tmp->set_lineno(@1.first_line); - delete $1; - $$ = tmp; - } - | indexed_identifier '[' expression ']' - { PEIdent*tmp = $1; - tmp->sel_ = PEIdent::SEL_NONE; - tmp->idx_.push_back($3); - $$ = tmp; - } - ; + hierarchical name from the left to the right, forming a list of + names. */ + +heirarchy_identifier + : IDENTIFIER + { $$ = new pform_name_t; + $$->push_back(name_component_t(lex_strings.make($1))); + delete $1; + } + | heirarchy_identifier '.' IDENTIFIER + { pform_name_t * tmp = $1; + tmp->push_back(name_component_t(lex_strings.make($3))); + delete $3; + $$ = tmp; + } + | heirarchy_identifier '[' expression ']' + { pform_name_t * tmp = $1; + name_component_t&tail = tmp->back(); + index_component_t itmp; + itmp.sel = index_component_t::SEL_BIT; + itmp.msb = $3; + tail.index.push_back(itmp); + $$ = tmp; + } + | heirarchy_identifier '[' expression ':' expression ']' + { pform_name_t * tmp = $1; + name_component_t&tail = tmp->back(); + index_component_t itmp; + itmp.sel = index_component_t::SEL_PART; + itmp.msb = $3; + itmp.lsb = $5; + tail.index.push_back(itmp); + $$ = tmp; + } + | heirarchy_identifier '[' expression K_PO_POS expression ']' + { pform_name_t * tmp = $1; + name_component_t&tail = tmp->back(); + index_component_t itmp; + itmp.sel = index_component_t::SEL_IDX_UP; + itmp.msb = $3; + itmp.lsb = $5; + tail.index.push_back(itmp); + $$ = tmp; + } + | heirarchy_identifier '[' expression K_PO_NEG expression ']' + { pform_name_t * tmp = $1; + name_component_t&tail = tmp->back(); + index_component_t itmp; + itmp.sel = index_component_t::SEL_IDX_DO; + itmp.msb = $3; + itmp.lsb = $5; + tail.index.push_back(itmp); + $$ = tmp; + } + ; /* This is a list of identifiers. The result is a list of strings, each one of the identifiers in the list. These are simple, @@ -1552,39 +1546,21 @@ signed_opt : K_signed { $$ = true; } | {$$ = false; } ; assignments. It is more limited then the general expr_primary rule to reflect the rules for assignment l-values. */ lpvalue - : indexed_identifier - { PEIdent*tmp = $1; - $$ = tmp; - } - | indexed_identifier '[' expression ':' expression ']' - { PEIdent*tmp = $1; - tmp->msb_ = $3; - tmp->lsb_ = $5; - tmp->sel_ = PEIdent::SEL_PART; - $$ = tmp; - } - | indexed_identifier '[' expression K_PO_POS expression ']' - { PEIdent*tmp = $1; - tmp->msb_ = $3; - tmp->lsb_ = $5; - tmp->sel_ = PEIdent::SEL_IDX_UP; - $$ = tmp; - } - | indexed_identifier '[' expression K_PO_NEG expression ']' - { PEIdent*tmp = $1; - tmp->msb_ = $3; - tmp->lsb_ = $5; - tmp->sel_ = PEIdent::SEL_IDX_DO; - $$ = tmp; - } - | '{' expression_list_proper '}' - { PEConcat*tmp = new PEConcat(*$2); - tmp->set_file(@1.text); - tmp->set_lineno(@1.first_line); - delete $2; - $$ = tmp; - } - ; + : heirarchy_identifier + { PEIdent*tmp = new PEIdent(*$1); + tmp->set_file(@1.text); + tmp->set_lineno(@1.first_line); + $$ = tmp; + delete $1; + } + | '{' expression_list_proper '}' + { PEConcat*tmp = new PEConcat(*$2); + tmp->set_file(@1.text); + tmp->set_lineno(@1.first_line); + delete $2; + $$ = tmp; + } + ; /* Continuous assignments have a list of individual assignments. */ @@ -2306,67 +2282,87 @@ port_opt port_reference - : IDENTIFIER - { Module::port_t*ptmp; - ptmp = pform_module_port_reference($1, @1.text, - @1.first_line); - delete $1; - $$ = ptmp; - } - - | IDENTIFIER '[' expression ':' expression ']' - { PEIdent*wtmp = new PEIdent(hname_t(lex_strings.make($1))); - wtmp->set_file(@1.text); - wtmp->set_lineno(@1.first_line); - if (!pform_expression_is_constant($3)) { - yyerror(@3, "error: msb expression of " - "port part select must be constant."); - } - if (!pform_expression_is_constant($5)) { - yyerror(@5, "error: lsb expression of " - "port part select must be constant."); - } - wtmp->msb_ = $3; - wtmp->lsb_ = $5; - wtmp->sel_ = PEIdent::SEL_PART; - Module::port_t*ptmp = new Module::port_t; - ptmp->name = perm_string(); - ptmp->expr = svector(1); - ptmp->expr[0] = wtmp; - delete $1; - $$ = ptmp; - } - - | IDENTIFIER '[' expression ']' - { PEIdent*tmp = new PEIdent(hname_t(lex_strings.make($1))); - tmp->set_file(@1.text); - tmp->set_lineno(@1.first_line); - if (!pform_expression_is_constant($3)) { - yyerror(@3, "error: port bit select " - "must be constant."); - } - tmp->msb_ = $3; - Module::port_t*ptmp = new Module::port_t; - ptmp->name = perm_string(); - ptmp->expr = svector(1); - ptmp->expr[0] = tmp; - delete $1; - $$ = ptmp; - } - - | IDENTIFIER '[' error ']' - { yyerror(@1, "error: invalid port bit select"); - Module::port_t*ptmp = new Module::port_t; - PEIdent*wtmp = new PEIdent(hname_t(lex_strings.make($1))); - wtmp->set_file(@1.text); - wtmp->set_lineno(@1.first_line); - ptmp->name = lex_strings.make($1); - ptmp->expr = svector(1); - ptmp->expr[0] = wtmp; - delete $1; - $$ = ptmp; - } - ; + : IDENTIFIER + { Module::port_t*ptmp; + ptmp = pform_module_port_reference($1, @1.text, @1.first_line); + delete $1; + $$ = ptmp; + } + + | IDENTIFIER '[' expression ':' expression ']' + { if (!pform_expression_is_constant($3)) { + yyerror(@3, "error: msb expression of " + "port part select must be constant."); + } + if (!pform_expression_is_constant($5)) { + yyerror(@5, "error: lsb expression of " + "port part select must be constant."); + } + index_component_t itmp; + itmp.sel = index_component_t::SEL_PART; + itmp.msb = $3; + itmp.lsb = $5; + + name_component_t ntmp (lex_strings.make($1)); + ntmp.index.push_back(itmp); + + pform_name_t pname; + pname.push_back(ntmp); + + PEIdent*wtmp = new PEIdent(pname); + wtmp->set_file(@1.text); + wtmp->set_lineno(@1.first_line); + + Module::port_t*ptmp = new Module::port_t; + ptmp->name = perm_string(); + ptmp->expr = svector(1); + ptmp->expr[0] = wtmp; + + delete $1; + $$ = ptmp; + } + + | IDENTIFIER '[' expression ']' + { if (!pform_expression_is_constant($3)) { + yyerror(@3, "error: port bit select " + "must be constant."); + } + index_component_t itmp; + itmp.sel = index_component_t::SEL_BIT; + itmp.msb = $3; + itmp.lsb = 0; + + name_component_t ntmp (lex_strings.make($1)); + ntmp.index.push_back(itmp); + + pform_name_t pname; + pname.push_back(ntmp); + + PEIdent*tmp = new PEIdent(pname); + tmp->set_file(@1.text); + tmp->set_lineno(@1.first_line); + + Module::port_t*ptmp = new Module::port_t; + ptmp->name = perm_string(); + ptmp->expr = svector(1); + ptmp->expr[0] = tmp; + delete $1; + $$ = ptmp; + } + + | IDENTIFIER '[' error ']' + { yyerror(@1, "error: invalid port bit select"); + Module::port_t*ptmp = new Module::port_t; + PEIdent*wtmp = new PEIdent(lex_strings.make($1)); + wtmp->set_file(@1.text); + wtmp->set_lineno(@1.first_line); + ptmp->name = lex_strings.make($1); + ptmp->expr = svector(1); + ptmp->expr[0] = wtmp; + delete $1; + $$ = ptmp; + } + ; port_reference_list @@ -2791,16 +2787,12 @@ spec_notifier_opt spec_notifier : ',' { } - | ',' identifier + | ',' heirarchy_identifier { delete $2; } | spec_notifier ',' { } - | spec_notifier ',' identifier + | spec_notifier ',' heirarchy_identifier { delete $3; } - | spec_notifier ',' identifier '[' expr_primary ']' - { delete $3; - delete $5; - } | IDENTIFIER { delete $1; } ; @@ -2917,14 +2909,14 @@ statement $$ = tmp; } - | K_disable identifier ';' + | K_disable heirarchy_identifier ';' { PDisable*tmp = new PDisable(*$2); tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); delete $2; $$ = tmp; } - | K_TRIGGER identifier ';' + | K_TRIGGER heirarchy_identifier ';' { PTrigger*tmp = new PTrigger(*$2); tmp->set_file(@2.text); tmp->set_lineno(@2.first_line); @@ -3132,7 +3124,7 @@ statement $$ = tmp; } | SYSTEM_IDENTIFIER '(' expression_list_with_nuls ')' ';' - { PCallTask*tmp = new PCallTask(hname_t(lex_strings.make($1)), *$3); + { PCallTask*tmp = new PCallTask(lex_strings.make($1), *$3); tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); delete $1; @@ -3141,13 +3133,13 @@ statement } | SYSTEM_IDENTIFIER ';' { svectorpt (0); - PCallTask*tmp = new PCallTask(hname_t(lex_strings.make($1)), pt); + PCallTask*tmp = new PCallTask(lex_strings.make($1), pt); tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); delete $1; $$ = tmp; } - | identifier '(' expression_list_proper ')' ';' + | heirarchy_identifier '(' expression_list_proper ')' ';' { PCallTask*tmp = new PCallTask(*$1, *$3); tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); @@ -3160,7 +3152,7 @@ statement between parentheses, but it seems natural, and people commonly want it. So accept it explicitly. */ - | identifier '(' ')' ';' + | heirarchy_identifier '(' ')' ';' { svectorpt (0); PCallTask*tmp = new PCallTask(*$1, pt); tmp->set_file(@1.text); @@ -3168,7 +3160,7 @@ statement delete $1; $$ = tmp; } - | identifier ';' + | heirarchy_identifier ';' { svectorpt (0); PCallTask*tmp = new PCallTask(*$1, pt); tmp->set_file(@1.text); @@ -3523,7 +3515,7 @@ udp_sequ_entry udp_initial : K_initial IDENTIFIER '=' number ';' { PExpr*etmp = new PENumber($4); - PEIdent*itmp = new PEIdent(hname_t(lex_strings.make($2))); + PEIdent*itmp = new PEIdent(lex_strings.make($2)); PAssign*atmp = new PAssign(itmp, etmp); atmp->set_file(@2.text); atmp->set_lineno(@2.first_line); @@ -3588,40 +3580,40 @@ udp_output_sym | '-' { $$ = '-'; } ; + /* Port declarations create wires for the inputs and the output. The + makes for these ports are scoped within the UDP, so there is no + heirarchy involved. */ udp_port_decl - : K_input list_of_identifiers ';' - { $$ = pform_make_udp_input_ports($2); } - | K_output IDENTIFIER ';' - { PWire*pp = new PWire(lex_strings.make($2), - NetNet::IMPLICIT, - NetNet::POUTPUT, - IVL_VT_LOGIC); - svector*tmp = new svector(1); - (*tmp)[0] = pp; - $$ = tmp; - delete $2; - } - | K_reg IDENTIFIER ';' - { PWire*pp = new PWire(lex_strings.make($2), - NetNet::REG, - NetNet::PIMPLICIT, - IVL_VT_LOGIC); - svector*tmp = new svector(1); - (*tmp)[0] = pp; - $$ = tmp; - delete $2; - } - | K_reg K_output IDENTIFIER ';' - { PWire*pp = new PWire(lex_strings.make($3), - NetNet::REG, - NetNet::POUTPUT, - IVL_VT_LOGIC); - svector*tmp = new svector(1); - (*tmp)[0] = pp; - $$ = tmp; - delete $3; - } - ; + : K_input list_of_identifiers ';' + { $$ = pform_make_udp_input_ports($2); } + | K_output IDENTIFIER ';' + { pform_name_t pname; + pname.push_back(lex_strings.make($2)); + PWire*pp = new PWire(pname, NetNet::IMPLICIT, NetNet::POUTPUT, IVL_VT_LOGIC); + svector*tmp = new svector(1); + (*tmp)[0] = pp; + $$ = tmp; + delete $2; + } + | K_reg IDENTIFIER ';' + { pform_name_t pname; + pname.push_back(lex_strings.make($2)); + PWire*pp = new PWire(pname, NetNet::REG, NetNet::PIMPLICIT, IVL_VT_LOGIC); + svector*tmp = new svector(1); + (*tmp)[0] = pp; + $$ = tmp; + delete $2; + } + | K_reg K_output IDENTIFIER ';' + { pform_name_t pname; + pname.push_back(lex_strings.make($3)); + PWire*pp = new PWire(pname, NetNet::REG, NetNet::POUTPUT, IVL_VT_LOGIC); + svector*tmp = new svector(1); + (*tmp)[0] = pp; + $$ = tmp; + delete $3; + } + ; udp_port_decls : udp_port_decl diff --git a/pform.cc b/pform.cc index 44297d9ef1..cf23bf6cc4 100644 --- a/pform.cc +++ b/pform.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2004 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2007 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 @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pform.cc,v 1.145 2007/04/26 03:06:22 steve Exp $" +#ident "$Id: pform.cc,v 1.146 2007/05/24 04:07:12 steve Exp $" #endif # include "config.h" @@ -33,6 +33,7 @@ # include # include # include +# include # include # include @@ -80,34 +81,34 @@ static unsigned pform_timescale_line = 0; * and named blocks causes scope to be pushed and popped. The module * name is not included in this scope stack. * - * The hier_name function, therefore, converts the name to the scope - * of the module currently in progress. + * The hier_name function, therefore, converts the name to the scoped + * name within the module currently in progress. It never includes an + * instance name. * * The scope stack does not include any scope created by a generate * scheme. */ -static hname_t scope_stack; +static pform_name_t scope_stack; void pform_push_scope(char*name) { - scope_stack.append(lex_strings.make(name)); + scope_stack.push_back(name_component_t(lex_strings.make(name))); } void pform_pop_scope() { - perm_string tmp = scope_stack.remove_tail_name(); - assert(tmp); + scope_stack.pop_back(); } -static hname_t hier_name(const char*tail) +static pform_name_t hier_name(const char*tail) { - hname_t name = scope_stack; - name.append(lex_strings.make(tail)); + pform_name_t name = scope_stack; + name.push_back(name_component_t(lex_strings.make(tail))); return name; } -static PWire*get_wire_in_module(const hname_t&name) +static PWire*get_wire_in_module(const pform_name_t&name) { /* Note that if we are processing a generate, then the scope depth will be empty because generate schemes @@ -277,7 +278,7 @@ Module::port_t* pform_module_port_reference(char*name, unsigned lineno) { Module::port_t*ptmp = new Module::port_t; - PEIdent*tmp = new PEIdent(hname_t(lex_strings.make(name))); + PEIdent*tmp = new PEIdent(lex_strings.make(name)); tmp->set_file(file); tmp->set_lineno(lineno); ptmp->name = lex_strings.make(name); @@ -511,9 +512,10 @@ void pform_make_udp(perm_string name, list*parms, map defs; for (unsigned idx = 0 ; idx < decl->count() ; idx += 1) { - hname_t pname = (*decl)[idx]->path(); + pform_name_t pname = (*decl)[idx]->path(); + string port_name = peek_tail_name(pname).str(); - if (PWire*cur = defs[pname.peek_name(0).str()]) { + if (PWire*cur = defs[port_name]) { bool rc = true; assert((*decl)[idx]); if ((*decl)[idx]->get_port_type() != NetNet::PIMPLICIT) { @@ -526,7 +528,7 @@ void pform_make_udp(perm_string name, list*parms, } } else { - defs[pname.peek_name(0).str()] = (*decl)[idx]; + defs[port_name] = (*decl)[idx]; } } @@ -672,7 +674,7 @@ void pform_make_udp(perm_string name, list*parms, // Make the port list for the UDP for (unsigned idx = 0 ; idx < pins.count() ; idx += 1) - udp->ports[idx] = pins[idx]->path().peek_name(0); + udp->ports[idx] = peek_tail_name(pins[idx]->path()); process_udp_table(udp, table, file, lineno); udp->initial = init; @@ -756,7 +758,7 @@ void pform_make_udp(perm_string name, bool synchronous_flag, // Make the port list for the UDP for (unsigned idx = 0 ; idx < pins.count() ; idx += 1) - udp->ports[idx] = pins[idx]->path().peek_name(0); + udp->ports[idx] = peek_tail_name(pins[idx]->path()); assert(udp); assert(table); @@ -1090,7 +1092,7 @@ void pform_make_pgassign_list(svector*alist, void pform_make_reginit(const struct vlltype&li, const char*name, PExpr*expr) { - const hname_t sname = hier_name(name); + const pform_name_t sname = hier_name(name); PWire*cur = pform_cur_module->get_wire(sname); if (cur == 0) { VLerror(li, "internal error: reginit to non-register?"); @@ -1129,11 +1131,11 @@ void pform_module_define_port(const struct vlltype&li, svector*range, svector*attr) { - hname_t name = hier_name(nm); + pform_name_t name = hier_name(nm); PWire*cur = pform_cur_module->get_wire(name); if (cur) { ostringstream msg; - msg << name << " definition conflicts with " + msg << nm << " definition conflicts with " << "definition at " << cur->get_line() << "."; VLerror(msg.str().c_str()); @@ -1196,7 +1198,7 @@ void pform_makewire(const vlltype&li, const char*nm, ivl_variable_type_t dt, svector*attr) { - hname_t name = hier_name(nm); + pform_name_t name = hier_name(nm); PWire*cur = get_wire_in_module(name); @@ -1206,7 +1208,7 @@ void pform_makewire(const vlltype&li, const char*nm, bool rc = cur->set_wire_type(type); if (rc == false) { ostringstream msg; - msg << name << " definition conflicts with " + msg << nm << " definition conflicts with " << "definition at " << cur->get_line() << "."; VLerror(msg.str().c_str()); @@ -1286,10 +1288,10 @@ void pform_makewire(const vlltype&li, pform_set_net_range(first->name, range, signed_flag, dt); perm_string first_name = lex_strings.make(first->name); - hname_t name = hier_name(first_name); + pform_name_t name = hier_name(first_name); PWire*cur = get_wire_in_module(name); if (cur != 0) { - PEIdent*lval = new PEIdent(hname_t(first_name)); + PEIdent*lval = new PEIdent(first_name); lval->set_file(li.text); lval->set_lineno(li.first_line); PGAssign*ass = pform_make_pgassign(lval, first->expr, @@ -1307,7 +1309,7 @@ void pform_makewire(const vlltype&li, void pform_set_port_type(perm_string nm, NetNet::PortType pt, const char*file, unsigned lineno) { - hname_t name = hier_name(nm); + pform_name_t name = hier_name(nm); PWire*cur = pform_cur_module->get_wire(name); if (cur == 0) { cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_LOGIC); @@ -1324,14 +1326,14 @@ void pform_set_port_type(perm_string nm, NetNet::PortType pt, case NetNet::NOT_A_PORT: cerr << file << ":" << lineno << ": error: " - << "port " << name << " is not in the port list." + << "port " << nm << " is not in the port list." << endl; error_count += 1; break; default: cerr << file << ":" << lineno << ": error: " - << "port " << name << " already has a port declaration." + << "port " << nm << " already has a port declaration." << endl; error_count += 1; break; @@ -1392,7 +1394,7 @@ svector*pform_make_task_ports(NetNet::PortType pt, ; cur != names->end() ; cur ++ ) { perm_string txt = *cur; - hname_t name = hier_name(txt); + pform_name_t name = hier_name(txt); /* Look for a preexisting wire. If it exists, set the port direction. If not, create it. */ @@ -1437,7 +1439,7 @@ void pform_set_function(perm_string name, PFunction*func) void pform_set_attrib(perm_string name, perm_string key, char*value) { - hname_t path (name); + pform_name_t path = hier_name(name); if (PWire*cur = pform_cur_module->get_wire(path)) { cur->attributes[key] = new PEString(value); @@ -1530,7 +1532,7 @@ void pform_set_specparam(perm_string name, PExpr*expr) pform_cur_module->specparams[name] = expr; } -void pform_set_defparam(const hname_t&name, PExpr*expr) +void pform_set_defparam(const pform_name_t&name, PExpr*expr) { assert(expr); pform_cur_module->defparms[name] = expr; @@ -1624,7 +1626,7 @@ void pform_set_port_type(const struct vlltype&li, static void pform_set_reg_integer(const char*nm) { - hname_t name = hier_name(nm); + pform_name_t name = hier_name(nm); PWire*cur = pform_cur_module->get_wire(name); if (cur == 0) { cur = new PWire(name, NetNet::INTEGER, @@ -1658,7 +1660,7 @@ void pform_set_reg_integer(list*names) static void pform_set_reg_time(const char*nm) { - hname_t name = hier_name(nm); + pform_name_t name = hier_name(nm); PWire*cur = pform_cur_module->get_wire(name); if (cur == 0) { cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_LOGIC); @@ -1695,7 +1697,9 @@ svector* pform_make_udp_input_ports(list*names) ; cur != names->end() ; cur ++ ) { perm_string txt = *cur; - PWire*pp = new PWire(hname_t(txt), + pform_name_t tmp; + tmp.push_back(name_component_t(txt)); + PWire*pp = new PWire(tmp, NetNet::IMPLICIT, NetNet::PINPUT, IVL_VT_LOGIC); @@ -1769,6 +1773,10 @@ int pform_parse(const char*path, FILE*file) /* * $Log: pform.cc,v $ + * Revision 1.146 2007/05/24 04:07:12 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.145 2007/04/26 03:06:22 steve * Rework hname_t to use perm_strings. * diff --git a/pform.h b/pform.h index 1847d31550..0f3f0a52e9 100644 --- a/pform.h +++ b/pform.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pform.h,v 1.90 2007/04/19 02:52:53 steve Exp $" +#ident "$Id: pform.h,v 1.91 2007/05/24 04:07:12 steve Exp $" #endif # include "netlist.h" @@ -261,7 +261,7 @@ extern void pform_set_localparam(perm_string name, bool signed_flag, svector*range, PExpr*expr); -extern void pform_set_defparam(const hname_t&name, PExpr*expr); +extern void pform_set_defparam(const pform_name_t&name, PExpr*expr); /* * Functions related to specify blocks. @@ -340,6 +340,10 @@ extern void pform_dump(ostream&out, Module*mod); /* * $Log: pform.h,v $ + * Revision 1.91 2007/05/24 04:07:12 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.90 2007/04/19 02:52:53 steve * Add support for -v flag in command file. * diff --git a/pform_dump.cc b/pform_dump.cc index 969a7468d9..538572950b 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pform_dump.cc,v 1.97 2007/03/07 00:38:15 steve Exp $" +#ident "$Id: pform_dump.cc,v 1.98 2007/05/24 04:07:12 steve Exp $" #endif # include "config.h" @@ -72,6 +72,58 @@ ostream& operator<< (ostream&o, PGate::strength_t str) return o; } +ostream& operator<< (ostream&out, perm_string that) +{ + out << that.str(); +} + +ostream& operator<< (ostream&out, const name_component_t&that) +{ + out << that.name.str(); + + typedef std::list::const_iterator index_it_t; + for (index_it_t idx = that.index.begin() + ; idx != that.index.end() ; idx++) { + + out << "["; + switch ((*idx).sel) { + case index_component_t::SEL_BIT: + out << *(*idx).msb; + break; + case index_component_t::SEL_PART: + out << *(*idx).msb << ":" << *(*idx).lsb; + break; + case index_component_t::SEL_IDX_UP: + out << *(*idx).msb << "+:" << *(*idx).lsb; + break; + case index_component_t::SEL_IDX_DO: + out << *(*idx).msb << "-:" << *(*idx).lsb; + break; + default: + out << "???"; + break; + } + out << "]"; + } + return out; +} + +ostream& operator<< (ostream&o, const pform_name_t&that) +{ + pform_name_t::const_iterator cur; + + cur = that.begin(); + o << *cur; + + cur++; + while (cur != that.end()) { + o << "." << *cur; + cur++; + } + + return o; +} + void PExpr::dump(ostream&out) const { out << typeid(*this).name(); @@ -145,29 +197,6 @@ void PENumber::dump(ostream&out) const void PEIdent::dump(ostream&out) const { out << path_; - if (msb_) { - out << "[" << *msb_; - if (lsb_) switch (sel_) { - case SEL_IDX_UP: - out << "+:" << *lsb_; - break; - case SEL_IDX_DO: - out << "-:" << *lsb_; - break; - case SEL_PART: - out << ":" << *lsb_; - break; - default: - out << ":?:" << *lsb_; - break; - } - out << "]"; - } - - typedef std::vector::const_iterator vector_it_t; - for (vector_it_t cur = idx_.begin() ; cur != idx_.end() ; cur++) { - out << "[" << *(*cur) << "]"; - } } void PEString::dump(ostream&out) const @@ -811,7 +840,7 @@ void PGenerate::dump(ostream&out) const out << endl; - for (map::const_iterator idx = wires.begin() + for (map::const_iterator idx = wires.begin() ; idx != wires.end() ; idx++) { (*idx).second->dump(out, 6); @@ -866,7 +895,7 @@ void Module::dump(ostream&out) const } typedef map::const_iterator parm_iter_t; - typedef map::const_iterator parm_hiter_t; + typedef map::const_iterator parm_hiter_t; for (parm_iter_t cur = parameters.begin() ; cur != parameters.end() ; cur ++) { out << " parameter "; @@ -931,7 +960,7 @@ void Module::dump(ostream&out) const } // Iterate through and display all the wires. - for (map::const_iterator wire = wires_.begin() + for (map::const_iterator wire = wires_.begin() ; wire != wires_.end() ; wire ++ ) { @@ -1032,6 +1061,10 @@ void PUdp::dump(ostream&out) const /* * $Log: pform_dump.cc,v $ + * Revision 1.98 2007/05/24 04:07:12 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.97 2007/03/07 00:38:15 steve * Lint fixes. * diff --git a/pform_types.cc b/pform_types.cc new file mode 100644 index 0000000000..6f31725c0e --- /dev/null +++ b/pform_types.cc @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2007 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: pform_types.cc,v 1.1 2007/05/24 04:07:12 steve Exp $" +#endif + + +# include "pform_types.h" + +bool operator < (const name_component_t&lef, const name_component_t&rig) +{ + if (lef.name < rig.name) + return true; + + return false; +} diff --git a/pform_types.h b/pform_types.h new file mode 100644 index 0000000000..94b15ee7d3 --- /dev/null +++ b/pform_types.h @@ -0,0 +1,72 @@ +#ifndef __pform_types_H +#define __pform_types_H +/* + * Copyright (c) 2007 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: pform_types.h,v 1.1 2007/05/24 04:07:12 steve Exp $" +#endif + +// This for the perm_string type. +# include "StringHeap.h" +# include +# include + +/* + * parse-form types. + */ + +struct index_component_t { + enum ctype_t { SEL_NONE, SEL_BIT, SEL_PART, SEL_IDX_UP, SEL_IDX_DO }; + + index_component_t() : sel(SEL_NONE), msb(0), lsb(0) { }; + ~index_component_t() { } + + ctype_t sel; + class PExpr*msb; + class PExpr*lsb; +}; + +struct name_component_t { + name_component_t(perm_string n) : name(n) { } + ~name_component_t() { } + + perm_string name; + std::listindex; +}; + +extern bool operator < (const name_component_t&lef, const name_component_t&rig); + +/* + * The pform_name_t is the general form for a heirarchical identifier. + */ +typedef std::list pform_name_t; + +inline perm_string peek_head_name(const pform_name_t&that) +{ + return that.front().name; +} + +inline perm_string peek_tail_name(const pform_name_t&that) +{ + return that.back().name; +} + +extern std::ostream& operator<< (std::ostream&o, const pform_name_t&); + +#endif diff --git a/symbol_search.cc b/symbol_search.cc index 9784cbed49..1d75e5712a 100644 --- a/symbol_search.cc +++ b/symbol_search.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: symbol_search.cc,v 1.5 2007/04/26 03:06:22 steve Exp $" +#ident "$Id: symbol_search.cc,v 1.6 2007/05/24 04:07:12 steve Exp $" #endif # include "netlist.h" @@ -27,7 +27,7 @@ /* * Search for the hierarchical name. */ -NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path, +NetScope*symbol_search(const Design*des, NetScope*scope, pform_name_t path, NetNet*&net, const NetExpr*&par, NetEvent*&eve, @@ -36,7 +36,8 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path, assert(scope); /* Get the tail name of the object we are looking for. */ - perm_string key = path.remove_tail_name(); + perm_string key = peek_tail_name(path); + path.pop_back(); /* Initialize output argument to cleared. */ net = 0; @@ -45,7 +46,7 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path, /* If the path has a scope part, then search for the specified scope that we are supposed to search. */ - if (path.peek_name(0)) + if (! path.empty()) scope = des->find_scope(scope, path); while (scope) { @@ -69,6 +70,10 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path, /* * $Log: symbol_search.cc,v $ + * Revision 1.6 2007/05/24 04:07:12 steve + * Rework the heirarchical identifier parse syntax and pform + * to handle more general combinations of heirarch and bit selects. + * * Revision 1.5 2007/04/26 03:06:22 steve * Rework hname_t to use perm_strings. *