2000-04-04 05:20:15 +02:00
|
|
|
/*
|
2008-04-02 05:21:20 +02:00
|
|
|
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
|
2000-04-04 05:20:15 +02:00
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
|
|
|
|
|
2001-07-25 05:10:48 +02:00
|
|
|
# include "config.h"
|
2003-03-01 07:25:30 +01:00
|
|
|
# include "compiler.h"
|
2001-07-25 05:10:48 +02:00
|
|
|
|
2000-04-04 05:20:15 +02:00
|
|
|
# include "netlist.h"
|
2008-01-05 00:23:47 +01:00
|
|
|
# include <cstring>
|
2003-01-14 22:16:18 +01:00
|
|
|
# include <sstream>
|
2000-04-04 05:20:15 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The NetScope class keeps a scope tree organized. Each node of the
|
|
|
|
|
* scope tree points to its parent, its right sibling and its leftmost
|
|
|
|
|
* child. The root node has no parent or siblings. The node stores the
|
|
|
|
|
* name of the scope. The complete hierarchical name of the scope is
|
|
|
|
|
* formed by appending the path of scopes from the root to the scope
|
|
|
|
|
* in question.
|
|
|
|
|
*/
|
|
|
|
|
|
2007-06-02 05:42:12 +02:00
|
|
|
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
|
2000-08-27 17:51:50 +02:00
|
|
|
: type_(t), up_(up), sib_(0), sub_(0)
|
2000-04-04 05:20:15 +02:00
|
|
|
{
|
2000-05-02 02:58:11 +02:00
|
|
|
signals_ = 0;
|
2000-04-09 19:04:56 +02:00
|
|
|
events_ = 0;
|
2002-07-22 23:07:08 +02:00
|
|
|
lcounter_ = 0;
|
2000-12-16 02:45:47 +01:00
|
|
|
|
|
|
|
|
if (up) {
|
2008-04-02 05:21:20 +02:00
|
|
|
default_nettype_ = up->default_nettype();
|
2000-12-16 02:45:47 +01:00
|
|
|
time_unit_ = up->time_unit();
|
|
|
|
|
time_prec_ = up->time_precision();
|
|
|
|
|
sib_ = up_->sub_;
|
|
|
|
|
up_->sub_ = this;
|
|
|
|
|
} else {
|
2008-04-02 05:21:20 +02:00
|
|
|
default_nettype_ = NetNet::NONE;
|
2000-12-16 02:45:47 +01:00
|
|
|
time_unit_ = 0;
|
|
|
|
|
time_prec_ = 0;
|
|
|
|
|
assert(t == MODULE);
|
|
|
|
|
}
|
2000-07-30 20:25:43 +02:00
|
|
|
|
|
|
|
|
switch (t) {
|
|
|
|
|
case NetScope::TASK:
|
|
|
|
|
task_ = 0;
|
|
|
|
|
break;
|
|
|
|
|
case NetScope::FUNC:
|
|
|
|
|
func_ = 0;
|
|
|
|
|
break;
|
2000-12-16 02:45:47 +01:00
|
|
|
case NetScope::MODULE:
|
2004-02-18 18:11:54 +01:00
|
|
|
module_name_ = perm_string();
|
2000-12-16 02:45:47 +01:00
|
|
|
break;
|
2003-09-13 03:30:07 +02:00
|
|
|
default: /* BEGIN_END and FORK_JOIN, do nothing */
|
|
|
|
|
break;
|
2000-07-30 20:25:43 +02:00
|
|
|
}
|
2004-02-18 18:11:54 +01:00
|
|
|
name_ = n;
|
2000-04-04 05:20:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetScope::~NetScope()
|
|
|
|
|
{
|
|
|
|
|
assert(sib_ == 0);
|
|
|
|
|
assert(sub_ == 0);
|
2000-04-10 07:26:05 +02:00
|
|
|
lcounter_ = 0;
|
2003-03-01 07:25:30 +01:00
|
|
|
|
|
|
|
|
/* name_ and module_name_ are perm-allocated. */
|
2000-04-04 05:20:15 +02:00
|
|
|
}
|
|
|
|
|
|
2004-02-20 07:22:56 +01:00
|
|
|
NetExpr* NetScope::set_parameter(perm_string key, NetExpr*expr,
|
2002-10-20 00:59:49 +02:00
|
|
|
NetExpr*msb, NetExpr*lsb, bool signed_flag)
|
2000-04-04 05:20:15 +02:00
|
|
|
{
|
2003-03-11 00:40:53 +01:00
|
|
|
param_expr_t&ref = parameters[key];
|
2002-10-20 00:59:49 +02:00
|
|
|
NetExpr* res = ref.expr;
|
|
|
|
|
ref.expr = expr;
|
|
|
|
|
ref.msb = msb;
|
|
|
|
|
ref.lsb = lsb;
|
|
|
|
|
ref.signed_flag = signed_flag;
|
2000-04-04 05:20:15 +02:00
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2007-11-17 19:17:23 +01:00
|
|
|
bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
|
|
|
|
|
{
|
|
|
|
|
char tmp[32];
|
|
|
|
|
int pad_pos = strlen(prefix);
|
|
|
|
|
int max_pos = sizeof(tmp) - strlen(suffix) - 1;
|
|
|
|
|
strncpy(tmp, prefix, sizeof(tmp));
|
|
|
|
|
while (pad_pos <= max_pos) {
|
|
|
|
|
strcat(tmp + pad_pos, suffix);
|
|
|
|
|
hname_t new_name(lex_strings.make(tmp));
|
|
|
|
|
if (!up_->child(new_name)) {
|
|
|
|
|
name_ = new_name;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
tmp[pad_pos++] = pad;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2002-10-20 00:59:49 +02:00
|
|
|
/*
|
|
|
|
|
* Return false if this creates a new parameter.
|
|
|
|
|
*/
|
2004-02-20 07:22:56 +01:00
|
|
|
bool NetScope::replace_parameter(perm_string key, NetExpr*expr)
|
2002-10-20 00:59:49 +02:00
|
|
|
{
|
|
|
|
|
bool flag = true;
|
2003-03-11 00:40:53 +01:00
|
|
|
param_expr_t&ref = parameters[key];
|
2002-10-20 00:59:49 +02:00
|
|
|
|
|
|
|
|
NetExpr* res = ref.expr;
|
|
|
|
|
|
|
|
|
|
if (res) {
|
|
|
|
|
delete res;
|
|
|
|
|
} else {
|
|
|
|
|
flag = false;
|
|
|
|
|
ref.msb = 0;
|
|
|
|
|
ref.lsb = 0;
|
|
|
|
|
ref.signed_flag = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ref.expr = expr;
|
|
|
|
|
return flag;
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-20 07:22:56 +01:00
|
|
|
NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr)
|
2000-04-04 05:20:15 +02:00
|
|
|
{
|
2003-03-11 00:40:53 +01:00
|
|
|
param_expr_t&ref = localparams[key];
|
2002-10-20 00:59:49 +02:00
|
|
|
NetExpr* res = ref.expr;
|
|
|
|
|
ref.expr = expr;
|
|
|
|
|
ref.msb = 0;
|
|
|
|
|
ref.lsb = 0;
|
|
|
|
|
ref.signed_flag = false;
|
2000-04-04 05:20:15 +02:00
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-20 07:22:56 +01:00
|
|
|
/*
|
|
|
|
|
* NOTE: This method takes a const char* as a key to lookup a
|
|
|
|
|
* parameter, because we don't save that pointer. However, due to the
|
|
|
|
|
* way the map<> template works, we need to *cheat* and use the
|
|
|
|
|
* perm_string::literal method to fake the compiler into doing the
|
|
|
|
|
* compare without actually creating a perm_string.
|
|
|
|
|
*/
|
2005-11-27 06:56:20 +01:00
|
|
|
const NetExpr* NetScope::get_parameter(const char* key,
|
|
|
|
|
const NetExpr*&msb,
|
|
|
|
|
const NetExpr*&lsb) const
|
2000-04-04 05:20:15 +02:00
|
|
|
{
|
2004-02-20 07:22:56 +01:00
|
|
|
map<perm_string,param_expr_t>::const_iterator idx;
|
2000-04-04 05:20:15 +02:00
|
|
|
|
2004-02-20 07:22:56 +01:00
|
|
|
idx = parameters.find(perm_string::literal(key));
|
2005-11-27 06:56:20 +01:00
|
|
|
if (idx != parameters.end()) {
|
|
|
|
|
msb = (*idx).second.msb;
|
|
|
|
|
lsb = (*idx).second.lsb;
|
2002-10-20 00:59:49 +02:00
|
|
|
return (*idx).second.expr;
|
2005-11-27 06:56:20 +01:00
|
|
|
}
|
2000-04-04 05:20:15 +02:00
|
|
|
|
2004-02-20 07:22:56 +01:00
|
|
|
idx = localparams.find(perm_string::literal(key));
|
2005-11-27 06:56:20 +01:00
|
|
|
if (idx != localparams.end()) {
|
|
|
|
|
msb = (*idx).second.msb;
|
|
|
|
|
lsb = (*idx).second.lsb;
|
2002-10-20 00:59:49 +02:00
|
|
|
return (*idx).second.expr;
|
2005-11-27 06:56:20 +01:00
|
|
|
}
|
2000-04-04 05:20:15 +02:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetScope::TYPE NetScope::type() const
|
|
|
|
|
{
|
|
|
|
|
return type_;
|
|
|
|
|
}
|
|
|
|
|
|
2000-07-30 20:25:43 +02:00
|
|
|
void NetScope::set_task_def(NetTaskDef*def)
|
|
|
|
|
{
|
|
|
|
|
assert( type_ == TASK );
|
|
|
|
|
assert( task_ == 0 );
|
|
|
|
|
task_ = def;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetTaskDef* NetScope::task_def()
|
|
|
|
|
{
|
|
|
|
|
assert( type_ == TASK );
|
|
|
|
|
return task_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NetTaskDef* NetScope::task_def() const
|
|
|
|
|
{
|
|
|
|
|
assert( type_ == TASK );
|
|
|
|
|
return task_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetScope::set_func_def(NetFuncDef*def)
|
|
|
|
|
{
|
|
|
|
|
assert( type_ == FUNC );
|
|
|
|
|
assert( func_ == 0 );
|
|
|
|
|
func_ = def;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetFuncDef* NetScope::func_def()
|
|
|
|
|
{
|
|
|
|
|
assert( type_ == FUNC );
|
|
|
|
|
return func_;
|
|
|
|
|
}
|
2007-08-25 03:48:24 +02:00
|
|
|
bool NetScope::in_func()
|
|
|
|
|
{
|
|
|
|
|
return (type_ == FUNC) ? true : false;
|
|
|
|
|
}
|
2000-07-30 20:25:43 +02:00
|
|
|
|
|
|
|
|
const NetFuncDef* NetScope::func_def() const
|
|
|
|
|
{
|
|
|
|
|
assert( type_ == FUNC );
|
|
|
|
|
return func_;
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-18 18:11:54 +01:00
|
|
|
void NetScope::set_module_name(perm_string n)
|
2000-12-16 02:45:47 +01:00
|
|
|
{
|
|
|
|
|
assert(type_ == MODULE);
|
2003-03-06 05:37:12 +01:00
|
|
|
module_name_ = n; /* NOTE: n mus have been permallocated. */
|
2000-12-16 02:45:47 +01:00
|
|
|
}
|
|
|
|
|
|
2004-02-18 18:11:54 +01:00
|
|
|
perm_string NetScope::module_name() const
|
2000-12-16 02:45:47 +01:00
|
|
|
{
|
|
|
|
|
assert(type_ == MODULE);
|
|
|
|
|
return module_name_;
|
|
|
|
|
}
|
|
|
|
|
|
2000-07-23 00:09:03 +02:00
|
|
|
void NetScope::time_unit(int val)
|
|
|
|
|
{
|
|
|
|
|
time_unit_ = val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetScope::time_precision(int val)
|
|
|
|
|
{
|
|
|
|
|
time_prec_ = val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int NetScope::time_unit() const
|
|
|
|
|
{
|
|
|
|
|
return time_unit_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int NetScope::time_precision() const
|
|
|
|
|
{
|
|
|
|
|
return time_prec_;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-13 06:56:53 +02:00
|
|
|
void NetScope::default_nettype(NetNet::Type nt)
|
|
|
|
|
{
|
|
|
|
|
default_nettype_ = nt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetNet::Type NetScope::default_nettype() const
|
|
|
|
|
{
|
|
|
|
|
return default_nettype_;
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-18 18:11:54 +01:00
|
|
|
perm_string NetScope::basename() const
|
2000-05-02 02:58:11 +02:00
|
|
|
{
|
2007-06-02 05:42:12 +02:00
|
|
|
return name_.peek_name();
|
2000-04-04 05:20:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetScope::add_event(NetEvent*ev)
|
|
|
|
|
{
|
|
|
|
|
assert(ev->scope_ == 0);
|
|
|
|
|
ev->scope_ = this;
|
|
|
|
|
ev->snext_ = events_;
|
|
|
|
|
events_ = ev;
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-18 06:50:19 +02:00
|
|
|
void NetScope::rem_event(NetEvent*ev)
|
|
|
|
|
{
|
|
|
|
|
assert(ev->scope_ == this);
|
|
|
|
|
ev->scope_ = 0;
|
|
|
|
|
if (events_ == ev) {
|
|
|
|
|
events_ = ev->snext_;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
NetEvent*cur = events_;
|
|
|
|
|
while (cur->snext_ != ev) {
|
|
|
|
|
assert(cur->snext_);
|
|
|
|
|
cur = cur->snext_;
|
|
|
|
|
}
|
2004-10-04 03:10:51 +02:00
|
|
|
cur->snext_ = ev->snext_;
|
2000-04-18 06:50:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ev->snext_ = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-02-25 04:40:54 +01:00
|
|
|
NetEvent* NetScope::find_event(perm_string name)
|
2000-04-04 05:20:15 +02:00
|
|
|
{
|
|
|
|
|
for (NetEvent*cur = events_; cur ; cur = cur->snext_)
|
2008-02-25 04:40:54 +01:00
|
|
|
if (cur->name() == name)
|
2000-04-04 05:20:15 +02:00
|
|
|
return cur;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-02 02:58:11 +02:00
|
|
|
void NetScope::add_signal(NetNet*net)
|
|
|
|
|
{
|
|
|
|
|
if (signals_ == 0) {
|
|
|
|
|
net->sig_next_ = net;
|
|
|
|
|
net->sig_prev_ = net;
|
|
|
|
|
} else {
|
|
|
|
|
net->sig_next_ = signals_->sig_next_;
|
|
|
|
|
net->sig_prev_ = signals_;
|
|
|
|
|
net->sig_next_->sig_prev_ = net;
|
|
|
|
|
net->sig_prev_->sig_next_ = net;
|
|
|
|
|
}
|
|
|
|
|
signals_ = net;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetScope::rem_signal(NetNet*net)
|
|
|
|
|
{
|
2000-10-07 01:46:50 +02:00
|
|
|
assert(net->scope() == this);
|
2000-05-02 02:58:11 +02:00
|
|
|
if (signals_ == net)
|
|
|
|
|
signals_ = net->sig_prev_;
|
|
|
|
|
|
|
|
|
|
if (signals_ == net) {
|
|
|
|
|
signals_ = 0;
|
|
|
|
|
} else {
|
|
|
|
|
net->sig_prev_->sig_next_ = net->sig_next_;
|
|
|
|
|
net->sig_next_->sig_prev_ = net->sig_prev_;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
/*
|
|
|
|
|
* This method looks for a signal within the current scope. The name
|
|
|
|
|
* is assumed to be the base name of the signal, so no sub-scopes are
|
2004-10-04 03:10:51 +02:00
|
|
|
* searched.
|
2001-12-03 05:47:14 +01:00
|
|
|
*/
|
2008-02-25 04:40:54 +01:00
|
|
|
NetNet* NetScope::find_signal(perm_string key)
|
2000-05-02 02:58:11 +02:00
|
|
|
{
|
|
|
|
|
if (signals_ == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
NetNet*cur = signals_;
|
|
|
|
|
do {
|
2003-03-06 01:28:41 +01:00
|
|
|
if (cur->name() == key)
|
2000-05-02 02:58:11 +02:00
|
|
|
return cur;
|
|
|
|
|
cur = cur->sig_prev_;
|
|
|
|
|
} while (cur != signals_);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-04 05:20:15 +02:00
|
|
|
/*
|
|
|
|
|
* This method locates a child scope by name. The name is the simple
|
2003-01-27 06:09:17 +01:00
|
|
|
* name of the child, no hierarchy is searched.
|
2000-04-04 05:20:15 +02:00
|
|
|
*/
|
2007-06-02 05:42:12 +02:00
|
|
|
NetScope* NetScope::child(const hname_t&name)
|
2000-04-04 05:20:15 +02:00
|
|
|
{
|
|
|
|
|
if (sub_ == 0) return 0;
|
|
|
|
|
|
|
|
|
|
NetScope*cur = sub_;
|
2007-06-02 05:42:12 +02:00
|
|
|
while (cur->name_ != name) {
|
2000-04-04 05:20:15 +02:00
|
|
|
if (cur->sib_ == 0) return 0;
|
|
|
|
|
cur = cur->sib_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return cur;
|
|
|
|
|
}
|
|
|
|
|
|
2007-06-02 05:42:12 +02:00
|
|
|
const NetScope* NetScope::child(const hname_t&name) const
|
2000-04-04 05:20:15 +02:00
|
|
|
{
|
|
|
|
|
if (sub_ == 0) return 0;
|
|
|
|
|
|
|
|
|
|
NetScope*cur = sub_;
|
2007-06-02 05:42:12 +02:00
|
|
|
while (cur->name_ != name) {
|
2000-04-04 05:20:15 +02:00
|
|
|
if (cur->sib_ == 0) return 0;
|
|
|
|
|
cur = cur->sib_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return cur;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetScope* NetScope::parent()
|
|
|
|
|
{
|
|
|
|
|
return up_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NetScope* NetScope::parent() const
|
|
|
|
|
{
|
|
|
|
|
return up_;
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-18 18:11:54 +01:00
|
|
|
perm_string NetScope::local_symbol()
|
2000-04-10 07:26:05 +02:00
|
|
|
{
|
2003-01-14 22:16:18 +01:00
|
|
|
ostringstream res;
|
|
|
|
|
res << "_s" << (lcounter_++);
|
2004-02-18 18:11:54 +01:00
|
|
|
return lex_strings.make(res.str());
|
2000-04-10 07:26:05 +02:00
|
|
|
}
|
2007-06-02 05:42:12 +02:00
|
|
|
#if 0
|
2001-11-08 06:15:50 +01:00
|
|
|
string NetScope::local_hsymbol()
|
|
|
|
|
{
|
2004-02-18 18:11:54 +01:00
|
|
|
return string(name()) + "." + string(local_symbol());
|
2001-11-08 06:15:50 +01:00
|
|
|
}
|
2007-06-02 05:42:12 +02:00
|
|
|
#endif
|