Merge branch 'pscope'
This commit is contained in:
commit
11a33a0907
|
|
@ -111,7 +111,7 @@ 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 \
|
||||
PExpr.o PGate.o PGenerate.o PSpec.o \
|
||||
PExpr.o PGate.o PGenerate.o PScope.o PSpec.o \
|
||||
PTask.o PUdp.o PFunction.o PWire.o Statement.o StringHeap.o \
|
||||
$(FF) $(TT)
|
||||
|
||||
|
|
|
|||
21
Module.cc
21
Module.cc
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
/* n is a permallocated string. */
|
||||
Module::Module(perm_string n)
|
||||
: name_(n)
|
||||
: PScope(n, 0)
|
||||
{
|
||||
library_flag = false;
|
||||
default_nettype = NetNet::NONE;
|
||||
|
|
@ -54,16 +54,6 @@ void Module::add_function(perm_string name, PFunction *func)
|
|||
funcs_[name] = func;
|
||||
}
|
||||
|
||||
PWire* Module::add_wire(PWire*wire)
|
||||
{
|
||||
PWire*&ep = wires_[wire->path()];
|
||||
if (ep) return ep;
|
||||
|
||||
assert(ep == 0);
|
||||
ep = wire;
|
||||
return wire;
|
||||
}
|
||||
|
||||
void Module::add_behavior(PProcess*b)
|
||||
{
|
||||
behaviors_.push_back(b);
|
||||
|
|
@ -111,15 +101,6 @@ unsigned Module::find_port(const char*name) const
|
|||
}
|
||||
|
||||
|
||||
PWire* Module::get_wire(const pform_name_t&name) const
|
||||
{
|
||||
map<pform_name_t,PWire*>::const_iterator obj = wires_.find(name);
|
||||
if (obj == wires_.end())
|
||||
return 0;
|
||||
else
|
||||
return (*obj).second;
|
||||
}
|
||||
|
||||
PGate* Module::get_gate(perm_string name)
|
||||
{
|
||||
for (list<PGate*>::iterator cur = gates_.begin()
|
||||
|
|
|
|||
50
Module.h
50
Module.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __Module_H
|
||||
#define __Module_H
|
||||
/*
|
||||
* Copyright (c) 1998-2004 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2008 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
|
||||
|
|
@ -18,9 +18,7 @@
|
|||
* 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: Module.h,v 1.43 2007/05/24 04:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
# include <list>
|
||||
# include <map>
|
||||
|
|
@ -28,10 +26,10 @@
|
|||
# include "StringHeap.h"
|
||||
# include "HName.h"
|
||||
# include "named.h"
|
||||
# include "PScope.h"
|
||||
# include "LineInfo.h"
|
||||
# include "netlist.h"
|
||||
# include "pform_types.h"
|
||||
class PEvent;
|
||||
class PExpr;
|
||||
class PEIdent;
|
||||
class PGate;
|
||||
|
|
@ -50,7 +48,7 @@ class NetScope;
|
|||
* therefore the handle for grasping the described circuit.
|
||||
*/
|
||||
|
||||
class Module : public LineInfo {
|
||||
class Module : public PScope, public LineInfo {
|
||||
|
||||
/* The module ports are in general a vector of port_t
|
||||
objects. Each port has a name and an ordered list of
|
||||
|
|
@ -113,9 +111,6 @@ class Module : public LineInfo {
|
|||
named array of PEident pointers. */
|
||||
svector<port_t*> ports;
|
||||
|
||||
/* Keep a table of named events declared in the module. */
|
||||
map<perm_string,PEvent*>events;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
/* These are the timescale for this module. The default is
|
||||
|
|
@ -132,15 +127,10 @@ class Module : public LineInfo {
|
|||
|
||||
list<PSpecPath*> specify_paths;
|
||||
|
||||
perm_string mod_name() const { return name_; }
|
||||
// The mod_name() is the name of the module type.
|
||||
perm_string mod_name() const { return pscope_name(); }
|
||||
|
||||
void add_gate(PGate*gate);
|
||||
|
||||
// The add_wire method adds a wire by name, but only if the
|
||||
// wire name doesn't already exist. Either way, the result is
|
||||
// the existing wire or the pointer passed in.
|
||||
PWire* add_wire(PWire*wire);
|
||||
|
||||
void add_behavior(PProcess*behave);
|
||||
void add_task(perm_string name, PTask*def);
|
||||
void add_function(perm_string name, PFunction*def);
|
||||
|
|
@ -149,9 +139,6 @@ class Module : public LineInfo {
|
|||
const svector<PEIdent*>& get_port(unsigned idx) const;
|
||||
unsigned find_port(const char*name) const;
|
||||
|
||||
// Find a wire by name. This is used for connecting gates to
|
||||
// existing wires, etc.
|
||||
PWire* get_wire(const pform_name_t&name) const;
|
||||
PGate* get_gate(perm_string name);
|
||||
|
||||
const list<PGate*>& get_gates() const;
|
||||
|
|
@ -166,9 +153,6 @@ class Module : public LineInfo {
|
|||
bool elaborate_sig(Design*, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
|
||||
map<pform_name_t,PWire*> wires_;
|
||||
list<PGate*> gates_;
|
||||
list<PProcess*> behaviors_;
|
||||
map<perm_string,PTask*> tasks_;
|
||||
|
|
@ -182,26 +166,4 @@ class Module : public LineInfo {
|
|||
Module& operator= (const Module&);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* $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.
|
||||
*
|
||||
* Revision 1.41 2006/09/23 04:57:19 steve
|
||||
* Basic support for specify timing.
|
||||
*
|
||||
* Revision 1.40 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.39 2006/03/30 01:49:07 steve
|
||||
* Fix instance arrays indexed by overridden parameters.
|
||||
*
|
||||
* Revision 1.38 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*/
|
||||
#endif
|
||||
|
|
|
|||
34
PFunction.cc
34
PFunction.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2008 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
|
||||
|
|
@ -16,16 +16,13 @@
|
|||
* 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: PFunction.cc,v 1.7 2004/05/31 23:34:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
#include "PTask.h"
|
||||
|
||||
PFunction::PFunction(perm_string name)
|
||||
: name_(name), ports_(0), statement_(0)
|
||||
PFunction::PFunction(perm_string name, PScope*parent)
|
||||
: PScope(name, parent), ports_(0), statement_(0)
|
||||
{
|
||||
return_type_.type = PTF_NONE;
|
||||
}
|
||||
|
|
@ -51,28 +48,3 @@ void PFunction::set_return(PTaskFuncArg t)
|
|||
{
|
||||
return_type_ = t;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PFunction.cc,v $
|
||||
* Revision 1.7 2004/05/31 23:34:36 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
* speed and more type support.
|
||||
*
|
||||
* Revision 1.6 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.5 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.4 2001/01/13 22:20:08 steve
|
||||
* Parse parameters within nested scopes.
|
||||
*
|
||||
* Revision 1.3 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/08/25 22:22:41 steve
|
||||
* elaborate some aspects of functions.
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
14
PGenerate.cc
14
PGenerate.cc
|
|
@ -33,19 +33,9 @@ PGenerate::~PGenerate()
|
|||
{
|
||||
}
|
||||
|
||||
PWire* PGenerate::add_wire(PWire*wire)
|
||||
PWire* PGenerate::get_wire(perm_string name) const
|
||||
{
|
||||
PWire*&ep = wires[wire->path()];
|
||||
if (ep) return ep;
|
||||
|
||||
assert(ep == 0);
|
||||
ep = wire;
|
||||
return wire;
|
||||
}
|
||||
|
||||
PWire* PGenerate::get_wire(const pform_name_t&name) const
|
||||
{
|
||||
map<pform_name_t,PWire*>::const_iterator obj = wires.find(name);
|
||||
map<perm_string,PWire*>::const_iterator obj = wires.find(name);
|
||||
if (obj == wires.end())
|
||||
return 0;
|
||||
else
|
||||
|
|
|
|||
|
|
@ -71,9 +71,8 @@ class PGenerate : public LineInfo {
|
|||
PExpr*loop_test;
|
||||
PExpr*loop_step;
|
||||
|
||||
map<pform_name_t,PWire*>wires;
|
||||
PWire* add_wire(PWire*);
|
||||
PWire* get_wire(const pform_name_t&name) const;
|
||||
map<perm_string,PWire*>wires;
|
||||
PWire* get_wire(perm_string name) const;
|
||||
|
||||
list<PGate*> gates;
|
||||
void add_gate(PGate*);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2008 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
|
||||
*/
|
||||
|
||||
# include "PScope.h"
|
||||
|
||||
PScope::PScope(perm_string n, PScope*p)
|
||||
: name_(n), parent_(p)
|
||||
{
|
||||
}
|
||||
|
||||
PScope::~PScope()
|
||||
{
|
||||
}
|
||||
|
||||
PWire* PScope::wires_find(perm_string name)
|
||||
{
|
||||
map<perm_string,PWire*>::const_iterator cur = wires.find(name);
|
||||
if (cur == wires.end())
|
||||
return 0;
|
||||
else
|
||||
return (*cur).second;
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef __PScope_H
|
||||
#define __PScope_H
|
||||
/*
|
||||
* Copyright (c) 2008 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
|
||||
*/
|
||||
|
||||
# include "StringHeap.h"
|
||||
# include "pform_types.h"
|
||||
# include <map>
|
||||
|
||||
class PEvent;
|
||||
class PWire;
|
||||
|
||||
class Design;
|
||||
class NetScope;
|
||||
|
||||
/*
|
||||
* The PScope class is a base representation of an object that
|
||||
* represents lexical scope. For example, a module, a function/task, a
|
||||
* named block is derived from a PScope.
|
||||
*
|
||||
* NOTE: This is note the same concept as the "scope" of an elaborated
|
||||
* hierarchy. That is represented by NetScope objects after elaboration.
|
||||
*/
|
||||
class PScope {
|
||||
|
||||
public:
|
||||
// When created, a scope has a name and a parent. The name is
|
||||
// the name of the definition. For example, if this is a
|
||||
// module declaration, the name is the name after the "module"
|
||||
// keyword, and if this is a task scope, the name is the task
|
||||
// name. The parent is the lexical parent of this scope. Since
|
||||
// modules do not nest in Verilog, the parent must be nil for
|
||||
// modules. Scopes for tasks and functions point to their
|
||||
// containing module.
|
||||
PScope(perm_string name, PScope*parent);
|
||||
virtual ~PScope();
|
||||
|
||||
perm_string pscope_name() const { return name_; }
|
||||
PScope* pscope_parent() { return parent_; }
|
||||
|
||||
// Nets an variables (wires) in the scope
|
||||
map<perm_string,PWire*>wires;
|
||||
PWire* wires_find(perm_string name);
|
||||
|
||||
// Named events in the scope.
|
||||
map<perm_string,PEvent*>events;
|
||||
|
||||
protected:
|
||||
void dump_wires_(ostream&out, unsigned indent) const;
|
||||
|
||||
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
PScope*parent_;
|
||||
};
|
||||
|
||||
#endif
|
||||
9
PTask.cc
9
PTask.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2008 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
|
||||
|
|
@ -16,16 +16,13 @@
|
|||
* 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: PTask.cc,v 1.7 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "PTask.h"
|
||||
|
||||
PTask::PTask()
|
||||
: ports_(0), statement_(0)
|
||||
PTask::PTask(perm_string name, PScope*parent)
|
||||
: PScope(name, parent), ports_(0), statement_(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
73
PTask.h
73
PTask.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PTask_H
|
||||
#define __PTask_H
|
||||
/*
|
||||
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2008 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
|
||||
|
|
@ -18,11 +18,9 @@
|
|||
* 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: PTask.h,v 1.14 2007/03/06 05:22:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include "PScope.h"
|
||||
# include "svector.h"
|
||||
# include "StringHeap.h"
|
||||
# include <string>
|
||||
|
|
@ -50,10 +48,10 @@ struct PTaskFuncArg {
|
|||
/*
|
||||
* The PTask holds the parsed definitions of a task.
|
||||
*/
|
||||
class PTask : public LineInfo {
|
||||
class PTask : public PScope, public LineInfo {
|
||||
|
||||
public:
|
||||
explicit PTask();
|
||||
explicit PTask(perm_string name, PScope*parent);
|
||||
~PTask();
|
||||
|
||||
void set_ports(svector<PWire *>*p);
|
||||
|
|
@ -89,10 +87,10 @@ class PTask : public LineInfo {
|
|||
*
|
||||
* The output value is not elaborated until elaborate_sig.
|
||||
*/
|
||||
class PFunction : public LineInfo {
|
||||
class PFunction : public PScope, public LineInfo {
|
||||
|
||||
public:
|
||||
explicit PFunction(perm_string name);
|
||||
explicit PFunction(perm_string name, PScope*parent);
|
||||
~PFunction();
|
||||
|
||||
void set_ports(svector<PWire *>*p);
|
||||
|
|
@ -110,68 +108,9 @@ class PFunction : public LineInfo {
|
|||
void dump(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
PTaskFuncArg return_type_;
|
||||
svector<PWire *> *ports_;
|
||||
Statement *statement_;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PTask.h,v $
|
||||
* Revision 1.14 2007/03/06 05:22:49 steve
|
||||
* Support signed function return values.
|
||||
*
|
||||
* Revision 1.13 2004/05/31 23:34:36 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
* speed and more type support.
|
||||
*
|
||||
* Revision 1.12 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.11 2001/11/22 06:20:59 steve
|
||||
* Use NetScope instead of string for scope path.
|
||||
*
|
||||
* Revision 1.10 2001/01/13 22:20:08 steve
|
||||
* Parse parameters within nested scopes.
|
||||
*
|
||||
* Revision 1.9 2000/07/30 18:25:43 steve
|
||||
* Rearrange task and function elaboration so that the
|
||||
* NetTaskDef and NetFuncDef functions are created during
|
||||
* signal enaboration, and carry these objects in the
|
||||
* NetScope class instead of the extra, useless map in
|
||||
* the Design class.
|
||||
*
|
||||
* Revision 1.8 2000/03/08 04:36:53 steve
|
||||
* Redesign the implementation of scopes and parameters.
|
||||
* I now generate the scopes and notice the parameters
|
||||
* in a separate pass over the pform. Once the scopes
|
||||
* are generated, I can process overrides and evalutate
|
||||
* paremeters before elaboration begins.
|
||||
*
|
||||
* Revision 1.7 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.6 1999/09/30 21:28:34 steve
|
||||
* Handle mutual reference of tasks by elaborating
|
||||
* task definitions in two passes, like functions.
|
||||
*
|
||||
* Revision 1.5 1999/09/01 20:46:19 steve
|
||||
* Handle recursive functions and arbitrary function
|
||||
* references to other functions, properly pass
|
||||
* function parameters and save function results.
|
||||
*
|
||||
* Revision 1.4 1999/08/25 22:22:41 steve
|
||||
* elaborate some aspects of functions.
|
||||
*
|
||||
* Revision 1.3 1999/07/31 19:14:47 steve
|
||||
* Add functions up to elaboration (Ed Carter)
|
||||
*
|
||||
* Revision 1.2 1999/07/24 02:11:19 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
* Revision 1.1 1999/07/03 02:12:51 steve
|
||||
* Elaborate user defined tasks.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
|
|
|||
18
PWire.cc
18
PWire.cc
|
|
@ -22,11 +22,11 @@
|
|||
# include "PExpr.h"
|
||||
# include <assert.h>
|
||||
|
||||
PWire::PWire(const pform_name_t&n,
|
||||
PWire::PWire(perm_string n,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt)
|
||||
: hname_(n), type_(t), port_type_(pt), data_type_(dt),
|
||||
: name_(n), type_(t), port_type_(pt), data_type_(dt),
|
||||
signed_(false), isint_(false),
|
||||
port_msb_(0), port_lsb_(0), port_set_(false),
|
||||
net_msb_(0), net_lsb_(0), net_set_(false), error_cnt_(0),
|
||||
|
|
@ -44,9 +44,9 @@ NetNet::Type PWire::get_wire_type() const
|
|||
return type_;
|
||||
}
|
||||
|
||||
const pform_name_t& PWire::path() const
|
||||
perm_string PWire::basename() const
|
||||
{
|
||||
return hname_;
|
||||
return name_;
|
||||
}
|
||||
|
||||
bool PWire::set_wire_type(NetNet::Type t)
|
||||
|
|
@ -153,7 +153,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
|
|||
switch (type) {
|
||||
case SR_PORT:
|
||||
if (port_set_) {
|
||||
cerr << get_fileline() << ": error: Port ``" << hname_
|
||||
cerr << get_fileline() << ": error: Port ``" << name_
|
||||
<< "'' has already been declared a port." << endl;
|
||||
error_cnt_ += 1;
|
||||
} else {
|
||||
|
|
@ -165,7 +165,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
|
|||
|
||||
case SR_NET:
|
||||
if (net_set_) {
|
||||
cerr << get_fileline() << ": error: Net ``" << hname_
|
||||
cerr << get_fileline() << ": error: Net ``" << name_
|
||||
<< "'' has already been declared." << endl;
|
||||
error_cnt_ += 1;
|
||||
} else {
|
||||
|
|
@ -178,12 +178,12 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
|
|||
case SR_BOTH:
|
||||
if (port_set_ || net_set_) {
|
||||
if (port_set_) {
|
||||
cerr << get_fileline() << ": error: Port ``" << hname_
|
||||
cerr << get_fileline() << ": error: Port ``" << name_
|
||||
<< "'' has already been declared a port." << endl;
|
||||
error_cnt_ += 1;
|
||||
}
|
||||
if (net_set_) {
|
||||
cerr << get_fileline() << ": error: Net ``" << hname_
|
||||
cerr << get_fileline() << ": error: Net ``" << name_
|
||||
<< "'' has already been declared." << endl;
|
||||
error_cnt_ += 1;
|
||||
}
|
||||
|
|
@ -202,7 +202,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
|
|||
void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
|
||||
{
|
||||
if (lidx_ != 0 || ridx_ != 0) {
|
||||
cerr << get_fileline() << ": error: Array ``" << hname_
|
||||
cerr << get_fileline() << ": error: Array ``" << name_
|
||||
<< "'' has already been declared." << endl;
|
||||
error_cnt_ += 1;
|
||||
} else {
|
||||
|
|
|
|||
6
PWire.h
6
PWire.h
|
|
@ -56,13 +56,13 @@ enum PWSRType {SR_PORT, SR_NET, SR_BOTH};
|
|||
class PWire : public LineInfo {
|
||||
|
||||
public:
|
||||
PWire(const pform_name_t&hname,
|
||||
PWire(perm_string name,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt);
|
||||
|
||||
// Return a hierarchical name.
|
||||
const pform_name_t&path() const;
|
||||
perm_string basename() const;
|
||||
|
||||
NetNet::Type get_wire_type() const;
|
||||
bool set_wire_type(NetNet::Type);
|
||||
|
|
@ -90,7 +90,7 @@ class PWire : public LineInfo {
|
|||
NetNet* elaborate_sig(Design*, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
pform_name_t hname_;
|
||||
perm_string name_;
|
||||
NetNet::Type type_;
|
||||
NetNet::PortType port_type_;
|
||||
ivl_variable_type_t data_type_;
|
||||
|
|
|
|||
16
Statement.cc
16
Statement.cc
|
|
@ -86,18 +86,13 @@ PAssignNB::~PAssignNB()
|
|||
{
|
||||
}
|
||||
|
||||
PBlock::PBlock(perm_string n, BL_TYPE t, const svector<Statement*>&st)
|
||||
: name_(n), bl_type_(t), list_(st)
|
||||
{
|
||||
}
|
||||
|
||||
PBlock::PBlock(BL_TYPE t, const svector<Statement*>&st)
|
||||
: bl_type_(t), list_(st)
|
||||
PBlock::PBlock(perm_string n, PScope*parent, BL_TYPE t)
|
||||
: PScope(n, parent), bl_type_(t)
|
||||
{
|
||||
}
|
||||
|
||||
PBlock::PBlock(BL_TYPE t)
|
||||
: bl_type_(t)
|
||||
: PScope(perm_string(),0), bl_type_(t)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -107,6 +102,11 @@ PBlock::~PBlock()
|
|||
delete list_[idx];
|
||||
}
|
||||
|
||||
void PBlock::set_statement(const svector<Statement*>&st)
|
||||
{
|
||||
list_ = st;
|
||||
}
|
||||
|
||||
PCallTask::PCallTask(const pform_name_t&n, const svector<PExpr*>&p)
|
||||
: path_(n), parms_(p)
|
||||
{
|
||||
|
|
|
|||
18
Statement.h
18
Statement.h
|
|
@ -27,6 +27,7 @@
|
|||
# include "StringHeap.h"
|
||||
# include "PDelays.h"
|
||||
# include "PExpr.h"
|
||||
# include "PScope.h"
|
||||
# include "HName.h"
|
||||
# include "LineInfo.h"
|
||||
class PExpr;
|
||||
|
|
@ -83,6 +84,7 @@ class Statement : public LineInfo {
|
|||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -147,25 +149,27 @@ class PAssignNB : public PAssign_ {
|
|||
* statements before constructing this object, so it knows a priori
|
||||
* what is contained.
|
||||
*/
|
||||
class PBlock : public Statement {
|
||||
class PBlock : public PScope, public Statement {
|
||||
|
||||
public:
|
||||
enum BL_TYPE { BL_SEQ, BL_PAR };
|
||||
|
||||
explicit PBlock(perm_string n, BL_TYPE t, const svector<Statement*>&st);
|
||||
explicit PBlock(BL_TYPE t, const svector<Statement*>&st);
|
||||
// If the block has a name, it is a scope and also has a parent.
|
||||
explicit PBlock(perm_string n, PScope*parent, BL_TYPE t);
|
||||
// If it doesn't have a name, it's not a scope
|
||||
explicit PBlock(BL_TYPE t);
|
||||
~PBlock();
|
||||
|
||||
BL_TYPE bl_type() const { return bl_type_; }
|
||||
|
||||
void set_statement(const svector<Statement*>&st);
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
const BL_TYPE bl_type_;
|
||||
svector<Statement*>list_;
|
||||
};
|
||||
|
|
@ -215,6 +219,7 @@ class PCase : public Statement {
|
|||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
|
|
@ -250,6 +255,7 @@ class PCondit : public Statement {
|
|||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
|
|
@ -284,6 +290,7 @@ class PDelayStatement : public Statement {
|
|||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
PExpr*delay_;
|
||||
|
|
@ -331,6 +338,7 @@ class PEventStatement : public Statement {
|
|||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
// This method is used to elaborate, but attach a previously
|
||||
// elaborated statement to the event.
|
||||
|
|
@ -364,6 +372,7 @@ class PForever : public Statement {
|
|||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
|
|
@ -379,6 +388,7 @@ class PForStatement : public Statement {
|
|||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -309,8 +309,14 @@ void NetPow::dump_node(ostream&o, unsigned ind) const
|
|||
{
|
||||
o << setw(ind) << "" << "LPM_POW (NetPow): " << name()
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< " delay=(" << *rise_time() << "," << *fall_time() << ","
|
||||
<< *decay_time() << ")" << endl;
|
||||
<< " delay=(";
|
||||
if (rise_time())
|
||||
o << *rise_time() << "," << *fall_time() << ","
|
||||
<< *decay_time();
|
||||
else
|
||||
o << "0,0,0";
|
||||
|
||||
o << ")" << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
|
@ -987,7 +993,10 @@ void NetScope::dump(ostream&o) const
|
|||
o << " MISSING FUNCTION DEFINITION" << endl;
|
||||
break;
|
||||
case TASK:
|
||||
if (task_def())
|
||||
task_def()->dump(o, 4);
|
||||
else
|
||||
o << " MISSING TASK DEFINITION" << endl;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -794,8 +794,8 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
|
|||
{
|
||||
NetScope*my_scope = scope;
|
||||
|
||||
if (name_ != 0) {
|
||||
hname_t use_name(name_);
|
||||
if (pscope_name() != 0) {
|
||||
hname_t use_name(pscope_name());
|
||||
if (scope->child(use_name)) {
|
||||
cerr << get_fileline() << ": error: block/scope name "
|
||||
<< use_name << " already used in this context."
|
||||
|
|
|
|||
314
elab_sig.cc
314
elab_sig.cc
|
|
@ -28,46 +28,58 @@
|
|||
# include "PGenerate.h"
|
||||
# include "PTask.h"
|
||||
# include "PWire.h"
|
||||
# include "Statement.h"
|
||||
# include "compiler.h"
|
||||
# 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
|
||||
* port. It looks in the array of ports passed, for NetEIdent objects
|
||||
* within the port_t that have a matching name.
|
||||
*/
|
||||
static bool signal_is_in_port(const svector<Module::port_t*>&ports,
|
||||
NetNet*sig)
|
||||
void Statement::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
perm_string name = sig->name();
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
Module::port_t*pp = ports[idx];
|
||||
// Skip internally unconnected ports.
|
||||
if (pp == 0)
|
||||
continue;
|
||||
for (map<perm_string,PWire*>::const_iterator wt = wires.begin()
|
||||
; wt != wires.end() ; wt ++ ) {
|
||||
|
||||
// This port has an internal connection. In this case,
|
||||
// the port has 0 or more NetEIdent objects concatenated
|
||||
// together that form the port.
|
||||
PWire*cur = (*wt).second;
|
||||
NetNet*sig = cur->elaborate_sig(des, scope);
|
||||
|
||||
// Note that module ports should not have any hierarchy
|
||||
// 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 (pname == name)
|
||||
return true;
|
||||
}
|
||||
/* If the signal is an input and is also declared as a
|
||||
reg, then report an error. */
|
||||
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (scope->type() == NetScope::MODULE)
|
||||
&& (sig->port_type() == NetNet::PINPUT)
|
||||
&& (sig->type() == NetNet::REG)) {
|
||||
|
||||
cerr << cur->get_fileline() << ": error: "
|
||||
<< cur->basename() << " in "
|
||||
<< scope->module_name()
|
||||
<< " declared as input and as a reg type." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (scope->type() == NetScope::MODULE)
|
||||
&& (sig->port_type() == NetNet::PINOUT)
|
||||
&& (sig->type() == NetNet::REG)) {
|
||||
|
||||
cerr << cur->get_fileline() << ": error: "
|
||||
<< cur->basename() << " in "
|
||||
<< scope->module_name()
|
||||
<< " declared as inout and as a reg type." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
|
@ -81,15 +93,27 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
|||
if (pp == 0)
|
||||
continue;
|
||||
|
||||
map<pform_name_t,PWire*>::const_iterator wt;
|
||||
// The port has a name and an array of expressions. The
|
||||
// expression are all identifiers that should reference
|
||||
// wires within the scope.
|
||||
map<perm_string,PWire*>::const_iterator wt;
|
||||
for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
|
||||
pform_name_t port_path (pp->expr[cc]->path());
|
||||
wt = wires_.find(port_path);
|
||||
// A concatenated wire of a port really should not
|
||||
// have any hierarchy.
|
||||
if (port_path.size() != 1) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Port " << port_path << " has a funny name?"
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (wt == wires_.end()) {
|
||||
wt = wires.find(peek_tail_name(port_path));
|
||||
|
||||
if (wt == wires.end()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Port " << pp->expr[cc]->path() << " ("
|
||||
<< (idx+1) << ") of module " << name_
|
||||
<< "Port " << port_path << " ("
|
||||
<< (idx+1) << ") of module " << mod_name()
|
||||
<< " is not declared within module." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
|
|
@ -98,7 +122,7 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
|||
if ((*wt).second->get_port_type() == NetNet::NOT_A_PORT) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Port " << pp->expr[cc]->path() << " ("
|
||||
<< (idx+1) << ") of module " << name_
|
||||
<< (idx+1) << ") of module " << mod_name()
|
||||
<< " has no direction declaration."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
|
|
@ -106,58 +130,7 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
|||
}
|
||||
}
|
||||
|
||||
for (map<pform_name_t,PWire*>::const_iterator wt = wires_.begin()
|
||||
; wt != wires_.end() ; wt ++ ) {
|
||||
|
||||
PWire*cur = (*wt).second;
|
||||
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
|
||||
// the module knows about it. We know that the signal is
|
||||
// the name of a signal within a subscope of a module
|
||||
// (a task, a function, etc.) if the name for the PWire
|
||||
// has hierarchy.
|
||||
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (cur->get_port_type() != NetNet::NOT_A_PORT)) {
|
||||
|
||||
if (! signal_is_in_port(ports, sig)) {
|
||||
|
||||
cerr << cur->get_fileline() << ": error: Signal "
|
||||
<< sig->name() << " has a declared direction "
|
||||
<< "but is not a port." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* If the signal is an input and is also declared as a
|
||||
reg, then report an error. */
|
||||
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (sig->port_type() == NetNet::PINPUT)
|
||||
&& (sig->type() == NetNet::REG)) {
|
||||
|
||||
cerr << cur->get_fileline() << ": error: "
|
||||
<< cur->path() << " in module "
|
||||
<< scope->module_name()
|
||||
<< " declared as input and as a reg type." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (sig->port_type() == NetNet::PINOUT)
|
||||
&& (sig->type() == NetNet::REG)) {
|
||||
|
||||
cerr << cur->get_fileline() << ": error: "
|
||||
<< cur->path() << " in module "
|
||||
<< scope->module_name()
|
||||
<< " declared as inout and as a reg type." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
}
|
||||
flag = elaborate_sig_wires_(des, scope) && flag;
|
||||
|
||||
// Run through all the generate schemes to elaborate the
|
||||
// signals that they hold. Note that the generate schemes hold
|
||||
|
|
@ -216,6 +189,18 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
|||
(*cur).second->elaborate_sig(des, tscope);
|
||||
}
|
||||
|
||||
// initial and always blocks may contain begin-end and
|
||||
// fork-join blocks that can introduce scopes. Therefore, I
|
||||
// get to scan processes here.
|
||||
|
||||
typedef list<PProcess*>::const_iterator proc_it_t;
|
||||
|
||||
for (proc_it_t cur = behaviors_.begin()
|
||||
; cur != behaviors_.end() ; cur ++ ) {
|
||||
|
||||
(*cur) -> statement() -> elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
|
|
@ -276,7 +261,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<pform_name_t,PWire*>::const_iterator wires_it_t;
|
||||
typedef map<perm_string,PWire*>::const_iterator wires_it_t;
|
||||
for (wires_it_t wt = wires.begin()
|
||||
; wt != wires.end() ; wt ++ ) {
|
||||
|
||||
|
|
@ -284,7 +269,7 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
|
|||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: Elaborate PWire "
|
||||
<< cur->path() << " in scope " << scope_path(scope) << endl;
|
||||
<< cur->basename() << " in scope " << scope_path(scope) << endl;
|
||||
|
||||
cur->elaborate_sig(des, scope);
|
||||
}
|
||||
|
|
@ -316,6 +301,8 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
perm_string fname = scope->basename();
|
||||
assert(scope->type() == NetScope::FUNC);
|
||||
|
||||
elaborate_sig_wires_(des, scope);
|
||||
|
||||
/* Make sure the function has at least one input port. If it
|
||||
fails this test, print an error message. Keep going so we
|
||||
can find more errors. */
|
||||
|
|
@ -416,19 +403,7 @@ 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>. */
|
||||
|
||||
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_fileline() << ": internal error: function "
|
||||
<< "port " << (*ports_)[idx]->path()
|
||||
<< " has wrong name for function "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
perm_string pname = (*ports_)[idx]->basename();
|
||||
|
||||
NetNet*tmp = scope->find_signal(pname);
|
||||
if (tmp == 0) {
|
||||
|
|
@ -449,6 +424,10 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
assert(def);
|
||||
scope->set_func_def(def);
|
||||
|
||||
// Look for further signals in the sub-statement
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -464,24 +443,12 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
|
|||
{
|
||||
assert(scope->type() == NetScope::TASK);
|
||||
|
||||
elaborate_sig_wires_(des, scope);
|
||||
|
||||
svector<NetNet*>ports (ports_? ports_->count() : 0);
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
|
||||
/* Parse the port name into the task name and the reg
|
||||
name. We know by design that the port name is given
|
||||
as two components: <task>.<port>. */
|
||||
|
||||
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. */
|
||||
ivl_assert(*this, scope->basename() == scope_name);
|
||||
perm_string port_name = (*ports_)[idx]->basename();
|
||||
|
||||
/* Find the signal for the port. We know by definition
|
||||
that it is in the scope of the task, so look only in
|
||||
|
|
@ -493,6 +460,7 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
|
|||
<< "Could not find port " << port_name
|
||||
<< " in scope " << scope_path(scope) << endl;
|
||||
scope->dump(cerr);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
ports[idx] = tmp;
|
||||
|
|
@ -500,6 +468,82 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
NetTaskDef*def = new NetTaskDef(scope, ports);
|
||||
scope->set_task_def(def);
|
||||
|
||||
// Look for further signals in the sub-statement
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PBlock::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetScope*my_scope = scope;
|
||||
|
||||
if (pscope_name() != 0) {
|
||||
hname_t use_name (pscope_name());
|
||||
my_scope = scope->child(use_name);
|
||||
if (my_scope == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unable to find child scope " << pscope_name()
|
||||
<< " in this context?" << endl;
|
||||
des->errors += 1;
|
||||
my_scope = scope;
|
||||
} else {
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "elaborate_sig descending into "
|
||||
<< scope_path(my_scope) << "." << endl;
|
||||
|
||||
elaborate_sig_wires_(des, my_scope);
|
||||
}
|
||||
}
|
||||
|
||||
// elaborate_sig in the statements included in the
|
||||
// block. There may be named blocks in there.
|
||||
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1)
|
||||
list_[idx] -> elaborate_sig(des, my_scope);
|
||||
}
|
||||
|
||||
void PCase::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (items_ == 0)
|
||||
return;
|
||||
|
||||
for (unsigned idx = 0 ; idx < items_->count() ; idx += 1) {
|
||||
if ( (*items_)[idx]->stat )
|
||||
(*items_)[idx]->stat ->elaborate_sig(des,scope);
|
||||
}
|
||||
}
|
||||
|
||||
void PCondit::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (if_)
|
||||
if_->elaborate_sig(des, scope);
|
||||
if (else_)
|
||||
else_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PDelayStatement::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PEventStatement::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PForever::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PForStatement::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
bool PGate::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
|
@ -516,27 +560,6 @@ bool PGate::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. */
|
||||
{ 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( hname_t(cur.name) );
|
||||
|
||||
if (scope == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Bad scope component for name "
|
||||
<< hname_ << endl;
|
||||
assert(scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NetNet::Type wtype = type_;
|
||||
if (wtype == NetNet::IMPLICIT)
|
||||
wtype = NetNet::WIRE;
|
||||
|
|
@ -619,12 +642,12 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
if (port_msb_ == 0) {
|
||||
if (!gn_io_range_error_flag) {
|
||||
cerr << get_fileline()
|
||||
<< ": warning: Scalar port ``" << hname_
|
||||
<< ": warning: Scalar port ``" << name_
|
||||
<< "'' has a vectored net declaration ["
|
||||
<< nmsb << ":" << nlsb << "]." << endl;
|
||||
} else {
|
||||
cerr << get_fileline()
|
||||
<< ": error: Scalar port ``" << hname_
|
||||
<< ": error: Scalar port ``" << name_
|
||||
<< "'' has a vectored net declaration ["
|
||||
<< nmsb << ":" << nlsb << "]." << endl;
|
||||
des->errors += 1;
|
||||
|
|
@ -636,7 +659,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
if (net_msb_ == 0) {
|
||||
cerr << port_msb_->get_fileline()
|
||||
<< ": error: Vectored port ``"
|
||||
<< hname_ << "'' [" << pmsb << ":" << plsb
|
||||
<< name_ << "'' [" << pmsb << ":" << plsb
|
||||
<< "] has a scalar net declaration at "
|
||||
<< get_fileline() << "." << endl;
|
||||
des->errors += 1;
|
||||
|
|
@ -647,7 +670,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
if (port_msb_ != 0 && net_msb_ != 0) {
|
||||
cerr << port_msb_->get_fileline()
|
||||
<< ": error: Vectored port ``"
|
||||
<< hname_ << "'' [" << pmsb << ":" << plsb
|
||||
<< name_ << "'' [" << pmsb << ":" << plsb
|
||||
<< "] has a net declaration [" << nmsb << ":"
|
||||
<< nlsb << "] at " << net_msb_->get_fileline()
|
||||
<< " that does not match." << endl;
|
||||
|
|
@ -687,7 +710,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
if ((lexp == 0) || (rexp == 0)) {
|
||||
cerr << get_fileline() << ": internal error: There is "
|
||||
<< "a problem evaluating indices for ``"
|
||||
<< hname_ << "''." << endl;
|
||||
<< name_ << "''." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -698,7 +721,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
if ((lcon == 0) || (rcon == 0)) {
|
||||
cerr << get_fileline() << ": internal error: The indices "
|
||||
<< "are not constant for array ``"
|
||||
<< hname_ << "''." << endl;
|
||||
<< name_ << "''." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -748,24 +771,23 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
}
|
||||
}
|
||||
|
||||
perm_string name = peek_tail_name(hname_);
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal "
|
||||
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name
|
||||
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_
|
||||
<< " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
|
||||
NetNet*sig = array_dimensions > 0
|
||||
? new NetNet(scope, name, wtype, msb, lsb, array_s0, array_e0)
|
||||
: new NetNet(scope, name, wtype, msb, lsb);
|
||||
? new NetNet(scope, name_, wtype, msb, lsb, array_s0, array_e0)
|
||||
: new NetNet(scope, name_, wtype, msb, lsb);
|
||||
|
||||
ivl_variable_type_t use_data_type = data_type_;
|
||||
if (use_data_type == IVL_VT_NO_TYPE) {
|
||||
use_data_type = IVL_VT_LOGIC;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Signal " << name
|
||||
<< "Signal " << name_
|
||||
<< " in scope " << scope_path(scope)
|
||||
<< " defaults to data type " << use_data_type << endl;
|
||||
}
|
||||
|
|
|
|||
10
elaborate.cc
10
elaborate.cc
|
|
@ -1866,12 +1866,12 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
|||
: NetBlock::SEQU;
|
||||
|
||||
NetScope*nscope = 0;
|
||||
if (name_.str() != 0) {
|
||||
nscope = scope->child(hname_t(name_));
|
||||
if (pscope_name() != 0) {
|
||||
nscope = scope->child(hname_t(pscope_name()));
|
||||
if (nscope == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
"unable to find block scope " << scope_path(scope)
|
||||
<< "<" << name_ << ">" << endl;
|
||||
<< "<" << pscope_name() << ">" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1889,7 +1889,7 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
|||
// statement. There is no need to keep the block node. Also,
|
||||
// don't elide named blocks, because they might be referenced
|
||||
// elsewhere.
|
||||
if ((list_.count() == 1) && (name_.str() == 0)) {
|
||||
if ((list_.count() == 1) && (pscope_name() == 0)) {
|
||||
assert(list_[0]);
|
||||
NetProc*tmp = list_[0]->elaborate(des, nscope);
|
||||
return tmp;
|
||||
|
|
@ -2934,7 +2934,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
|||
NetNet*sig = des->find_signal(scope, id1->path());
|
||||
if (sig == 0) {
|
||||
cerr << id1->get_fileline() << ": register ``" << id1->path()
|
||||
<< "'' unknown in this context." << endl;
|
||||
<< "'' unknown in " << scope_path(scope) << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -295,10 +295,10 @@ void NetScope::rem_event(NetEvent*ev)
|
|||
}
|
||||
|
||||
|
||||
NetEvent* NetScope::find_event(const char*name)
|
||||
NetEvent* NetScope::find_event(perm_string name)
|
||||
{
|
||||
for (NetEvent*cur = events_; cur ; cur = cur->snext_)
|
||||
if (strcmp(cur->name(), name) == 0)
|
||||
if (cur->name() == name)
|
||||
return cur;
|
||||
|
||||
return 0;
|
||||
|
|
@ -337,7 +337,7 @@ void NetScope::rem_signal(NetNet*net)
|
|||
* is assumed to be the base name of the signal, so no sub-scopes are
|
||||
* searched.
|
||||
*/
|
||||
NetNet* NetScope::find_signal(const char*key)
|
||||
NetNet* NetScope::find_signal(perm_string key)
|
||||
{
|
||||
if (signals_ == 0)
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -3275,7 +3275,7 @@ class NetScope : public Attrib {
|
|||
|
||||
void add_event(NetEvent*);
|
||||
void rem_event(NetEvent*);
|
||||
NetEvent*find_event(const char*name);
|
||||
NetEvent*find_event(perm_string name);
|
||||
|
||||
|
||||
/* These methods manage signals. The add_ and rem_signal
|
||||
|
|
@ -3285,7 +3285,7 @@ class NetScope : public Attrib {
|
|||
|
||||
void add_signal(NetNet*);
|
||||
void rem_signal(NetNet*);
|
||||
NetNet* find_signal(const char*name);
|
||||
NetNet* find_signal(perm_string name);
|
||||
|
||||
/* The parent and child() methods allow users of NetScope
|
||||
objects to locate nearby scopes. */
|
||||
|
|
|
|||
182
parse.y
182
parse.y
|
|
@ -26,6 +26,7 @@
|
|||
# include "pform.h"
|
||||
# include "Statement.h"
|
||||
# include "PSpec.h"
|
||||
# include <stack>
|
||||
# include <cstring>
|
||||
# include <sstream>
|
||||
|
||||
|
|
@ -45,6 +46,12 @@ static struct {
|
|||
svector<PExpr*>* range;
|
||||
} port_declaration_context;
|
||||
|
||||
/* The task and function rules need to briefly hold the pointer to the
|
||||
task/function that is currently in progress. */
|
||||
static PTask* current_task = 0;
|
||||
static PFunction* current_function = 0;
|
||||
static stack<PBlock*> current_block_stack;
|
||||
|
||||
/* Later version of bison (including 1.35) will not compile in stack
|
||||
extension if the output is compiled with C++ and either the YYSTYPE
|
||||
or YYLTYPE are provided by the source code. However, I can get the
|
||||
|
|
@ -191,7 +198,8 @@ static inline void FILE_NAME(LineInfo*tmp, const struct vlltype&where)
|
|||
%type <text> udp_input_list udp_sequ_entry udp_comb_entry
|
||||
%type <perm_strings> udp_input_declaration_list
|
||||
%type <strings> udp_entry_list udp_comb_entry_list udp_sequ_entry_list
|
||||
%type <strings> udp_body udp_port_list
|
||||
%type <strings> udp_body
|
||||
%type <perm_strings> udp_port_list
|
||||
%type <wires> udp_port_decl udp_port_decls
|
||||
%type <statement> udp_initial udp_init_opt
|
||||
%type <expr> udp_initial_expr_opt
|
||||
|
|
@ -1405,28 +1413,18 @@ list_of_port_declarations
|
|||
{ svector<Module::port_t*>*tmp
|
||||
= new svector<Module::port_t*>(1);
|
||||
(*tmp)[0] = $1;
|
||||
/*
|
||||
* Uncommenting this makes lopd always fully specified.
|
||||
* Some wanted an implicit net to not be fully defined.
|
||||
*
|
||||
* pform_set_net_range($1[0].name);
|
||||
*/
|
||||
$$ = tmp;
|
||||
}
|
||||
| list_of_port_declarations ',' port_declaration
|
||||
{ svector<Module::port_t*>*tmp
|
||||
= new svector<Module::port_t*>(*$1, $3);
|
||||
delete $1;
|
||||
/*
|
||||
* Same as above.
|
||||
*
|
||||
* pform_set_net_range($3[0].name);
|
||||
*/
|
||||
$$ = tmp;
|
||||
}
|
||||
| list_of_port_declarations ',' IDENTIFIER
|
||||
{ Module::port_t*ptmp;
|
||||
ptmp = pform_module_port_reference($3, @3.text,
|
||||
perm_string name = lex_strings.make($3);
|
||||
ptmp = pform_module_port_reference(name, @3.text,
|
||||
@3.first_line);
|
||||
svector<Module::port_t*>*tmp
|
||||
= new svector<Module::port_t*>(*$1, ptmp);
|
||||
|
|
@ -1434,17 +1432,13 @@ list_of_port_declarations
|
|||
/* Get the port declaration details, the port type
|
||||
and what not, from context data stored by the
|
||||
last port_declaration rule. */
|
||||
pform_module_define_port(@3, $3,
|
||||
pform_module_define_port(@3, name,
|
||||
port_declaration_context.port_type,
|
||||
port_declaration_context.port_net_type,
|
||||
port_declaration_context.sign_flag,
|
||||
port_declaration_context.range, 0);
|
||||
delete $1;
|
||||
/*
|
||||
* Same as above.
|
||||
*
|
||||
* pform_set_net_range($3);
|
||||
*/
|
||||
delete $3;
|
||||
$$ = tmp;
|
||||
}
|
||||
| list_of_port_declarations ','
|
||||
|
|
@ -1463,9 +1457,10 @@ port_declaration
|
|||
: attribute_list_opt
|
||||
K_input net_type_opt signed_opt range_opt IDENTIFIER
|
||||
{ Module::port_t*ptmp;
|
||||
ptmp = pform_module_port_reference($6, @2.text,
|
||||
perm_string name = lex_strings.make($6);
|
||||
ptmp = pform_module_port_reference(name, @2.text,
|
||||
@2.first_line);
|
||||
pform_module_define_port(@2, $6, NetNet::PINPUT,
|
||||
pform_module_define_port(@2, name, NetNet::PINPUT,
|
||||
$3, $4, $5, $1);
|
||||
port_declaration_context.port_type = NetNet::PINPUT;
|
||||
port_declaration_context.port_net_type = $3;
|
||||
|
|
@ -1478,9 +1473,10 @@ port_declaration
|
|||
| attribute_list_opt
|
||||
K_inout net_type_opt signed_opt range_opt IDENTIFIER
|
||||
{ Module::port_t*ptmp;
|
||||
ptmp = pform_module_port_reference($6, @2.text,
|
||||
perm_string name = lex_strings.make($6);
|
||||
ptmp = pform_module_port_reference(name, @2.text,
|
||||
@2.first_line);
|
||||
pform_module_define_port(@2, $6, NetNet::PINOUT,
|
||||
pform_module_define_port(@2, name, NetNet::PINOUT,
|
||||
$3, $4, $5, $1);
|
||||
port_declaration_context.port_type = NetNet::PINOUT;
|
||||
port_declaration_context.port_net_type = $3;
|
||||
|
|
@ -1493,9 +1489,10 @@ port_declaration
|
|||
| attribute_list_opt
|
||||
K_output net_type_opt signed_opt range_opt IDENTIFIER
|
||||
{ Module::port_t*ptmp;
|
||||
ptmp = pform_module_port_reference($6, @2.text,
|
||||
perm_string name = lex_strings.make($6);
|
||||
ptmp = pform_module_port_reference(name, @2.text,
|
||||
@2.first_line);
|
||||
pform_module_define_port(@2, $6, NetNet::POUTPUT,
|
||||
pform_module_define_port(@2, name, NetNet::POUTPUT,
|
||||
$3, $4, $5, $1);
|
||||
port_declaration_context.port_type = NetNet::POUTPUT;
|
||||
port_declaration_context.port_net_type = $3;
|
||||
|
|
@ -1508,9 +1505,10 @@ port_declaration
|
|||
| attribute_list_opt
|
||||
K_output var_type signed_opt range_opt IDENTIFIER
|
||||
{ Module::port_t*ptmp;
|
||||
ptmp = pform_module_port_reference($6, @2.text,
|
||||
perm_string name = lex_strings.make($6);
|
||||
ptmp = pform_module_port_reference(name, @2.text,
|
||||
@2.first_line);
|
||||
pform_module_define_port(@2, $6, NetNet::POUTPUT,
|
||||
pform_module_define_port(@2, name, NetNet::POUTPUT,
|
||||
$3, $4, $5, $1);
|
||||
port_declaration_context.port_type = NetNet::POUTPUT;
|
||||
port_declaration_context.port_net_type = $3;
|
||||
|
|
@ -1523,9 +1521,10 @@ port_declaration
|
|||
| attribute_list_opt
|
||||
K_output var_type signed_opt range_opt IDENTIFIER '=' expression
|
||||
{ Module::port_t*ptmp;
|
||||
ptmp = pform_module_port_reference($6, @2.text,
|
||||
perm_string name = lex_strings.make($6);
|
||||
ptmp = pform_module_port_reference(name, @2.text,
|
||||
@2.first_line);
|
||||
pform_module_define_port(@2, $6, NetNet::POUTPUT,
|
||||
pform_module_define_port(@2, name, NetNet::POUTPUT,
|
||||
$3, $4, $5, $1);
|
||||
port_declaration_context.port_type = NetNet::POUTPUT;
|
||||
port_declaration_context.port_net_type = $3;
|
||||
|
|
@ -1535,7 +1534,7 @@ port_declaration
|
|||
if (! pform_expression_is_constant($8))
|
||||
yyerror(@8, "error: register declaration assignment"
|
||||
" value must be a constant expression.");
|
||||
pform_make_reginit(@6, $6, $8);
|
||||
pform_make_reginit(@6, name, $8);
|
||||
|
||||
delete $1;
|
||||
delete $6;
|
||||
|
|
@ -1843,33 +1842,33 @@ module_item
|
|||
extension. */
|
||||
|
||||
| K_task IDENTIFIER ';'
|
||||
{ pform_push_scope($2); }
|
||||
{ assert(current_task == 0);
|
||||
current_task = pform_push_task_scope($2);
|
||||
FILE_NAME(current_task, @1);
|
||||
}
|
||||
task_item_list_opt
|
||||
statement_or_null
|
||||
K_endtask
|
||||
{ PTask*tmp = new PTask;
|
||||
perm_string tmp2 = lex_strings.make($2);
|
||||
FILE_NAME(tmp, @1);
|
||||
tmp->set_ports($5);
|
||||
tmp->set_statement($6);
|
||||
pform_set_task(tmp2, tmp);
|
||||
{ current_task->set_ports($5);
|
||||
current_task->set_statement($6);
|
||||
pform_pop_scope();
|
||||
current_task = 0;
|
||||
delete $2;
|
||||
}
|
||||
|
||||
| K_task IDENTIFIER
|
||||
{ pform_push_scope($2); }
|
||||
{ assert(current_task == 0);
|
||||
current_task = pform_push_task_scope($2);
|
||||
FILE_NAME(current_task, @1);
|
||||
}
|
||||
'(' task_port_decl_list ')' ';'
|
||||
task_item_list_opt
|
||||
statement_or_null
|
||||
K_endtask
|
||||
{ PTask*tmp = new PTask;
|
||||
perm_string tmp2 = lex_strings.make($2);
|
||||
FILE_NAME(tmp, @1);
|
||||
tmp->set_ports($5);
|
||||
tmp->set_statement($9);
|
||||
pform_set_task(tmp2, tmp);
|
||||
{ current_task->set_ports($5);
|
||||
current_task->set_statement($9);
|
||||
pform_pop_scope();
|
||||
current_task = 0;
|
||||
delete $2;
|
||||
}
|
||||
|
||||
|
|
@ -1879,17 +1878,16 @@ module_item
|
|||
instead of the module. */
|
||||
|
||||
| K_function function_range_or_type_opt IDENTIFIER ';'
|
||||
{ pform_push_scope($3); }
|
||||
{ assert(current_function == 0);
|
||||
current_function = pform_push_function_scope($3);
|
||||
}
|
||||
function_item_list statement
|
||||
K_endfunction
|
||||
{ perm_string name = lex_strings.make($3);
|
||||
PFunction *tmp = new PFunction(name);
|
||||
FILE_NAME(tmp, @1);
|
||||
tmp->set_ports($6);
|
||||
tmp->set_statement($7);
|
||||
tmp->set_return($2);
|
||||
pform_set_function(name, tmp);
|
||||
{ current_function->set_ports($6);
|
||||
current_function->set_statement($7);
|
||||
current_function->set_return($2);
|
||||
pform_pop_scope();
|
||||
current_function = 0;
|
||||
delete $3;
|
||||
}
|
||||
|
||||
|
|
@ -2039,8 +2037,9 @@ net_decl_assign
|
|||
: IDENTIFIER '=' expression
|
||||
{ net_decl_assign_t*tmp = new net_decl_assign_t;
|
||||
tmp->next = tmp;
|
||||
tmp->name = $1;
|
||||
tmp->name = lex_strings.make($1);
|
||||
tmp->expr = $3;
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
|
@ -2319,7 +2318,8 @@ port_reference
|
|||
|
||||
: IDENTIFIER
|
||||
{ Module::port_t*ptmp;
|
||||
ptmp = pform_module_port_reference($1, @1.text, @1.first_line);
|
||||
perm_string name = lex_strings.make($1);
|
||||
ptmp = pform_module_port_reference(name, @1.text, @1.first_line);
|
||||
delete $1;
|
||||
$$ = ptmp;
|
||||
}
|
||||
|
|
@ -2530,7 +2530,8 @@ function_range_or_type_opt
|
|||
so that bit ranges can be assigned. */
|
||||
register_variable
|
||||
: IDENTIFIER dimensions_opt
|
||||
{ pform_makewire(@1, $1, NetNet::REG,
|
||||
{ perm_string ident_name = lex_strings.make($1);
|
||||
pform_makewire(@1, ident_name, NetNet::REG,
|
||||
NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
|
||||
if ($2 != 0) {
|
||||
index_component_t index;
|
||||
|
|
@ -2539,19 +2540,19 @@ register_variable
|
|||
"are currently supported.");
|
||||
}
|
||||
index = $2->front();
|
||||
pform_set_reg_idx($1, index.msb, index.lsb);
|
||||
pform_set_reg_idx(ident_name, index.msb, index.lsb);
|
||||
delete $2;
|
||||
}
|
||||
$$ = $1;
|
||||
}
|
||||
| IDENTIFIER '=' expression
|
||||
{ pform_makewire(@1, $1, NetNet::REG,
|
||||
NetNet::NOT_A_PORT,
|
||||
IVL_VT_NO_TYPE, 0);
|
||||
{ perm_string ident_name = lex_strings.make($1);
|
||||
pform_makewire(@1, ident_name, NetNet::REG,
|
||||
NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
|
||||
if (! pform_expression_is_constant($3))
|
||||
yyerror(@3, "error: register declaration assignment"
|
||||
" value must be a constant expression.");
|
||||
pform_make_reginit(@1, $1, $3);
|
||||
pform_make_reginit(@1, ident_name, $3);
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
|
@ -2573,7 +2574,8 @@ register_variable_list
|
|||
|
||||
real_variable
|
||||
: IDENTIFIER dimensions_opt
|
||||
{ pform_makewire(@1, $1, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
|
||||
{ perm_string name = lex_strings.make($1);
|
||||
pform_makewire(@1, name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
|
||||
if ($2 != 0) {
|
||||
yyerror(@2, "sorry: real variables do not currently support arrays.");
|
||||
delete $2;
|
||||
|
|
@ -2581,8 +2583,9 @@ real_variable
|
|||
$$ = $1;
|
||||
}
|
||||
| IDENTIFIER '=' expression
|
||||
{ pform_makewire(@1, $1, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
|
||||
pform_make_reginit(@1, $1, $3);
|
||||
{ perm_string name = lex_strings.make($1);
|
||||
pform_makewire(@1, name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
|
||||
pform_make_reginit(@1, name, $3);
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
|
@ -2604,7 +2607,8 @@ real_variable_list
|
|||
|
||||
net_variable
|
||||
: IDENTIFIER dimensions_opt
|
||||
{ pform_makewire(@1, $1, NetNet::IMPLICIT,
|
||||
{ perm_string name = lex_strings.make($1);
|
||||
pform_makewire(@1, name, NetNet::IMPLICIT,
|
||||
NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
|
||||
if ($2 != 0) {
|
||||
index_component_t index;
|
||||
|
|
@ -2613,12 +2617,13 @@ net_variable
|
|||
"are currently supported.");
|
||||
}
|
||||
index = $2->front();
|
||||
pform_set_reg_idx($1, index.msb, index.lsb);
|
||||
pform_set_reg_idx(name, index.msb, index.lsb);
|
||||
delete $2;
|
||||
}
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
net_variable_list
|
||||
: net_variable
|
||||
{ list<perm_string>*tmp = new list<perm_string>;
|
||||
|
|
@ -2962,19 +2967,24 @@ statement
|
|||
the declarations. The scope is popped at the end of the block. */
|
||||
|
||||
| K_begin statement_list K_end
|
||||
{ PBlock*tmp = new PBlock(PBlock::BL_SEQ, *$2);
|
||||
{ PBlock*tmp = new PBlock(PBlock::BL_SEQ);
|
||||
FILE_NAME(tmp, @1);
|
||||
tmp->set_statement(*$2);
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_begin ':' IDENTIFIER
|
||||
{ pform_push_scope($3); }
|
||||
{ PBlock*tmp = pform_push_block_scope($3, PBlock::BL_SEQ);
|
||||
FILE_NAME(tmp, @1);
|
||||
current_block_stack.push(tmp);
|
||||
}
|
||||
block_item_decls_opt
|
||||
statement_list K_end
|
||||
{ pform_pop_scope();
|
||||
PBlock*tmp = new PBlock(lex_strings.make($3),
|
||||
PBlock::BL_SEQ, *$6);
|
||||
FILE_NAME(tmp, @1);
|
||||
assert(! current_block_stack.empty());
|
||||
PBlock*tmp = current_block_stack.top();
|
||||
current_block_stack.pop();
|
||||
tmp->set_statement(*$6);
|
||||
delete $3;
|
||||
delete $6;
|
||||
$$ = tmp;
|
||||
|
|
@ -2998,13 +3008,17 @@ statement
|
|||
code generator can do the right thing. */
|
||||
|
||||
| K_fork ':' IDENTIFIER
|
||||
{ pform_push_scope($3); }
|
||||
{ PBlock*tmp = pform_push_block_scope($3, PBlock::BL_PAR);
|
||||
FILE_NAME(tmp, @1);
|
||||
current_block_stack.push(tmp);
|
||||
}
|
||||
block_item_decls_opt
|
||||
statement_list K_join
|
||||
{ pform_pop_scope();
|
||||
PBlock*tmp = new PBlock(lex_strings.make($3),
|
||||
PBlock::BL_PAR, *$6);
|
||||
FILE_NAME(tmp, @1);
|
||||
assert(! current_block_stack.empty());
|
||||
PBlock*tmp = current_block_stack.top();
|
||||
current_block_stack.pop();
|
||||
tmp->set_statement(*$6);
|
||||
delete $3;
|
||||
delete $6;
|
||||
$$ = tmp;
|
||||
|
|
@ -3039,8 +3053,9 @@ statement
|
|||
$$ = tmp;
|
||||
}
|
||||
| K_fork statement_list K_join
|
||||
{ PBlock*tmp = new PBlock(PBlock::BL_PAR, *$2);
|
||||
{ PBlock*tmp = new PBlock(PBlock::BL_PAR);
|
||||
FILE_NAME(tmp, @1);
|
||||
tmp->set_statement(*$2);
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
@ -3672,8 +3687,7 @@ udp_port_decl
|
|||
: K_input list_of_identifiers ';'
|
||||
{ $$ = pform_make_udp_input_ports($2); }
|
||||
| K_output IDENTIFIER ';'
|
||||
{ pform_name_t pname;
|
||||
pname.push_back(name_component_t(lex_strings.make($2)));
|
||||
{ perm_string pname = 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;
|
||||
|
|
@ -3681,8 +3695,7 @@ udp_port_decl
|
|||
delete $2;
|
||||
}
|
||||
| K_reg IDENTIFIER ';'
|
||||
{ pform_name_t pname;
|
||||
pname.push_back(name_component_t(lex_strings.make($2)));
|
||||
{ perm_string pname = 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;
|
||||
|
|
@ -3690,8 +3703,7 @@ udp_port_decl
|
|||
delete $2;
|
||||
}
|
||||
| K_reg K_output IDENTIFIER ';'
|
||||
{ pform_name_t pname;
|
||||
pname.push_back(name_component_t(lex_strings.make($3)));
|
||||
{ perm_string pname = 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;
|
||||
|
|
@ -3713,14 +3725,14 @@ udp_port_decls
|
|||
|
||||
udp_port_list
|
||||
: IDENTIFIER
|
||||
{ list<string>*tmp = new list<string>;
|
||||
tmp->push_back($1);
|
||||
{ list<perm_string>*tmp = new list<perm_string>;
|
||||
tmp->push_back(lex_strings.make($1));
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| udp_port_list ',' IDENTIFIER
|
||||
{ list<string>*tmp = $1;
|
||||
tmp->push_back($3);
|
||||
{ list<perm_string>*tmp = $1;
|
||||
tmp->push_back(lex_strings.make($3));
|
||||
delete $3;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
|
|||
230
pform.cc
230
pform.cc
|
|
@ -38,6 +38,7 @@
|
|||
|
||||
# include "ivl_assert.h"
|
||||
|
||||
|
||||
map<perm_string,Module*> pform_modules;
|
||||
map<perm_string,PUdp*> pform_primitives;
|
||||
|
||||
|
|
@ -88,40 +89,55 @@ static inline void FILE_NAME(LineInfo*tmp, const struct vlltype&where)
|
|||
}
|
||||
|
||||
/*
|
||||
* The scope stack and the following functions handle the processing
|
||||
* of scope. As I enter a scope, the push function is called, and as I
|
||||
* leave a scope the pop function is called. Entering tasks, functions
|
||||
* and named blocks causes scope to be pushed and popped. The module
|
||||
* name is not included in this scope stack.
|
||||
* The lexical_scope keeps track of the current lexical scope that is
|
||||
* being parsed. The lexical scope may stack, so the current scope may
|
||||
* have a parent, that is restored when the current scope ends.
|
||||
*
|
||||
* 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.
|
||||
* Items that have scoped names are put in the lexical_scope object.
|
||||
*/
|
||||
|
||||
static pform_name_t scope_stack;
|
||||
|
||||
void pform_push_scope(char*name)
|
||||
{
|
||||
scope_stack.push_back(name_component_t(lex_strings.make(name)));
|
||||
}
|
||||
static PScope* lexical_scope = 0;
|
||||
|
||||
void pform_pop_scope()
|
||||
{
|
||||
scope_stack.pop_back();
|
||||
lexical_scope = lexical_scope->pscope_parent();
|
||||
}
|
||||
|
||||
static pform_name_t hier_name(const char*tail)
|
||||
PTask* pform_push_task_scope(char*name)
|
||||
{
|
||||
pform_name_t name = scope_stack;
|
||||
name.push_back(name_component_t(lex_strings.make(tail)));
|
||||
return name;
|
||||
perm_string task_name = lex_strings.make(name);
|
||||
PTask*task = new PTask(task_name, pform_cur_module);
|
||||
|
||||
// Add the task to the current module
|
||||
pform_cur_module->add_task(task->pscope_name(), task);
|
||||
// Make this the current lexical scope
|
||||
lexical_scope = task;
|
||||
return task;
|
||||
}
|
||||
|
||||
static PWire*get_wire_in_module(const pform_name_t&name)
|
||||
PFunction* pform_push_function_scope(char*name)
|
||||
{
|
||||
perm_string func_name = lex_strings.make(name);
|
||||
PFunction*func = new PFunction(func_name, lexical_scope);
|
||||
|
||||
// Add the task to the current module
|
||||
pform_cur_module->add_function(func->pscope_name(), func);
|
||||
// Make this the current lexical scope
|
||||
lexical_scope = func;
|
||||
return func;
|
||||
}
|
||||
|
||||
PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
|
||||
{
|
||||
perm_string block_name = lex_strings.make(name);
|
||||
PBlock*block = new PBlock(block_name, lexical_scope, bt);
|
||||
|
||||
// Make this the current lexical scope
|
||||
lexical_scope = block;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
static PWire*get_wire_in_scope(perm_string name)
|
||||
{
|
||||
/* Note that if we are processing a generate, then the
|
||||
scope depth will be empty because generate schemes
|
||||
|
|
@ -130,7 +146,7 @@ static PWire*get_wire_in_module(const pform_name_t&name)
|
|||
if (pform_cur_generate)
|
||||
return pform_cur_generate->get_wire(name);
|
||||
|
||||
return pform_cur_module->get_wire(name);
|
||||
return lexical_scope->wires_find(name);
|
||||
}
|
||||
|
||||
void pform_set_default_nettype(NetNet::Type type,
|
||||
|
|
@ -259,6 +275,9 @@ void pform_startmodule(const char*name, const char*file, unsigned lineno,
|
|||
FILE_NAME(pform_cur_module, file, lineno);
|
||||
pform_cur_module->library_flag = pform_library_flag;
|
||||
|
||||
ivl_assert(*pform_cur_module, lexical_scope == 0);
|
||||
lexical_scope = pform_cur_module;
|
||||
|
||||
/* The generate scheme numbering starts with *1*, not
|
||||
zero. That's just the way it is, thanks to the standard. */
|
||||
scope_generate_counter = 1;
|
||||
|
|
@ -285,14 +304,14 @@ void pform_startmodule(const char*name, const char*file, unsigned lineno,
|
|||
* reference. This is a name without a .X(...), so the internal name
|
||||
* should be generated to be the same as the X.
|
||||
*/
|
||||
Module::port_t* pform_module_port_reference(char*name,
|
||||
Module::port_t* pform_module_port_reference(perm_string name,
|
||||
const char*file,
|
||||
unsigned lineno)
|
||||
{
|
||||
Module::port_t*ptmp = new Module::port_t;
|
||||
PEIdent*tmp = new PEIdent(lex_strings.make(name));
|
||||
PEIdent*tmp = new PEIdent(name);
|
||||
FILE_NAME(tmp, file, lineno);
|
||||
ptmp->name = lex_strings.make(name);
|
||||
ptmp->name = name;
|
||||
ptmp->expr = svector<PEIdent*>(1);
|
||||
ptmp->expr[0] = tmp;
|
||||
|
||||
|
|
@ -334,6 +353,13 @@ void pform_endmodule(const char*name)
|
|||
pform_cur_module = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// The current lexical scope should be this module by now, and
|
||||
// this module should not have a parent lexical scope.
|
||||
ivl_assert(*pform_cur_module, lexical_scope == pform_cur_module);
|
||||
lexical_scope = pform_cur_module->pscope_parent();
|
||||
ivl_assert(*pform_cur_module, lexical_scope == 0);
|
||||
|
||||
pform_modules[mod_name] = pform_cur_module;
|
||||
pform_cur_module = 0;
|
||||
}
|
||||
|
|
@ -545,6 +571,11 @@ PExpr* pform_select_mtm_expr(PExpr*min, PExpr*typ, PExpr*max)
|
|||
return res;
|
||||
}
|
||||
|
||||
template <> inline svector<perm_string>::svector(unsigned size)
|
||||
: nitems_(size), items_(new perm_string[size])
|
||||
{
|
||||
}
|
||||
|
||||
static void process_udp_table(PUdp*udp, list<string>*table,
|
||||
const char*file, unsigned lineno)
|
||||
{
|
||||
|
|
@ -612,7 +643,7 @@ static void process_udp_table(PUdp*udp, list<string>*table,
|
|||
udp->toutput = output;
|
||||
}
|
||||
|
||||
void pform_make_udp(perm_string name, list<string>*parms,
|
||||
void pform_make_udp(perm_string name, list<perm_string>*parms,
|
||||
svector<PWire*>*decl, list<string>*table,
|
||||
Statement*init_expr,
|
||||
const char*file, unsigned lineno)
|
||||
|
|
@ -624,11 +655,10 @@ void pform_make_udp(perm_string name, list<string>*parms,
|
|||
off with the parameters in the list. If the port is already
|
||||
in the map, merge the port type. I will rebuild a list
|
||||
of parameters for the PUdp object. */
|
||||
map<string,PWire*> defs;
|
||||
map<perm_string,PWire*> defs;
|
||||
for (unsigned idx = 0 ; idx < decl->count() ; idx += 1) {
|
||||
|
||||
pform_name_t pname = (*decl)[idx]->path();
|
||||
string port_name = peek_tail_name(pname).str();
|
||||
perm_string port_name = (*decl)[idx]->basename();
|
||||
|
||||
if (PWire*cur = defs[port_name]) {
|
||||
bool rc = true;
|
||||
|
|
@ -654,8 +684,8 @@ void pform_make_udp(perm_string name, list<string>*parms,
|
|||
UDP declaration, and the defs map maps that name to a
|
||||
PWire* created by an input or output declaration. */
|
||||
svector<PWire*> pins (parms->size());
|
||||
svector<string> pin_names (parms->size());
|
||||
{ list<string>::iterator cur;
|
||||
svector<perm_string> pin_names (parms->size());
|
||||
{ list<perm_string>::iterator cur;
|
||||
unsigned idx;
|
||||
for (cur = parms->begin(), idx = 0
|
||||
; cur != parms->end()
|
||||
|
|
@ -789,7 +819,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] = peek_tail_name(pins[idx]->path());
|
||||
udp->ports[idx] = pins[idx]->basename();
|
||||
|
||||
process_udp_table(udp, table, file, lineno);
|
||||
udp->initial = init;
|
||||
|
|
@ -814,10 +844,9 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
|
|||
svector<PWire*> pins(parms->size() + 1);
|
||||
|
||||
/* Make the PWire for the output port. */
|
||||
pins[0] = new PWire(hier_name(out_name),
|
||||
pins[0] = new PWire(out_name,
|
||||
synchronous_flag? NetNet::REG : NetNet::WIRE,
|
||||
NetNet::POUTPUT,
|
||||
IVL_VT_LOGIC);
|
||||
NetNet::POUTPUT, IVL_VT_LOGIC);
|
||||
FILE_NAME(pins[0], file, lineno);
|
||||
|
||||
/* Make the PWire objects for the input ports. */
|
||||
|
|
@ -827,10 +856,8 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
|
|||
; cur != parms->end()
|
||||
; idx += 1, cur++) {
|
||||
assert(idx < pins.count());
|
||||
pins[idx] = new PWire(hier_name(*cur),
|
||||
NetNet::WIRE,
|
||||
NetNet::PINPUT,
|
||||
IVL_VT_LOGIC);
|
||||
pins[idx] = new PWire(*cur, NetNet::WIRE,
|
||||
NetNet::PINPUT, IVL_VT_LOGIC);
|
||||
FILE_NAME(pins[idx], file, lineno);
|
||||
}
|
||||
assert(idx == pins.count());
|
||||
|
|
@ -871,7 +898,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] = peek_tail_name(pins[idx]->path());
|
||||
udp->ports[idx] = pins[idx]->basename();
|
||||
|
||||
assert(udp);
|
||||
assert(table);
|
||||
|
|
@ -886,39 +913,18 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
|
|||
delete init_expr;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is used to set the net range for a port that uses
|
||||
* the new (1364-2001) list_of_port_declarations, but omitted a
|
||||
* register/wire/etc. that would have triggered it to be set elsewhere.
|
||||
*/
|
||||
/*
|
||||
* Since implicitly defined list of port declarations are no longer
|
||||
* considered fully defined we no longer need this routine to force
|
||||
* them to be fully defined.
|
||||
*
|
||||
void pform_set_net_range(const char* name)
|
||||
{
|
||||
PWire*cur = get_wire_in_module(hier_name(name));
|
||||
if (cur == 0) {
|
||||
VLerror("error: name is not a valid net.");
|
||||
return;
|
||||
}
|
||||
cur->set_net_range();
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* This function attaches a range to a given name. The function is
|
||||
* only called by the parser within the scope of the net declaration,
|
||||
* and the name that I receive only has the tail component.
|
||||
*/
|
||||
static void pform_set_net_range(const char* name,
|
||||
static void pform_set_net_range(perm_string name,
|
||||
const svector<PExpr*>*range,
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t dt,
|
||||
PWSRType rt)
|
||||
{
|
||||
PWire*cur = get_wire_in_module(hier_name(name));
|
||||
PWire*cur = get_wire_in_scope(name);
|
||||
if (cur == 0) {
|
||||
VLerror("error: name is not a valid net.");
|
||||
return;
|
||||
|
|
@ -1233,17 +1239,16 @@ void pform_make_pgassign_list(svector<PExpr*>*alist,
|
|||
* BTF-B14.
|
||||
*/
|
||||
void pform_make_reginit(const struct vlltype&li,
|
||||
const char*name, PExpr*expr)
|
||||
perm_string name, PExpr*expr)
|
||||
{
|
||||
const pform_name_t sname = hier_name(name);
|
||||
PWire*cur = pform_cur_module->get_wire(sname);
|
||||
PWire*cur = lexical_scope->wires_find(name);
|
||||
if (cur == 0) {
|
||||
VLerror(li, "internal error: reginit to non-register?");
|
||||
delete expr;
|
||||
return;
|
||||
}
|
||||
|
||||
PEIdent*lval = new PEIdent(sname);
|
||||
PEIdent*lval = new PEIdent(name);
|
||||
FILE_NAME(lval, li);
|
||||
PAssign*ass = new PAssign(lval, expr);
|
||||
FILE_NAME(ass, li);
|
||||
|
|
@ -1264,18 +1269,17 @@ void pform_make_reginit(const struct vlltype&li,
|
|||
* as is done for the old method.
|
||||
*/
|
||||
void pform_module_define_port(const struct vlltype&li,
|
||||
const char*nm,
|
||||
perm_string name,
|
||||
NetNet::PortType port_type,
|
||||
NetNet::Type type,
|
||||
bool signed_flag,
|
||||
svector<PExpr*>*range,
|
||||
svector<named_pexpr_t*>*attr)
|
||||
{
|
||||
pform_name_t name = hier_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
PWire*cur = lexical_scope->wires_find(name);
|
||||
if (cur) {
|
||||
ostringstream msg;
|
||||
msg << nm << " definition conflicts with "
|
||||
msg << name << " definition conflicts with "
|
||||
<< "definition at " << cur->get_fileline()
|
||||
<< ".";
|
||||
VLerror(msg.str().c_str());
|
||||
|
|
@ -1306,7 +1310,7 @@ void pform_module_define_port(const struct vlltype&li,
|
|||
cur->attributes[tmp->name] = tmp->parm;
|
||||
}
|
||||
}
|
||||
pform_cur_module->add_wire(cur);
|
||||
lexical_scope->wires[name] = cur;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1334,14 +1338,12 @@ void pform_module_define_port(const struct vlltype&li,
|
|||
* the variable/net. Other forms of pform_makewire ultimately call
|
||||
* this one to create the wire and stash it.
|
||||
*/
|
||||
void pform_makewire(const vlltype&li, const char*nm,
|
||||
void pform_makewire(const vlltype&li, perm_string name,
|
||||
NetNet::Type type, NetNet::PortType pt,
|
||||
ivl_variable_type_t dt,
|
||||
svector<named_pexpr_t*>*attr)
|
||||
{
|
||||
pform_name_t name = hier_name(nm);
|
||||
|
||||
PWire*cur = get_wire_in_module(name);
|
||||
PWire*cur = get_wire_in_scope(name);
|
||||
|
||||
// If this is not implicit ("implicit" meaning we don't know
|
||||
// what the type is yet) then set the type now.
|
||||
|
|
@ -1349,7 +1351,7 @@ void pform_makewire(const vlltype&li, const char*nm,
|
|||
bool rc = cur->set_wire_type(type);
|
||||
if (rc == false) {
|
||||
ostringstream msg;
|
||||
msg << nm << " definition conflicts with "
|
||||
msg << name << " definition conflicts with "
|
||||
<< "definition at " << cur->get_fileline()
|
||||
<< ".";
|
||||
VLerror(msg.str().c_str());
|
||||
|
|
@ -1393,9 +1395,9 @@ void pform_makewire(const vlltype&li, const char*nm,
|
|||
|
||||
if (new_wire_flag) {
|
||||
if (pform_cur_generate)
|
||||
pform_cur_generate->add_wire(cur);
|
||||
pform_cur_generate->wires[name] = cur;
|
||||
else
|
||||
pform_cur_module->add_wire(cur);
|
||||
lexical_scope->wires[name] = cur;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1455,32 +1457,28 @@ void pform_makewire(const vlltype&li,
|
|||
SR_NET);
|
||||
}
|
||||
|
||||
perm_string first_name = lex_strings.make(first->name);
|
||||
pform_name_t name = hier_name(first_name);
|
||||
PWire*cur = get_wire_in_module(name);
|
||||
PWire*cur = get_wire_in_scope(first->name);
|
||||
if (cur != 0) {
|
||||
PEIdent*lval = new PEIdent(first_name);
|
||||
PEIdent*lval = new PEIdent(first->name);
|
||||
FILE_NAME(lval, li.text, li.first_line);
|
||||
PGAssign*ass = pform_make_pgassign(lval, first->expr,
|
||||
delay, str);
|
||||
FILE_NAME(ass, li.text, li.first_line);
|
||||
}
|
||||
|
||||
free(first->name);
|
||||
delete first;
|
||||
first = next;
|
||||
}
|
||||
}
|
||||
|
||||
void pform_set_port_type(perm_string nm, NetNet::PortType pt,
|
||||
void pform_set_port_type(perm_string name, NetNet::PortType pt,
|
||||
const char*file, unsigned lineno)
|
||||
{
|
||||
pform_name_t name = hier_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
PWire*cur = lexical_scope->wires_find(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_NO_TYPE);
|
||||
FILE_NAME(cur, file, lineno);
|
||||
pform_cur_module->add_wire(cur);
|
||||
lexical_scope->wires[name] = cur;
|
||||
}
|
||||
|
||||
switch (cur->get_port_type()) {
|
||||
|
|
@ -1491,14 +1489,14 @@ void pform_set_port_type(perm_string nm, NetNet::PortType pt,
|
|||
|
||||
case NetNet::NOT_A_PORT:
|
||||
cerr << file << ":" << lineno << ": error: "
|
||||
<< "port " << nm << " is not in the port list."
|
||||
<< "port " << name << " is not in the port list."
|
||||
<< endl;
|
||||
error_count += 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << file << ":" << lineno << ": error: "
|
||||
<< "port " << nm << " already has a port declaration."
|
||||
<< "port " << name << " already has a port declaration."
|
||||
<< endl;
|
||||
error_count += 1;
|
||||
break;
|
||||
|
|
@ -1558,18 +1556,17 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
|||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; cur ++ ) {
|
||||
|
||||
perm_string txt = *cur;
|
||||
pform_name_t name = hier_name(txt);
|
||||
perm_string name = *cur;
|
||||
|
||||
/* Look for a preexisting wire. If it exists, set the
|
||||
port direction. If not, create it. */
|
||||
PWire*curw = pform_cur_module->get_wire(name);
|
||||
PWire*curw = lexical_scope->wires_find(name);
|
||||
if (curw) {
|
||||
curw->set_port_type(pt);
|
||||
} else {
|
||||
curw = new PWire(name, NetNet::IMPLICIT_REG, pt, vtype);
|
||||
FILE_NAME(curw, file, lineno);
|
||||
pform_cur_module->add_wire(curw);
|
||||
lexical_scope->wires[name] = curw;
|
||||
}
|
||||
|
||||
curw->set_signed(signed_flag);
|
||||
|
|
@ -1590,22 +1587,9 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
|||
return res;
|
||||
}
|
||||
|
||||
void pform_set_task(perm_string name, PTask*task)
|
||||
{
|
||||
pform_cur_module->add_task(name, task);
|
||||
}
|
||||
|
||||
|
||||
void pform_set_function(perm_string name, PFunction*func)
|
||||
{
|
||||
pform_cur_module->add_function(name, func);
|
||||
}
|
||||
|
||||
void pform_set_attrib(perm_string name, perm_string key, char*value)
|
||||
{
|
||||
pform_name_t path = hier_name(name);
|
||||
|
||||
if (PWire*cur = pform_cur_module->get_wire(path)) {
|
||||
if (PWire*cur = lexical_scope->wires_find(name)) {
|
||||
cur->attributes[key] = new PEString(value);
|
||||
|
||||
} else if (PGate*cur = pform_cur_module->get_gate(name)) {
|
||||
|
|
@ -1639,13 +1623,13 @@ void pform_set_type_attrib(perm_string name, const string&key,
|
|||
* This function attaches a memory index range to an existing
|
||||
* register. (The named wire must be a register.
|
||||
*/
|
||||
void pform_set_reg_idx(const char*name, PExpr*l, PExpr*r)
|
||||
void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r)
|
||||
{
|
||||
PWire*cur = 0;
|
||||
if (pform_cur_generate) {
|
||||
cur = pform_cur_generate->get_wire(hier_name(name));
|
||||
cur = pform_cur_generate->get_wire(name);
|
||||
} else {
|
||||
cur = pform_cur_module->get_wire(hier_name(name));
|
||||
cur = lexical_scope->wires_find(name);
|
||||
}
|
||||
if (cur == 0) {
|
||||
VLerror("internal error: name is not a valid memory for index.");
|
||||
|
|
@ -1792,16 +1776,15 @@ void pform_set_port_type(const struct vlltype&li,
|
|||
delete range;
|
||||
}
|
||||
|
||||
static void pform_set_reg_integer(const char*nm)
|
||||
static void pform_set_reg_integer(perm_string name)
|
||||
{
|
||||
pform_name_t name = hier_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
PWire*cur = lexical_scope->wires_find(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::INTEGER,
|
||||
NetNet::NOT_A_PORT,
|
||||
IVL_VT_LOGIC);
|
||||
cur->set_signed(true);
|
||||
pform_cur_module->add_wire(cur);
|
||||
lexical_scope->wires[name] = cur;
|
||||
} else {
|
||||
bool rc = cur->set_wire_type(NetNet::INTEGER);
|
||||
assert(rc);
|
||||
|
|
@ -1827,13 +1810,12 @@ void pform_set_reg_integer(list<perm_string>*names)
|
|||
delete names;
|
||||
}
|
||||
|
||||
static void pform_set_reg_time(const char*nm)
|
||||
static void pform_set_reg_time(perm_string name)
|
||||
{
|
||||
pform_name_t name = hier_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
PWire*cur = lexical_scope->wires_find(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
|
||||
pform_cur_module->add_wire(cur);
|
||||
lexical_scope->wires[name] = cur;
|
||||
} else {
|
||||
bool rc = cur->set_wire_type(NetNet::REG);
|
||||
assert(rc);
|
||||
|
|
@ -1867,9 +1849,7 @@ svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
|
|||
; cur != names->end()
|
||||
; cur ++ ) {
|
||||
perm_string txt = *cur;
|
||||
pform_name_t tmp;
|
||||
tmp.push_back(name_component_t(txt));
|
||||
PWire*pp = new PWire(tmp,
|
||||
PWire*pp = new PWire(txt,
|
||||
NetNet::IMPLICIT,
|
||||
NetNet::PINPUT,
|
||||
IVL_VT_LOGIC);
|
||||
|
|
|
|||
22
pform.h
22
pform.h
|
|
@ -95,7 +95,7 @@ struct parmvalue_t {
|
|||
struct str_pair_t { PGate::strength_t str0, str1; };
|
||||
|
||||
struct net_decl_assign_t {
|
||||
char*name;
|
||||
perm_string name;
|
||||
PExpr*expr;
|
||||
struct net_decl_assign_t*next;
|
||||
};
|
||||
|
|
@ -138,19 +138,19 @@ extern void pform_module_set_ports(svector<Module::port_t*>*);
|
|||
port_definition_list. In this case, we have everything needed to
|
||||
define the port, all in one place. */
|
||||
extern void pform_module_define_port(const struct vlltype&li,
|
||||
const char*name,
|
||||
perm_string name,
|
||||
NetNet::PortType,
|
||||
NetNet::Type type,
|
||||
bool signed_flag,
|
||||
svector<PExpr*>*range,
|
||||
svector<named_pexpr_t*>*attr);
|
||||
|
||||
extern Module::port_t* pform_module_port_reference(char*name,
|
||||
extern Module::port_t* pform_module_port_reference(perm_string name,
|
||||
const char*file,
|
||||
unsigned lineno);
|
||||
extern void pform_endmodule(const char*);
|
||||
|
||||
extern void pform_make_udp(perm_string name, list<string>*parms,
|
||||
extern void pform_make_udp(perm_string name, list<perm_string>*parms,
|
||||
svector<PWire*>*decl, list<string>*table,
|
||||
Statement*init,
|
||||
const char*file, unsigned lineno);
|
||||
|
|
@ -167,9 +167,12 @@ extern void pform_make_udp(perm_string name,
|
|||
* name string onto the scope hierarchy. The pop pulls it off and
|
||||
* deletes it. Thus, the string pushed must be allocated.
|
||||
*/
|
||||
extern void pform_push_scope(char*name);
|
||||
extern void pform_pop_scope();
|
||||
|
||||
extern PTask*pform_push_task_scope(char*name);
|
||||
extern PFunction*pform_push_function_scope(char*name);
|
||||
extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt);
|
||||
|
||||
|
||||
extern verinum* pform_verinum_with_size(verinum*s, verinum*val,
|
||||
const char*file, unsigned loneno);
|
||||
|
|
@ -198,7 +201,7 @@ extern void pform_endgenerate();
|
|||
* The makewire functions announce to the pform code new wires. These
|
||||
* go into a module that is currently opened.
|
||||
*/
|
||||
extern void pform_makewire(const struct vlltype&li, const char*name,
|
||||
extern void pform_makewire(const struct vlltype&li, perm_string name,
|
||||
NetNet::Type type,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t,
|
||||
|
|
@ -226,7 +229,7 @@ extern void pform_makewire(const struct vlltype&li,
|
|||
ivl_variable_type_t);
|
||||
|
||||
extern void pform_make_reginit(const struct vlltype&li,
|
||||
const char*name, PExpr*expr);
|
||||
perm_string name, PExpr*expr);
|
||||
|
||||
/* Look up the names of the wires, and set the port type,
|
||||
i.e. input, output or inout. If the wire does not exist, create
|
||||
|
|
@ -239,17 +242,14 @@ extern void pform_set_port_type(const struct vlltype&li,
|
|||
extern void pform_set_port_type(perm_string nm, NetNet::PortType pt,
|
||||
const char*file, unsigned lineno);
|
||||
|
||||
extern void pform_set_net_range(const char* name);
|
||||
extern void pform_set_net_range(list<perm_string>*names,
|
||||
svector<PExpr*>*,
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t,
|
||||
PWSRType rt = SR_NET);
|
||||
extern void pform_set_reg_idx(const char*name, PExpr*l, PExpr*r);
|
||||
extern void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r);
|
||||
extern void pform_set_reg_integer(list<perm_string>*names);
|
||||
extern void pform_set_reg_time(list<perm_string>*names);
|
||||
extern void pform_set_task(perm_string name, PTask*);
|
||||
extern void pform_set_function(perm_string name, PFunction*);
|
||||
|
||||
/* pform_set_attrib and pform_set_type_attrib exist to support the
|
||||
$attribute syntax, which can only set string values to
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ void PWire::dump(ostream&out, unsigned ind) const
|
|||
}
|
||||
}
|
||||
|
||||
out << " " << hname_;
|
||||
out << " " << name_;
|
||||
|
||||
// If the wire has indices, dump them.
|
||||
if (lidx_ || ridx_) {
|
||||
|
|
@ -504,10 +504,13 @@ void PAssignNB::dump(ostream&out, unsigned ind) const
|
|||
void PBlock::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "" << "begin";
|
||||
if (name_ != 0)
|
||||
out << " : " << name_;
|
||||
if (pscope_name() != 0)
|
||||
out << " : " << pscope_name();
|
||||
out << endl;
|
||||
|
||||
if (pscope_name() != 0)
|
||||
dump_wires_(out, ind+2);
|
||||
|
||||
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1) {
|
||||
if (list_[idx])
|
||||
list_[idx]->dump(out, ind+2);
|
||||
|
|
@ -697,15 +700,17 @@ void PFunction::dump(ostream&out, unsigned ind) const
|
|||
out << "] ";
|
||||
}
|
||||
|
||||
out << name_ << ";" << endl;
|
||||
out << pscope_name() << ";" << endl;
|
||||
|
||||
if (ports_)
|
||||
for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) {
|
||||
out << setw(ind) << "";
|
||||
out << "input ";
|
||||
out << (*ports_)[idx]->path() << ";" << endl;
|
||||
out << (*ports_)[idx]->basename() << ";" << endl;
|
||||
}
|
||||
|
||||
dump_wires_(out, ind);
|
||||
|
||||
if (statement_)
|
||||
statement_->dump(out, ind);
|
||||
else
|
||||
|
|
@ -743,9 +748,11 @@ void PTask::dump(ostream&out, unsigned ind) const
|
|||
assert(0);
|
||||
break;
|
||||
}
|
||||
out << (*ports_)[idx]->path() << ";" << endl;
|
||||
out << (*ports_)[idx]->basename() << ";" << endl;
|
||||
}
|
||||
|
||||
dump_wires_(out, ind);
|
||||
|
||||
if (statement_)
|
||||
statement_->dump(out, ind);
|
||||
else
|
||||
|
|
@ -870,7 +877,7 @@ void PGenerate::dump(ostream&out, unsigned indent) const
|
|||
|
||||
out << endl;
|
||||
|
||||
for (map<pform_name_t,PWire*>::const_iterator idx = wires.begin()
|
||||
for (map<perm_string,PWire*>::const_iterator idx = wires.begin()
|
||||
; idx != wires.end() ; idx++) {
|
||||
|
||||
(*idx).second->dump(out, indent+2);
|
||||
|
|
@ -894,6 +901,16 @@ void PGenerate::dump(ostream&out, unsigned indent) const
|
|||
out << setw(indent) << "" << "endgenerate" << endl;
|
||||
}
|
||||
|
||||
void PScope::dump_wires_(ostream&out, unsigned indent) const
|
||||
{
|
||||
// Iterate through and display all the wires.
|
||||
for (map<perm_string,PWire*>::const_iterator wire = wires.begin()
|
||||
; wire != wires.end() ; wire ++ ) {
|
||||
|
||||
(*wire).second->dump(out, indent);
|
||||
}
|
||||
}
|
||||
|
||||
void Module::dump(ostream&out) const
|
||||
{
|
||||
if (attributes.begin() != attributes.end()) {
|
||||
|
|
@ -911,7 +928,7 @@ void Module::dump(ostream&out) const
|
|||
out << " *) ";
|
||||
}
|
||||
|
||||
out << "module " << name_ << ";" << endl;
|
||||
out << "module " << mod_name() << ";" << endl;
|
||||
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
port_t*cur = ports[idx];
|
||||
|
|
@ -995,12 +1012,7 @@ void Module::dump(ostream&out) const
|
|||
}
|
||||
|
||||
// Iterate through and display all the wires.
|
||||
for (map<pform_name_t,PWire*>::const_iterator wire = wires_.begin()
|
||||
; wire != wires_.end()
|
||||
; wire ++ ) {
|
||||
|
||||
(*wire).second->dump(out);
|
||||
}
|
||||
dump_wires_(out, 4);
|
||||
|
||||
// Dump the task definitions.
|
||||
typedef map<perm_string,PTask*>::const_iterator task_iter_t;
|
||||
|
|
|
|||
Loading…
Reference in New Issue