Rework the heirarchical identifier parse syntax and pform

to handle more general combinations of heirarch and bit selects.
This commit is contained in:
steve 2007-05-24 04:07:11 +00:00
parent 67b1eee7ce
commit ddd36ecb6c
30 changed files with 1035 additions and 680 deletions

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # 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 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_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_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 \ 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 \ set_width.o symbol_search.o sync.o sys_funcs.o \
verinum.o verireal.o target.o targets.o \ verinum.o verireal.o target.o targets.o \
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \ Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # 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<hname_t,PWire*>::const_iterator obj = wires_.find(name); map<pform_name_t,PWire*>::const_iterator obj = wires_.find(name);
if (obj == wires_.end()) if (obj == wires_.end())
return 0; return 0;
else else
@ -133,11 +133,6 @@ PGate* Module::get_gate(perm_string name)
return 0; return 0;
} }
const map<hname_t,PWire*>& Module::get_wires() const
{
return wires_;
}
const list<PGate*>& Module::get_gates() const const list<PGate*>& Module::get_gates() const
{ {
return gates_; return gates_;
@ -151,6 +146,10 @@ const list<PProcess*>& Module::get_behaviors() const
/* /*
* $Log: Module.cc,v $ * $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 * Revision 1.26 2007/04/19 02:52:53 steve
* Add support for -v flag in command file. * Add support for -v flag in command file.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include <list> # include <list>
@ -30,6 +30,7 @@
# include "named.h" # include "named.h"
# include "LineInfo.h" # include "LineInfo.h"
# include "netlist.h" # include "netlist.h"
# include "pform_types.h"
class PEvent; class PEvent;
class PExpr; class PExpr;
class PEIdent; class PEIdent;
@ -98,7 +99,7 @@ class Module : public LineInfo {
new parameters within the module, but may be used to set new parameters within the module, but may be used to set
values within this module (when instantiated) or in other values within this module (when instantiated) or in other
instantiated modules. */ instantiated modules. */
map<hname_t,PExpr*>defparms; map<pform_name_t,PExpr*>defparms;
/* Parameters may be overridden at instantiation time; /* Parameters may be overridden at instantiation time;
the overrides do not contain explicit parameter names, 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 // Find a wire by name. This is used for connecting gates to
// existing wires, etc. // 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); PGate* get_gate(perm_string name);
const map<hname_t,PWire*>& get_wires() const;
const list<PGate*>& get_gates() const; const list<PGate*>& get_gates() const;
const list<PProcess*>& get_behaviors() const; const list<PProcess*>& get_behaviors() const;
@ -168,7 +168,7 @@ class Module : public LineInfo {
private: private:
perm_string name_; perm_string name_;
map<hname_t,PWire*> wires_; map<pform_name_t,PWire*> wires_;
list<PGate*> gates_; list<PGate*> gates_;
list<PProcess*> behaviors_; list<PProcess*> behaviors_;
map<perm_string,PTask*> tasks_; map<perm_string,PTask*> tasks_;
@ -182,6 +182,10 @@ class Module : public LineInfo {
/* /*
* $Log: Module.h,v $ * $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 * Revision 1.42 2007/04/19 02:52:53 steve
* Add support for -v flag in command file. * Add support for -v flag in command file.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -93,13 +93,26 @@ PEBShift::~PEBShift()
{ {
} }
PECallFunction::PECallFunction(const hname_t&n, const svector<PExpr *> &parms) PECallFunction::PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms)
: path_(n), parms_(parms) : path_(n), parms_(parms)
{ {
} }
PECallFunction::PECallFunction(const hname_t&n) static pform_name_t pn_from_ps(perm_string n)
: path_(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<PExpr*>&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; return true;
} }
PEIdent::PEIdent(const hname_t&s) PEIdent::PEIdent(const pform_name_t&that)
: path_(s), msb_(0), lsb_(0), sel_(SEL_NONE), idx_(0) : path_(that)
{ {
} }
PEIdent::PEIdent(perm_string s)
{
path_.push_back(name_component_t(s));
}
PEIdent::~PEIdent() PEIdent::~PEIdent()
{ {
} }
const hname_t& PEIdent::path() const
{
return path_;
}
/* /*
* An identifier can be in a constant expression if (and only if) it is * An identifier can be in a constant expression if (and only if) it is
* a parameter. * a parameter.
*
* NOTE: This test does not work if the name is hierarchical!
*/ */
bool PEIdent::is_constant(Module*mod) const bool PEIdent::is_constant(Module*mod) const
{ {
if (mod == 0) return false; 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. perm_string tmp = path_.back().name;
The real fix is to make the path_ carry perm_strings. */
perm_string tmp = perm_string::literal(path_.peek_name(0));
{ map<perm_string,Module::param_expr_t>::const_iterator cur; { map<perm_string,Module::param_expr_t>::const_iterator cur;
cur = mod->parameters.find(tmp); cur = mod->parameters.find(tmp);
@ -288,6 +300,10 @@ bool PEUnary::is_constant(Module*m) const
/* /*
* $Log: PExpr.cc,v $ * $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 * Revision 1.38 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width. * Expression widths with unsized literals are pseudo-infinite width.
* *

31
PExpr.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include <string> # include <string>
@ -27,6 +27,7 @@
# include "netlist.h" # include "netlist.h"
# include "verinum.h" # include "verinum.h"
# include "LineInfo.h" # include "LineInfo.h"
# include "pform_types.h"
class Design; class Design;
class Module; class Module;
@ -247,9 +248,14 @@ class PEFNumber : public PExpr {
class PEIdent : public PExpr { class PEIdent : public PExpr {
public: public:
explicit PEIdent(const hname_t&s); explicit PEIdent(perm_string);
explicit PEIdent(const pform_name_t&);
~PEIdent(); ~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 void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
@ -286,7 +292,10 @@ class PEIdent : public PExpr {
virtual bool is_constant(Module*) const; virtual bool is_constant(Module*) const;
verinum* eval_const(const Design*des, NetScope*sc) 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: private:
// Common functions to calculate parts of part/bit selects. // Common functions to calculate parts of part/bit selects.
@ -332,9 +341,9 @@ class PEIdent : public PExpr {
NetScope*scope, NetScope*scope,
NetESignal*net, NetESignal*net,
NetScope*found) const; NetScope*found) const;
hname_t path_;
public: public:
#if 0
// Use these to support part-select operators. // Use these to support part-select operators.
PExpr*msb_; PExpr*msb_;
PExpr*lsb_; PExpr*lsb_;
@ -345,6 +354,8 @@ class PEIdent : public PExpr {
// expression. If this is a reference to a vector, this is a // expression. If this is a reference to a vector, this is a
// bit select. // bit select.
std::vector<PExpr*> idx_; std::vector<PExpr*> idx_;
#endif
NetNet* elaborate_net_array_(Design*des, NetScope*scope, NetNet* elaborate_net_array_(Design*des, NetScope*scope,
NetNet*sig, unsigned lwidth, NetNet*sig, unsigned lwidth,
const NetExpr* rise, const NetExpr* rise,
@ -621,8 +632,10 @@ class PETernary : public PExpr {
*/ */
class PECallFunction : public PExpr { class PECallFunction : public PExpr {
public: public:
explicit PECallFunction(const hname_t&n, const svector<PExpr *> &parms); explicit PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms);
explicit PECallFunction(const hname_t&n); // Call of system function (name is not heirarchical)
explicit PECallFunction(perm_string n, const svector<PExpr *> &parms);
explicit PECallFunction(perm_string n);
~PECallFunction(); ~PECallFunction();
virtual void dump(ostream &) const; virtual void dump(ostream &) const;
@ -638,7 +651,7 @@ class PECallFunction : public PExpr {
int expr_wid, bool sys_task_arg) const; int expr_wid, bool sys_task_arg) const;
private: private:
hname_t path_; pform_name_t path_;
svector<PExpr *> parms_; svector<PExpr *> parms_;
bool check_call_matches_definition_(Design*des, NetScope*dscope) const; bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
@ -655,6 +668,10 @@ class PECallFunction : public PExpr {
/* /*
* $Log: PExpr.h,v $ * $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 * Revision 1.87 2007/01/16 05:44:14 steve
* Major rework of array handling. Memories are replaced with the * Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory * more general concept of arrays. The NetMemory and NetEMemory

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "PGenerate.h" # include "PGenerate.h"
@ -42,9 +42,9 @@ PWire* PGenerate::add_wire(PWire*wire)
return wire; return wire;
} }
PWire* PGenerate::get_wire(const hname_t&name) const PWire* PGenerate::get_wire(const pform_name_t&name) const
{ {
map<hname_t,PWire*>::const_iterator obj = wires.find(name); map<pform_name_t,PWire*>::const_iterator obj = wires.find(name);
if (obj == wires.end()) if (obj == wires.end())
return 0; return 0;
else else

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "LineInfo.h" # include "LineInfo.h"
@ -27,6 +27,7 @@
# include "HName.h" # include "HName.h"
# include <list> # include <list>
# include <map> # include <map>
# include "pform_types.h"
class Design; class Design;
class NetScope; class NetScope;
@ -59,9 +60,9 @@ class PGenerate : public LineInfo {
PExpr*loop_test; PExpr*loop_test;
PExpr*loop_step; PExpr*loop_step;
map<hname_t,PWire*>wires; map<pform_name_t,PWire*>wires;
PWire* add_wire(PWire*); PWire* add_wire(PWire*);
PWire* get_wire(const hname_t&name) const; PWire* get_wire(const pform_name_t&name) const;
list<PGate*> gates; list<PGate*> gates;
void add_gate(PGate*); void add_gate(PGate*);

View File

@ -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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
# include "PWire.h" # include "PWire.h"
# include <assert.h> # include <assert.h>
PWire::PWire(const hname_t&n, PWire::PWire(const pform_name_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,
NetNet::Type t, NetNet::Type t,
NetNet::PortType pt, NetNet::PortType pt,
ivl_variable_type_t dt) ivl_variable_type_t dt)
@ -59,7 +44,7 @@ NetNet::Type PWire::get_wire_type() const
return type_; return type_;
} }
const hname_t& PWire::path() const const pform_name_t& PWire::path() const
{ {
return hname_; return hname_;
} }
@ -160,6 +145,10 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
/* /*
* $Log: PWire.cc,v $ * $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 * Revision 1.13 2007/04/26 03:06:21 steve
* Rework hname_t to use perm_strings. * Rework hname_t to use perm_strings.
* *

25
PWire.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "netlist.h" # include "netlist.h"
@ -43,24 +43,21 @@ class Design;
* identifies a port by keeping it in its port list. * identifies a port by keeping it in its port list.
* *
* The hname parameter to the constructor is a hierarchical name. It * The hname parameter to the constructor is a hierarchical name. It
* is an array of strings starting with the root, running towards * is the name of the wire within a module, so does not include the
* the base name, and terminated by a null pointer. The environment * current scope or any instances. Modules contain all the wires, so
* allocates the memory for me. * from that perspective, sub-scopes within the module are a part of
* the wire name.
*/ */
class PWire : public LineInfo { class PWire : public LineInfo {
public: public:
PWire(const hname_t&hname, PWire(const pform_name_t&hname,
NetNet::Type t,
NetNet::PortType pt,
ivl_variable_type_t dt);
PWire(perm_string name,
NetNet::Type t, NetNet::Type t,
NetNet::PortType pt, NetNet::PortType pt,
ivl_variable_type_t dt); ivl_variable_type_t dt);
// Return a hierarchical name. // Return a hierarchical name.
const hname_t&path() const; const pform_name_t&path() const;
NetNet::Type get_wire_type() const; NetNet::Type get_wire_type() const;
bool set_wire_type(NetNet::Type); bool set_wire_type(NetNet::Type);
@ -84,10 +81,10 @@ class PWire : public LineInfo {
// Write myself to the specified stream. // Write myself to the specified stream.
void dump(ostream&out, unsigned ind=4) const; void dump(ostream&out, unsigned ind=4) const;
void elaborate_sig(Design*, NetScope*scope) const; NetNet* elaborate_sig(Design*, NetScope*scope) const;
private: private:
hname_t hname_; pform_name_t hname_;
NetNet::Type type_; NetNet::Type type_;
NetNet::PortType port_type_; NetNet::PortType port_type_;
ivl_variable_type_t data_type_; ivl_variable_type_t data_type_;
@ -111,6 +108,10 @@ class PWire : public LineInfo {
/* /*
* $Log: PWire.h,v $ * $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 * Revision 1.20 2007/04/26 03:06:22 steve
* Rework hname_t to use perm_strings. * Rework hname_t to use perm_strings.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -107,16 +107,22 @@ PBlock::~PBlock()
delete list_[idx]; delete list_[idx];
} }
PCallTask::PCallTask(const hname_t&n, const svector<PExpr*>&p) PCallTask::PCallTask(const pform_name_t&n, const svector<PExpr*>&p)
: path_(n), parms_(p) : path_(n), parms_(p)
{ {
} }
PCallTask::PCallTask(perm_string n, const svector<PExpr*>&p)
: parms_(p)
{
path_.push_back(name_component_t(n));
}
PCallTask::~PCallTask() PCallTask::~PCallTask()
{ {
} }
const hname_t& PCallTask::path() const const pform_name_t& PCallTask::path() const
{ {
return path_; return path_;
} }
@ -178,7 +184,7 @@ PDelayStatement::~PDelayStatement()
{ {
} }
PDisable::PDisable(const hname_t&sc) PDisable::PDisable(const pform_name_t&sc)
: scope_(sc) : scope_(sc)
{ {
} }
@ -273,7 +279,7 @@ PRepeat::~PRepeat()
delete statement_; delete statement_;
} }
PTrigger::PTrigger(const hname_t&e) PTrigger::PTrigger(const pform_name_t&e)
: event_(e) : event_(e)
{ {
} }
@ -295,6 +301,10 @@ PWhile::~PWhile()
/* /*
* $Log: Statement.cc,v $ * $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 * Revision 1.29 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items. * Use perm_strings for named langiage items.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include <string> # include <string>
@ -173,10 +173,11 @@ class PBlock : public Statement {
class PCallTask : public Statement { class PCallTask : public Statement {
public: public:
explicit PCallTask(const hname_t&n, const svector<PExpr*>&parms); explicit PCallTask(const pform_name_t&n, const svector<PExpr*>&parms);
explicit PCallTask(perm_string n, const svector<PExpr*>&parms);
~PCallTask(); ~PCallTask();
const hname_t& path() const; const pform_name_t& path() const;
unsigned nparms() const { return parms_.count(); } unsigned nparms() const { return parms_.count(); }
@ -197,7 +198,7 @@ class PCallTask : public Statement {
NetProc* elaborate_sys(Design*des, NetScope*scope) const; NetProc* elaborate_sys(Design*des, NetScope*scope) const;
NetProc* elaborate_usr(Design*des, NetScope*scope) const; NetProc* elaborate_usr(Design*des, NetScope*scope) const;
hname_t path_; pform_name_t path_;
svector<PExpr*> parms_; svector<PExpr*> parms_;
}; };
@ -296,14 +297,14 @@ class PDelayStatement : public Statement {
class PDisable : public Statement { class PDisable : public Statement {
public: public:
explicit PDisable(const hname_t&sc); explicit PDisable(const pform_name_t&sc);
~PDisable(); ~PDisable();
virtual void dump(ostream&out, unsigned ind) const; virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const;
private: private:
hname_t scope_; pform_name_t scope_;
}; };
/* /*
@ -433,14 +434,14 @@ class PRelease : public Statement {
class PTrigger : public Statement { class PTrigger : public Statement {
public: public:
explicit PTrigger(const hname_t&ev); explicit PTrigger(const pform_name_t&ev);
~PTrigger(); ~PTrigger();
virtual NetProc* elaborate(Design*des, NetScope*scope) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const; virtual void dump(ostream&out, unsigned ind) const;
private: private:
hname_t event_; pform_name_t event_;
}; };
class PWhile : public Statement { class PWhile : public Statement {
@ -460,6 +461,10 @@ class PWhile : public Statement {
/* /*
* $Log: Statement.h,v $ * $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 * Revision 1.43 2007/03/05 05:59:10 steve
* Handle processes within generate loops. * Handle processes within generate loops.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -871,7 +871,7 @@ void NetScope::dump(ostream&o) const
/* Dump the saved defparam assignments here. */ /* Dump the saved defparam assignments here. */
{ {
map<hname_t,NetExpr*>::const_iterator pp; map<pform_name_t,NetExpr*>::const_iterator pp;
for (pp = defparams.begin() for (pp = defparams.begin()
; pp != defparams.end() ; pp ++ ) { ; pp != defparams.end() ; pp ++ ) {
o << " defparam " << (*pp).first << " = " << o << " defparam " << (*pp).first << " = " <<
@ -1205,6 +1205,10 @@ void Design::dump(ostream&o) const
/* /*
* $Log: design_dump.cc,v $ * $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 * Revision 1.174 2007/03/02 06:13:22 steve
* Add support for edge sensitive spec paths. * Add support for edge sensitive spec paths.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # 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 not lead to executable code but takes the single parameter
and makes it into a signed expression. No bits are changed, and makes it into a signed expression. No bits are changed,
it just changes the interpretation. */ 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)) { if ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_line() << ": error: The $signed() function " cerr << get_line() << ": error: The $signed() function "
<< "takes exactly one(1) argument." << endl; << "takes exactly one(1) argument." << endl;
@ -336,7 +336,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
return sub; return sub;
} }
/* add $unsigned to match $signed */ /* 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)) { if ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_line() << ": error: The $unsigned() function " cerr << get_line() << ": error: The $unsigned() function "
<< "takes exactly one(1) argument." << endl; << "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 the bit width of the sub-expression. The value of the
sub-expression is not used, so the expression itself can be sub-expression is not used, so the expression itself can be
deleted. */ deleted. */
if ((strcmp(path_.peek_name(0), "$sizeof") == 0) if ((strcmp(peek_tail_name(path_), "$sizeof") == 0)
|| (strcmp(path_.peek_name(0), "$bits") == 0)) { || (strcmp(peek_tail_name(path_), "$bits") == 0)) {
if ((parms_.count() != 1) || (parms_[0] == 0)) { if ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_line() << ": error: The $bits() function " cerr << get_line() << ": error: The $bits() function "
<< "takes exactly one(1) argument." << endl; << "takes exactly one(1) argument." << endl;
@ -363,7 +363,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
return 0; 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." cerr << get_line() << ": warning: $sizeof is deprecated."
<< " Use $bits() instead." << endl; << " 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 a single bit flag -- 1 if the expression is signed, 0
otherwise. The subexpression is elaborated but not otherwise. The subexpression is elaborated but not
evaluated. */ 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)) { if ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_line() << ": error: The $is_signed() function " cerr << get_line() << ": error: The $is_signed() function "
<< "takes exactly one(1) argument." << endl; << "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 /* Get the return type of the system function by looking it up
in the sfunc_table. */ in the sfunc_table. */
const struct sfunc_return_type*sfunc_info 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; ivl_variable_type_t sfunc_type = sfunc_info->type;
unsigned wid = sfunc_info->wid; unsigned wid = sfunc_info->wid;
@ -423,7 +423,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
if ((nparms == 1) && (parms_[0] == 0)) if ((nparms == 1) && (parms_[0] == 0))
nparms = 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); wid, nparms);
if (sfunc_info->signed_flag) if (sfunc_info->signed_flag)
fun->cast_signed(true); fun->cast_signed(true);
@ -455,7 +455,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
if (missing_parms > 0) { if (missing_parms > 0) {
cerr << get_line() << ": error: The function " cerr << get_line() << ": error: The function "
<< path_.peek_name(0) << peek_tail_name(path_)
<< " has been called with empty parameters." << endl; << " has been called with empty parameters." << endl;
cerr << get_line() << ": : Verilog doesn't allow " cerr << get_line() << ": : Verilog doesn't allow "
<< "passing empty parameters to functions." << endl; << "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, NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
int expr_wid, bool) const int expr_wid, bool) const
{ {
if (path_.peek_name(0)[0] == '$') if (peek_tail_name(path_)[0] == '$')
return elaborate_sfunc_(des, scope); return elaborate_sfunc_(des, scope);
NetFuncDef*def = des->find_function(scope, path_); 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, bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
long&msb, long&lsb) const long&msb, long&lsb) const
{ {
assert(lsb_ != 0); const name_component_t&name_tail = path_.back();
assert(msb_ != 0); 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 /* This handles part selects. In this case, there are
two bit select expressions, and both must be two bit select expressions, and both must be
constant. Evaluate them and pass the results back to constant. Evaluate them and pass the results back to
the caller. */ 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<NetEConst*>(lsb_ex); NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex);
if (lsb_c == 0) { if (lsb_c == 0) {
cerr << lsb_->get_line() << ": error: " cerr << index_tail.lsb->get_line() << ": error: "
"Part select expressions must be constant." "Part select expressions must be constant."
<< endl; << endl;
cerr << lsb_->get_line() << ": : This lsb expression " cerr << index_tail.lsb->get_line() << ": : "
"violates the rule: " << *lsb_ << endl; "This lsb expression violates the rule: "
<< *index_tail.lsb << endl;
des->errors += 1; des->errors += 1;
return false; 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<NetEConst*>(msb_ex); NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
if (msb_c == 0) { if (msb_c == 0) {
cerr << msb_->get_line() << ": error: " cerr << index_tail.msb->get_line() << ": error: "
"Part select expressions must be constant." "Part select expressions must be constant."
<< endl; << endl;
cerr << msb_->get_line() << ": : This msb expression " cerr << index_tail.msb->get_line() << ": : This msb expression "
"violates the rule: " << *msb_ << endl; "violates the rule: " << *index_tail.msb << endl;
des->errors += 1; des->errors += 1;
return false; return false;
} }
@ -662,13 +667,18 @@ bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
bool PEIdent::calculate_up_do_width_(Design*des, NetScope*scope, bool PEIdent::calculate_up_do_width_(Design*des, NetScope*scope,
unsigned long&wid) const 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; bool flag = true;
/* Calculate the width expression (in the lsb_ position) /* Calculate the width expression (in the lsb_ position)
first. If the expression is not constant, error but guess 1 first. If the expression is not constant, error but guess 1
so we can keep going and find more errors. */ 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<NetEConst*>(wid_ex); NetEConst*wid_c = dynamic_cast<NetEConst*>(wid_ex);
if (wid_c == 0) { if (wid_c == 0) {
@ -695,30 +705,36 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
const NetExpr*ex1, *ex2; const NetExpr*ex1, *ex2;
symbol_search(des, scope, path_, symbol_search(des, scope, path_, net, par, eve, ex1, ex2);
net, par, eve,
ex1, ex2);
if (net != 0) { 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(); unsigned use_width = net->vector_width();
switch (sel_) { switch (use_sel) {
case SEL_NONE: case index_component_t::SEL_NONE:
break; break;
case SEL_PART: case index_component_t::SEL_PART:
{ long msb, lsb; { long msb, lsb;
calculate_parts_(des, scope, msb, lsb); calculate_parts_(des, scope, msb, lsb);
use_width = 1 + ((msb>lsb)? (msb-lsb) : (lsb-msb)); use_width = 1 + ((msb>lsb)? (msb-lsb) : (lsb-msb));
break; break;
} }
case SEL_IDX_UP: case index_component_t::SEL_IDX_UP:
case SEL_IDX_DO: case index_component_t::SEL_IDX_DO:
{ unsigned long tmp = 0; { unsigned long tmp = 0;
calculate_up_do_width_(des, scope, tmp); calculate_up_do_width_(des, scope, tmp);
use_width = tmp; use_width = tmp;
break; break;
} }
case index_component_t::SEL_BIT:
use_width = 1;
break;
default: default:
assert(0); ivl_assert(*this, 0);
} }
return use_width; 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 // Hmm... maybe this is a genvar? This is only possible while
// processing generate blocks, but then the genvar_tmp will be // processing generate blocks, but then the genvar_tmp will be
// set in the scope. // set in the scope.
if (path_.component_count() == 1 if (path_.size() == 1
&& scope->genvar_tmp.str() && 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); verinum val (scope->genvar_tmp_val);
NetEConst*tmp = new NetEConst(val); NetEConst*tmp = new NetEConst(val);
tmp->set_line(*this); tmp->set_line(*this);
@ -790,8 +806,8 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
if (gn_specify_blocks_flag) { if (gn_specify_blocks_flag) {
map<perm_string,NetScope::spec_val_t>::const_iterator specp; map<perm_string,NetScope::spec_val_t>::const_iterator specp;
perm_string key = perm_string::literal(path_.peek_name(0)); perm_string key = peek_tail_name(path_);
if (path_.component_count() == 1 if (path_.size() == 1
&& ((specp = scope->specparams.find(key)) != scope->specparams.end())) { && ((specp = scope->specparams.find(key)) != scope->specparams.end())) {
NetScope::spec_val_t value = (*specp).second; NetScope::spec_val_t value = (*specp).second;
NetExpr*tmp = 0; 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 // Finally, if this is a scope name, then return that. Look
// first to see if this is a name of a local scope. Failing // first to see if this is a name of a local scope. Failing
// that, search globally for a hierarchical name. // that, search globally for a hierarchical name.
if ((path_.peek_name(1) == 0)) if ((path_.size() == 1))
if (NetScope*nsc = scope->child(path_.peek_name(0))) { if (NetScope*nsc = scope->child(peek_tail_name(path_))) {
NetEScope*tmp = new NetEScope(nsc); NetEScope*tmp = new NetEScope(nsc);
tmp->set_line(*this); tmp->set_line(*this);
return tmp; return tmp;
@ -854,13 +870,18 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
const NetExpr*par_msb, const NetExpr*par_msb,
const NetExpr*par_lsb) const 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) { if (use_sel == index_component_t::SEL_PART) {
assert(msb_ && lsb_); ivl_assert(*this, !name_tail.index.empty());
assert(idx_.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 /* If the identifier has a part select, we support
it by pulling the right bits out and making a 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 lsb of a parameter is 0 and the msb is the
width of the parameter. */ width of the parameter. */
verinum*lsn = lsb_->eval_const(des, scope); verinum*lsn = index_tail.lsb->eval_const(des, scope);
verinum*msn = msb_->eval_const(des, scope); verinum*msn = index_tail.msb->eval_const(des, scope);
if ((lsn == 0) || (msn == 0)) { if ((lsn == 0) || (msn == 0)) {
cerr << get_line() << ": error: " cerr << get_line() << ": error: "
"Part select expressions must be " "Part select expressions must be "
@ -926,17 +947,19 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
delete tmp; delete tmp;
tmp = new NetEConst(result); tmp = new NetEConst(result);
} else if (sel_ == SEL_IDX_UP || sel_ == SEL_IDX_DO) { } else if (use_sel == index_component_t::SEL_IDX_UP || use_sel == index_component_t::SEL_IDX_DO) {
assert(msb_);
assert(lsb_); ivl_assert(*this, !name_tail.index.empty());
assert(idx_.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 /* Get and evaluate the width of the index
select. This must be constant. */ 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<NetEConst*> (wid_ex); NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
if (wid_ec == 0) { if (wid_ec == 0) {
cerr << lsb_->get_line() << ": error: " cerr << index_tail.lsb->get_line() << ": error: "
<< "Second expression of indexed part select " << "Second expression of indexed part select "
<< "most be constant." << endl; << "most be constant." << endl;
des->errors += 1; des->errors += 1;
@ -945,12 +968,12 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
unsigned wid = wid_ec->value().as_ulong(); 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) { if (idx_ex == 0) {
return 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); 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); tmp = new NetESelect(tmp, idx_ex, wid);
} else if (!idx_.empty()) { } else if (use_sel == index_component_t::SEL_BIT) {
assert(!msb_); ivl_assert(*this, !name_tail.index.empty());
assert(!lsb_); const index_component_t&index_tail = name_tail.index.back();
assert(idx_.size() == 1); ivl_assert(*this, index_tail.msb);
assert(sel_ == SEL_NONE); ivl_assert(*this, !index_tail.lsb);
/* Handle the case where a parameter has a bit /* Handle the case where a parameter has a bit
select attached to it. Generate a NetESelect select attached to it. Generate a NetESelect
object to select the bit as desired. */ 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<NetEConst*>(mtmp)) { if (! dynamic_cast<NetEConst*>(mtmp)) {
NetExpr*re = mtmp->eval_tree(); NetExpr*re = mtmp->eval_tree();
if (re) { if (re) {
@ -1045,8 +1068,7 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
NetEConstParam if possible. */ NetEConstParam if possible. */
NetEConst*ctmp = dynamic_cast<NetEConst*>(tmp); NetEConst*ctmp = dynamic_cast<NetEConst*>(tmp);
if (ctmp != 0) { if (ctmp != 0) {
perm_string name perm_string name = peek_tail_name(path_);
= lex_strings.make(path_.peek_tail_name());
NetEConstParam*ptmp NetEConstParam*ptmp
= new NetEConstParam(found_in, name, ctmp->value()); = new NetEConstParam(found_in, name, ctmp->value());
delete tmp; delete tmp;
@ -1065,17 +1087,32 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
NetNet*net, NetScope*found_in, NetNet*net, NetScope*found_in,
bool sys_task_arg) const 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() cerr << get_line() << ": error: Array " << path()
<< " Needs an array index here." << endl; << " Needs an array index here." << endl;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }
ivl_assert(*this, sys_task_arg || !idx_.empty()); index_component_t index_front;
NetExpr*word_index = idx_.empty() 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 ? 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) if (word_index == 0 && !sys_task_arg)
return 0; return 0;
@ -1106,15 +1143,22 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
NetESignal*res = new NetESignal(net, word_index); NetESignal*res = new NetESignal(net, word_index);
res->set_line(*this); 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); 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); 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); return elaborate_expr_net_idx_do_(des, scope, res, found_in);
ivl_assert(*this, word_sel == index_component_t::SEL_NONE);
return res; return res;
} }
@ -1125,7 +1169,6 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
NetESignal*net, NetScope*found_in) const NetESignal*net, NetScope*found_in) const
{ {
long msv, lsv; long msv, lsv;
ivl_assert(*this, (idx_.empty()&& !net->word_index()) || (!idx_.empty()&& net->word_index()));
bool flag = calculate_parts_(des, scope, msv, lsv); bool flag = calculate_parts_(des, scope, msv, lsv);
if (!flag) if (!flag)
return 0; 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, NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
NetESignal*net, NetScope*found_in) const NetESignal*net, NetScope*found_in) const
{ {
assert(lsb_ != 0); const name_component_t&name_tail = path_.back();
assert(msb_ != 0); 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; unsigned long wid = 0;
calculate_up_do_width_(des, scope, wid); 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, NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
NetESignal*net, NetScope*found_in)const NetESignal*net, NetScope*found_in)const
{ {
assert(lsb_ != 0); const name_component_t&name_tail = path_.back();
assert(msb_ != 0); 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; unsigned long wid = 0;
calculate_up_do_width_(des, scope, wid); 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, NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
NetESignal*net, NetScope*found_in) const NetESignal*net, NetScope*found_in) const
{ {
assert(msb_ == 0); const name_component_t&name_tail = path_.back();
assert(lsb_ == 0); ivl_assert(*this, !name_tail.index.empty());
assert(idx_.size() == 1);
NetExpr*ex = elab_and_eval(des, scope, idx_[0], -1); 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, index_tail.msb, -1);
// If the bit select is constant, then treat it similar // If the bit select is constant, then treat it similar
// to the part select, so that I save the effort of // 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); NetESignal*node = new NetESignal(net);
node->set_line(*this); 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 // If this is a part select of a signal, then make a new
// temporary signal that is connected to just the // temporary signal that is connected to just the
// selected bits. The lsb_ and msb_ expressions are from // selected bits. The lsb_ and msb_ expressions are from
// the foo[msb:lsb] expression in the original. // 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); 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); 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); 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); return elaborate_expr_net_bit_(des, scope, node, found_in);
// It's not anything else, so this must be a simple identifier // It's not anything else, so this must be a simple identifier
// expression with no part or bit select. Return the signal // expression with no part or bit select. Return the signal
// itself as the expression. // itself as the expression.
assert(sel_ == SEL_NONE); assert(use_sel == index_component_t::SEL_NONE);
assert(msb_ == 0);
assert(lsb_ == 0);
assert(idx_.empty());
return node; return node;
} }
@ -1633,6 +1684,10 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
/* /*
* $Log: elab_expr.cc,v $ * $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 * Revision 1.124 2007/04/01 05:28:26 steve
* Get offsets into indexed part selects correct. * Get offsets into indexed part selects correct.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -163,11 +163,17 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
return 0; 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 // This is the special case that the l-value is an entire
// memory. This is, in fact, an error. // 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 " cerr << get_line() << ": error: Cannot assign to array "
<< path_ << ". Did you forget a word index?" << endl; << path_ << ". Did you forget a word index?" << endl;
des->errors += 1; des->errors += 1;
@ -177,19 +183,19 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
if (reg->array_dimensions() > 0) if (reg->array_dimensions() > 0)
return elaborate_lval_net_word_(des, scope, reg); 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); NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_part_(des, scope, lv); elaborate_lval_net_part_(des, scope, lv);
return lv; return lv;
} }
if (sel_ == SEL_IDX_UP) { if (use_sel == index_component_t::SEL_IDX_UP) {
NetAssign_*lv = new NetAssign_(reg); NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_idx_up_(des, scope, lv); elaborate_lval_net_idx_up_(des, scope, lv);
return lv; return lv;
} }
if (sel_ == SEL_IDX_DO) { if (use_sel == index_component_t::SEL_IDX_DO) {
NetAssign_*lv = new NetAssign_(reg); NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_idx_do_(des, scope, lv); elaborate_lval_net_idx_do_(des, scope, lv);
return lv; return lv;
@ -208,12 +214,14 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
return 0; return 0;
} }
ivl_assert(*this, msb_ == 0);
ivl_assert(*this, lsb_ == 0);
long msb, lsb; long msb, lsb;
NetExpr*mux; 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 /* If there is only a single select expression, it is a
bit select. Evaluate the constant value and treat it 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 it not constant, then return the
expression as a mux. */ expression as a mux. */
ivl_assert(*this, idx_.size() == 1); NetExpr*index_expr = elab_and_eval(des, scope, index_tail.msb, -1);
NetExpr*index_expr = elab_and_eval(des, scope, idx_[0], -1);
if (NetEConst*index_con = dynamic_cast<NetEConst*> (index_expr)) { if (NetEConst*index_con = dynamic_cast<NetEConst*> (index_expr)) {
msb = index_con->value().as_long(); msb = index_con->value().as_long();
@ -311,9 +317,15 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
NetScope*scope, NetScope*scope,
NetNet*reg) const NetNet*reg) const
{ {
assert(idx_.size() == 1); const name_component_t&name_tail = path_.back();
ivl_assert(*this, !name_tail.index.empty());
NetExpr*word = elab_and_eval(des, scope, idx_[0], -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*word = elab_and_eval(des, scope, index_head.msb, -1);
// If there is a non-zero base to the memory, then build an // If there is a non-zero base to the memory, then build an
// expression to calculate the canonical address. // 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. */ /* 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); 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); 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); elaborate_lval_net_idx_do_(des, scope, lv);
return lv; return lv;
@ -417,8 +433,12 @@ bool PEIdent::elaborate_lval_net_idx_up_(Design*des,
NetScope*scope, NetScope*scope,
NetAssign_*lv) const NetAssign_*lv) const
{ {
assert(lsb_); const name_component_t&name_tail = path_.back();;
assert(msb_); 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(); NetNet*reg = lv->sig();
assert(reg); assert(reg);
@ -436,7 +456,7 @@ bool PEIdent::elaborate_lval_net_idx_up_(Design*des,
unsigned long wid; unsigned long wid;
calculate_up_do_width_(des, scope, 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. */ /* Correct the mux for the range of the vector. */
if (reg->msb() < reg->lsb()) if (reg->msb() < reg->lsb())
@ -457,8 +477,13 @@ bool PEIdent::elaborate_lval_net_idx_do_(Design*des,
NetScope*scope, NetScope*scope,
NetAssign_*lv) const NetAssign_*lv) const
{ {
assert(lsb_); const name_component_t&name_tail = path_.back();;
assert(msb_); 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 " cerr << get_line() << ": internal error: don't know how to "
"deal with SEL_IDX_DO in lval?" << endl; "deal with SEL_IDX_DO in lval?" << endl;
des->errors += 1; des->errors += 1;
@ -475,6 +500,10 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
/* /*
* $Log: elab_lval.cc,v $ * $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 * Revision 1.42 2007/03/14 05:06:49 steve
* Replace some asserts with ivl_asserts. * Replace some asserts with ivl_asserts.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -1230,7 +1230,7 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
unsigned errors = 0; unsigned errors = 0;
unsigned func_pins = 0; unsigned func_pins = 0;
if (path_.peek_name(0)[0] == '$') if (path_.front().name[0] == '$')
return elaborate_net_sfunc_(des, scope, return elaborate_net_sfunc_(des, scope,
width, rise, fall, decay, width, rise, fall, decay,
drive0, drive1); drive0, drive1);
@ -1320,11 +1320,13 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
Link::strength_t drive0, Link::strength_t drive0,
Link::strength_t drive1) const Link::strength_t drive1) const
{ {
perm_string name = peek_tail_name(path_);
/* Handle the special case that the function call is to /* Handle the special case that the function call is to
$signed. This takes a single expression argument, and $signed. This takes a single expression argument, and
forces it to be a signed result. Otherwise, it is as if the forces it to be a signed result. Otherwise, it is as if the
$signed did not exist. */ $signed did not exist. */
if (strcmp(path_.peek_name(0), "$signed") == 0) { if (strcmp(name, "$signed") == 0) {
if ((parms_.count() != 1) || (parms_[0] == 0)) { if ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_line() << ": error: The $signed() function " cerr << get_line() << ": error: The $signed() function "
<< "takes exactly one(1) argument." << endl; << "takes exactly one(1) argument." << endl;
@ -1340,7 +1342,7 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
} }
/* handle $unsigned like $signed */ /* handle $unsigned like $signed */
if (strcmp(path_.peek_name(0), "$unsigned") == 0) { if (strcmp(name, "$unsigned") == 0) {
if ((parms_.count() != 1) || (parms_[0] == 0)) { if ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_line() << ": error: The $unsigned() function " cerr << get_line() << ": error: The $unsigned() function "
<< "takes exactly one(1) argument." << endl; << "takes exactly one(1) argument." << endl;
@ -1355,11 +1357,11 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
return sub; 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) { if (def == 0) {
cerr << get_line() << ": error: System function " cerr << get_line() << ": error: System function "
<< path_.peek_name(0) << " not defined." << endl; << peek_tail_name(path_) << " not defined." << endl;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }
@ -1545,15 +1547,19 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
Link::strength_t drive0, Link::strength_t drive0,
Link::strength_t drive1) const Link::strength_t drive1) const
{ {
assert(msb_ == 0); const name_component_t&name_tail = path_.back();
assert(lsb_ == 0); ivl_assert(*this, !name_tail.index.empty());
assert(idx_.size() == 1);
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. */ /* Elaborate the selector. */
NetNet*sel; NetNet*sel;
if (sig->msb() < sig->lsb()) { 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); sel_expr = make_sub_expr(sig->lsb(), sel_expr);
if (NetExpr*tmp = sel_expr->eval_tree()) { if (NetExpr*tmp = sel_expr->eval_tree()) {
delete sel_expr; delete sel_expr;
@ -1563,7 +1569,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
sel = sel_expr->synthesize(des); sel = sel_expr->synthesize(des);
} else if (sig->lsb() != 0) { } 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()); sel_expr = make_add_expr(sel_expr, - sig->lsb());
if (NetExpr*tmp = sel_expr->eval_tree()) { if (NetExpr*tmp = sel_expr->eval_tree()) {
delete sel_expr; delete sel_expr;
@ -1573,7 +1579,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
sel = sel_expr->synthesize(des); sel = sel_expr->synthesize(des);
} else { } 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) { if (debug_elaborate) {
@ -1604,7 +1610,9 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
Link::strength_t drive0, Link::strength_t drive0,
Link::strength_t drive1) const Link::strength_t drive1) const
{ {
assert(scope); ivl_assert(*this, scope);
const name_component_t&name_tail = path_.back();
NetNet* sig = 0; NetNet* sig = 0;
const NetExpr*par = 0; const NetExpr*par = 0;
@ -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 /* Check for the error case that the name is not found, and it
is hierarchical. We can't just create a name in another is hierarchical. We can't just create a name in another
scope, it's just not allowed. */ 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 " cerr << get_line() << ": error: The hierarchical name "
<< path_ << " is undefined in " << path_ << " is undefined in "
<< scope->name() << "." << endl; << scope->name() << "." << endl;
hname_t tmp_path = path_; pform_name_t tmp_path = path_;
delete[] tmp_path.remove_tail_name(); tmp_path.pop_back();
NetScope*tmp_scope = des->find_scope(scope, tmp_path); NetScope*tmp_scope = des->find_scope(scope, tmp_path);
if (tmp_scope == 0) { if (tmp_scope == 0) {
@ -1667,28 +1675,28 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
/* Fallback, this may be an implicitly declared net. */ /* Fallback, this may be an implicitly declared net. */
if (sig == 0) { if (sig == 0) {
NetNet::Type nettype = scope->default_nettype(); 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); nettype, 1);
sig->data_type(IVL_VT_LOGIC); sig->data_type(IVL_VT_LOGIC);
if (error_implicit || (nettype == NetNet::NONE)) { if (error_implicit || (nettype == NetNet::NONE)) {
cerr << get_line() << ": error: " cerr << get_line() << ": error: "
<< scope->name() << "." << path_.peek_name(0) << scope->name() << "." << name_tail.name
<< " not defined in this scope." << endl; << " not defined in this scope." << endl;
des->errors += 1; des->errors += 1;
} else if (warn_implicit) { } else if (warn_implicit) {
cerr << get_line() << ": warning: implicit " cerr << get_line() << ": warning: implicit "
"definition of wire " << scope->name() "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. */ /* Handle the case that this is an array elsewhere. */
if (sig->array_dimensions() > 0) { if (sig->array_dimensions() > 0) {
if (idx_.size() == 0) { if (name_tail.index.size() == 0) {
cerr << get_line() << ": error: Array " << sig->name() cerr << get_line() << ": error: Array " << sig->name()
<< " cannot be used here without an index." << endl; << " cannot be used here without an index." << endl;
des->errors += 1; des->errors += 1;
@ -1700,14 +1708,16 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
drive0, drive1); 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 /* Catch the case of a non-constant bit select. That should be
handled elsewhere. */ handled elsewhere. */
if (! idx_.empty()) { if (use_sel == index_component_t::SEL_BIT) {
assert(msb_ == 0); const index_component_t&index_tail = name_tail.index.back();
assert(lsb_ == 0);
assert(idx_.size() == 1);
verinum*mval = idx_[0]->eval_const(des, scope); verinum*mval = index_tail.msb->eval_const(des, scope);
if (mval == 0) { if (mval == 0) {
return elaborate_net_bitmux_(des, scope, sig, rise, return elaborate_net_bitmux_(des, scope, sig, rise,
fall, decay, drive0, drive1); fall, decay, drive0, drive1);
@ -1755,9 +1765,14 @@ NetNet* PEIdent::elaborate_net_array_(Design*des, NetScope*scope,
Link::strength_t drive0, Link::strength_t drive0,
Link::strength_t drive1) const Link::strength_t drive1) const
{ {
ivl_assert(*this, idx_.size() >= 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, idx_[0], -1); NetExpr*index_ex = elab_and_eval(des, scope, index_head.msb, -1);
if (index_ex == 0) if (index_ex == 0)
return 0; return 0;
@ -1821,6 +1836,10 @@ NetNet* PEIdent::elaborate_net_array_(Design*des, NetScope*scope,
tmp->data_type(sig->data_type()); tmp->data_type(sig->data_type());
connect(tmp->pin(0), mux->pin_Result()); 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; unsigned midx, lidx;
if (eval_part_select_(des, scope, sig, midx, lidx)) do { 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; NetNet*sig = 0;
if (!error_implicit && nettype!=NetNet::NONE) { 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); NetNet::IMPLICIT, 1);
/* Implicit nets are always scalar logic. */ /* Implicit nets are always scalar logic. */
sig->data_type(IVL_VT_LOGIC); sig->data_type(IVL_VT_LOGIC);
@ -2014,7 +2033,7 @@ NetNet* PEIdent::make_implicit_net_(Design*des, NetScope*scope) const
if (warn_implicit) { if (warn_implicit) {
cerr << get_line() << ": warning: implicit " cerr << get_line() << ": warning: implicit "
"definition of wire logic " << scope->name() "definition of wire logic " << scope->name()
<< "." << path_.peek_name(0) << "." << endl; << "." << peek_tail_name(path_) << "." << endl;
} }
} else { } 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, bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
unsigned&midx, unsigned&lidx) const 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: default:
cerr << get_line() << ": internal error: " cerr << get_line() << ": internal error: "
<< "Unexpected sel_ value = " << sel_ << endl; << "Unexpected sel_ value = " << index_tail.sel << endl;
assert(0); ivl_assert(*this, 0);
break; break;
case PEIdent::SEL_IDX_DO: case index_component_t::SEL_IDX_DO:
case PEIdent::SEL_IDX_UP: { case index_component_t::SEL_IDX_UP: {
assert(msb_); NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1);
assert(lsb_);
assert(idx_.size() == sig->array_dimensions());
NetExpr*tmp_ex = elab_and_eval(des, scope, msb_, -1);
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex); NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
assert(tmp); assert(tmp);
@ -2058,14 +2087,14 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
midx = sig->sb_to_idx(midx_val); midx = sig->sb_to_idx(midx_val);
delete tmp_ex; 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<NetEConst*>(tmp_ex); tmp = dynamic_cast<NetEConst*>(tmp_ex);
assert(tmp); assert(tmp);
long wid = tmp->value().as_long(); long wid = tmp->value().as_long();
delete tmp_ex; 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); lidx = sig->sb_to_idx(midx_val+wid-1);
else else
lidx = sig->sb_to_idx(midx_val-wid+1); 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; break;
} }
case PEIdent::SEL_PART: { case index_component_t::SEL_PART: {
assert(msb_);
assert(lsb_);
assert(idx_.size() == sig->array_dimensions());
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<NetEConst*>(tmp_ex); NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
assert(tmp); assert(tmp);
@ -2092,12 +2118,12 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
midx = sig->sb_to_idx(midx_val); midx = sig->sb_to_idx(midx_val);
delete tmp_ex; 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<NetEConst*>(tmp_ex); tmp = dynamic_cast<NetEConst*>(tmp_ex);
if (tmp == 0) { if (tmp == 0) {
cerr << get_line() << ": internal error: " cerr << get_line() << ": internal error: "
<< "lsb expression is not constant?: " << "lsb expression is not constant?: "
<< *tmp_ex << ", " << *lsb_ << endl; << *tmp_ex << ", " << *index_tail.lsb << endl;
} }
assert(tmp); assert(tmp);
@ -2131,19 +2157,16 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
break; break;
} }
case PEIdent::SEL_NONE: case index_component_t::SEL_BIT:
if (idx_.size() > sig->array_dimensions()) { if (name_tail.index.size() > sig->array_dimensions()) {
unsigned a_dims = sig->array_dimensions(); const index_component_t&index_head = name_tail.index.front();
assert(msb_ == 0); verinum*mval = index_head.msb->eval_const(des, scope);
assert(lsb_ == 0);
assert(idx_.size() == a_dims+1);
verinum*mval = idx_[a_dims]->eval_const(des, scope);
if (mval == 0) { if (mval == 0) {
cerr << get_line() << ": error: Index of " << path_ << cerr << get_line() << ": error: Index of " << path_ <<
" needs to be constant in this context." << " needs to be constant in this context." <<
endl; endl;
cerr << get_line() << ": : Index expression is: " cerr << get_line() << ": : Index expression is: "
<< *(idx_[0]) << endl; << *index_head.msb << endl;
des->errors += 1; des->errors += 1;
return false; return false;
} }
@ -2160,17 +2183,9 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
lidx = midx; lidx = midx;
} else { } else {
if (msb_ || lsb_) {
cerr << get_line() << ": internal error: " cerr << get_line() << ": internal error: "
<< "Unexpected msb_/lsb_ values?" << endl; << "Bit select " << path_ << endl;
if (msb_) ivl_assert(*this, 0);
cerr << get_line() << " : "
<< *msb_ << endl;
if (lsb_)
cerr << get_line() << " : "
<< *lsb_ << endl;
}
assert(msb_ == 0 && lsb_ == 0);
midx = sig->vector_width() - 1; midx = sig->vector_width() - 1;
lidx = 0; lidx = 0;
} }
@ -2245,10 +2260,16 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
// The default word select is the first. // The default word select is the first.
unsigned widx = 0; unsigned widx = 0;
if (sig->array_dimensions() > 0) { const name_component_t&name_tail = path_.back();
assert(!idx_.empty());
NetExpr*tmp_ex = elab_and_eval(des, scope, idx_[0], -1); if (sig->array_dimensions() > 0) {
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<NetEConst*>(tmp_ex); NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
assert(tmp); assert(tmp);
@ -2260,7 +2281,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
cerr << get_line() << ": debug: Use [" << widx << "]" cerr << get_line() << ": debug: Use [" << widx << "]"
<< " to index l-value array." << endl; << " to index l-value array." << endl;
} else { } else if (!name_tail.index.empty()) {
if (! eval_part_select_(des, scope, sig, midx, lidx)) if (! eval_part_select_(des, scope, sig, midx, lidx))
return 0; return 0;
} }
@ -2941,6 +2962,10 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/* /*
* $Log: elab_net.cc,v $ * $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 * Revision 1.203 2007/04/18 01:40:49 steve
* Fix elaboration of multiply of two constants. * Fix elaboration of multiply of two constants.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # 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 NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
{ {
hname_t path = path_; pform_name_t path = path_;
perm_string name = path.remove_tail_name(); name_component_t name_tail = path_.back();
path.pop_back();
NetScope*pscope = scope; NetScope*pscope = scope;
if (path.peek_name(0)) if (path_.size() > 0)
pscope = des->find_scope(scope, path); pscope = des->find_scope(scope, path);
const NetExpr*ex_msb; const NetExpr*ex_msb;
const NetExpr*ex_lsb; 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) { 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; "'' is not a parameter in " << scope->name() << "." << endl;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }
NetExpr*res = new NetEParam(des, pscope, name); NetExpr*res = new NetEParam(des, pscope, name_tail.name);
res->set_line(*this); res->set_line(*this);
assert(res); assert(res);
if (msb_ && lsb_) { index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
assert(idx_.empty()); 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 " cerr << get_line() << ": sorry: Cannot part select "
"bits of parameters." << endl; "bits of parameters." << endl;
des->errors += 1; des->errors += 1;
break;
} else if (!idx_.empty()) { case index_component_t::SEL_BIT:
assert(msb_==0);
assert(lsb_==0);
assert(idx_.size() == 1);
/* We have here a bit select. Insert a NetESelect node /* We have here a bit select. Insert a NetESelect node
to handle it. */ 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) { if (tmp != 0) {
res = new NetESelect(res, tmp, 1); res = new NetESelect(res, tmp, 1);
} }
break;
} }
return res; return res;
@ -233,6 +240,10 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
/* /*
* $Log: elab_pexpr.cc,v $ * $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 * Revision 1.26 2007/04/26 03:06:22 steve
* Rework hname_t to use perm_strings. * Rework hname_t to use perm_strings.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -66,7 +66,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// place of the elaborated expression. // place of the elaborated expression.
typedef map<perm_string,param_expr_t>::const_iterator mparm_it_t; typedef map<perm_string,param_expr_t>::const_iterator mparm_it_t;
typedef map<hname_t,PExpr*>::const_iterator hparm_it_t; typedef map<pform_name_t,PExpr*>::const_iterator pform_parm_it_t;
// This loop scans the parameters in the module, and creates // 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 // here because the parameter receiving the assignment may be
// in a scope not discovered by this pass. // 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 ++ ) { ; cur != defparms.end() ; cur ++ ) {
PExpr*ex = (*cur).second; PExpr*ex = (*cur).second;
@ -761,6 +761,10 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const
/* /*
* $Log: elab_scope.cc,v $ * $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 * Revision 1.44 2007/03/22 16:08:15 steve
* Spelling fixes from Larry * Spelling fixes from Larry
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -34,6 +34,7 @@
# include "netlist.h" # include "netlist.h"
# include "netmisc.h" # include "netmisc.h"
# include "util.h" # include "util.h"
# include "ivl_assert.h"
/* /*
* This local function checks if a named signal is connected to a * 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. * within the port_t that have a matching name.
*/ */
static bool signal_is_in_port(const svector<Module::port_t*>&ports, static bool signal_is_in_port(const svector<Module::port_t*>&ports,
const hname_t&name) NetNet*sig)
{ {
perm_string name = sig->name();
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) { for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
Module::port_t*pp = ports[idx]; Module::port_t*pp = ports[idx];
@ -53,9 +56,15 @@ static bool signal_is_in_port(const svector<Module::port_t*>&ports,
// This port has an internal connection. In this case, // This port has an internal connection. In this case,
// the port has 0 or more NetEIdent objects concatenated // the port has 0 or more NetEIdent objects concatenated
// together that form the port. // 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) { for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
perm_string pname = peek_tail_name(pp->expr[cc]->path());
assert(pp->expr[cc]); assert(pp->expr[cc]);
if (pp->expr[cc]->path() == name) if (pname == name)
return true; return true;
} }
} }
@ -63,6 +72,7 @@ static bool signal_is_in_port(const svector<Module::port_t*>&ports,
return false; return false;
} }
#if 0
static NetNet*find_signal_in_scope(NetScope*scope, const hname_t&path) static NetNet*find_signal_in_scope(NetScope*scope, const hname_t&path)
{ {
NetScope*cur = scope; 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)); return cur->find_signal(path.peek_name(idx));
} }
#endif
bool Module::elaborate_sig(Design*des, NetScope*scope) const bool Module::elaborate_sig(Design*des, NetScope*scope) const
{ {
bool flag = true; bool flag = true;
// Get all the explicitly declared wires of the module and
// start the signals list with them.
const map<hname_t,PWire*>&wl = get_wires();
// Scan all the ports of the module, and make sure that each // Scan all the ports of the module, and make sure that each
// is connected to wires that have port declarations. // is connected to wires that have port declarations.
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) { 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) if (pp == 0)
continue; continue;
map<hname_t,PWire*>::const_iterator wt; map<pform_name_t,PWire*>::const_iterator wt;
for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) { for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
hname_t port_path (pp->expr[cc]->path()); pform_name_t port_path (pp->expr[cc]->path());
wt = wl.find(port_path); wt = wires_.find(port_path);
if (wt == wl.end()) { if (wt == wires_.end()) {
cerr << get_line() << ": error: " cerr << get_line() << ": error: "
<< "Port " << pp->expr[cc]->path() << " (" << "Port " << pp->expr[cc]->path() << " ("
<< (idx+1) << ") of module " << name_ << (idx+1) << ") of module " << name_
@ -119,14 +126,11 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
} }
} }
for (map<hname_t,PWire*>::const_iterator wt = wl.begin() for (map<pform_name_t,PWire*>::const_iterator wt = wires_.begin()
; wt != wl.end() ; wt != wires_.end() ; wt ++ ) {
; wt ++ ) {
PWire*cur = (*wt).second; PWire*cur = (*wt).second;
cur->elaborate_sig(des, scope); NetNet*sig = cur->elaborate_sig(des, scope);
NetNet*sig = find_signal_in_scope(scope, cur->path());
// If this wire is a signal of the module (as opposed to // If this wire is a signal of the module (as opposed to
// a port of a function) and is a port, then check that // 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) if (sig && (sig->scope() == scope)
&& (cur->get_port_type() != NetNet::NOT_A_PORT)) { && (cur->get_port_type() != NetNet::NOT_A_PORT)) {
hname_t name = (*wt).first; if (! signal_is_in_port(ports, sig)) {
if (! signal_is_in_port(ports, name)) {
cerr << cur->get_line() << ": error: Signal " cerr << cur->get_line() << ": error: Signal "
<< name << " has a declared direction " << sig->name() << " has a declared direction "
<< "but is not a port." << endl; << "but is not a port." << endl;
des->errors += 1; 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 // Scan the declared PWires to elaborate the obvious signals
// in the current scope. // in the current scope.
typedef map<hname_t,PWire*>::const_iterator wires_it_t; typedef map<pform_name_t,PWire*>::const_iterator wires_it_t;
for (wires_it_t wt = wires.begin() for (wires_it_t wt = wires.begin()
; wt != wires.end() ; wt ++ ) { ; 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 name. We know by design that the port name is given
as two components: <func>.<port>. */ as two components: <func>.<port>. */
hname_t path = (*ports_)[idx]->path(); pform_name_t path = (*ports_)[idx]->path();
perm_string pname = lex_strings.make(path.peek_name(1)); ivl_assert(*this, path.size() == 2);
perm_string ppath = lex_strings.make(path.peek_name(0));
perm_string pname = peek_tail_name(path);
perm_string ppath = peek_head_name(path);
if (ppath != scope->basename()) { if (ppath != scope->basename()) {
cerr << get_line() << ": internal error: function " 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 name. We know by design that the port name is given
as two components: <task>.<port>. */ as two components: <task>.<port>. */
hname_t path = (*ports_)[idx]->path(); pform_name_t path = (*ports_)[idx]->path();
assert(path.peek_name(0) && path.peek_name(1)); 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 /* check that the current scope really does have the
name of the first component of the task port name. Do name of the first component of the task port name. Do
this by looking up the task scope in the parent of this by looking up the task scope in the parent of
the current scope. */ the current scope. */
if (scope->parent()->child(path.peek_name(0)) != scope) { ivl_assert(*this, scope->basename() == scope_name);
cerr << "internal error: task scope " << path
<< " not the same as scope " << scope->name()
<< "?!" << endl;
return;
}
/* Find the signal for the port. We know by definition /* Find the signal for the port. We know by definition
that it is in the scope of the task, so look only in that it is in the scope of the task, so look only in
the scope. */ the scope. */
NetNet*tmp = scope->find_signal(path.peek_name(1)); NetNet*tmp = scope->find_signal(port_name);
if (tmp == 0) { if (tmp == 0) {
cerr << get_line() << ": internal error: " cerr << get_line() << ": internal error: "
<< "Could not find port " << path.peek_name(1) << "Could not find port " << port_name
<< " in scope " << scope->name() << endl; << " in scope " << scope->name() << endl;
scope->dump(cerr); 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 * elaboration this creates an object in the design that represent the
* defined item. * 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 /* The parser may produce hierarchical names for wires. I here
follow the scopes down to the base where I actually want to follow the scopes down to the base where I actually want to
elaborate the NetNet object. */ elaborate the NetNet object. */
{ hname_t tmp_path = hname_; { pform_name_t tmp_path = hname_;
tmp_path.remove_tail_name(); tmp_path.pop_back();
for (unsigned idx = 0 ; tmp_path.peek_name(idx) ; idx += 1) { while (! tmp_path.empty()) {
scope = scope->child(tmp_path.peek_name(idx)); name_component_t cur = tmp_path.front();
tmp_path.pop_front();
scope = scope->child(cur.name);
if (scope == 0) { if (scope == 0) {
cerr << get_line() << ": internal error: " cerr << get_line() << ": internal error: "
@ -580,7 +585,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
"Unable to evaluate constant expression ``" << "Unable to evaluate constant expression ``" <<
*msb_[idx] << "''." << endl; *msb_[idx] << "''." << endl;
des->errors += 1; des->errors += 1;
return; return 0;
} }
mnum[idx] = tmp->value().as_long(); mnum[idx] = tmp->value().as_long();
@ -593,7 +598,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
"Unable to evaluate constant expression ``" << "Unable to evaluate constant expression ``" <<
*lsb_[idx] << "''." << endl; *lsb_[idx] << "''." << endl;
des->errors += 1; des->errors += 1;
return; return 0;
} }
lnum[idx] = tmp->value().as_long(); 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." << "'' declared both as a vector and a scalar."
<< endl; << endl;
des->errors += 1; des->errors += 1;
return; return 0;
} }
@ -622,7 +627,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
" vs. [" << mnum[0] << ":" << lnum[0] << "]" " vs. [" << mnum[0] << ":" << lnum[0] << "]"
" for signal ``" << hname_ << "''" << endl; " for signal ``" << hname_ << "''" << endl;
des->errors += 1; des->errors += 1;
return; return 0;
} }
} }
@ -657,9 +662,9 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
if ((lexp == 0) || (rexp == 0)) { if ((lexp == 0) || (rexp == 0)) {
cerr << get_line() << ": internal error: There is " cerr << get_line() << ": internal error: There is "
<< "a problem evaluating indices for ``" << "a problem evaluating indices for ``"
<< hname_.peek_tail_name() << "''." << endl; << hname_ << "''." << endl;
des->errors += 1; des->errors += 1;
return; return 0;
} }
NetEConst*lcon = dynamic_cast<NetEConst*> (lexp); NetEConst*lcon = dynamic_cast<NetEConst*> (lexp);
@ -668,9 +673,9 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
if ((lcon == 0) || (rcon == 0)) { if ((lcon == 0) || (rcon == 0)) {
cerr << get_line() << ": internal error: The indices " cerr << get_line() << ": internal error: The indices "
<< "are not constant for array ``" << "are not constant for array ``"
<< hname_.peek_tail_name() << "''." << endl; << hname_ << "''." << endl;
des->errors += 1; des->errors += 1;
return; return 0;
} }
verinum lval = lcon->value(); verinum lval = lcon->value();
@ -679,8 +684,6 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
delete lexp; delete lexp;
delete rexp; delete rexp;
perm_string name = lex_strings.make(hname_.peek_tail_name());
array_dimensions = 1; array_dimensions = 1;
array_s0 = lval.as_long(); array_s0 = lval.as_long();
array_e0 = rval.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) { if (debug_elaborate) {
cerr << get_line() << ": debug: Create signal " cerr << get_line() << ": debug: Create signal "
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name << wtype << " ["<<msb<<":"<<lsb<<"] " << name
@ -754,10 +757,16 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
for (unsigned idx = 0 ; idx < nattrib ; idx += 1) for (unsigned idx = 0 ; idx < nattrib ; idx += 1)
sig->attribute(attrib_list[idx].key, attrib_list[idx].val); sig->attribute(attrib_list[idx].key, attrib_list[idx].val);
return sig;
} }
/* /*
* $Log: elab_sig.cc,v $ * $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 * Revision 1.50 2007/04/26 03:06:22 steve
* Rework hname_t to use perm_strings. * Rework hname_t to use perm_strings.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -770,8 +770,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
if (mport.count() == 0) if (mport.count() == 0)
continue; continue;
NetNet*tmp = des->find_signal(instance[0], perm_string pname = peek_tail_name(mport[0]->path());
mport[0]->path());
NetNet*tmp = instance[0]->find_signal(pname);
assert(tmp); assert(tmp);
if (tmp->port_type() == NetNet::PINPUT) { 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 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); return elaborate_sys(des, scope);
else else
return elaborate_usr(des, scope); 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; return cur;
} }
@ -3416,6 +3417,10 @@ Design* elaborate(list<perm_string>roots)
/* /*
* $Log: elaborate.cc,v $ * $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 * Revision 1.370 2007/04/16 01:10:07 steve
* Properly ignore unsupported ifnone. * Properly ignore unsupported ifnone.
* *

15
eval.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -177,16 +177,17 @@ verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const
NetEvent*eve; NetEvent*eve;
const NetExpr*expr; const NetExpr*expr;
const name_component_t&name_tail = path_.back();
// Handle the special case that this ident is a genvar // Handle the special case that this ident is a genvar
// variable name. In that case, the genvar meaning preempts // variable name. In that case, the genvar meaning preempts
// everything and we just return that value immediately. // everything and we just return that value immediately.
if (scope->genvar_tmp 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); return new verinum(scope->genvar_tmp_val);
} }
symbol_search(des, scope, path_, symbol_search(des, scope, path_, net, expr, eve);
net, expr, eve);
if (expr == 0) if (expr == 0)
return 0; return 0;
@ -201,7 +202,7 @@ verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const
assert(eval); assert(eval);
if (msb_ || lsb_) if (!name_tail.index.empty())
return 0; return 0;
@ -275,6 +276,10 @@ verinum* PEUnary::eval_const(const Design*des, NetScope*scope) const
/* /*
* $Log: eval.cc,v $ * $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 * Revision 1.45 2007/03/07 00:38:15 steve
* Lint fixes. * Lint fixes.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -114,26 +114,28 @@ const list<NetScope*> Design::find_root_scopes() const
* more step down the tree until the name runs out or the search * more step down the tree until the name runs out or the search
* fails. * 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; return 0;
for (list<NetScope*>::const_iterator scope = root_scopes_.begin() for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
; scope != root_scopes_.end(); scope++) { ; scope != root_scopes_.end(); scope++) {
NetScope*cur = *scope; NetScope*cur = *scope;
if (strcmp(path.peek_name(0), cur->basename()) != 0) if (strcmp(peek_head_name(path), cur->basename()) != 0)
continue; continue;
unsigned hidx = 1; pform_name_t tmp = path;
while (cur) { tmp.pop_front();
const char*name = path.peek_name(hidx);
if (name == 0)
return cur;
while (cur) {
if (tmp.empty()) return cur;
perm_string name = peek_head_name(tmp);
cur = cur->child(name); 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 * 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 parameter within which I start looking for the scope. If
* the scope. If I do not find the scope within the passed scope, * I do not find the scope within the passed scope, start looking in
* start looking in parent scopes until I find it, or I run out of * parent scopes until I find it, or I run out of parent scopes.
* 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); assert(scope);
if (path.peek_name(0) == 0) if (path.empty())
return scope; return scope;
for ( ; scope ; scope = scope->parent()) { 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; NetScope*cur = scope;
do { do {
cur = cur->child(key); cur = cur->child(key);
if (cur == 0) break; if (cur == 0) break;
hidx += 1; tmp.pop_front();
key = path.peek_name(hidx); if (tmp.empty()) break;
name_front = tmp.front();
key = name_front.name;
} while (key); } while (key);
if (cur) return cur; if (cur) return cur;
@ -196,12 +201,13 @@ void NetScope::run_defparams(Design*des)
} }
} }
map<hname_t,NetExpr*>::const_iterator pp; map<pform_name_t,NetExpr*>::const_iterator pp;
for (pp = defparams.begin() ; pp != defparams.end() ; pp ++ ) { for (pp = defparams.begin() ; pp != defparams.end() ; pp ++ ) {
NetExpr*val = (*pp).second; 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 /* If there is no path on the name, then the targ_scope
is the current 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 * It is the job of this function to properly implement Verilog scope
* rules as signals are concerned. * 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); assert(scope);
perm_string key = path.remove_tail_name(); perm_string key = peek_tail_name(path);
if (path.peek_name(0)) path.pop_back();
if (! path.empty())
scope = find_scope(scope, path); scope = find_scope(scope, path);
while (scope) { while (scope) {
@ -444,7 +451,7 @@ NetNet* Design::find_signal(NetScope*scope, hname_t path)
return 0; 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); assert(scope);
NetScope*func = find_scope(scope, name); NetScope*func = find_scope(scope, name);
@ -454,7 +461,7 @@ NetFuncDef* Design::find_function(NetScope*scope, const hname_t&name)
return 0; return 0;
} }
NetFuncDef* Design::find_function(const hname_t&key) NetFuncDef* Design::find_function(const pform_name_t&key)
{ {
NetScope*func = find_scope(key); NetScope*func = find_scope(key);
if (func && (func->type() == NetScope::FUNC)) if (func && (func->type() == NetScope::FUNC))
@ -463,7 +470,7 @@ NetFuncDef* Design::find_function(const hname_t&key)
return 0; 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); NetScope*task = find_scope(scope, name);
if (task && (task->type() == NetScope::TASK)) if (task && (task->type() == NetScope::TASK))
@ -472,7 +479,7 @@ NetScope* Design::find_task(NetScope*scope, const hname_t&name)
return 0; return 0;
} }
NetScope* Design::find_task(const hname_t&key) NetScope* Design::find_task(const pform_name_t&key)
{ {
NetScope*task = find_scope(key); NetScope*task = find_scope(key);
if (task && (task->type() == NetScope::TASK)) if (task && (task->type() == NetScope::TASK))
@ -558,6 +565,10 @@ void Design::delete_process(NetProcTop*top)
/* /*
* $Log: net_design.cc,v $ * $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 * Revision 1.51 2007/04/26 03:06:22 steve
* Rework hname_t to use perm_strings. * Rework hname_t to use perm_strings.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
/* /*
@ -33,6 +33,7 @@
# include <list> # include <list>
# include <vector> # include <vector>
# include "ivl_target.h" # include "ivl_target.h"
# include "pform_types.h"
# include "config.h" # include "config.h"
# include "verinum.h" # include "verinum.h"
# include "verireal.h" # include "verireal.h"
@ -3291,7 +3292,7 @@ class NetScope : public Attrib {
assignments from the scope pass to the parameter evaluation assignments from the scope pass to the parameter evaluation
step. After that, it is not used. */ step. After that, it is not used. */
map<hname_t,NetExpr*>defparams; map<pform_name_t,NetExpr*>defparams;
public: public:
/* After everything is all set up, the code generators like /* 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 path is taken as an absolute scope name. Otherwise, the
scope is located starting at the passed scope and working scope is located starting at the passed scope and working
up if needed. */ up if needed. */
NetScope* find_scope(const hname_t&path) const; NetScope* find_scope(const pform_name_t&path) const;
NetScope* find_scope(NetScope*, const hname_t&path) const; NetScope* find_scope(NetScope*, const pform_name_t&path) const;
// PARAMETERS // PARAMETERS
@ -3404,15 +3405,15 @@ class Design {
this method, unlike the NetScope::find_signal method, this method, unlike the NetScope::find_signal method,
handles global name binding. */ handles global name binding. */
NetNet*find_signal(NetScope*scope, hname_t path); NetNet*find_signal(NetScope*scope, pform_name_t path);
// Functions // Functions
NetFuncDef* find_function(NetScope*scope, const hname_t&key); NetFuncDef* find_function(NetScope*scope, const pform_name_t&key);
NetFuncDef* find_function(const hname_t&path); NetFuncDef* find_function(const pform_name_t&path);
// Tasks // Tasks
NetScope* find_task(NetScope*scope, const hname_t&name); NetScope* find_task(NetScope*scope, const pform_name_t&name);
NetScope* find_task(const hname_t&key); NetScope* find_task(const pform_name_t&key);
// NODES // NODES
void add_node(NetNode*); void add_node(NetNode*);
@ -3500,6 +3501,10 @@ extern ostream& operator << (ostream&, NetNet::Type);
/* /*
* $Log: netlist.h,v $ * $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 * Revision 1.378 2007/04/26 03:06:22 steve
* Rework hname_t to use perm_strings. * Rework hname_t to use perm_strings.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "netlist.h" # include "netlist.h"
@ -40,20 +40,20 @@
* these values are set to 0. * these values are set to 0.
*/ */
extern NetScope* symbol_search(const Design*des, extern NetScope* symbol_search(const Design*des,
NetScope*start, hname_t path, NetScope*start, pform_name_t path,
NetNet*&net, /* net/reg */ NetNet*&net, /* net/reg */
const NetExpr*&par,/* parameter */ const NetExpr*&par,/* parameter */
NetEvent*&eve, /* named event */ NetEvent*&eve, /* named event */
const NetExpr*&ex1, const NetExpr*&ex2); const NetExpr*&ex1, const NetExpr*&ex2);
inline NetScope* symbol_search(const Design*des, inline NetScope* symbol_search(const Design*des,
NetScope*start, const hname_t&path, NetScope*start, const pform_name_t&path,
NetNet*&net, /* net/reg */ NetNet*&net, /* net/reg */
const NetExpr*&par,/* parameter */ const NetExpr*&par,/* parameter */
NetEvent*&eve /* named event */) NetEvent*&eve /* named event */)
{ {
const NetExpr*ex1, *ex2; 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 $ * $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 * Revision 1.29 2007/03/08 05:30:03 steve
* Limit the calculated widths of constants. * Limit the calculated widths of constants.
* *

256
parse.y
View File

@ -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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -98,6 +98,7 @@ static list<perm_string>* list_from_identifier(list<perm_string>*tmp, char*id)
strdup. They can be put into lists with the texts type. */ strdup. They can be put into lists with the texts type. */
char*text; char*text;
list<perm_string>*perm_strings; list<perm_string>*perm_strings;
pform_name_t*pform_name;
hname_t*hier; hname_t*hier;
@ -123,8 +124,6 @@ static list<perm_string>* list_from_identifier(list<perm_string>*tmp, char*id)
svector<PEEvent*>*event_expr; svector<PEEvent*>*event_expr;
PEIdent*indexed_identifier;
NetNet::Type nettype; NetNet::Type nettype;
PGBuiltin::Type gatetype; PGBuiltin::Type gatetype;
NetNet::PortType porttype; NetNet::PortType porttype;
@ -191,7 +190,6 @@ static list<perm_string>* list_from_identifier(list<perm_string>*tmp, char*id)
%type <statement> udp_initial udp_init_opt %type <statement> udp_initial udp_init_opt
%type <expr> udp_initial_expr_opt %type <expr> udp_initial_expr_opt
%type <hier> identifier
%type <text> register_variable net_variable %type <text> register_variable net_variable
%type <perm_strings> register_variable_list net_variable_list list_of_identifiers %type <perm_strings> register_variable_list net_variable_list list_of_identifiers
@ -217,13 +215,13 @@ static list<perm_string>* list_from_identifier(list<perm_string>*tmp, char*id)
%type <gate> gate_instance %type <gate> gate_instance
%type <gates> gate_instance_list %type <gates> gate_instance_list
%type <pform_name> heirarchy_identifier
%type <expr> expression expr_primary %type <expr> expression expr_primary
%type <expr> lpvalue %type <expr> lpvalue
%type <expr> delay_value delay_value_simple %type <expr> delay_value delay_value_simple
%type <exprs> delay1 delay3 delay3_opt delay_value_list %type <exprs> delay1 delay3 delay3_opt delay_value_list
%type <exprs> expression_list_with_nuls expression_list_proper %type <exprs> expression_list_with_nuls expression_list_proper
%type <exprs> cont_assign cont_assign_list %type <exprs> cont_assign cont_assign_list
%type <indexed_identifier> indexed_identifier
%type <exprs> range range_opt %type <exprs> range range_opt
%type <nettype> net_type var_type net_type_opt %type <nettype> net_type var_type net_type_opt
@ -492,7 +490,7 @@ charge_strength_opt
; ;
defparam_assign defparam_assign
: identifier '=' expression : heirarchy_identifier '=' expression
{ PExpr*tmp = $3; { PExpr*tmp = $3;
if (!pform_expression_is_constant(tmp)) { if (!pform_expression_is_constant(tmp)) {
yyerror(@3, "error: parameter value " yyerror(@3, "error: parameter value "
@ -605,7 +603,7 @@ delay_value_simple
} }
} }
| IDENTIFIER | 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_file(@1.text);
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
$$ = tmp; $$ = tmp;
@ -671,16 +669,14 @@ dr_strength1
; ;
event_control event_control
: '@' identifier : '@' heirarchy_identifier
{ PEIdent*tmpi = new PEIdent(*$2); { 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); PEEvent*tmpe = new PEEvent(PEEvent::ANYEDGE, tmpi);
PEventStatement*tmps = new PEventStatement(tmpe); PEventStatement*tmps = new PEventStatement(tmpe);
tmps->set_file(@1.text); tmps->set_file(@1.text);
tmps->set_lineno(@1.first_line); tmps->set_lineno(@1.first_line);
$$ = tmps; $$ = tmps;
delete $2;
} }
| '@' '(' event_expression_list ')' | '@' '(' event_expression_list ')'
{ PEventStatement*tmp = new PEventStatement(*$3); { PEventStatement*tmp = new PEventStatement(*$3);
@ -1034,53 +1030,29 @@ expr_primary
} }
| SYSTEM_IDENTIFIER | SYSTEM_IDENTIFIER
{ perm_string tn = lex_strings.make($1); { 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_file(@1.text);
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
$$ = tmp; $$ = tmp;
delete $1; delete $1;
} }
/* The indexed_identifier rule matches simple identifiers as well as /* The heirarchy_identifier rule matches simple identifiers as well as
indexed arrays. Part selects are handled below. */ indexed arrays and part selects */
| indexed_identifier | heirarchy_identifier
{ PEIdent*tmp = $1; { PEIdent*tmp = new PEIdent(*$1);
$$ = tmp; tmp->set_file(@1.text);
} tmp->set_lineno(@1.first_line);
/* 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; $$ = tmp;
delete $1;
} }
/* An identifer followed by an expression list in parentheses is a /* An identifer followed by an expression list in parentheses is a
function call. If a system identifier, then a system function function call. If a system identifier, then a system function
call. */ call. */
| identifier '(' expression_list_proper ')' | heirarchy_identifier '(' expression_list_proper ')'
{ PECallFunction*tmp = new PECallFunction(*$1, *$3); { PECallFunction*tmp = new PECallFunction(*$1, *$3);
tmp->set_file(@1.text); tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
@ -1089,7 +1061,7 @@ expr_primary
} }
| SYSTEM_IDENTIFIER '(' expression_list_proper ')' | SYSTEM_IDENTIFIER '(' expression_list_proper ')'
{ perm_string tn = lex_strings.make($1); { 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_file(@1.text);
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
$$ = tmp; $$ = tmp;
@ -1345,36 +1317,58 @@ gatetype
/* A general identifier is a hierarchical name, with the right most /* A general identifier is a hierarchical name, with the right most
name the base of the identifier. This rule builds up a name the base of the identifier. This rule builds up a
hierarchical name from left to right, forming a list of names. */ hierarchical name from the left to the right, forming a list of
identifier names. */
heirarchy_identifier
: IDENTIFIER : IDENTIFIER
{ $$ = new hname_t(lex_strings.make($1)); { $$ = new pform_name_t;
$$->push_back(name_component_t(lex_strings.make($1)));
delete $1; delete $1;
} }
| identifier '.' IDENTIFIER | heirarchy_identifier '.' IDENTIFIER
{ hname_t * tmp = $1; { pform_name_t * tmp = $1;
tmp->append(lex_strings.make($3)); tmp->push_back(name_component_t(lex_strings.make($3)));
delete $3; delete $3;
$$ = tmp; $$ = tmp;
} }
; | heirarchy_identifier '[' expression ']'
{ pform_name_t * tmp = $1;
/* An indexed_identifier is an identifier with a bit-select name_component_t&tail = tmp->back();
expression. This bit select may be an array index or bit index, index_component_t itmp;
to be sorted out later. */ itmp.sel = index_component_t::SEL_BIT;
indexed_identifier itmp.msb = $3;
: identifier tail.index.push_back(itmp);
{ PEIdent*tmp = new PEIdent(*$1);
tmp->sel_ = PEIdent::SEL_NONE;
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
$$ = tmp; $$ = tmp;
} }
| indexed_identifier '[' expression ']' | heirarchy_identifier '[' expression ':' expression ']'
{ PEIdent*tmp = $1; { pform_name_t * tmp = $1;
tmp->sel_ = PEIdent::SEL_NONE; name_component_t&tail = tmp->back();
tmp->idx_.push_back($3); 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; $$ = tmp;
} }
; ;
@ -1552,30 +1546,12 @@ signed_opt : K_signed { $$ = true; } | {$$ = false; } ;
assignments. It is more limited then the general expr_primary assignments. It is more limited then the general expr_primary
rule to reflect the rules for assignment l-values. */ rule to reflect the rules for assignment l-values. */
lpvalue lpvalue
: indexed_identifier : heirarchy_identifier
{ PEIdent*tmp = $1; { PEIdent*tmp = new PEIdent(*$1);
$$ = tmp; tmp->set_file(@1.text);
} tmp->set_lineno(@1.first_line);
| 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; $$ = tmp;
delete $1;
} }
| '{' expression_list_proper '}' | '{' expression_list_proper '}'
{ PEConcat*tmp = new PEConcat(*$2); { PEConcat*tmp = new PEConcat(*$2);
@ -2308,17 +2284,13 @@ port_reference
: IDENTIFIER : IDENTIFIER
{ Module::port_t*ptmp; { Module::port_t*ptmp;
ptmp = pform_module_port_reference($1, @1.text, ptmp = pform_module_port_reference($1, @1.text, @1.first_line);
@1.first_line);
delete $1; delete $1;
$$ = ptmp; $$ = ptmp;
} }
| IDENTIFIER '[' expression ':' expression ']' | IDENTIFIER '[' expression ':' expression ']'
{ PEIdent*wtmp = new PEIdent(hname_t(lex_strings.make($1))); { if (!pform_expression_is_constant($3)) {
wtmp->set_file(@1.text);
wtmp->set_lineno(@1.first_line);
if (!pform_expression_is_constant($3)) {
yyerror(@3, "error: msb expression of " yyerror(@3, "error: msb expression of "
"port part select must be constant."); "port part select must be constant.");
} }
@ -2326,26 +2298,50 @@ port_reference
yyerror(@5, "error: lsb expression of " yyerror(@5, "error: lsb expression of "
"port part select must be constant."); "port part select must be constant.");
} }
wtmp->msb_ = $3; index_component_t itmp;
wtmp->lsb_ = $5; itmp.sel = index_component_t::SEL_PART;
wtmp->sel_ = PEIdent::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; Module::port_t*ptmp = new Module::port_t;
ptmp->name = perm_string(); ptmp->name = perm_string();
ptmp->expr = svector<PEIdent*>(1); ptmp->expr = svector<PEIdent*>(1);
ptmp->expr[0] = wtmp; ptmp->expr[0] = wtmp;
delete $1; delete $1;
$$ = ptmp; $$ = ptmp;
} }
| IDENTIFIER '[' expression ']' | IDENTIFIER '[' expression ']'
{ PEIdent*tmp = new PEIdent(hname_t(lex_strings.make($1))); { if (!pform_expression_is_constant($3)) {
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
if (!pform_expression_is_constant($3)) {
yyerror(@3, "error: port bit select " yyerror(@3, "error: port bit select "
"must be constant."); "must be constant.");
} }
tmp->msb_ = $3; 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; Module::port_t*ptmp = new Module::port_t;
ptmp->name = perm_string(); ptmp->name = perm_string();
ptmp->expr = svector<PEIdent*>(1); ptmp->expr = svector<PEIdent*>(1);
@ -2357,7 +2353,7 @@ port_reference
| IDENTIFIER '[' error ']' | IDENTIFIER '[' error ']'
{ yyerror(@1, "error: invalid port bit select"); { yyerror(@1, "error: invalid port bit select");
Module::port_t*ptmp = new Module::port_t; Module::port_t*ptmp = new Module::port_t;
PEIdent*wtmp = new PEIdent(hname_t(lex_strings.make($1))); PEIdent*wtmp = new PEIdent(lex_strings.make($1));
wtmp->set_file(@1.text); wtmp->set_file(@1.text);
wtmp->set_lineno(@1.first_line); wtmp->set_lineno(@1.first_line);
ptmp->name = lex_strings.make($1); ptmp->name = lex_strings.make($1);
@ -2791,16 +2787,12 @@ spec_notifier_opt
spec_notifier spec_notifier
: ',' : ','
{ } { }
| ',' identifier | ',' heirarchy_identifier
{ delete $2; } { delete $2; }
| spec_notifier ',' | spec_notifier ','
{ } { }
| spec_notifier ',' identifier | spec_notifier ',' heirarchy_identifier
{ delete $3; } { delete $3; }
| spec_notifier ',' identifier '[' expr_primary ']'
{ delete $3;
delete $5;
}
| IDENTIFIER | IDENTIFIER
{ delete $1; } { delete $1; }
; ;
@ -2917,14 +2909,14 @@ statement
$$ = tmp; $$ = tmp;
} }
| K_disable identifier ';' | K_disable heirarchy_identifier ';'
{ PDisable*tmp = new PDisable(*$2); { PDisable*tmp = new PDisable(*$2);
tmp->set_file(@1.text); tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
delete $2; delete $2;
$$ = tmp; $$ = tmp;
} }
| K_TRIGGER identifier ';' | K_TRIGGER heirarchy_identifier ';'
{ PTrigger*tmp = new PTrigger(*$2); { PTrigger*tmp = new PTrigger(*$2);
tmp->set_file(@2.text); tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line); tmp->set_lineno(@2.first_line);
@ -3132,7 +3124,7 @@ statement
$$ = tmp; $$ = tmp;
} }
| SYSTEM_IDENTIFIER '(' expression_list_with_nuls ')' ';' | 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_file(@1.text);
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
delete $1; delete $1;
@ -3141,13 +3133,13 @@ statement
} }
| SYSTEM_IDENTIFIER ';' | SYSTEM_IDENTIFIER ';'
{ svector<PExpr*>pt (0); { svector<PExpr*>pt (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_file(@1.text);
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
delete $1; delete $1;
$$ = tmp; $$ = tmp;
} }
| identifier '(' expression_list_proper ')' ';' | heirarchy_identifier '(' expression_list_proper ')' ';'
{ PCallTask*tmp = new PCallTask(*$1, *$3); { PCallTask*tmp = new PCallTask(*$1, *$3);
tmp->set_file(@1.text); tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
@ -3160,7 +3152,7 @@ statement
between parentheses, but it seems natural, and people commonly between parentheses, but it seems natural, and people commonly
want it. So accept it explicitly. */ want it. So accept it explicitly. */
| identifier '(' ')' ';' | heirarchy_identifier '(' ')' ';'
{ svector<PExpr*>pt (0); { svector<PExpr*>pt (0);
PCallTask*tmp = new PCallTask(*$1, pt); PCallTask*tmp = new PCallTask(*$1, pt);
tmp->set_file(@1.text); tmp->set_file(@1.text);
@ -3168,7 +3160,7 @@ statement
delete $1; delete $1;
$$ = tmp; $$ = tmp;
} }
| identifier ';' | heirarchy_identifier ';'
{ svector<PExpr*>pt (0); { svector<PExpr*>pt (0);
PCallTask*tmp = new PCallTask(*$1, pt); PCallTask*tmp = new PCallTask(*$1, pt);
tmp->set_file(@1.text); tmp->set_file(@1.text);
@ -3523,7 +3515,7 @@ udp_sequ_entry
udp_initial udp_initial
: K_initial IDENTIFIER '=' number ';' : K_initial IDENTIFIER '=' number ';'
{ PExpr*etmp = new PENumber($4); { 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); PAssign*atmp = new PAssign(itmp, etmp);
atmp->set_file(@2.text); atmp->set_file(@2.text);
atmp->set_lineno(@2.first_line); atmp->set_lineno(@2.first_line);
@ -3588,34 +3580,34 @@ 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 udp_port_decl
: K_input list_of_identifiers ';' : K_input list_of_identifiers ';'
{ $$ = pform_make_udp_input_ports($2); } { $$ = pform_make_udp_input_ports($2); }
| K_output IDENTIFIER ';' | K_output IDENTIFIER ';'
{ PWire*pp = new PWire(lex_strings.make($2), { pform_name_t pname;
NetNet::IMPLICIT, pname.push_back(lex_strings.make($2));
NetNet::POUTPUT, PWire*pp = new PWire(pname, NetNet::IMPLICIT, NetNet::POUTPUT, IVL_VT_LOGIC);
IVL_VT_LOGIC);
svector<PWire*>*tmp = new svector<PWire*>(1); svector<PWire*>*tmp = new svector<PWire*>(1);
(*tmp)[0] = pp; (*tmp)[0] = pp;
$$ = tmp; $$ = tmp;
delete $2; delete $2;
} }
| K_reg IDENTIFIER ';' | K_reg IDENTIFIER ';'
{ PWire*pp = new PWire(lex_strings.make($2), { pform_name_t pname;
NetNet::REG, pname.push_back(lex_strings.make($2));
NetNet::PIMPLICIT, PWire*pp = new PWire(pname, NetNet::REG, NetNet::PIMPLICIT, IVL_VT_LOGIC);
IVL_VT_LOGIC);
svector<PWire*>*tmp = new svector<PWire*>(1); svector<PWire*>*tmp = new svector<PWire*>(1);
(*tmp)[0] = pp; (*tmp)[0] = pp;
$$ = tmp; $$ = tmp;
delete $2; delete $2;
} }
| K_reg K_output IDENTIFIER ';' | K_reg K_output IDENTIFIER ';'
{ PWire*pp = new PWire(lex_strings.make($3), { pform_name_t pname;
NetNet::REG, pname.push_back(lex_strings.make($3));
NetNet::POUTPUT, PWire*pp = new PWire(pname, NetNet::REG, NetNet::POUTPUT, IVL_VT_LOGIC);
IVL_VT_LOGIC);
svector<PWire*>*tmp = new svector<PWire*>(1); svector<PWire*>*tmp = new svector<PWire*>(1);
(*tmp)[0] = pp; (*tmp)[0] = pp;
$$ = tmp; $$ = tmp;

View File

@ -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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -33,6 +33,7 @@
# include <list> # include <list>
# include <map> # include <map>
# include <assert.h> # include <assert.h>
# include <stack>
# include <typeinfo> # include <typeinfo>
# include <sstream> # include <sstream>
@ -80,34 +81,34 @@ static unsigned pform_timescale_line = 0;
* and named blocks causes scope to be pushed and popped. The module * and named blocks causes scope to be pushed and popped. The module
* name is not included in this scope stack. * name is not included in this scope stack.
* *
* The hier_name function, therefore, converts the name to the scope * The hier_name function, therefore, converts the name to the scoped
* of the module currently in progress. * 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 * The scope stack does not include any scope created by a generate
* scheme. * scheme.
*/ */
static hname_t scope_stack; static pform_name_t scope_stack;
void pform_push_scope(char*name) 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() void pform_pop_scope()
{ {
perm_string tmp = scope_stack.remove_tail_name(); scope_stack.pop_back();
assert(tmp);
} }
static hname_t hier_name(const char*tail) static pform_name_t hier_name(const char*tail)
{ {
hname_t name = scope_stack; pform_name_t name = scope_stack;
name.append(lex_strings.make(tail)); name.push_back(name_component_t(lex_strings.make(tail)));
return name; 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 /* Note that if we are processing a generate, then the
scope depth will be empty because generate schemes scope depth will be empty because generate schemes
@ -277,7 +278,7 @@ Module::port_t* pform_module_port_reference(char*name,
unsigned lineno) unsigned lineno)
{ {
Module::port_t*ptmp = new Module::port_t; 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_file(file);
tmp->set_lineno(lineno); tmp->set_lineno(lineno);
ptmp->name = lex_strings.make(name); ptmp->name = lex_strings.make(name);
@ -511,9 +512,10 @@ void pform_make_udp(perm_string name, list<string>*parms,
map<string,PWire*> defs; map<string,PWire*> defs;
for (unsigned idx = 0 ; idx < decl->count() ; idx += 1) { 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; bool rc = true;
assert((*decl)[idx]); assert((*decl)[idx]);
if ((*decl)[idx]->get_port_type() != NetNet::PIMPLICIT) { if ((*decl)[idx]->get_port_type() != NetNet::PIMPLICIT) {
@ -526,7 +528,7 @@ void pform_make_udp(perm_string name, list<string>*parms,
} }
} else { } 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<string>*parms,
// Make the port list for the UDP // Make the port list for the UDP
for (unsigned idx = 0 ; idx < pins.count() ; idx += 1) 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); process_udp_table(udp, table, file, lineno);
udp->initial = init; udp->initial = init;
@ -756,7 +758,7 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
// Make the port list for the UDP // Make the port list for the UDP
for (unsigned idx = 0 ; idx < pins.count() ; idx += 1) 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(udp);
assert(table); assert(table);
@ -1090,7 +1092,7 @@ void pform_make_pgassign_list(svector<PExpr*>*alist,
void pform_make_reginit(const struct vlltype&li, void pform_make_reginit(const struct vlltype&li,
const char*name, PExpr*expr) 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); PWire*cur = pform_cur_module->get_wire(sname);
if (cur == 0) { if (cur == 0) {
VLerror(li, "internal error: reginit to non-register?"); VLerror(li, "internal error: reginit to non-register?");
@ -1129,11 +1131,11 @@ void pform_module_define_port(const struct vlltype&li,
svector<PExpr*>*range, svector<PExpr*>*range,
svector<named_pexpr_t*>*attr) svector<named_pexpr_t*>*attr)
{ {
hname_t name = hier_name(nm); pform_name_t name = hier_name(nm);
PWire*cur = pform_cur_module->get_wire(name); PWire*cur = pform_cur_module->get_wire(name);
if (cur) { if (cur) {
ostringstream msg; ostringstream msg;
msg << name << " definition conflicts with " msg << nm << " definition conflicts with "
<< "definition at " << cur->get_line() << "definition at " << cur->get_line()
<< "."; << ".";
VLerror(msg.str().c_str()); VLerror(msg.str().c_str());
@ -1196,7 +1198,7 @@ void pform_makewire(const vlltype&li, const char*nm,
ivl_variable_type_t dt, ivl_variable_type_t dt,
svector<named_pexpr_t*>*attr) svector<named_pexpr_t*>*attr)
{ {
hname_t name = hier_name(nm); pform_name_t name = hier_name(nm);
PWire*cur = get_wire_in_module(name); 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); bool rc = cur->set_wire_type(type);
if (rc == false) { if (rc == false) {
ostringstream msg; ostringstream msg;
msg << name << " definition conflicts with " msg << nm << " definition conflicts with "
<< "definition at " << cur->get_line() << "definition at " << cur->get_line()
<< "."; << ".";
VLerror(msg.str().c_str()); 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); pform_set_net_range(first->name, range, signed_flag, dt);
perm_string first_name = lex_strings.make(first->name); 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); PWire*cur = get_wire_in_module(name);
if (cur != 0) { if (cur != 0) {
PEIdent*lval = new PEIdent(hname_t(first_name)); PEIdent*lval = new PEIdent(first_name);
lval->set_file(li.text); lval->set_file(li.text);
lval->set_lineno(li.first_line); lval->set_lineno(li.first_line);
PGAssign*ass = pform_make_pgassign(lval, first->expr, 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, void pform_set_port_type(perm_string nm, NetNet::PortType pt,
const char*file, unsigned lineno) 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); PWire*cur = pform_cur_module->get_wire(name);
if (cur == 0) { if (cur == 0) {
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_LOGIC); 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: case NetNet::NOT_A_PORT:
cerr << file << ":" << lineno << ": error: " cerr << file << ":" << lineno << ": error: "
<< "port " << name << " is not in the port list." << "port " << nm << " is not in the port list."
<< endl; << endl;
error_count += 1; error_count += 1;
break; break;
default: default:
cerr << file << ":" << lineno << ": error: " cerr << file << ":" << lineno << ": error: "
<< "port " << name << " already has a port declaration." << "port " << nm << " already has a port declaration."
<< endl; << endl;
error_count += 1; error_count += 1;
break; break;
@ -1392,7 +1394,7 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
; cur != names->end() ; cur ++ ) { ; cur != names->end() ; cur ++ ) {
perm_string txt = *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 /* Look for a preexisting wire. If it exists, set the
port direction. If not, create it. */ 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) 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)) { if (PWire*cur = pform_cur_module->get_wire(path)) {
cur->attributes[key] = new PEString(value); 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; 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); assert(expr);
pform_cur_module->defparms[name] = 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) 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); PWire*cur = pform_cur_module->get_wire(name);
if (cur == 0) { if (cur == 0) {
cur = new PWire(name, NetNet::INTEGER, cur = new PWire(name, NetNet::INTEGER,
@ -1658,7 +1660,7 @@ void pform_set_reg_integer(list<perm_string>*names)
static void pform_set_reg_time(const char*nm) 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); PWire*cur = pform_cur_module->get_wire(name);
if (cur == 0) { if (cur == 0) {
cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_LOGIC); cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
@ -1695,7 +1697,9 @@ svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
; cur != names->end() ; cur != names->end()
; cur ++ ) { ; cur ++ ) {
perm_string txt = *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::IMPLICIT,
NetNet::PINPUT, NetNet::PINPUT,
IVL_VT_LOGIC); IVL_VT_LOGIC);
@ -1769,6 +1773,10 @@ int pform_parse(const char*path, FILE*file)
/* /*
* $Log: pform.cc,v $ * $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 * Revision 1.145 2007/04/26 03:06:22 steve
* Rework hname_t to use perm_strings. * Rework hname_t to use perm_strings.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "netlist.h" # include "netlist.h"
@ -261,7 +261,7 @@ extern void pform_set_localparam(perm_string name,
bool signed_flag, bool signed_flag,
svector<PExpr*>*range, svector<PExpr*>*range,
PExpr*expr); 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. * Functions related to specify blocks.
@ -340,6 +340,10 @@ extern void pform_dump(ostream&out, Module*mod);
/* /*
* $Log: pform.h,v $ * $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 * Revision 1.90 2007/04/19 02:52:53 steve
* Add support for -v flag in command file. * Add support for -v flag in command file.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -72,6 +72,58 @@ ostream& operator<< (ostream&o, PGate::strength_t str)
return o; 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<index_component_t>::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 void PExpr::dump(ostream&out) const
{ {
out << typeid(*this).name(); out << typeid(*this).name();
@ -145,29 +197,6 @@ void PENumber::dump(ostream&out) const
void PEIdent::dump(ostream&out) const void PEIdent::dump(ostream&out) const
{ {
out << path_; 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<PExpr*>::const_iterator vector_it_t;
for (vector_it_t cur = idx_.begin() ; cur != idx_.end() ; cur++) {
out << "[" << *(*cur) << "]";
}
} }
void PEString::dump(ostream&out) const void PEString::dump(ostream&out) const
@ -811,7 +840,7 @@ void PGenerate::dump(ostream&out) const
out << endl; out << endl;
for (map<hname_t,PWire*>::const_iterator idx = wires.begin() for (map<pform_name_t,PWire*>::const_iterator idx = wires.begin()
; idx != wires.end() ; idx++) { ; idx != wires.end() ; idx++) {
(*idx).second->dump(out, 6); (*idx).second->dump(out, 6);
@ -866,7 +895,7 @@ void Module::dump(ostream&out) const
} }
typedef map<perm_string,param_expr_t>::const_iterator parm_iter_t; typedef map<perm_string,param_expr_t>::const_iterator parm_iter_t;
typedef map<hname_t,PExpr*>::const_iterator parm_hiter_t; typedef map<pform_name_t,PExpr*>::const_iterator parm_hiter_t;
for (parm_iter_t cur = parameters.begin() for (parm_iter_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) { ; cur != parameters.end() ; cur ++) {
out << " parameter "; out << " parameter ";
@ -931,7 +960,7 @@ void Module::dump(ostream&out) const
} }
// Iterate through and display all the wires. // Iterate through and display all the wires.
for (map<hname_t,PWire*>::const_iterator wire = wires_.begin() for (map<pform_name_t,PWire*>::const_iterator wire = wires_.begin()
; wire != wires_.end() ; wire != wires_.end()
; wire ++ ) { ; wire ++ ) {
@ -1032,6 +1061,10 @@ void PUdp::dump(ostream&out) const
/* /*
* $Log: pform_dump.cc,v $ * $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 * Revision 1.97 2007/03/07 00:38:15 steve
* Lint fixes. * Lint fixes.
* *

32
pform_types.cc Normal file
View File

@ -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;
}

72
pform_types.h Normal file
View File

@ -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 <iostream>
# include <list>
/*
* 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::list<index_component_t>index;
};
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<name_component_t> 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

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "netlist.h" # include "netlist.h"
@ -27,7 +27,7 @@
/* /*
* Search for the hierarchical name. * 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, NetNet*&net,
const NetExpr*&par, const NetExpr*&par,
NetEvent*&eve, NetEvent*&eve,
@ -36,7 +36,8 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
assert(scope); assert(scope);
/* Get the tail name of the object we are looking for. */ /* 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. */ /* Initialize output argument to cleared. */
net = 0; 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 /* If the path has a scope part, then search for the specified
scope that we are supposed to search. */ scope that we are supposed to search. */
if (path.peek_name(0)) if (! path.empty())
scope = des->find_scope(scope, path); scope = des->find_scope(scope, path);
while (scope) { while (scope) {
@ -69,6 +70,10 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
/* /*
* $Log: symbol_search.cc,v $ * $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 * Revision 1.5 2007/04/26 03:06:22 steve
* Rework hname_t to use perm_strings. * Rework hname_t to use perm_strings.
* *