Rework handling of lexical scope

Move the storage of wires (signals) out of the Module class into
the PScope base class, and instead of putting the PWires all into
the Module object, distribute them into the various lexical scopes
(derived from PScope) so that the wire names do not need to carry
scope information.

This required some rewiring of elaboration of signals, and rewriting
of lexical scope handling.
This commit is contained in:
Stephen Williams 2008-02-24 19:40:54 -08:00
parent b0e4a6884a
commit 8e704cbf93
18 changed files with 551 additions and 581 deletions

View File

@ -54,16 +54,6 @@ void Module::add_function(perm_string name, PFunction *func)
funcs_[name] = 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) void Module::add_behavior(PProcess*b)
{ {
behaviors_.push_back(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) PGate* Module::get_gate(perm_string name)
{ {
for (list<PGate*>::iterator cur = gates_.begin() for (list<PGate*>::iterator cur = gates_.begin()

View File

@ -1,7 +1,7 @@
#ifndef __Module_H #ifndef __Module_H
#define __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 * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -18,9 +18,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT
#ident "$Id: Module.h,v 1.43 2007/05/24 04:07:11 steve Exp $"
#endif
# include <list> # include <list>
# include <map> # include <map>
@ -133,12 +131,6 @@ class Module : public PScope, public LineInfo {
perm_string mod_name() const { return pscope_name(); } perm_string mod_name() const { return pscope_name(); }
void add_gate(PGate*gate); 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_behavior(PProcess*behave);
void add_task(perm_string name, PTask*def); void add_task(perm_string name, PTask*def);
void add_function(perm_string name, PFunction*def); void add_function(perm_string name, PFunction*def);
@ -147,9 +139,6 @@ class Module : public PScope, public LineInfo {
const svector<PEIdent*>& get_port(unsigned idx) const; const svector<PEIdent*>& get_port(unsigned idx) const;
unsigned find_port(const char*name) 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); PGate* get_gate(perm_string name);
const list<PGate*>& get_gates() const; const list<PGate*>& get_gates() const;
@ -164,7 +153,6 @@ class Module : public PScope, public LineInfo {
bool elaborate_sig(Design*, NetScope*scope) const; bool elaborate_sig(Design*, NetScope*scope) const;
private: private:
map<pform_name_t,PWire*> wires_;
list<PGate*> gates_; list<PGate*> gates_;
list<PProcess*> behaviors_; list<PProcess*> behaviors_;
map<perm_string,PTask*> tasks_; map<perm_string,PTask*> tasks_;
@ -178,26 +166,4 @@ class Module : public PScope, public LineInfo {
Module& operator= (const Module&); 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 #endif

View File

@ -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()]; map<perm_string,PWire*>::const_iterator obj = wires.find(name);
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);
if (obj == wires.end()) if (obj == wires.end())
return 0; return 0;
else else

View File

@ -71,9 +71,8 @@ class PGenerate : public LineInfo {
PExpr*loop_test; PExpr*loop_test;
PExpr*loop_step; PExpr*loop_step;
map<pform_name_t,PWire*>wires; map<perm_string,PWire*>wires;
PWire* add_wire(PWire*); PWire* get_wire(perm_string name) const;
PWire* get_wire(const pform_name_t&name) const;
list<PGate*> gates; list<PGate*> gates;
void add_gate(PGate*); void add_gate(PGate*);

View File

@ -27,3 +27,12 @@ PScope::PScope(perm_string n, PScope*p)
PScope::~PScope() 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;
}

View File

@ -24,6 +24,10 @@
# include <map> # include <map>
class PEvent; class PEvent;
class PWire;
class Design;
class NetScope;
/* /*
* The PScope class is a base representation of an object that * The PScope class is a base representation of an object that
@ -50,9 +54,18 @@ class PScope {
perm_string pscope_name() const { return name_; } perm_string pscope_name() const { return name_; }
PScope* pscope_parent() { return parent_; } 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. // Named events in the scope.
map<perm_string,PEvent*>events; map<perm_string,PEvent*>events;
protected:
void dump_wires_(ostream&out, unsigned indent) const;
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
private: private:
perm_string name_; perm_string name_;
PScope*parent_; PScope*parent_;

View File

@ -22,11 +22,11 @@
# include "PExpr.h" # include "PExpr.h"
# include <assert.h> # include <assert.h>
PWire::PWire(const pform_name_t&n, PWire::PWire(perm_string n,
NetNet::Type t, NetNet::Type t,
NetNet::PortType pt, NetNet::PortType pt,
ivl_variable_type_t dt) ivl_variable_type_t dt)
: hname_(n), type_(t), port_type_(pt), data_type_(dt), : name_(n), type_(t), port_type_(pt), data_type_(dt),
signed_(false), isint_(false), signed_(false), isint_(false),
port_msb_(0), port_lsb_(0), port_set_(false), port_msb_(0), port_lsb_(0), port_set_(false),
net_msb_(0), net_lsb_(0), net_set_(false), error_cnt_(0), 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_; 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) bool PWire::set_wire_type(NetNet::Type t)
@ -153,7 +153,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
switch (type) { switch (type) {
case SR_PORT: case SR_PORT:
if (port_set_) { if (port_set_) {
cerr << get_fileline() << ": error: Port ``" << hname_ cerr << get_fileline() << ": error: Port ``" << name_
<< "'' has already been declared a port." << endl; << "'' has already been declared a port." << endl;
error_cnt_ += 1; error_cnt_ += 1;
} else { } else {
@ -165,7 +165,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
case SR_NET: case SR_NET:
if (net_set_) { if (net_set_) {
cerr << get_fileline() << ": error: Net ``" << hname_ cerr << get_fileline() << ": error: Net ``" << name_
<< "'' has already been declared." << endl; << "'' has already been declared." << endl;
error_cnt_ += 1; error_cnt_ += 1;
} else { } else {
@ -178,12 +178,12 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
case SR_BOTH: case SR_BOTH:
if (port_set_ || net_set_) { if (port_set_ || net_set_) {
if (port_set_) { if (port_set_) {
cerr << get_fileline() << ": error: Port ``" << hname_ cerr << get_fileline() << ": error: Port ``" << name_
<< "'' has already been declared a port." << endl; << "'' has already been declared a port." << endl;
error_cnt_ += 1; error_cnt_ += 1;
} }
if (net_set_) { if (net_set_) {
cerr << get_fileline() << ": error: Net ``" << hname_ cerr << get_fileline() << ": error: Net ``" << name_
<< "'' has already been declared." << endl; << "'' has already been declared." << endl;
error_cnt_ += 1; 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) void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
{ {
if (lidx_ != 0 || ridx_ != 0) { if (lidx_ != 0 || ridx_ != 0) {
cerr << get_fileline() << ": error: Array ``" << hname_ cerr << get_fileline() << ": error: Array ``" << name_
<< "'' has already been declared." << endl; << "'' has already been declared." << endl;
error_cnt_ += 1; error_cnt_ += 1;
} else { } else {

View File

@ -56,13 +56,13 @@ enum PWSRType {SR_PORT, SR_NET, SR_BOTH};
class PWire : public LineInfo { class PWire : public LineInfo {
public: public:
PWire(const pform_name_t&hname, PWire(perm_string name,
NetNet::Type t, NetNet::Type t,
NetNet::PortType pt, NetNet::PortType pt,
ivl_variable_type_t dt); ivl_variable_type_t dt);
// Return a hierarchical name. // Return a hierarchical name.
const pform_name_t&path() const; perm_string basename() const;
NetNet::Type get_wire_type() const; NetNet::Type get_wire_type() const;
bool set_wire_type(NetNet::Type); bool set_wire_type(NetNet::Type);
@ -90,7 +90,7 @@ class PWire : public LineInfo {
NetNet* elaborate_sig(Design*, NetScope*scope) const; NetNet* elaborate_sig(Design*, NetScope*scope) const;
private: private:
pform_name_t hname_; perm_string name_;
NetNet::Type type_; NetNet::Type type_;
NetNet::PortType port_type_; NetNet::PortType port_type_;
ivl_variable_type_t data_type_; ivl_variable_type_t data_type_;

View File

@ -84,6 +84,7 @@ class Statement : public LineInfo {
virtual void dump(ostream&out, unsigned ind) const; virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const; virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
}; };
/* /*
@ -166,6 +167,7 @@ class PBlock : public PScope, public Statement {
virtual void dump(ostream&out, unsigned ind) const; virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const; virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
private: private:
const BL_TYPE bl_type_; const BL_TYPE bl_type_;
@ -217,6 +219,7 @@ class PCase : public Statement {
virtual NetProc* elaborate(Design*des, NetScope*scope) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(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; virtual void dump(ostream&out, unsigned ind) const;
private: private:
@ -252,6 +255,7 @@ class PCondit : public Statement {
virtual NetProc* elaborate(Design*des, NetScope*scope) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(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; virtual void dump(ostream&out, unsigned ind) const;
private: private:
@ -286,6 +290,7 @@ class PDelayStatement : public Statement {
virtual void dump(ostream&out, unsigned ind) const; virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const; virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
private: private:
PExpr*delay_; PExpr*delay_;
@ -333,6 +338,7 @@ class PEventStatement : public Statement {
virtual void dump(ostream&out, unsigned ind) const; virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(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 // This method is used to elaborate, but attach a previously
// elaborated statement to the event. // elaborated statement to the event.
@ -366,6 +372,7 @@ class PForever : public Statement {
virtual NetProc* elaborate(Design*des, NetScope*scope) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(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; virtual void dump(ostream&out, unsigned ind) const;
private: private:
@ -381,6 +388,7 @@ class PForStatement : public Statement {
virtual NetProc* elaborate(Design*des, NetScope*scope) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(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; virtual void dump(ostream&out, unsigned ind) const;
private: private:

View File

@ -309,8 +309,14 @@ void NetPow::dump_node(ostream&o, unsigned ind) const
{ {
o << setw(ind) << "" << "LPM_POW (NetPow): " << name() o << setw(ind) << "" << "LPM_POW (NetPow): " << name()
<< " scope=" << scope_path(scope()) << " scope=" << scope_path(scope())
<< " delay=(" << *rise_time() << "," << *fall_time() << "," << " delay=(";
<< *decay_time() << ")" << endl; if (rise_time())
o << *rise_time() << "," << *fall_time() << ","
<< *decay_time();
else
o << "0,0,0";
o << ")" << endl;
dump_node_pins(o, ind+4); dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4); dump_obj_attr(o, ind+4);
} }
@ -980,7 +986,10 @@ void NetScope::dump(ostream&o) const
o << " MISSING FUNCTION DEFINITION" << endl; o << " MISSING FUNCTION DEFINITION" << endl;
break; break;
case TASK: case TASK:
if (task_def())
task_def()->dump(o, 4); task_def()->dump(o, 4);
else
o << " MISSING TASK DEFINITION" << endl;
break; break;
default: default:
break; break;

View File

@ -28,46 +28,58 @@
# include "PGenerate.h" # include "PGenerate.h"
# include "PTask.h" # include "PTask.h"
# include "PWire.h" # include "PWire.h"
# include "Statement.h"
# include "compiler.h" # include "compiler.h"
# include "netlist.h" # include "netlist.h"
# include "netmisc.h" # include "netmisc.h"
# include "util.h" # include "util.h"
# include "ivl_assert.h" # include "ivl_assert.h"
/* void Statement::elaborate_sig(Design*des, NetScope*scope) const
* 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)
{ {
perm_string name = sig->name();
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
Module::port_t*pp = ports[idx];
// Skip internally unconnected ports.
if (pp == 0)
continue;
// 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 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;
}
} }
return false; bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
{
bool flag = true;
for (map<perm_string,PWire*>::const_iterator wt = wires.begin()
; wt != wires.end() ; wt ++ ) {
PWire*cur = (*wt).second;
NetNet*sig = cur->elaborate_sig(des, scope);
/* 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;
}
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 bool Module::elaborate_sig(Design*des, NetScope*scope) const
@ -81,14 +93,26 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
if (pp == 0) if (pp == 0)
continue; 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) { for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
pform_name_t port_path (pp->expr[cc]->path()); 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: " cerr << get_fileline() << ": error: "
<< "Port " << pp->expr[cc]->path() << " (" << "Port " << port_path << " ("
<< (idx+1) << ") of module " << mod_name() << (idx+1) << ") of module " << mod_name()
<< " is not declared within module." << endl; << " is not declared within module." << endl;
des->errors += 1; 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() flag = elaborate_sig_wires_(des, scope) && flag;
; 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;
}
}
// Run through all the generate schemes to elaborate the // Run through all the generate schemes to elaborate the
// signals that they hold. Note that the generate schemes hold // 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); (*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; return flag;
} }
@ -276,7 +261,7 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
{ {
// Scan the declared PWires to elaborate the obvious signals // Scan the declared PWires to elaborate the obvious signals
// in the current scope. // in the current scope.
typedef map<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() for (wires_it_t wt = wires.begin()
; wt != wires.end() ; wt ++ ) { ; wt != wires.end() ; wt ++ ) {
@ -284,7 +269,7 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
if (debug_elaborate) if (debug_elaborate)
cerr << get_fileline() << ": debug: Elaborate PWire " 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); cur->elaborate_sig(des, scope);
} }
@ -316,6 +301,8 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
perm_string fname = scope->basename(); perm_string fname = scope->basename();
assert(scope->type() == NetScope::FUNC); assert(scope->type() == NetScope::FUNC);
elaborate_sig_wires_(des, scope);
/* Make sure the function has at least one input port. If it /* Make sure the function has at least one input port. If it
fails this test, print an error message. Keep going so we fails this test, print an error message. Keep going so we
can find more errors. */ 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 name. We know by design that the port name is given
as two components: <func>.<port>. */ as two components: <func>.<port>. */
pform_name_t path = (*ports_)[idx]->path(); perm_string pname = (*ports_)[idx]->basename();
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;
}
NetNet*tmp = scope->find_signal(pname); NetNet*tmp = scope->find_signal(pname);
if (tmp == 0) { if (tmp == 0) {
@ -449,6 +424,10 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
assert(def); assert(def);
scope->set_func_def(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); assert(scope->type() == NetScope::TASK);
elaborate_sig_wires_(des, scope);
svector<NetNet*>ports (ports_? ports_->count() : 0); svector<NetNet*>ports (ports_? ports_->count() : 0);
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) { for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
/* Parse the port name into the task name and the reg perm_string port_name = (*ports_)[idx]->basename();
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);
/* Find the signal for the port. We know by definition /* Find the signal for the port. We know by definition
that it is in the scope of the task, so look only in that it is in the scope of the task, so look only in
@ -493,6 +460,7 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
<< "Could not find port " << port_name << "Could not find port " << port_name
<< " in scope " << scope_path(scope) << endl; << " in scope " << scope_path(scope) << endl;
scope->dump(cerr); scope->dump(cerr);
des->errors += 1;
} }
ports[idx] = tmp; ports[idx] = tmp;
@ -500,6 +468,82 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
NetTaskDef*def = new NetTaskDef(scope, ports); NetTaskDef*def = new NetTaskDef(scope, ports);
scope->set_task_def(def); 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 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 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_; NetNet::Type wtype = type_;
if (wtype == NetNet::IMPLICIT) if (wtype == NetNet::IMPLICIT)
wtype = NetNet::WIRE; wtype = NetNet::WIRE;
@ -619,12 +642,12 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (port_msb_ == 0) { if (port_msb_ == 0) {
if (!gn_io_range_error_flag) { if (!gn_io_range_error_flag) {
cerr << get_fileline() cerr << get_fileline()
<< ": warning: Scalar port ``" << hname_ << ": warning: Scalar port ``" << name_
<< "'' has a vectored net declaration [" << "'' has a vectored net declaration ["
<< nmsb << ":" << nlsb << "]." << endl; << nmsb << ":" << nlsb << "]." << endl;
} else { } else {
cerr << get_fileline() cerr << get_fileline()
<< ": error: Scalar port ``" << hname_ << ": error: Scalar port ``" << name_
<< "'' has a vectored net declaration [" << "'' has a vectored net declaration ["
<< nmsb << ":" << nlsb << "]." << endl; << nmsb << ":" << nlsb << "]." << endl;
des->errors += 1; des->errors += 1;
@ -636,7 +659,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (net_msb_ == 0) { if (net_msb_ == 0) {
cerr << port_msb_->get_fileline() cerr << port_msb_->get_fileline()
<< ": error: Vectored port ``" << ": error: Vectored port ``"
<< hname_ << "'' [" << pmsb << ":" << plsb << name_ << "'' [" << pmsb << ":" << plsb
<< "] has a scalar net declaration at " << "] has a scalar net declaration at "
<< get_fileline() << "." << endl; << get_fileline() << "." << endl;
des->errors += 1; des->errors += 1;
@ -647,7 +670,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (port_msb_ != 0 && net_msb_ != 0) { if (port_msb_ != 0 && net_msb_ != 0) {
cerr << port_msb_->get_fileline() cerr << port_msb_->get_fileline()
<< ": error: Vectored port ``" << ": error: Vectored port ``"
<< hname_ << "'' [" << pmsb << ":" << plsb << name_ << "'' [" << pmsb << ":" << plsb
<< "] has a net declaration [" << nmsb << ":" << "] has a net declaration [" << nmsb << ":"
<< nlsb << "] at " << net_msb_->get_fileline() << nlsb << "] at " << net_msb_->get_fileline()
<< " that does not match." << endl; << " that does not match." << endl;
@ -687,7 +710,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if ((lexp == 0) || (rexp == 0)) { if ((lexp == 0) || (rexp == 0)) {
cerr << get_fileline() << ": internal error: There is " cerr << get_fileline() << ": internal error: There is "
<< "a problem evaluating indices for ``" << "a problem evaluating indices for ``"
<< hname_ << "''." << endl; << name_ << "''." << endl;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }
@ -698,7 +721,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if ((lcon == 0) || (rcon == 0)) { if ((lcon == 0) || (rcon == 0)) {
cerr << get_fileline() << ": internal error: The indices " cerr << get_fileline() << ": internal error: The indices "
<< "are not constant for array ``" << "are not constant for array ``"
<< hname_ << "''." << endl; << name_ << "''." << endl;
des->errors += 1; des->errors += 1;
return 0; 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) { if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " cerr << get_fileline() << ": debug: Create signal "
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name << wtype << " ["<<msb<<":"<<lsb<<"] " << name_
<< " in scope " << scope_path(scope) << endl; << " in scope " << scope_path(scope) << endl;
} }
NetNet*sig = array_dimensions > 0 NetNet*sig = array_dimensions > 0
? new NetNet(scope, name, wtype, msb, lsb, array_s0, array_e0) ? 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);
ivl_variable_type_t use_data_type = data_type_; ivl_variable_type_t use_data_type = data_type_;
if (use_data_type == IVL_VT_NO_TYPE) { if (use_data_type == IVL_VT_NO_TYPE) {
use_data_type = IVL_VT_LOGIC; use_data_type = IVL_VT_LOGIC;
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": debug: " cerr << get_fileline() << ": debug: "
<< "Signal " << name << "Signal " << name_
<< " in scope " << scope_path(scope) << " in scope " << scope_path(scope)
<< " defaults to data type " << use_data_type << endl; << " defaults to data type " << use_data_type << endl;
} }

View File

@ -2914,7 +2914,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
NetNet*sig = des->find_signal(scope, id1->path()); NetNet*sig = des->find_signal(scope, id1->path());
if (sig == 0) { if (sig == 0) {
cerr << id1->get_fileline() << ": register ``" << id1->path() cerr << id1->get_fileline() << ": register ``" << id1->path()
<< "'' unknown in this context." << endl; << "'' unknown in " << scope_path(scope) << "." << endl;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }

View File

@ -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_) for (NetEvent*cur = events_; cur ; cur = cur->snext_)
if (strcmp(cur->name(), name) == 0) if (cur->name() == name)
return cur; return cur;
return 0; 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 * is assumed to be the base name of the signal, so no sub-scopes are
* searched. * searched.
*/ */
NetNet* NetScope::find_signal(const char*key) NetNet* NetScope::find_signal(perm_string key)
{ {
if (signals_ == 0) if (signals_ == 0)
return 0; return 0;

View File

@ -3272,7 +3272,7 @@ class NetScope : public Attrib {
void add_event(NetEvent*); void add_event(NetEvent*);
void rem_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 /* These methods manage signals. The add_ and rem_signal
@ -3282,7 +3282,7 @@ class NetScope : public Attrib {
void add_signal(NetNet*); void add_signal(NetNet*);
void rem_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 /* The parent and child() methods allow users of NetScope
objects to locate nearby scopes. */ objects to locate nearby scopes. */

139
parse.y
View File

@ -26,6 +26,7 @@
# include "pform.h" # include "pform.h"
# include "Statement.h" # include "Statement.h"
# include "PSpec.h" # include "PSpec.h"
# include <stack>
# include <cstring> # include <cstring>
# include <sstream> # include <sstream>
@ -49,7 +50,7 @@ static struct {
task/function that is currently in progress. */ task/function that is currently in progress. */
static PTask* current_task = 0; static PTask* current_task = 0;
static PFunction* current_function = 0; static PFunction* current_function = 0;
static PBlock* current_block = 0; static stack<PBlock*> current_block_stack;
/* Later version of bison (including 1.35) will not compile in 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 extension if the output is compiled with C++ and either the YYSTYPE
@ -197,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 <text> udp_input_list udp_sequ_entry udp_comb_entry
%type <perm_strings> udp_input_declaration_list %type <perm_strings> udp_input_declaration_list
%type <strings> udp_entry_list udp_comb_entry_list udp_sequ_entry_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 <wires> udp_port_decl udp_port_decls
%type <statement> udp_initial udp_init_opt %type <statement> udp_initial udp_init_opt
%type <expr> udp_initial_expr_opt %type <expr> udp_initial_expr_opt
@ -1411,28 +1413,18 @@ list_of_port_declarations
{ svector<Module::port_t*>*tmp { svector<Module::port_t*>*tmp
= new svector<Module::port_t*>(1); = new svector<Module::port_t*>(1);
(*tmp)[0] = $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; $$ = tmp;
} }
| list_of_port_declarations ',' port_declaration | list_of_port_declarations ',' port_declaration
{ svector<Module::port_t*>*tmp { svector<Module::port_t*>*tmp
= new svector<Module::port_t*>(*$1, $3); = new svector<Module::port_t*>(*$1, $3);
delete $1; delete $1;
/*
* Same as above.
*
* pform_set_net_range($3[0].name);
*/
$$ = tmp; $$ = tmp;
} }
| list_of_port_declarations ',' IDENTIFIER | list_of_port_declarations ',' IDENTIFIER
{ Module::port_t*ptmp; { 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); @3.first_line);
svector<Module::port_t*>*tmp svector<Module::port_t*>*tmp
= new svector<Module::port_t*>(*$1, ptmp); = new svector<Module::port_t*>(*$1, ptmp);
@ -1440,17 +1432,13 @@ list_of_port_declarations
/* Get the port declaration details, the port type /* Get the port declaration details, the port type
and what not, from context data stored by the and what not, from context data stored by the
last port_declaration rule. */ 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_type,
port_declaration_context.port_net_type, port_declaration_context.port_net_type,
port_declaration_context.sign_flag, port_declaration_context.sign_flag,
port_declaration_context.range, 0); port_declaration_context.range, 0);
delete $1; delete $1;
/* delete $3;
* Same as above.
*
* pform_set_net_range($3);
*/
$$ = tmp; $$ = tmp;
} }
| list_of_port_declarations ',' | list_of_port_declarations ','
@ -1469,9 +1457,10 @@ port_declaration
: attribute_list_opt : attribute_list_opt
K_input net_type_opt signed_opt range_opt IDENTIFIER K_input net_type_opt signed_opt range_opt IDENTIFIER
{ Module::port_t*ptmp; { 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); @2.first_line);
pform_module_define_port(@2, $6, NetNet::PINPUT, pform_module_define_port(@2, name, NetNet::PINPUT,
$3, $4, $5, $1); $3, $4, $5, $1);
port_declaration_context.port_type = NetNet::PINPUT; port_declaration_context.port_type = NetNet::PINPUT;
port_declaration_context.port_net_type = $3; port_declaration_context.port_net_type = $3;
@ -1484,9 +1473,10 @@ port_declaration
| attribute_list_opt | attribute_list_opt
K_inout net_type_opt signed_opt range_opt IDENTIFIER K_inout net_type_opt signed_opt range_opt IDENTIFIER
{ Module::port_t*ptmp; { 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); @2.first_line);
pform_module_define_port(@2, $6, NetNet::PINOUT, pform_module_define_port(@2, name, NetNet::PINOUT,
$3, $4, $5, $1); $3, $4, $5, $1);
port_declaration_context.port_type = NetNet::PINOUT; port_declaration_context.port_type = NetNet::PINOUT;
port_declaration_context.port_net_type = $3; port_declaration_context.port_net_type = $3;
@ -1499,9 +1489,10 @@ port_declaration
| attribute_list_opt | attribute_list_opt
K_output net_type_opt signed_opt range_opt IDENTIFIER K_output net_type_opt signed_opt range_opt IDENTIFIER
{ Module::port_t*ptmp; { 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); @2.first_line);
pform_module_define_port(@2, $6, NetNet::POUTPUT, pform_module_define_port(@2, name, NetNet::POUTPUT,
$3, $4, $5, $1); $3, $4, $5, $1);
port_declaration_context.port_type = NetNet::POUTPUT; port_declaration_context.port_type = NetNet::POUTPUT;
port_declaration_context.port_net_type = $3; port_declaration_context.port_net_type = $3;
@ -1514,9 +1505,10 @@ port_declaration
| attribute_list_opt | attribute_list_opt
K_output var_type signed_opt range_opt IDENTIFIER K_output var_type signed_opt range_opt IDENTIFIER
{ Module::port_t*ptmp; { 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); @2.first_line);
pform_module_define_port(@2, $6, NetNet::POUTPUT, pform_module_define_port(@2, name, NetNet::POUTPUT,
$3, $4, $5, $1); $3, $4, $5, $1);
port_declaration_context.port_type = NetNet::POUTPUT; port_declaration_context.port_type = NetNet::POUTPUT;
port_declaration_context.port_net_type = $3; port_declaration_context.port_net_type = $3;
@ -1529,9 +1521,10 @@ port_declaration
| attribute_list_opt | attribute_list_opt
K_output var_type signed_opt range_opt IDENTIFIER '=' expression K_output var_type signed_opt range_opt IDENTIFIER '=' expression
{ Module::port_t*ptmp; { 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); @2.first_line);
pform_module_define_port(@2, $6, NetNet::POUTPUT, pform_module_define_port(@2, name, NetNet::POUTPUT,
$3, $4, $5, $1); $3, $4, $5, $1);
port_declaration_context.port_type = NetNet::POUTPUT; port_declaration_context.port_type = NetNet::POUTPUT;
port_declaration_context.port_net_type = $3; port_declaration_context.port_net_type = $3;
@ -1541,7 +1534,7 @@ port_declaration
if (! pform_expression_is_constant($8)) if (! pform_expression_is_constant($8))
yyerror(@8, "error: register declaration assignment" yyerror(@8, "error: register declaration assignment"
" value must be a constant expression."); " value must be a constant expression.");
pform_make_reginit(@6, $6, $8); pform_make_reginit(@6, name, $8);
delete $1; delete $1;
delete $6; delete $6;
@ -1849,7 +1842,8 @@ module_item
extension. */ extension. */
| K_task IDENTIFIER ';' | K_task IDENTIFIER ';'
{ current_task = pform_push_task_scope($2); { assert(current_task == 0);
current_task = pform_push_task_scope($2);
FILE_NAME(current_task, @1); FILE_NAME(current_task, @1);
} }
task_item_list_opt task_item_list_opt
@ -1863,7 +1857,8 @@ module_item
} }
| K_task IDENTIFIER | K_task IDENTIFIER
{ current_task = pform_push_task_scope($2); { assert(current_task == 0);
current_task = pform_push_task_scope($2);
FILE_NAME(current_task, @1); FILE_NAME(current_task, @1);
} }
'(' task_port_decl_list ')' ';' '(' task_port_decl_list ')' ';'
@ -1883,7 +1878,9 @@ module_item
instead of the module. */ instead of the module. */
| K_function function_range_or_type_opt IDENTIFIER ';' | K_function function_range_or_type_opt IDENTIFIER ';'
{ current_function = pform_push_function_scope($3); } { assert(current_function == 0);
current_function = pform_push_function_scope($3);
}
function_item_list statement function_item_list statement
K_endfunction K_endfunction
{ current_function->set_ports($6); { current_function->set_ports($6);
@ -2040,8 +2037,9 @@ net_decl_assign
: IDENTIFIER '=' expression : IDENTIFIER '=' expression
{ net_decl_assign_t*tmp = new net_decl_assign_t; { net_decl_assign_t*tmp = new net_decl_assign_t;
tmp->next = tmp; tmp->next = tmp;
tmp->name = $1; tmp->name = lex_strings.make($1);
tmp->expr = $3; tmp->expr = $3;
delete $1;
$$ = tmp; $$ = tmp;
} }
; ;
@ -2320,7 +2318,8 @@ port_reference
: IDENTIFIER : IDENTIFIER
{ Module::port_t*ptmp; { 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; delete $1;
$$ = ptmp; $$ = ptmp;
} }
@ -2531,7 +2530,8 @@ function_range_or_type_opt
so that bit ranges can be assigned. */ so that bit ranges can be assigned. */
register_variable register_variable
: IDENTIFIER dimensions_opt : 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); NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
if ($2 != 0) { if ($2 != 0) {
index_component_t index; index_component_t index;
@ -2540,19 +2540,19 @@ register_variable
"are currently supported."); "are currently supported.");
} }
index = $2->front(); index = $2->front();
pform_set_reg_idx($1, index.msb, index.lsb); pform_set_reg_idx(ident_name, index.msb, index.lsb);
delete $2; delete $2;
} }
$$ = $1; $$ = $1;
} }
| IDENTIFIER '=' expression | IDENTIFIER '=' expression
{ pform_makewire(@1, $1, NetNet::REG, { perm_string ident_name = lex_strings.make($1);
NetNet::NOT_A_PORT, pform_makewire(@1, ident_name, NetNet::REG,
IVL_VT_NO_TYPE, 0); NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
if (! pform_expression_is_constant($3)) if (! pform_expression_is_constant($3))
yyerror(@3, "error: register declaration assignment" yyerror(@3, "error: register declaration assignment"
" value must be a constant expression."); " value must be a constant expression.");
pform_make_reginit(@1, $1, $3); pform_make_reginit(@1, ident_name, $3);
$$ = $1; $$ = $1;
} }
; ;
@ -2574,7 +2574,8 @@ register_variable_list
real_variable real_variable
: IDENTIFIER dimensions_opt : 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) { if ($2 != 0) {
yyerror(@2, "sorry: real variables do not currently support arrays."); yyerror(@2, "sorry: real variables do not currently support arrays.");
delete $2; delete $2;
@ -2582,8 +2583,9 @@ real_variable
$$ = $1; $$ = $1;
} }
| IDENTIFIER '=' expression | IDENTIFIER '=' expression
{ pform_makewire(@1, $1, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_REAL, 0); { perm_string name = lex_strings.make($1);
pform_make_reginit(@1, $1, $3); pform_makewire(@1, name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
pform_make_reginit(@1, name, $3);
$$ = $1; $$ = $1;
} }
; ;
@ -2605,7 +2607,8 @@ real_variable_list
net_variable net_variable
: IDENTIFIER dimensions_opt : 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); NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
if ($2 != 0) { if ($2 != 0) {
index_component_t index; index_component_t index;
@ -2614,12 +2617,13 @@ net_variable
"are currently supported."); "are currently supported.");
} }
index = $2->front(); index = $2->front();
pform_set_reg_idx($1, index.msb, index.lsb); pform_set_reg_idx(name, index.msb, index.lsb);
delete $2; delete $2;
} }
$$ = $1; $$ = $1;
} }
; ;
net_variable_list net_variable_list
: net_variable : net_variable
{ list<perm_string>*tmp = new list<perm_string>; { list<perm_string>*tmp = new list<perm_string>;
@ -2970,16 +2974,20 @@ statement
$$ = tmp; $$ = tmp;
} }
| K_begin ':' IDENTIFIER | K_begin ':' IDENTIFIER
{ current_block = pform_push_block_scope($3, PBlock::BL_SEQ); { PBlock*tmp = pform_push_block_scope($3, PBlock::BL_SEQ);
FILE_NAME(current_block, @1); FILE_NAME(tmp, @1);
current_block_stack.push(tmp);
} }
block_item_decls_opt block_item_decls_opt
statement_list K_end statement_list K_end
{ pform_pop_scope(); { pform_pop_scope();
current_block->set_statement(*$6); assert(! current_block_stack.empty());
PBlock*tmp = current_block_stack.top();
current_block_stack.pop();
tmp->set_statement(*$6);
delete $3; delete $3;
delete $6; delete $6;
$$ = current_block; $$ = tmp;
} }
| K_begin K_end | K_begin K_end
{ PBlock*tmp = new PBlock(PBlock::BL_SEQ); { PBlock*tmp = new PBlock(PBlock::BL_SEQ);
@ -3000,16 +3008,20 @@ statement
code generator can do the right thing. */ code generator can do the right thing. */
| K_fork ':' IDENTIFIER | K_fork ':' IDENTIFIER
{ current_block = pform_push_block_scope($3, PBlock::BL_PAR); { PBlock*tmp = pform_push_block_scope($3, PBlock::BL_PAR);
FILE_NAME(current_block, @1); FILE_NAME(tmp, @1);
current_block_stack.push(tmp);
} }
block_item_decls_opt block_item_decls_opt
statement_list K_join statement_list K_join
{ pform_pop_scope(); { pform_pop_scope();
current_block->set_statement(*$6); assert(! current_block_stack.empty());
PBlock*tmp = current_block_stack.top();
current_block_stack.pop();
tmp->set_statement(*$6);
delete $3; delete $3;
delete $6; delete $6;
$$ = current_block; $$ = tmp;
} }
| K_fork K_join | K_fork K_join
{ PBlock*tmp = new PBlock(PBlock::BL_PAR); { PBlock*tmp = new PBlock(PBlock::BL_PAR);
@ -3675,8 +3687,7 @@ udp_port_decl
: K_input list_of_identifiers ';' : K_input list_of_identifiers ';'
{ $$ = pform_make_udp_input_ports($2); } { $$ = pform_make_udp_input_ports($2); }
| K_output IDENTIFIER ';' | K_output IDENTIFIER ';'
{ pform_name_t pname; { perm_string pname = lex_strings.make($2);
pname.push_back(name_component_t(lex_strings.make($2)));
PWire*pp = new PWire(pname, NetNet::IMPLICIT, NetNet::POUTPUT, IVL_VT_LOGIC); PWire*pp = new PWire(pname, NetNet::IMPLICIT, NetNet::POUTPUT, IVL_VT_LOGIC);
svector<PWire*>*tmp = new svector<PWire*>(1); svector<PWire*>*tmp = new svector<PWire*>(1);
(*tmp)[0] = pp; (*tmp)[0] = pp;
@ -3684,8 +3695,7 @@ udp_port_decl
delete $2; delete $2;
} }
| K_reg IDENTIFIER ';' | K_reg IDENTIFIER ';'
{ pform_name_t pname; { perm_string pname = lex_strings.make($2);
pname.push_back(name_component_t(lex_strings.make($2)));
PWire*pp = new PWire(pname, NetNet::REG, NetNet::PIMPLICIT, IVL_VT_LOGIC); PWire*pp = new PWire(pname, NetNet::REG, NetNet::PIMPLICIT, IVL_VT_LOGIC);
svector<PWire*>*tmp = new svector<PWire*>(1); svector<PWire*>*tmp = new svector<PWire*>(1);
(*tmp)[0] = pp; (*tmp)[0] = pp;
@ -3693,8 +3703,7 @@ udp_port_decl
delete $2; delete $2;
} }
| K_reg K_output IDENTIFIER ';' | K_reg K_output IDENTIFIER ';'
{ pform_name_t pname; { perm_string pname = lex_strings.make($3);
pname.push_back(name_component_t(lex_strings.make($3)));
PWire*pp = new PWire(pname, NetNet::REG, NetNet::POUTPUT, IVL_VT_LOGIC); PWire*pp = new PWire(pname, NetNet::REG, NetNet::POUTPUT, IVL_VT_LOGIC);
svector<PWire*>*tmp = new svector<PWire*>(1); svector<PWire*>*tmp = new svector<PWire*>(1);
(*tmp)[0] = pp; (*tmp)[0] = pp;
@ -3716,14 +3725,14 @@ udp_port_decls
udp_port_list udp_port_list
: IDENTIFIER : IDENTIFIER
{ list<string>*tmp = new list<string>; { list<perm_string>*tmp = new list<perm_string>;
tmp->push_back($1); tmp->push_back(lex_strings.make($1));
delete $1; delete $1;
$$ = tmp; $$ = tmp;
} }
| udp_port_list ',' IDENTIFIER | udp_port_list ',' IDENTIFIER
{ list<string>*tmp = $1; { list<perm_string>*tmp = $1;
tmp->push_back($3); tmp->push_back(lex_strings.make($3));
delete $3; delete $3;
$$ = tmp; $$ = tmp;
} }

193
pform.cc
View File

@ -89,44 +89,21 @@ static inline void FILE_NAME(LineInfo*tmp, const struct vlltype&where)
} }
/* /*
* The scope stack and the following functions handle the processing * The lexical_scope keeps track of the current lexical scope that is
* of scope. As I enter a scope, the push function is called, and as I * being parsed. The lexical scope may stack, so the current scope may
* leave a scope the pop function is called. Entering tasks, functions * have a parent, that is restored when the current scope ends.
* 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 scoped * Items that have scoped names are put in the lexical_scope object.
* 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 pform_name_t scope_stack;
static PScope* lexical_scope = 0; static PScope* lexical_scope = 0;
void pform_push_scope(char*name)
{
scope_stack.push_back(name_component_t(lex_strings.make(name)));
}
void pform_pop_scope() void pform_pop_scope()
{ {
scope_stack.pop_back();
lexical_scope = lexical_scope->pscope_parent(); lexical_scope = lexical_scope->pscope_parent();
} }
static pform_name_t hier_name(const char*tail)
{
pform_name_t name = scope_stack;
name.push_back(name_component_t(lex_strings.make(tail)));
return name;
}
PTask* pform_push_task_scope(char*name) PTask* pform_push_task_scope(char*name)
{ {
pform_push_scope(name);
perm_string task_name = lex_strings.make(name); perm_string task_name = lex_strings.make(name);
PTask*task = new PTask(task_name, pform_cur_module); PTask*task = new PTask(task_name, pform_cur_module);
@ -139,7 +116,6 @@ PTask* pform_push_task_scope(char*name)
PFunction* pform_push_function_scope(char*name) PFunction* pform_push_function_scope(char*name)
{ {
pform_push_scope(name);
perm_string func_name = lex_strings.make(name); perm_string func_name = lex_strings.make(name);
PFunction*func = new PFunction(func_name, lexical_scope); PFunction*func = new PFunction(func_name, lexical_scope);
@ -152,14 +128,16 @@ PFunction* pform_push_function_scope(char*name)
PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt) PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
{ {
pform_push_scope(name);
perm_string block_name = lex_strings.make(name); perm_string block_name = lex_strings.make(name);
PBlock*block = new PBlock(block_name, lexical_scope, bt); PBlock*block = new PBlock(block_name, lexical_scope, bt);
// Make this the current lexical scope
lexical_scope = block;
return block; return block;
} }
static PWire*get_wire_in_module(const pform_name_t&name) static PWire*get_wire_in_scope(perm_string name)
{ {
/* Note that if we are processing a generate, then the /* Note that if we are processing a generate, then the
scope depth will be empty because generate schemes scope depth will be empty because generate schemes
@ -168,7 +146,7 @@ static PWire*get_wire_in_module(const pform_name_t&name)
if (pform_cur_generate) if (pform_cur_generate)
return pform_cur_generate->get_wire(name); 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, void pform_set_default_nettype(NetNet::Type type,
@ -297,6 +275,9 @@ void pform_startmodule(const char*name, const char*file, unsigned lineno,
FILE_NAME(pform_cur_module, file, lineno); FILE_NAME(pform_cur_module, file, lineno);
pform_cur_module->library_flag = pform_library_flag; 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 /* The generate scheme numbering starts with *1*, not
zero. That's just the way it is, thanks to the standard. */ zero. That's just the way it is, thanks to the standard. */
scope_generate_counter = 1; scope_generate_counter = 1;
@ -323,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 * reference. This is a name without a .X(...), so the internal name
* should be generated to be the same as the X. * 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, const char*file,
unsigned lineno) unsigned lineno)
{ {
Module::port_t*ptmp = new Module::port_t; 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); FILE_NAME(tmp, file, lineno);
ptmp->name = lex_strings.make(name); ptmp->name = name;
ptmp->expr = svector<PEIdent*>(1); ptmp->expr = svector<PEIdent*>(1);
ptmp->expr[0] = tmp; ptmp->expr[0] = tmp;
@ -372,6 +353,13 @@ void pform_endmodule(const char*name)
pform_cur_module = 0; pform_cur_module = 0;
return; 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_modules[mod_name] = pform_cur_module;
pform_cur_module = 0; pform_cur_module = 0;
} }
@ -583,6 +571,11 @@ PExpr* pform_select_mtm_expr(PExpr*min, PExpr*typ, PExpr*max)
return res; 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, static void process_udp_table(PUdp*udp, list<string>*table,
const char*file, unsigned lineno) const char*file, unsigned lineno)
{ {
@ -650,7 +643,7 @@ static void process_udp_table(PUdp*udp, list<string>*table,
udp->toutput = output; 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, svector<PWire*>*decl, list<string>*table,
Statement*init_expr, Statement*init_expr,
const char*file, unsigned lineno) const char*file, unsigned lineno)
@ -662,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 off with the parameters in the list. If the port is already
in the map, merge the port type. I will rebuild a list in the map, merge the port type. I will rebuild a list
of parameters for the PUdp object. */ of parameters for the PUdp object. */
map<string,PWire*> defs; map<perm_string,PWire*> defs;
for (unsigned idx = 0 ; idx < decl->count() ; idx += 1) { for (unsigned idx = 0 ; idx < decl->count() ; idx += 1) {
pform_name_t pname = (*decl)[idx]->path(); perm_string port_name = (*decl)[idx]->basename();
string port_name = peek_tail_name(pname).str();
if (PWire*cur = defs[port_name]) { if (PWire*cur = defs[port_name]) {
bool rc = true; bool rc = true;
@ -692,8 +684,8 @@ void pform_make_udp(perm_string name, list<string>*parms,
UDP declaration, and the defs map maps that name to a UDP declaration, and the defs map maps that name to a
PWire* created by an input or output declaration. */ PWire* created by an input or output declaration. */
svector<PWire*> pins (parms->size()); svector<PWire*> pins (parms->size());
svector<string> pin_names (parms->size()); svector<perm_string> pin_names (parms->size());
{ list<string>::iterator cur; { list<perm_string>::iterator cur;
unsigned idx; unsigned idx;
for (cur = parms->begin(), idx = 0 for (cur = parms->begin(), idx = 0
; cur != parms->end() ; cur != parms->end()
@ -827,7 +819,7 @@ void pform_make_udp(perm_string name, list<string>*parms,
// Make the port list for the UDP // Make the port list for the UDP
for (unsigned idx = 0 ; idx < pins.count() ; idx += 1) for (unsigned idx = 0 ; idx < pins.count() ; idx += 1)
udp->ports[idx] = peek_tail_name(pins[idx]->path()); udp->ports[idx] = pins[idx]->basename();
process_udp_table(udp, table, file, lineno); process_udp_table(udp, table, file, lineno);
udp->initial = init; udp->initial = init;
@ -852,10 +844,9 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
svector<PWire*> pins(parms->size() + 1); svector<PWire*> pins(parms->size() + 1);
/* Make the PWire for the output port. */ /* 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, synchronous_flag? NetNet::REG : NetNet::WIRE,
NetNet::POUTPUT, NetNet::POUTPUT, IVL_VT_LOGIC);
IVL_VT_LOGIC);
FILE_NAME(pins[0], file, lineno); FILE_NAME(pins[0], file, lineno);
/* Make the PWire objects for the input ports. */ /* Make the PWire objects for the input ports. */
@ -865,10 +856,8 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
; cur != parms->end() ; cur != parms->end()
; idx += 1, cur++) { ; idx += 1, cur++) {
assert(idx < pins.count()); assert(idx < pins.count());
pins[idx] = new PWire(hier_name(*cur), pins[idx] = new PWire(*cur, NetNet::WIRE,
NetNet::WIRE, NetNet::PINPUT, IVL_VT_LOGIC);
NetNet::PINPUT,
IVL_VT_LOGIC);
FILE_NAME(pins[idx], file, lineno); FILE_NAME(pins[idx], file, lineno);
} }
assert(idx == pins.count()); assert(idx == pins.count());
@ -909,7 +898,7 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
// Make the port list for the UDP // Make the port list for the UDP
for (unsigned idx = 0 ; idx < pins.count() ; idx += 1) for (unsigned idx = 0 ; idx < pins.count() ; idx += 1)
udp->ports[idx] = peek_tail_name(pins[idx]->path()); udp->ports[idx] = pins[idx]->basename();
assert(udp); assert(udp);
assert(table); assert(table);
@ -924,39 +913,18 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
delete init_expr; 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 * This function attaches a range to a given name. The function is
* only called by the parser within the scope of the net declaration, * only called by the parser within the scope of the net declaration,
* and the name that I receive only has the tail component. * 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, const svector<PExpr*>*range,
bool signed_flag, bool signed_flag,
ivl_variable_type_t dt, ivl_variable_type_t dt,
PWSRType rt) PWSRType rt)
{ {
PWire*cur = get_wire_in_module(hier_name(name)); PWire*cur = get_wire_in_scope(name);
if (cur == 0) { if (cur == 0) {
VLerror("error: name is not a valid net."); VLerror("error: name is not a valid net.");
return; return;
@ -1271,17 +1239,16 @@ void pform_make_pgassign_list(svector<PExpr*>*alist,
* BTF-B14. * BTF-B14.
*/ */
void pform_make_reginit(const struct vlltype&li, 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 = lexical_scope->wires_find(name);
PWire*cur = pform_cur_module->get_wire(sname);
if (cur == 0) { if (cur == 0) {
VLerror(li, "internal error: reginit to non-register?"); VLerror(li, "internal error: reginit to non-register?");
delete expr; delete expr;
return; return;
} }
PEIdent*lval = new PEIdent(sname); PEIdent*lval = new PEIdent(name);
FILE_NAME(lval, li); FILE_NAME(lval, li);
PAssign*ass = new PAssign(lval, expr); PAssign*ass = new PAssign(lval, expr);
FILE_NAME(ass, li); FILE_NAME(ass, li);
@ -1302,18 +1269,17 @@ void pform_make_reginit(const struct vlltype&li,
* as is done for the old method. * as is done for the old method.
*/ */
void pform_module_define_port(const struct vlltype&li, void pform_module_define_port(const struct vlltype&li,
const char*nm, perm_string name,
NetNet::PortType port_type, NetNet::PortType port_type,
NetNet::Type type, NetNet::Type type,
bool signed_flag, bool signed_flag,
svector<PExpr*>*range, svector<PExpr*>*range,
svector<named_pexpr_t*>*attr) svector<named_pexpr_t*>*attr)
{ {
pform_name_t name = hier_name(nm); PWire*cur = lexical_scope->wires_find(name);
PWire*cur = pform_cur_module->get_wire(name);
if (cur) { if (cur) {
ostringstream msg; ostringstream msg;
msg << nm << " definition conflicts with " msg << name << " definition conflicts with "
<< "definition at " << cur->get_fileline() << "definition at " << cur->get_fileline()
<< "."; << ".";
VLerror(msg.str().c_str()); VLerror(msg.str().c_str());
@ -1344,7 +1310,7 @@ void pform_module_define_port(const struct vlltype&li,
cur->attributes[tmp->name] = tmp->parm; cur->attributes[tmp->name] = tmp->parm;
} }
} }
pform_cur_module->add_wire(cur); lexical_scope->wires[name] = cur;
} }
/* /*
@ -1372,14 +1338,12 @@ void pform_module_define_port(const struct vlltype&li,
* the variable/net. Other forms of pform_makewire ultimately call * the variable/net. Other forms of pform_makewire ultimately call
* this one to create the wire and stash it. * 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, NetNet::Type type, NetNet::PortType pt,
ivl_variable_type_t dt, ivl_variable_type_t dt,
svector<named_pexpr_t*>*attr) svector<named_pexpr_t*>*attr)
{ {
pform_name_t name = hier_name(nm); PWire*cur = get_wire_in_scope(name);
PWire*cur = get_wire_in_module(name);
// If this is not implicit ("implicit" meaning we don't know // If this is not implicit ("implicit" meaning we don't know
// what the type is yet) then set the type now. // what the type is yet) then set the type now.
@ -1387,7 +1351,7 @@ void pform_makewire(const vlltype&li, const char*nm,
bool rc = cur->set_wire_type(type); bool rc = cur->set_wire_type(type);
if (rc == false) { if (rc == false) {
ostringstream msg; ostringstream msg;
msg << nm << " definition conflicts with " msg << name << " definition conflicts with "
<< "definition at " << cur->get_fileline() << "definition at " << cur->get_fileline()
<< "."; << ".";
VLerror(msg.str().c_str()); VLerror(msg.str().c_str());
@ -1431,9 +1395,9 @@ void pform_makewire(const vlltype&li, const char*nm,
if (new_wire_flag) { if (new_wire_flag) {
if (pform_cur_generate) if (pform_cur_generate)
pform_cur_generate->add_wire(cur); pform_cur_generate->wires[name] = cur;
else else
pform_cur_module->add_wire(cur); lexical_scope->wires[name] = cur;
} }
} }
@ -1493,32 +1457,28 @@ void pform_makewire(const vlltype&li,
SR_NET); SR_NET);
} }
perm_string first_name = lex_strings.make(first->name); PWire*cur = get_wire_in_scope(first->name);
pform_name_t name = hier_name(first_name);
PWire*cur = get_wire_in_module(name);
if (cur != 0) { if (cur != 0) {
PEIdent*lval = new PEIdent(first_name); PEIdent*lval = new PEIdent(first->name);
FILE_NAME(lval, li.text, li.first_line); FILE_NAME(lval, li.text, li.first_line);
PGAssign*ass = pform_make_pgassign(lval, first->expr, PGAssign*ass = pform_make_pgassign(lval, first->expr,
delay, str); delay, str);
FILE_NAME(ass, li.text, li.first_line); FILE_NAME(ass, li.text, li.first_line);
} }
free(first->name);
delete first; delete first;
first = next; 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) const char*file, unsigned lineno)
{ {
pform_name_t name = hier_name(nm); PWire*cur = lexical_scope->wires_find(name);
PWire*cur = pform_cur_module->get_wire(name);
if (cur == 0) { if (cur == 0) {
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_NO_TYPE); cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_NO_TYPE);
FILE_NAME(cur, file, lineno); FILE_NAME(cur, file, lineno);
pform_cur_module->add_wire(cur); lexical_scope->wires[name] = cur;
} }
switch (cur->get_port_type()) { switch (cur->get_port_type()) {
@ -1529,14 +1489,14 @@ void pform_set_port_type(perm_string nm, NetNet::PortType pt,
case NetNet::NOT_A_PORT: case NetNet::NOT_A_PORT:
cerr << file << ":" << lineno << ": error: " cerr << file << ":" << lineno << ": error: "
<< "port " << nm << " is not in the port list." << "port " << name << " is not in the port list."
<< endl; << endl;
error_count += 1; error_count += 1;
break; break;
default: default:
cerr << file << ":" << lineno << ": error: " cerr << file << ":" << lineno << ": error: "
<< "port " << nm << " already has a port declaration." << "port " << name << " already has a port declaration."
<< endl; << endl;
error_count += 1; error_count += 1;
break; break;
@ -1596,18 +1556,17 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
for (list<perm_string>::iterator cur = names->begin() for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; cur ++ ) { ; cur != names->end() ; cur ++ ) {
perm_string txt = *cur; perm_string name = *cur;
pform_name_t name = hier_name(txt);
/* Look for a preexisting wire. If it exists, set the /* Look for a preexisting wire. If it exists, set the
port direction. If not, create it. */ port direction. If not, create it. */
PWire*curw = pform_cur_module->get_wire(name); PWire*curw = lexical_scope->wires_find(name);
if (curw) { if (curw) {
curw->set_port_type(pt); curw->set_port_type(pt);
} else { } else {
curw = new PWire(name, NetNet::IMPLICIT_REG, pt, vtype); curw = new PWire(name, NetNet::IMPLICIT_REG, pt, vtype);
FILE_NAME(curw, file, lineno); FILE_NAME(curw, file, lineno);
pform_cur_module->add_wire(curw); lexical_scope->wires[name] = curw;
} }
curw->set_signed(signed_flag); curw->set_signed(signed_flag);
@ -1630,9 +1589,7 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
void pform_set_attrib(perm_string name, perm_string key, char*value) void pform_set_attrib(perm_string name, perm_string key, char*value)
{ {
pform_name_t path = hier_name(name); if (PWire*cur = lexical_scope->wires_find(name)) {
if (PWire*cur = pform_cur_module->get_wire(path)) {
cur->attributes[key] = new PEString(value); cur->attributes[key] = new PEString(value);
} else if (PGate*cur = pform_cur_module->get_gate(name)) { } else if (PGate*cur = pform_cur_module->get_gate(name)) {
@ -1666,13 +1623,13 @@ void pform_set_type_attrib(perm_string name, const string&key,
* This function attaches a memory index range to an existing * This function attaches a memory index range to an existing
* register. (The named wire must be a register. * 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; PWire*cur = 0;
if (pform_cur_generate) { if (pform_cur_generate) {
cur = pform_cur_generate->get_wire(hier_name(name)); cur = pform_cur_generate->get_wire(name);
} else { } else {
cur = pform_cur_module->get_wire(hier_name(name)); cur = lexical_scope->wires_find(name);
} }
if (cur == 0) { if (cur == 0) {
VLerror("internal error: name is not a valid memory for index."); VLerror("internal error: name is not a valid memory for index.");
@ -1819,16 +1776,15 @@ void pform_set_port_type(const struct vlltype&li,
delete range; 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 = lexical_scope->wires_find(name);
PWire*cur = pform_cur_module->get_wire(name);
if (cur == 0) { if (cur == 0) {
cur = new PWire(name, NetNet::INTEGER, cur = new PWire(name, NetNet::INTEGER,
NetNet::NOT_A_PORT, NetNet::NOT_A_PORT,
IVL_VT_LOGIC); IVL_VT_LOGIC);
cur->set_signed(true); cur->set_signed(true);
pform_cur_module->add_wire(cur); lexical_scope->wires[name] = cur;
} else { } else {
bool rc = cur->set_wire_type(NetNet::INTEGER); bool rc = cur->set_wire_type(NetNet::INTEGER);
assert(rc); assert(rc);
@ -1854,13 +1810,12 @@ void pform_set_reg_integer(list<perm_string>*names)
delete 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 = lexical_scope->wires_find(name);
PWire*cur = pform_cur_module->get_wire(name);
if (cur == 0) { if (cur == 0) {
cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_LOGIC); cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
pform_cur_module->add_wire(cur); lexical_scope->wires[name] = cur;
} else { } else {
bool rc = cur->set_wire_type(NetNet::REG); bool rc = cur->set_wire_type(NetNet::REG);
assert(rc); assert(rc);
@ -1894,9 +1849,7 @@ svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
; cur != names->end() ; cur != names->end()
; cur ++ ) { ; cur ++ ) {
perm_string txt = *cur; perm_string txt = *cur;
pform_name_t tmp; PWire*pp = new PWire(txt,
tmp.push_back(name_component_t(txt));
PWire*pp = new PWire(tmp,
NetNet::IMPLICIT, NetNet::IMPLICIT,
NetNet::PINPUT, NetNet::PINPUT,
IVL_VT_LOGIC); IVL_VT_LOGIC);

15
pform.h
View File

@ -95,7 +95,7 @@ struct parmvalue_t {
struct str_pair_t { PGate::strength_t str0, str1; }; struct str_pair_t { PGate::strength_t str0, str1; };
struct net_decl_assign_t { struct net_decl_assign_t {
char*name; perm_string name;
PExpr*expr; PExpr*expr;
struct net_decl_assign_t*next; 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 port_definition_list. In this case, we have everything needed to
define the port, all in one place. */ define the port, all in one place. */
extern void pform_module_define_port(const struct vlltype&li, extern void pform_module_define_port(const struct vlltype&li,
const char*name, perm_string name,
NetNet::PortType, NetNet::PortType,
NetNet::Type type, NetNet::Type type,
bool signed_flag, bool signed_flag,
svector<PExpr*>*range, svector<PExpr*>*range,
svector<named_pexpr_t*>*attr); 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, const char*file,
unsigned lineno); unsigned lineno);
extern void pform_endmodule(const char*); 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, svector<PWire*>*decl, list<string>*table,
Statement*init, Statement*init,
const char*file, unsigned lineno); const char*file, unsigned lineno);
@ -201,7 +201,7 @@ extern void pform_endgenerate();
* The makewire functions announce to the pform code new wires. These * The makewire functions announce to the pform code new wires. These
* go into a module that is currently opened. * 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::Type type,
NetNet::PortType pt, NetNet::PortType pt,
ivl_variable_type_t, ivl_variable_type_t,
@ -229,7 +229,7 @@ extern void pform_makewire(const struct vlltype&li,
ivl_variable_type_t); ivl_variable_type_t);
extern void pform_make_reginit(const struct vlltype&li, 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, /* 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 i.e. input, output or inout. If the wire does not exist, create
@ -242,13 +242,12 @@ extern void pform_set_port_type(const struct vlltype&li,
extern void pform_set_port_type(perm_string nm, NetNet::PortType pt, extern void pform_set_port_type(perm_string nm, NetNet::PortType pt,
const char*file, unsigned lineno); const char*file, unsigned lineno);
extern void pform_set_net_range(const char* name);
extern void pform_set_net_range(list<perm_string>*names, extern void pform_set_net_range(list<perm_string>*names,
svector<PExpr*>*, svector<PExpr*>*,
bool signed_flag, bool signed_flag,
ivl_variable_type_t, ivl_variable_type_t,
PWSRType rt = SR_NET); 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_integer(list<perm_string>*names);
extern void pform_set_reg_time(list<perm_string>*names); extern void pform_set_reg_time(list<perm_string>*names);

View File

@ -296,7 +296,7 @@ void PWire::dump(ostream&out, unsigned ind) const
} }
} }
out << " " << hname_; out << " " << name_;
// If the wire has indices, dump them. // If the wire has indices, dump them.
if (lidx_ || ridx_) { if (lidx_ || ridx_) {
@ -508,6 +508,9 @@ void PBlock::dump(ostream&out, unsigned ind) const
out << " : " << pscope_name(); out << " : " << pscope_name();
out << endl; out << endl;
if (pscope_name() != 0)
dump_wires_(out, ind+2);
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1) { for (unsigned idx = 0 ; idx < list_.count() ; idx += 1) {
if (list_[idx]) if (list_[idx])
list_[idx]->dump(out, ind+2); list_[idx]->dump(out, ind+2);
@ -703,9 +706,11 @@ void PFunction::dump(ostream&out, unsigned ind) const
for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) { for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) {
out << setw(ind) << ""; out << setw(ind) << "";
out << "input "; out << "input ";
out << (*ports_)[idx]->path() << ";" << endl; out << (*ports_)[idx]->basename() << ";" << endl;
} }
dump_wires_(out, ind);
if (statement_) if (statement_)
statement_->dump(out, ind); statement_->dump(out, ind);
else else
@ -743,9 +748,11 @@ void PTask::dump(ostream&out, unsigned ind) const
assert(0); assert(0);
break; break;
} }
out << (*ports_)[idx]->path() << ";" << endl; out << (*ports_)[idx]->basename() << ";" << endl;
} }
dump_wires_(out, ind);
if (statement_) if (statement_)
statement_->dump(out, ind); statement_->dump(out, ind);
else else
@ -870,7 +877,7 @@ void PGenerate::dump(ostream&out, unsigned indent) const
out << endl; 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 != wires.end() ; idx++) {
(*idx).second->dump(out, indent+2); (*idx).second->dump(out, indent+2);
@ -894,6 +901,16 @@ void PGenerate::dump(ostream&out, unsigned indent) const
out << setw(indent) << "" << "endgenerate" << endl; 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 void Module::dump(ostream&out) const
{ {
if (attributes.begin() != attributes.end()) { if (attributes.begin() != attributes.end()) {
@ -995,12 +1012,7 @@ void Module::dump(ostream&out) const
} }
// Iterate through and display all the wires. // Iterate through and display all the wires.
for (map<pform_name_t,PWire*>::const_iterator wire = wires_.begin() dump_wires_(out, 4);
; wire != wires_.end()
; wire ++ ) {
(*wire).second->dump(out);
}
// Dump the task definitions. // Dump the task definitions.
typedef map<perm_string,PTask*>::const_iterator task_iter_t; typedef map<perm_string,PTask*>::const_iterator task_iter_t;