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
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.180 2007/02/06 05:07:31 steve Exp $"
#ident "$Id: Makefile.in,v 1.181 2007/05/24 04:07:11 steve Exp $"
#
#
SHELL = /bin/sh
@ -108,7 +108,7 @@ load_module.o netlist.o netmisc.o net_assign.o \
net_design.o net_event.o net_expr.o net_force.o net_func.o \
net_link.o net_modulo.o net_nex_input.o net_nex_output.o \
net_proc.o net_scope.o net_udp.o pad_to_width.o \
parse.o parse_misc.o pform.o pform_dump.o \
parse.o parse_misc.o pform.o pform_dump.o pform_types.o \
set_width.o symbol_search.o sync.o sys_funcs.o \
verinum.o verireal.o target.o targets.o \
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: Module.cc,v 1.26 2007/04/19 02:52:53 steve Exp $"
#ident "$Id: Module.cc,v 1.27 2007/05/24 04:07:11 steve Exp $"
#endif
# include "config.h"
@ -111,9 +111,9 @@ unsigned Module::find_port(const char*name) const
}
PWire* Module::get_wire(const hname_t&name) const
PWire* Module::get_wire(const pform_name_t&name) const
{
map<hname_t,PWire*>::const_iterator obj = wires_.find(name);
map<pform_name_t,PWire*>::const_iterator obj = wires_.find(name);
if (obj == wires_.end())
return 0;
else
@ -133,11 +133,6 @@ PGate* Module::get_gate(perm_string name)
return 0;
}
const map<hname_t,PWire*>& Module::get_wires() const
{
return wires_;
}
const list<PGate*>& Module::get_gates() const
{
return gates_;
@ -151,6 +146,10 @@ const list<PProcess*>& Module::get_behaviors() const
/*
* $Log: Module.cc,v $
* Revision 1.27 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.26 2007/04/19 02:52:53 steve
* Add support for -v flag in command file.
*

View File

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

View File

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

31
PExpr.h
View File

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

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PGenerate.cc,v 1.2 2007/03/05 05:59:10 steve Exp $"
#ident "$Id: PGenerate.cc,v 1.3 2007/05/24 04:07:11 steve Exp $"
#endif
# include "PGenerate.h"
@ -42,9 +42,9 @@ PWire* PGenerate::add_wire(PWire*wire)
return wire;
}
PWire* PGenerate::get_wire(const hname_t&name) const
PWire* PGenerate::get_wire(const pform_name_t&name) const
{
map<hname_t,PWire*>::const_iterator obj = wires.find(name);
map<pform_name_t,PWire*>::const_iterator obj = wires.find(name);
if (obj == wires.end())
return 0;
else

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PGenerate.h,v 1.2 2007/03/05 05:59:10 steve Exp $"
#ident "$Id: PGenerate.h,v 1.3 2007/05/24 04:07:11 steve Exp $"
#endif
# include "LineInfo.h"
@ -27,6 +27,7 @@
# include "HName.h"
# include <list>
# include <map>
# include "pform_types.h"
class Design;
class NetScope;
@ -59,9 +60,9 @@ class PGenerate : public LineInfo {
PExpr*loop_test;
PExpr*loop_step;
map<hname_t,PWire*>wires;
map<pform_name_t,PWire*>wires;
PWire* add_wire(PWire*);
PWire* get_wire(const hname_t&name) const;
PWire* get_wire(const pform_name_t&name) const;
list<PGate*> gates;
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
* and/or modify it in source code form under the terms of the GNU
@ -17,29 +17,14 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PWire.cc,v 1.13 2007/04/26 03:06:21 steve Exp $"
#ident "$Id: PWire.cc,v 1.14 2007/05/24 04:07:11 steve Exp $"
#endif
# include "config.h"
# include "PWire.h"
# include <assert.h>
PWire::PWire(const hname_t&n,
NetNet::Type t,
NetNet::PortType pt,
ivl_variable_type_t dt)
: hname_(n), type_(t), port_type_(pt), data_type_(dt),
signed_(false), isint_(false),
lidx_(0), ridx_(0)
{
if (t == NetNet::INTEGER) {
type_ = NetNet::REG;
signed_ = true;
isint_ = true;
}
}
PWire::PWire(perm_string n,
PWire::PWire(const pform_name_t&n,
NetNet::Type t,
NetNet::PortType pt,
ivl_variable_type_t dt)
@ -59,7 +44,7 @@ NetNet::Type PWire::get_wire_type() const
return type_;
}
const hname_t& PWire::path() const
const pform_name_t& PWire::path() const
{
return hname_;
}
@ -160,6 +145,10 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
/*
* $Log: PWire.cc,v $
* Revision 1.14 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.13 2007/04/26 03:06:21 steve
* Rework hname_t to use perm_strings.
*

25
PWire.h
View File

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

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: Statement.cc,v 1.29 2004/02/18 17:11:54 steve Exp $"
#ident "$Id: Statement.cc,v 1.30 2007/05/24 04:07:11 steve Exp $"
#endif
# include "config.h"
@ -107,16 +107,22 @@ PBlock::~PBlock()
delete list_[idx];
}
PCallTask::PCallTask(const hname_t&n, const svector<PExpr*>&p)
PCallTask::PCallTask(const pform_name_t&n, const svector<PExpr*>&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()
{
}
const hname_t& PCallTask::path() const
const pform_name_t& PCallTask::path() const
{
return path_;
}
@ -178,7 +184,7 @@ PDelayStatement::~PDelayStatement()
{
}
PDisable::PDisable(const hname_t&sc)
PDisable::PDisable(const pform_name_t&sc)
: scope_(sc)
{
}
@ -273,7 +279,7 @@ PRepeat::~PRepeat()
delete statement_;
}
PTrigger::PTrigger(const hname_t&e)
PTrigger::PTrigger(const pform_name_t&e)
: event_(e)
{
}
@ -295,6 +301,10 @@ PWhile::~PWhile()
/*
* $Log: Statement.cc,v $
* Revision 1.30 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.29 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: Statement.h,v 1.43 2007/03/05 05:59:10 steve Exp $"
#ident "$Id: Statement.h,v 1.44 2007/05/24 04:07:11 steve Exp $"
#endif
# include <string>
@ -173,10 +173,11 @@ class PBlock : public Statement {
class PCallTask : public Statement {
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();
const hname_t& path() const;
const pform_name_t& path() const;
unsigned nparms() const { return parms_.count(); }
@ -197,7 +198,7 @@ class PCallTask : public Statement {
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
NetProc* elaborate_usr(Design*des, NetScope*scope) const;
hname_t path_;
pform_name_t path_;
svector<PExpr*> parms_;
};
@ -296,14 +297,14 @@ class PDelayStatement : public Statement {
class PDisable : public Statement {
public:
explicit PDisable(const hname_t&sc);
explicit PDisable(const pform_name_t&sc);
~PDisable();
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
private:
hname_t scope_;
pform_name_t scope_;
};
/*
@ -433,14 +434,14 @@ class PRelease : public Statement {
class PTrigger : public Statement {
public:
explicit PTrigger(const hname_t&ev);
explicit PTrigger(const pform_name_t&ev);
~PTrigger();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
hname_t event_;
pform_name_t event_;
};
class PWhile : public Statement {
@ -460,6 +461,10 @@ class PWhile : public Statement {
/*
* $Log: Statement.h,v $
* Revision 1.44 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.43 2007/03/05 05:59:10 steve
* Handle processes within generate loops.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: design_dump.cc,v 1.174 2007/03/02 06:13:22 steve Exp $"
#ident "$Id: design_dump.cc,v 1.175 2007/05/24 04:07:11 steve Exp $"
#endif
# include "config.h"
@ -871,7 +871,7 @@ void NetScope::dump(ostream&o) const
/* Dump the saved defparam assignments here. */
{
map<hname_t,NetExpr*>::const_iterator pp;
map<pform_name_t,NetExpr*>::const_iterator pp;
for (pp = defparams.begin()
; pp != defparams.end() ; pp ++ ) {
o << " defparam " << (*pp).first << " = " <<
@ -1205,6 +1205,10 @@ void Design::dump(ostream&o) const
/*
* $Log: design_dump.cc,v $
* Revision 1.175 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.174 2007/03/02 06:13:22 steve
* Add support for edge sensitive spec paths.
*

View File

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

View File

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

View File

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

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_pexpr.cc,v 1.26 2007/04/26 03:06:22 steve Exp $"
#ident "$Id: elab_pexpr.cc,v 1.27 2007/05/24 04:07:11 steve Exp $"
#endif
# include "config.h"
@ -130,44 +130,51 @@ NetExpr*PEFNumber::elaborate_pexpr(Design*des, NetScope*scope) const
*/
NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
{
hname_t path = path_;
perm_string name = path.remove_tail_name();
pform_name_t path = path_;
name_component_t name_tail = path_.back();
path.pop_back();
NetScope*pscope = scope;
if (path.peek_name(0))
if (path_.size() > 0)
pscope = des->find_scope(scope, path);
const NetExpr*ex_msb;
const NetExpr*ex_lsb;
const NetExpr*ex = pscope->get_parameter(name, ex_msb, ex_lsb);
const NetExpr*ex = pscope->get_parameter(name_tail.name, ex_msb, ex_lsb);
if (ex == 0) {
cerr << get_line() << ": error: identifier ``" << path_ <<
cerr << get_line() << ": error: identifier ``" << name_tail.name <<
"'' is not a parameter in " << scope->name() << "." << endl;
des->errors += 1;
return 0;
}
NetExpr*res = new NetEParam(des, pscope, name);
NetExpr*res = new NetEParam(des, pscope, name_tail.name);
res->set_line(*this);
assert(res);
if (msb_ && lsb_) {
assert(idx_.empty());
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (!name_tail.index.empty())
use_sel = name_tail.index.back().sel;
switch (use_sel) {
case index_component_t::SEL_NONE:
break;
default:
case index_component_t::SEL_PART:
cerr << get_line() << ": sorry: Cannot part select "
"bits of parameters." << endl;
des->errors += 1;
break;
} else if (!idx_.empty()) {
assert(msb_==0);
assert(lsb_==0);
assert(idx_.size() == 1);
case index_component_t::SEL_BIT:
/* We have here a bit select. Insert a NetESelect node
to handle it. */
NetExpr*tmp = idx_[0]->elaborate_pexpr(des, scope);
NetExpr*tmp = name_tail.index.back().msb->elaborate_pexpr(des, scope);
if (tmp != 0) {
res = new NetESelect(res, tmp, 1);
}
break;
}
return res;
@ -233,6 +240,10 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
/*
* $Log: elab_pexpr.cc,v $
* Revision 1.27 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.26 2007/04/26 03:06:22 steve
* Rework hname_t to use perm_strings.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_scope.cc,v 1.44 2007/03/22 16:08:15 steve Exp $"
#ident "$Id: elab_scope.cc,v 1.45 2007/05/24 04:07:11 steve Exp $"
#endif
# include "config.h"
@ -66,7 +66,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// place of the elaborated expression.
typedef map<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
@ -200,7 +200,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// here because the parameter receiving the assignment may be
// in a scope not discovered by this pass.
for (hparm_it_t cur = defparms.begin()
for (pform_parm_it_t cur = defparms.begin()
; cur != defparms.end() ; cur ++ ) {
PExpr*ex = (*cur).second;
@ -761,6 +761,10 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const
/*
* $Log: elab_scope.cc,v $
* Revision 1.45 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.44 2007/03/22 16:08:15 steve
* Spelling fixes from Larry
*

View File

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

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elaborate.cc,v 1.370 2007/04/16 01:10:07 steve Exp $"
#ident "$Id: elaborate.cc,v 1.371 2007/05/24 04:07:11 steve Exp $"
#endif
# include "config.h"
@ -770,8 +770,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
if (mport.count() == 0)
continue;
NetNet*tmp = des->find_signal(instance[0],
mport[0]->path());
perm_string pname = peek_tail_name(mport[0]->path());
NetNet*tmp = instance[0]->find_signal(pname);
assert(tmp);
if (tmp->port_type() == NetNet::PINPUT) {
@ -1833,7 +1834,7 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
NetProc* PCallTask::elaborate(Design*des, NetScope*scope) const
{
if (path_.peek_name(0)[0] == '$')
if (peek_tail_name(path_)[0] == '$')
return elaborate_sys(des, scope);
else
return elaborate_usr(des, scope);
@ -1877,7 +1878,7 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
}
}
NetSTask*cur = new NetSTask(path_.peek_name(0), eparms);
NetSTask*cur = new NetSTask(peek_tail_name(path_), eparms);
return cur;
}
@ -3416,6 +3417,10 @@ Design* elaborate(list<perm_string>roots)
/*
* $Log: elaborate.cc,v $
* Revision 1.371 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.370 2007/04/16 01:10:07 steve
* Properly ignore unsupported ifnone.
*

15
eval.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval.cc,v 1.45 2007/03/07 00:38:15 steve Exp $"
#ident "$Id: eval.cc,v 1.46 2007/05/24 04:07:12 steve Exp $"
#endif
# include "config.h"
@ -177,16 +177,17 @@ verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const
NetEvent*eve;
const NetExpr*expr;
const name_component_t&name_tail = path_.back();
// Handle the special case that this ident is a genvar
// variable name. In that case, the genvar meaning preempts
// everything and we just return that value immediately.
if (scope->genvar_tmp
&& strcmp(path_.peek_tail_name(),scope->genvar_tmp) == 0) {
&& strcmp(name_tail.name,scope->genvar_tmp) == 0) {
return new verinum(scope->genvar_tmp_val);
}
symbol_search(des, scope, path_,
net, expr, eve);
symbol_search(des, scope, path_, net, expr, eve);
if (expr == 0)
return 0;
@ -201,7 +202,7 @@ verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const
assert(eval);
if (msb_ || lsb_)
if (!name_tail.index.empty())
return 0;
@ -275,6 +276,10 @@ verinum* PEUnary::eval_const(const Design*des, NetScope*scope) const
/*
* $Log: eval.cc,v $
* Revision 1.46 2007/05/24 04:07:12 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.45 2007/03/07 00:38:15 steve
* Lint fixes.
*

View File

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

View File

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

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netmisc.h,v 1.29 2007/03/08 05:30:03 steve Exp $"
#ident "$Id: netmisc.h,v 1.30 2007/05/24 04:07:12 steve Exp $"
#endif
# include "netlist.h"
@ -40,20 +40,20 @@
* these values are set to 0.
*/
extern NetScope* symbol_search(const Design*des,
NetScope*start, hname_t path,
NetScope*start, pform_name_t path,
NetNet*&net, /* net/reg */
const NetExpr*&par,/* parameter */
NetEvent*&eve, /* named event */
const NetExpr*&ex1, const NetExpr*&ex2);
inline NetScope* symbol_search(const Design*des,
NetScope*start, const hname_t&path,
NetScope*start, const pform_name_t&path,
NetNet*&net, /* net/reg */
const NetExpr*&par,/* parameter */
NetEvent*&eve /* named event */)
{
const NetExpr*ex1, *ex2;
return symbol_search(des, start, path, net, /*mem,*/ par, eve, ex1, ex2);
return symbol_search(des, start, path, net, par, eve, ex1, ex2);
}
/*
@ -125,6 +125,10 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
/*
* $Log: netmisc.h,v $
* Revision 1.30 2007/05/24 04:07:12 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.29 2007/03/08 05:30:03 steve
* Limit the calculated widths of constants.
*

428
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
* and/or modify it in source code form under the terms of the GNU
@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: parse.y,v 1.236 2007/04/26 03:06:22 steve Exp $"
#ident "$Id: parse.y,v 1.237 2007/05/24 04:07:12 steve Exp $"
#endif
# include "config.h"
@ -98,6 +98,7 @@ static list<perm_string>* list_from_identifier(list<perm_string>*tmp, char*id)
strdup. They can be put into lists with the texts type. */
char*text;
list<perm_string>*perm_strings;
pform_name_t*pform_name;
hname_t*hier;
@ -123,8 +124,6 @@ static list<perm_string>* list_from_identifier(list<perm_string>*tmp, char*id)
svector<PEEvent*>*event_expr;
PEIdent*indexed_identifier;
NetNet::Type nettype;
PGBuiltin::Type gatetype;
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 <expr> udp_initial_expr_opt
%type <hier> identifier
%type <text> register_variable net_variable
%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 <gates> gate_instance_list
%type <pform_name> heirarchy_identifier
%type <expr> expression expr_primary
%type <expr> lpvalue
%type <expr> delay_value delay_value_simple
%type <exprs> delay1 delay3 delay3_opt delay_value_list
%type <exprs> expression_list_with_nuls expression_list_proper
%type <exprs> cont_assign cont_assign_list
%type <indexed_identifier> indexed_identifier
%type <exprs> range range_opt
%type <nettype> net_type var_type net_type_opt
@ -492,7 +490,7 @@ charge_strength_opt
;
defparam_assign
: identifier '=' expression
: heirarchy_identifier '=' expression
{ PExpr*tmp = $3;
if (!pform_expression_is_constant(tmp)) {
yyerror(@3, "error: parameter value "
@ -605,7 +603,7 @@ delay_value_simple
}
}
| IDENTIFIER
{ PEIdent*tmp = new PEIdent(hname_t(lex_strings.make($1)));
{ PEIdent*tmp = new PEIdent(lex_strings.make($1));
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
@ -671,16 +669,14 @@ dr_strength1
;
event_control
: '@' identifier
: '@' heirarchy_identifier
{ PEIdent*tmpi = new PEIdent(*$2);
tmpi->set_file(@2.text);
tmpi->set_lineno(@2.first_line);
delete $2;
PEEvent*tmpe = new PEEvent(PEEvent::ANYEDGE, tmpi);
PEventStatement*tmps = new PEventStatement(tmpe);
tmps->set_file(@1.text);
tmps->set_lineno(@1.first_line);
$$ = tmps;
delete $2;
}
| '@' '(' event_expression_list ')'
{ PEventStatement*tmp = new PEventStatement(*$3);
@ -1034,53 +1030,29 @@ expr_primary
}
| SYSTEM_IDENTIFIER
{ perm_string tn = lex_strings.make($1);
PECallFunction*tmp = new PECallFunction(hname_t(tn));
PECallFunction*tmp = new PECallFunction(tn);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
delete $1;
}
/* The indexed_identifier rule matches simple identifiers as well as
indexed arrays. Part selects are handled below. */
/* The heirarchy_identifier rule matches simple identifiers as well as
indexed arrays and part selects */
| indexed_identifier
{ PEIdent*tmp = $1;
$$ = tmp;
}
/* There are 3 kinds of part selects. The basic part select has the
usual [M:L] syntax. The indexed part selects use +: or -: in
place of the : in the basic part select, and the first expression
is not limited to constant values. */
| indexed_identifier '[' expression ':' expression ']'
{ PEIdent*tmp = $1;
tmp->msb_ = $3;
tmp->lsb_ = $5;
tmp->sel_ = PEIdent::SEL_PART;
$$ = tmp;
}
| indexed_identifier '[' expression K_PO_POS expression ']'
{ PEIdent*tmp = $1;
tmp->msb_ = $3;
tmp->lsb_ = $5;
tmp->sel_ = PEIdent::SEL_IDX_UP;
$$ = tmp;
}
| indexed_identifier '[' expression K_PO_NEG expression ']'
{ PEIdent*tmp = $1;
tmp->msb_ = $3;
tmp->lsb_ = $5;
tmp->sel_ = PEIdent::SEL_IDX_DO;
$$ = tmp;
}
| heirarchy_identifier
{ PEIdent*tmp = new PEIdent(*$1);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
delete $1;
}
/* An identifer followed by an expression list in parentheses is a
function call. If a system identifier, then a system function
call. */
| identifier '(' expression_list_proper ')'
| heirarchy_identifier '(' expression_list_proper ')'
{ PECallFunction*tmp = new PECallFunction(*$1, *$3);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
@ -1089,7 +1061,7 @@ expr_primary
}
| SYSTEM_IDENTIFIER '(' expression_list_proper ')'
{ perm_string tn = lex_strings.make($1);
PECallFunction*tmp = new PECallFunction(hname_t(tn), *$3);
PECallFunction*tmp = new PECallFunction(tn, *$3);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
@ -1345,39 +1317,61 @@ gatetype
/* A general identifier is a hierarchical name, with the right most
name the base of the identifier. This rule builds up a
hierarchical name from left to right, forming a list of names. */
identifier
: IDENTIFIER
{ $$ = new hname_t(lex_strings.make($1));
delete $1;
}
| identifier '.' IDENTIFIER
{ hname_t * tmp = $1;
tmp->append(lex_strings.make($3));
delete $3;
$$ = tmp;
}
;
hierarchical name from the left to the right, forming a list of
names. */
/* An indexed_identifier is an identifier with a bit-select
expression. This bit select may be an array index or bit index,
to be sorted out later. */
indexed_identifier
: identifier
{ PEIdent*tmp = new PEIdent(*$1);
tmp->sel_ = PEIdent::SEL_NONE;
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
$$ = tmp;
}
| indexed_identifier '[' expression ']'
{ PEIdent*tmp = $1;
tmp->sel_ = PEIdent::SEL_NONE;
tmp->idx_.push_back($3);
$$ = tmp;
}
;
heirarchy_identifier
: IDENTIFIER
{ $$ = new pform_name_t;
$$->push_back(name_component_t(lex_strings.make($1)));
delete $1;
}
| heirarchy_identifier '.' IDENTIFIER
{ pform_name_t * tmp = $1;
tmp->push_back(name_component_t(lex_strings.make($3)));
delete $3;
$$ = tmp;
}
| heirarchy_identifier '[' expression ']'
{ pform_name_t * tmp = $1;
name_component_t&tail = tmp->back();
index_component_t itmp;
itmp.sel = index_component_t::SEL_BIT;
itmp.msb = $3;
tail.index.push_back(itmp);
$$ = tmp;
}
| heirarchy_identifier '[' expression ':' expression ']'
{ pform_name_t * tmp = $1;
name_component_t&tail = tmp->back();
index_component_t itmp;
itmp.sel = index_component_t::SEL_PART;
itmp.msb = $3;
itmp.lsb = $5;
tail.index.push_back(itmp);
$$ = tmp;
}
| heirarchy_identifier '[' expression K_PO_POS expression ']'
{ pform_name_t * tmp = $1;
name_component_t&tail = tmp->back();
index_component_t itmp;
itmp.sel = index_component_t::SEL_IDX_UP;
itmp.msb = $3;
itmp.lsb = $5;
tail.index.push_back(itmp);
$$ = tmp;
}
| heirarchy_identifier '[' expression K_PO_NEG expression ']'
{ pform_name_t * tmp = $1;
name_component_t&tail = tmp->back();
index_component_t itmp;
itmp.sel = index_component_t::SEL_IDX_DO;
itmp.msb = $3;
itmp.lsb = $5;
tail.index.push_back(itmp);
$$ = tmp;
}
;
/* This is a list of identifiers. The result is a list of strings,
each one of the identifiers in the list. These are simple,
@ -1552,39 +1546,21 @@ signed_opt : K_signed { $$ = true; } | {$$ = false; } ;
assignments. It is more limited then the general expr_primary
rule to reflect the rules for assignment l-values. */
lpvalue
: indexed_identifier
{ PEIdent*tmp = $1;
$$ = tmp;
}
| indexed_identifier '[' expression ':' expression ']'
{ PEIdent*tmp = $1;
tmp->msb_ = $3;
tmp->lsb_ = $5;
tmp->sel_ = PEIdent::SEL_PART;
$$ = tmp;
}
| indexed_identifier '[' expression K_PO_POS expression ']'
{ PEIdent*tmp = $1;
tmp->msb_ = $3;
tmp->lsb_ = $5;
tmp->sel_ = PEIdent::SEL_IDX_UP;
$$ = tmp;
}
| indexed_identifier '[' expression K_PO_NEG expression ']'
{ PEIdent*tmp = $1;
tmp->msb_ = $3;
tmp->lsb_ = $5;
tmp->sel_ = PEIdent::SEL_IDX_DO;
$$ = tmp;
}
| '{' expression_list_proper '}'
{ PEConcat*tmp = new PEConcat(*$2);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $2;
$$ = tmp;
}
;
: heirarchy_identifier
{ PEIdent*tmp = new PEIdent(*$1);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
delete $1;
}
| '{' expression_list_proper '}'
{ PEConcat*tmp = new PEConcat(*$2);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $2;
$$ = tmp;
}
;
/* Continuous assignments have a list of individual assignments. */
@ -2306,67 +2282,87 @@ port_opt
port_reference
: IDENTIFIER
{ Module::port_t*ptmp;
ptmp = pform_module_port_reference($1, @1.text,
@1.first_line);
delete $1;
$$ = ptmp;
}
: IDENTIFIER
{ Module::port_t*ptmp;
ptmp = pform_module_port_reference($1, @1.text, @1.first_line);
delete $1;
$$ = ptmp;
}
| IDENTIFIER '[' expression ':' expression ']'
{ PEIdent*wtmp = new PEIdent(hname_t(lex_strings.make($1)));
wtmp->set_file(@1.text);
wtmp->set_lineno(@1.first_line);
if (!pform_expression_is_constant($3)) {
yyerror(@3, "error: msb expression of "
"port part select must be constant.");
}
if (!pform_expression_is_constant($5)) {
yyerror(@5, "error: lsb expression of "
"port part select must be constant.");
}
wtmp->msb_ = $3;
wtmp->lsb_ = $5;
wtmp->sel_ = PEIdent::SEL_PART;
Module::port_t*ptmp = new Module::port_t;
ptmp->name = perm_string();
ptmp->expr = svector<PEIdent*>(1);
ptmp->expr[0] = wtmp;
delete $1;
$$ = ptmp;
}
| IDENTIFIER '[' expression ':' expression ']'
{ if (!pform_expression_is_constant($3)) {
yyerror(@3, "error: msb expression of "
"port part select must be constant.");
}
if (!pform_expression_is_constant($5)) {
yyerror(@5, "error: lsb expression of "
"port part select must be constant.");
}
index_component_t itmp;
itmp.sel = index_component_t::SEL_PART;
itmp.msb = $3;
itmp.lsb = $5;
| IDENTIFIER '[' expression ']'
{ PEIdent*tmp = new PEIdent(hname_t(lex_strings.make($1)));
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
if (!pform_expression_is_constant($3)) {
yyerror(@3, "error: port bit select "
"must be constant.");
}
tmp->msb_ = $3;
Module::port_t*ptmp = new Module::port_t;
ptmp->name = perm_string();
ptmp->expr = svector<PEIdent*>(1);
ptmp->expr[0] = tmp;
delete $1;
$$ = ptmp;
}
name_component_t ntmp (lex_strings.make($1));
ntmp.index.push_back(itmp);
| IDENTIFIER '[' error ']'
{ yyerror(@1, "error: invalid port bit select");
Module::port_t*ptmp = new Module::port_t;
PEIdent*wtmp = new PEIdent(hname_t(lex_strings.make($1)));
wtmp->set_file(@1.text);
wtmp->set_lineno(@1.first_line);
ptmp->name = lex_strings.make($1);
ptmp->expr = svector<PEIdent*>(1);
ptmp->expr[0] = wtmp;
delete $1;
$$ = ptmp;
}
;
pform_name_t pname;
pname.push_back(ntmp);
PEIdent*wtmp = new PEIdent(pname);
wtmp->set_file(@1.text);
wtmp->set_lineno(@1.first_line);
Module::port_t*ptmp = new Module::port_t;
ptmp->name = perm_string();
ptmp->expr = svector<PEIdent*>(1);
ptmp->expr[0] = wtmp;
delete $1;
$$ = ptmp;
}
| IDENTIFIER '[' expression ']'
{ if (!pform_expression_is_constant($3)) {
yyerror(@3, "error: port bit select "
"must be constant.");
}
index_component_t itmp;
itmp.sel = index_component_t::SEL_BIT;
itmp.msb = $3;
itmp.lsb = 0;
name_component_t ntmp (lex_strings.make($1));
ntmp.index.push_back(itmp);
pform_name_t pname;
pname.push_back(ntmp);
PEIdent*tmp = new PEIdent(pname);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
Module::port_t*ptmp = new Module::port_t;
ptmp->name = perm_string();
ptmp->expr = svector<PEIdent*>(1);
ptmp->expr[0] = tmp;
delete $1;
$$ = ptmp;
}
| IDENTIFIER '[' error ']'
{ yyerror(@1, "error: invalid port bit select");
Module::port_t*ptmp = new Module::port_t;
PEIdent*wtmp = new PEIdent(lex_strings.make($1));
wtmp->set_file(@1.text);
wtmp->set_lineno(@1.first_line);
ptmp->name = lex_strings.make($1);
ptmp->expr = svector<PEIdent*>(1);
ptmp->expr[0] = wtmp;
delete $1;
$$ = ptmp;
}
;
port_reference_list
@ -2791,16 +2787,12 @@ spec_notifier_opt
spec_notifier
: ','
{ }
| ',' identifier
| ',' heirarchy_identifier
{ delete $2; }
| spec_notifier ','
{ }
| spec_notifier ',' identifier
| spec_notifier ',' heirarchy_identifier
{ delete $3; }
| spec_notifier ',' identifier '[' expr_primary ']'
{ delete $3;
delete $5;
}
| IDENTIFIER
{ delete $1; }
;
@ -2917,14 +2909,14 @@ statement
$$ = tmp;
}
| K_disable identifier ';'
| K_disable heirarchy_identifier ';'
{ PDisable*tmp = new PDisable(*$2);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $2;
$$ = tmp;
}
| K_TRIGGER identifier ';'
| K_TRIGGER heirarchy_identifier ';'
{ PTrigger*tmp = new PTrigger(*$2);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
@ -3132,7 +3124,7 @@ statement
$$ = tmp;
}
| SYSTEM_IDENTIFIER '(' expression_list_with_nuls ')' ';'
{ PCallTask*tmp = new PCallTask(hname_t(lex_strings.make($1)), *$3);
{ PCallTask*tmp = new PCallTask(lex_strings.make($1), *$3);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
@ -3141,13 +3133,13 @@ statement
}
| SYSTEM_IDENTIFIER ';'
{ 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_lineno(@1.first_line);
delete $1;
$$ = tmp;
}
| identifier '(' expression_list_proper ')' ';'
| heirarchy_identifier '(' expression_list_proper ')' ';'
{ PCallTask*tmp = new PCallTask(*$1, *$3);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
@ -3160,7 +3152,7 @@ statement
between parentheses, but it seems natural, and people commonly
want it. So accept it explicitly. */
| identifier '(' ')' ';'
| heirarchy_identifier '(' ')' ';'
{ svector<PExpr*>pt (0);
PCallTask*tmp = new PCallTask(*$1, pt);
tmp->set_file(@1.text);
@ -3168,7 +3160,7 @@ statement
delete $1;
$$ = tmp;
}
| identifier ';'
| heirarchy_identifier ';'
{ svector<PExpr*>pt (0);
PCallTask*tmp = new PCallTask(*$1, pt);
tmp->set_file(@1.text);
@ -3523,7 +3515,7 @@ udp_sequ_entry
udp_initial
: K_initial IDENTIFIER '=' number ';'
{ PExpr*etmp = new PENumber($4);
PEIdent*itmp = new PEIdent(hname_t(lex_strings.make($2)));
PEIdent*itmp = new PEIdent(lex_strings.make($2));
PAssign*atmp = new PAssign(itmp, etmp);
atmp->set_file(@2.text);
atmp->set_lineno(@2.first_line);
@ -3588,40 +3580,40 @@ udp_output_sym
| '-' { $$ = '-'; }
;
/* Port declarations create wires for the inputs and the output. The
makes for these ports are scoped within the UDP, so there is no
heirarchy involved. */
udp_port_decl
: K_input list_of_identifiers ';'
{ $$ = pform_make_udp_input_ports($2); }
| K_output IDENTIFIER ';'
{ PWire*pp = new PWire(lex_strings.make($2),
NetNet::IMPLICIT,
NetNet::POUTPUT,
IVL_VT_LOGIC);
svector<PWire*>*tmp = new svector<PWire*>(1);
(*tmp)[0] = pp;
$$ = tmp;
delete $2;
}
| K_reg IDENTIFIER ';'
{ PWire*pp = new PWire(lex_strings.make($2),
NetNet::REG,
NetNet::PIMPLICIT,
IVL_VT_LOGIC);
svector<PWire*>*tmp = new svector<PWire*>(1);
(*tmp)[0] = pp;
$$ = tmp;
delete $2;
}
| K_reg K_output IDENTIFIER ';'
{ PWire*pp = new PWire(lex_strings.make($3),
NetNet::REG,
NetNet::POUTPUT,
IVL_VT_LOGIC);
svector<PWire*>*tmp = new svector<PWire*>(1);
(*tmp)[0] = pp;
$$ = tmp;
delete $3;
}
;
: K_input list_of_identifiers ';'
{ $$ = pform_make_udp_input_ports($2); }
| K_output IDENTIFIER ';'
{ pform_name_t pname;
pname.push_back(lex_strings.make($2));
PWire*pp = new PWire(pname, NetNet::IMPLICIT, NetNet::POUTPUT, IVL_VT_LOGIC);
svector<PWire*>*tmp = new svector<PWire*>(1);
(*tmp)[0] = pp;
$$ = tmp;
delete $2;
}
| K_reg IDENTIFIER ';'
{ pform_name_t pname;
pname.push_back(lex_strings.make($2));
PWire*pp = new PWire(pname, NetNet::REG, NetNet::PIMPLICIT, IVL_VT_LOGIC);
svector<PWire*>*tmp = new svector<PWire*>(1);
(*tmp)[0] = pp;
$$ = tmp;
delete $2;
}
| K_reg K_output IDENTIFIER ';'
{ pform_name_t pname;
pname.push_back(lex_strings.make($3));
PWire*pp = new PWire(pname, NetNet::REG, NetNet::POUTPUT, IVL_VT_LOGIC);
svector<PWire*>*tmp = new svector<PWire*>(1);
(*tmp)[0] = pp;
$$ = tmp;
delete $3;
}
;
udp_port_decls
: udp_port_decl

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

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform.h,v 1.90 2007/04/19 02:52:53 steve Exp $"
#ident "$Id: pform.h,v 1.91 2007/05/24 04:07:12 steve Exp $"
#endif
# include "netlist.h"
@ -261,7 +261,7 @@ extern void pform_set_localparam(perm_string name,
bool signed_flag,
svector<PExpr*>*range,
PExpr*expr);
extern void pform_set_defparam(const hname_t&name, PExpr*expr);
extern void pform_set_defparam(const pform_name_t&name, PExpr*expr);
/*
* Functions related to specify blocks.
@ -340,6 +340,10 @@ extern void pform_dump(ostream&out, Module*mod);
/*
* $Log: pform.h,v $
* Revision 1.91 2007/05/24 04:07:12 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.90 2007/04/19 02:52:53 steve
* Add support for -v flag in command file.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform_dump.cc,v 1.97 2007/03/07 00:38:15 steve Exp $"
#ident "$Id: pform_dump.cc,v 1.98 2007/05/24 04:07:12 steve Exp $"
#endif
# include "config.h"
@ -72,6 +72,58 @@ ostream& operator<< (ostream&o, PGate::strength_t str)
return o;
}
ostream& operator<< (ostream&out, perm_string that)
{
out << that.str();
}
ostream& operator<< (ostream&out, const name_component_t&that)
{
out << that.name.str();
typedef std::list<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
{
out << typeid(*this).name();
@ -145,29 +197,6 @@ void PENumber::dump(ostream&out) const
void PEIdent::dump(ostream&out) const
{
out << path_;
if (msb_) {
out << "[" << *msb_;
if (lsb_) switch (sel_) {
case SEL_IDX_UP:
out << "+:" << *lsb_;
break;
case SEL_IDX_DO:
out << "-:" << *lsb_;
break;
case SEL_PART:
out << ":" << *lsb_;
break;
default:
out << ":?:" << *lsb_;
break;
}
out << "]";
}
typedef std::vector<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
@ -811,7 +840,7 @@ void PGenerate::dump(ostream&out) const
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).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<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()
; cur != parameters.end() ; cur ++) {
out << " parameter ";
@ -931,7 +960,7 @@ void Module::dump(ostream&out) const
}
// Iterate through and display all the wires.
for (map<hname_t,PWire*>::const_iterator wire = wires_.begin()
for (map<pform_name_t,PWire*>::const_iterator wire = wires_.begin()
; wire != wires_.end()
; wire ++ ) {
@ -1032,6 +1061,10 @@ void PUdp::dump(ostream&out) const
/*
* $Log: pform_dump.cc,v $
* Revision 1.98 2007/05/24 04:07:12 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.97 2007/03/07 00:38:15 steve
* Lint fixes.
*

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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: symbol_search.cc,v 1.5 2007/04/26 03:06:22 steve Exp $"
#ident "$Id: symbol_search.cc,v 1.6 2007/05/24 04:07:12 steve Exp $"
#endif
# include "netlist.h"
@ -27,7 +27,7 @@
/*
* Search for the hierarchical name.
*/
NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
NetScope*symbol_search(const Design*des, NetScope*scope, pform_name_t path,
NetNet*&net,
const NetExpr*&par,
NetEvent*&eve,
@ -36,7 +36,8 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
assert(scope);
/* Get the tail name of the object we are looking for. */
perm_string key = path.remove_tail_name();
perm_string key = peek_tail_name(path);
path.pop_back();
/* Initialize output argument to cleared. */
net = 0;
@ -45,7 +46,7 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
/* If the path has a scope part, then search for the specified
scope that we are supposed to search. */
if (path.peek_name(0))
if (! path.empty())
scope = des->find_scope(scope, path);
while (scope) {
@ -69,6 +70,10 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
/*
* $Log: symbol_search.cc,v $
* Revision 1.6 2007/05/24 04:07:12 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.5 2007/04/26 03:06:22 steve
* Rework hname_t to use perm_strings.
*