2000-03-08 05:36:53 +01:00
|
|
|
/*
|
2002-10-20 00:59:49 +02:00
|
|
|
* Copyright (c) 2000-2002 Stephen Williams (steve@icarus.com)
|
2000-03-08 05:36:53 +01: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
|
|
|
|
|
*/
|
2002-08-12 03:34:58 +02:00
|
|
|
#ifdef HAVE_CVS_IDENT
|
2002-12-07 03:49:24 +01:00
|
|
|
#ident "$Id: net_design.cc,v 1.30 2002/12/07 02:49:24 steve Exp $"
|
2000-03-08 05:36:53 +01:00
|
|
|
#endif
|
|
|
|
|
|
2001-07-25 05:10:48 +02:00
|
|
|
# include "config.h"
|
|
|
|
|
|
|
|
|
|
# include <iostream>
|
|
|
|
|
|
2000-03-08 05:36:53 +01:00
|
|
|
/*
|
|
|
|
|
* This source file contains all the implementations of the Design
|
|
|
|
|
* class declared in netlist.h.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
# include "netlist.h"
|
2000-04-28 18:50:53 +02:00
|
|
|
# include "util.h"
|
2000-04-10 07:26:05 +02:00
|
|
|
# include <strstream>
|
2000-03-08 05:36:53 +01:00
|
|
|
|
|
|
|
|
Design:: Design()
|
2001-10-19 23:53:24 +02:00
|
|
|
: errors(0), nodes_(0), procs_(0), lcounter_(0)
|
2000-03-08 05:36:53 +01:00
|
|
|
{
|
2000-07-16 06:56:07 +02:00
|
|
|
procs_idx_ = 0;
|
2000-07-23 00:09:03 +02:00
|
|
|
des_precision_ = 0;
|
2002-08-16 07:18:27 +02:00
|
|
|
nodes_functor_cur_ = 0;
|
|
|
|
|
nodes_functor_nxt_ = 0;
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Design::~Design()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-10 07:26:05 +02:00
|
|
|
string Design::local_symbol(const string&path)
|
|
|
|
|
{
|
|
|
|
|
strstream res;
|
|
|
|
|
res << "_L" << (lcounter_++) << ends;
|
|
|
|
|
|
|
|
|
|
return path + "." + res.str();
|
|
|
|
|
}
|
|
|
|
|
|
2000-07-23 00:09:03 +02:00
|
|
|
void Design::set_precision(int val)
|
|
|
|
|
{
|
|
|
|
|
if (val < des_precision_)
|
|
|
|
|
des_precision_ = val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Design::get_precision() const
|
|
|
|
|
{
|
|
|
|
|
return des_precision_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned long Design::scale_to_precision(unsigned long val,
|
|
|
|
|
const NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
int units = scope->time_unit();
|
2000-07-23 04:41:32 +02:00
|
|
|
assert( units >= des_precision_ );
|
2000-07-23 00:09:03 +02:00
|
|
|
|
|
|
|
|
while (units > des_precision_) {
|
|
|
|
|
units -= 1;
|
|
|
|
|
val *= 10;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
2001-10-20 07:21:51 +02:00
|
|
|
NetScope* Design::make_root_scope(const char*root)
|
2000-03-08 05:36:53 +01:00
|
|
|
{
|
2001-10-19 23:53:24 +02:00
|
|
|
NetScope *root_scope_;
|
2000-12-16 02:45:47 +01:00
|
|
|
root_scope_ = new NetScope(0, root, NetScope::MODULE);
|
2001-10-20 07:21:51 +02:00
|
|
|
root_scope_->set_module_name(root);
|
2001-10-19 23:53:24 +02:00
|
|
|
root_scopes_.push_back(root_scope_);
|
2000-03-08 05:36:53 +01:00
|
|
|
return root_scope_;
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-02 02:58:11 +02:00
|
|
|
NetScope* Design::find_root_scope()
|
|
|
|
|
{
|
2001-10-19 23:53:24 +02:00
|
|
|
assert(root_scopes_.front());
|
|
|
|
|
return root_scopes_.front();
|
2000-05-02 02:58:11 +02:00
|
|
|
}
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2001-10-19 23:53:24 +02:00
|
|
|
list<NetScope*> Design::find_root_scopes()
|
|
|
|
|
{
|
|
|
|
|
return root_scopes_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const list<NetScope*> Design::find_root_scopes() const
|
|
|
|
|
{
|
|
|
|
|
return root_scopes_;
|
2000-08-26 02:54:03 +02:00
|
|
|
}
|
|
|
|
|
|
2000-03-08 05:36:53 +01:00
|
|
|
/*
|
|
|
|
|
* This method locates a scope in the design, given its rooted
|
|
|
|
|
* heirarchical name. Each component of the key is used to scan one
|
|
|
|
|
* more step down the tree until the name runs out or the search
|
|
|
|
|
* fails.
|
|
|
|
|
*/
|
2001-12-03 05:47:14 +01:00
|
|
|
NetScope* Design::find_scope(const hname_t&path) const
|
2000-03-08 05:36:53 +01:00
|
|
|
{
|
2002-06-25 04:39:34 +02:00
|
|
|
if (path.peek_name(0) == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
|
|
|
|
|
; scope != root_scopes_.end(); scope++) {
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2001-10-19 23:53:24 +02:00
|
|
|
NetScope*cur = *scope;
|
2001-12-03 05:47:14 +01:00
|
|
|
if (strcmp(path.peek_name(0), cur->basename()) != 0)
|
2001-10-19 23:53:24 +02:00
|
|
|
continue;
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
unsigned hidx = 1;
|
2001-10-19 23:53:24 +02:00
|
|
|
while (cur) {
|
2001-12-03 05:47:14 +01:00
|
|
|
const char*name = path.peek_name(hidx);
|
|
|
|
|
if (name == 0)
|
|
|
|
|
return cur;
|
|
|
|
|
|
|
|
|
|
cur = cur->child(name);
|
|
|
|
|
hidx += 1;
|
2001-10-19 23:53:24 +02:00
|
|
|
}
|
2001-12-03 05:47:14 +01:00
|
|
|
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
2001-12-03 05:47:14 +01:00
|
|
|
|
2001-10-19 23:53:24 +02:00
|
|
|
return 0;
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
2000-03-10 07:20:48 +01:00
|
|
|
/*
|
|
|
|
|
* This is a relative lookup of a scope by name. The starting point is
|
|
|
|
|
* the scope parameter is the place within which I start looking for
|
|
|
|
|
* the scope. If I do not find the scope within the passed scope,
|
|
|
|
|
* start looking in parent scopes until I find it, or I run out of
|
|
|
|
|
* parent scopes.
|
|
|
|
|
*/
|
2001-12-03 05:47:14 +01:00
|
|
|
NetScope* Design::find_scope(NetScope*scope, const hname_t&path) const
|
2000-03-10 07:20:48 +01:00
|
|
|
{
|
|
|
|
|
assert(scope);
|
2002-06-25 04:39:34 +02:00
|
|
|
if (path.peek_name(0) == 0)
|
|
|
|
|
return scope;
|
2000-03-10 07:20:48 +01:00
|
|
|
|
|
|
|
|
for ( ; scope ; scope = scope->parent()) {
|
2001-12-03 05:47:14 +01:00
|
|
|
unsigned hidx = 0;
|
|
|
|
|
const char*key = path.peek_name(hidx);
|
2000-03-10 07:20:48 +01:00
|
|
|
|
|
|
|
|
NetScope*cur = scope;
|
|
|
|
|
do {
|
|
|
|
|
cur = cur->child(key);
|
|
|
|
|
if (cur == 0) break;
|
2001-12-03 05:47:14 +01:00
|
|
|
hidx += 1;
|
|
|
|
|
key = path.peek_name(hidx);
|
|
|
|
|
} while (key);
|
2000-03-10 07:20:48 +01:00
|
|
|
|
|
|
|
|
if (cur) return cur;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Last chance. Look for the name starting at the root.
|
2001-12-03 05:47:14 +01:00
|
|
|
return find_scope(path);
|
2000-03-10 07:20:48 +01:00
|
|
|
}
|
|
|
|
|
|
2000-03-08 05:36:53 +01:00
|
|
|
/*
|
|
|
|
|
* Find a parameter from within a specified context. If the name is
|
|
|
|
|
* not here, keep looking up until I run out of up to look at. The
|
|
|
|
|
* method works by scanning scopes, starting with the passed scope and
|
|
|
|
|
* working up towards the root, looking for the named parameter. The
|
|
|
|
|
* name in this case can be hierarchical, so there is an inner loop to
|
|
|
|
|
* follow the scopes of the name down to to key.
|
|
|
|
|
*/
|
|
|
|
|
const NetExpr* Design::find_parameter(const NetScope*scope,
|
2001-12-03 05:47:14 +01:00
|
|
|
const hname_t&path) const
|
2000-03-08 05:36:53 +01:00
|
|
|
{
|
|
|
|
|
for ( ; scope ; scope = scope->parent()) {
|
2001-12-03 05:47:14 +01:00
|
|
|
unsigned hidx = 0;
|
2000-03-08 05:36:53 +01:00
|
|
|
|
|
|
|
|
const NetScope*cur = scope;
|
2001-12-03 05:47:14 +01:00
|
|
|
while (path.peek_name(hidx+1)) {
|
|
|
|
|
cur = cur->child(path.peek_name(hidx));
|
|
|
|
|
if (cur == 0)
|
|
|
|
|
break;
|
|
|
|
|
hidx += 1;
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
if (cur == 0)
|
|
|
|
|
continue;
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
if (const NetExpr*res = cur->get_parameter(path.peek_name(hidx)))
|
2000-03-08 05:36:53 +01:00
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This method runs through the scope, noticing the defparam
|
|
|
|
|
* statements that were collected during the elaborate_scope pass and
|
|
|
|
|
* applying them to the target parameters. The implementation actually
|
|
|
|
|
* works by using a specialized method from the NetScope class that
|
|
|
|
|
* does all the work for me.
|
|
|
|
|
*/
|
|
|
|
|
void Design::run_defparams()
|
|
|
|
|
{
|
2001-10-19 23:53:24 +02:00
|
|
|
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
|
|
|
|
|
scope != root_scopes_.end(); scope++)
|
|
|
|
|
(*scope)->run_defparams(this);
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetScope::run_defparams(Design*des)
|
|
|
|
|
{
|
2002-06-25 04:39:34 +02:00
|
|
|
{ NetScope*cur = sub_;
|
|
|
|
|
while (cur) {
|
|
|
|
|
cur->run_defparams(des);
|
|
|
|
|
cur = cur->sib_;
|
|
|
|
|
}
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
map<hname_t,NetExpr*>::const_iterator pp;
|
2000-03-08 05:36:53 +01:00
|
|
|
for (pp = defparams.begin() ; pp != defparams.end() ; pp ++ ) {
|
|
|
|
|
NetExpr*val = (*pp).second;
|
2001-12-03 05:47:14 +01:00
|
|
|
hname_t path = (*pp).first;
|
|
|
|
|
|
|
|
|
|
char*name = path.remove_tail_name();
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2002-06-25 04:39:34 +02:00
|
|
|
/* If there is no path on the name, then the targ_scope
|
|
|
|
|
is the current scope. */
|
2000-03-10 07:20:48 +01:00
|
|
|
NetScope*targ_scope = des->find_scope(this, path);
|
2000-03-08 05:36:53 +01:00
|
|
|
if (targ_scope == 0) {
|
|
|
|
|
cerr << val->get_line() << ": warning: scope of " <<
|
|
|
|
|
path << "." << name << " not found." << endl;
|
2001-12-03 05:47:14 +01:00
|
|
|
delete[]name;
|
2000-03-08 05:36:53 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2002-10-20 00:59:49 +02:00
|
|
|
bool flag = targ_scope->replace_parameter(name, val);
|
|
|
|
|
if (! flag) {
|
2000-03-08 05:36:53 +01:00
|
|
|
cerr << val->get_line() << ": warning: parameter "
|
2002-10-20 00:59:49 +02:00
|
|
|
<< name << " not found in "
|
|
|
|
|
<< targ_scope->name() << "." << endl;
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
2001-12-03 05:47:14 +01:00
|
|
|
|
|
|
|
|
delete[]name;
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Design::evaluate_parameters()
|
|
|
|
|
{
|
2001-10-19 23:53:24 +02:00
|
|
|
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
|
|
|
|
|
scope != root_scopes_.end(); scope++)
|
|
|
|
|
(*scope)->evaluate_parameters(this);
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetScope::evaluate_parameters(Design*des)
|
|
|
|
|
{
|
|
|
|
|
NetScope*cur = sub_;
|
|
|
|
|
while (cur) {
|
|
|
|
|
cur->evaluate_parameters(des);
|
|
|
|
|
cur = cur->sib_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Evaluate the parameter values. The parameter expressions
|
|
|
|
|
// have already been elaborated and replaced by the scope
|
|
|
|
|
// scanning code. Now the parameter expression can be fully
|
|
|
|
|
// evaluated, or it cannot be evaluated at all.
|
|
|
|
|
|
2002-10-20 00:59:49 +02:00
|
|
|
typedef map<string,param_expr_t>::iterator mparm_it_t;
|
2000-03-08 05:36:53 +01:00
|
|
|
|
|
|
|
|
for (mparm_it_t cur = parameters_.begin()
|
|
|
|
|
; cur != parameters_.end() ; cur ++) {
|
|
|
|
|
|
2002-10-20 00:59:49 +02:00
|
|
|
long msb = 0;
|
|
|
|
|
long lsb = 0;
|
|
|
|
|
bool range_flag = false;
|
|
|
|
|
NetExpr*expr;
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2002-10-20 00:59:49 +02:00
|
|
|
/* Evaluate the msb expression, if it is present. */
|
|
|
|
|
expr = (*cur).second.msb;
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2002-10-20 00:59:49 +02:00
|
|
|
if (expr) {
|
|
|
|
|
|
|
|
|
|
NetEConst*tmp = dynamic_cast<NetEConst*>(expr);
|
|
|
|
|
|
|
|
|
|
if (! tmp) {
|
|
|
|
|
|
|
|
|
|
NetExpr*nexpr = expr->eval_tree();
|
|
|
|
|
if (nexpr == 0) {
|
|
|
|
|
cerr << (*cur).second.expr->get_line()
|
|
|
|
|
<< ": internal error: "
|
|
|
|
|
<< "unable to evaluate msb expression "
|
|
|
|
|
<< "for parameter " << (*cur).first << ": "
|
|
|
|
|
<< *expr << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(nexpr);
|
|
|
|
|
delete expr;
|
|
|
|
|
(*cur).second.msb = nexpr;
|
|
|
|
|
|
|
|
|
|
tmp = dynamic_cast<NetEConst*>(nexpr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(tmp);
|
|
|
|
|
msb = tmp->value().as_long();
|
|
|
|
|
range_flag = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Evaluate the lsb expression, if it is present. */
|
|
|
|
|
expr = (*cur).second.lsb;
|
|
|
|
|
if (expr) {
|
|
|
|
|
|
|
|
|
|
NetEConst*tmp = dynamic_cast<NetEConst*>(expr);
|
|
|
|
|
|
|
|
|
|
if (! tmp) {
|
|
|
|
|
|
|
|
|
|
NetExpr*nexpr = expr->eval_tree();
|
|
|
|
|
if (nexpr == 0) {
|
|
|
|
|
cerr << (*cur).second.expr->get_line()
|
|
|
|
|
<< ": internal error: "
|
|
|
|
|
<< "unable to evaluate lsb expression "
|
|
|
|
|
<< "for parameter " << (*cur).first << ": "
|
|
|
|
|
<< *expr << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(nexpr);
|
|
|
|
|
delete expr;
|
|
|
|
|
(*cur).second.lsb = nexpr;
|
|
|
|
|
|
|
|
|
|
tmp = dynamic_cast<NetEConst*>(nexpr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(tmp);
|
|
|
|
|
lsb = tmp->value().as_long();
|
|
|
|
|
|
|
|
|
|
assert(range_flag);
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
2002-10-20 00:59:49 +02:00
|
|
|
|
|
|
|
|
/* Evaluate the parameter expression, if necessary. */
|
|
|
|
|
expr = (*cur).second.expr;
|
|
|
|
|
assert(expr);
|
|
|
|
|
if (! dynamic_cast<const NetEConst*>(expr)) {
|
|
|
|
|
|
|
|
|
|
// Try to evaluate the expression.
|
|
|
|
|
NetExpr*nexpr = expr->eval_tree();
|
|
|
|
|
if (nexpr == 0) {
|
|
|
|
|
cerr << (*cur).second.expr->get_line()
|
|
|
|
|
<< ": internal error: "
|
|
|
|
|
"unable to evaluate parameter value: " <<
|
|
|
|
|
*expr << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The evaluate worked, replace the old expression with
|
|
|
|
|
// this constant value.
|
|
|
|
|
assert(nexpr);
|
|
|
|
|
delete expr;
|
|
|
|
|
(*cur).second.expr = nexpr;
|
|
|
|
|
|
|
|
|
|
// Set the signedness flag.
|
|
|
|
|
(*cur).second.expr->cast_signed( (*cur).second.signed_flag );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If the parameter has range information, then make
|
|
|
|
|
sure the value is set right. */
|
|
|
|
|
if (range_flag) {
|
|
|
|
|
long wid = (msb >= lsb)? msb - lsb : lsb - msb;
|
|
|
|
|
wid += 1;
|
|
|
|
|
|
|
|
|
|
NetEConst*val = dynamic_cast<NetEConst*>((*cur).second.expr);
|
|
|
|
|
assert(val);
|
|
|
|
|
|
|
|
|
|
verinum value = val->value();
|
|
|
|
|
|
|
|
|
|
if (! (value.has_len()
|
|
|
|
|
&& (value.len() == wid)
|
|
|
|
|
&& (value.has_sign() == (*cur).second.signed_flag))) {
|
|
|
|
|
|
|
|
|
|
verinum tmp (value, wid);
|
|
|
|
|
tmp.has_sign ( (*cur).second.signed_flag );
|
|
|
|
|
delete val;
|
|
|
|
|
val = new NetEConst(tmp);
|
|
|
|
|
(*cur).second.expr = val;
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string Design::get_flag(const string&key) const
|
|
|
|
|
{
|
|
|
|
|
map<string,string>::const_iterator tmp = flags_.find(key);
|
|
|
|
|
if (tmp == flags_.end())
|
|
|
|
|
return "";
|
|
|
|
|
else
|
|
|
|
|
return (*tmp).second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2000-08-12 19:59:48 +02:00
|
|
|
* This method looks for a signal (reg, wire, whatever) starting at
|
|
|
|
|
* the specified scope. If the name is hierarchical, it is split into
|
|
|
|
|
* scope and name and the scope used to find the proper starting point
|
|
|
|
|
* for the real search.
|
|
|
|
|
*
|
|
|
|
|
* It is the job of this function to properly implement Verilog scope
|
|
|
|
|
* rules as signals are concerned.
|
2000-03-08 05:36:53 +01:00
|
|
|
*/
|
2001-12-03 05:47:14 +01:00
|
|
|
NetNet* Design::find_signal(NetScope*scope, hname_t path)
|
2000-03-08 05:36:53 +01:00
|
|
|
{
|
|
|
|
|
assert(scope);
|
|
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
char*key = path.remove_tail_name();
|
|
|
|
|
if (path.peek_name(0))
|
2000-05-02 18:27:38 +02:00
|
|
|
scope = find_scope(scope, path);
|
|
|
|
|
|
2000-05-02 02:58:11 +02:00
|
|
|
while (scope) {
|
2001-12-03 05:47:14 +01:00
|
|
|
if (NetNet*net = scope->find_signal(key)) {
|
|
|
|
|
delete key;
|
2000-05-02 02:58:11 +02:00
|
|
|
return net;
|
2001-12-03 05:47:14 +01:00
|
|
|
}
|
2000-08-12 19:59:48 +02:00
|
|
|
|
|
|
|
|
if (scope->type() == NetScope::MODULE)
|
|
|
|
|
break;
|
2000-03-08 05:36:53 +01:00
|
|
|
scope = scope->parent();
|
|
|
|
|
}
|
2000-05-02 02:58:11 +02:00
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
delete key;
|
2000-05-02 02:58:11 +02:00
|
|
|
return 0;
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
NetMemory* Design::find_memory(NetScope*scope, hname_t path)
|
2000-03-08 05:36:53 +01:00
|
|
|
{
|
2000-05-02 05:13:30 +02:00
|
|
|
assert(scope);
|
2000-05-02 18:27:38 +02:00
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
char*key = path.remove_tail_name();
|
|
|
|
|
if (path.peek_name(0))
|
2000-05-02 18:27:38 +02:00
|
|
|
scope = find_scope(scope, path);
|
|
|
|
|
|
2000-05-02 05:13:30 +02:00
|
|
|
while (scope) {
|
2001-12-03 05:47:14 +01:00
|
|
|
if (NetMemory*mem = scope->find_memory(key)) {
|
|
|
|
|
delete key;
|
2000-05-02 05:13:30 +02:00
|
|
|
return mem;
|
|
|
|
|
}
|
2000-04-28 18:50:53 +02:00
|
|
|
|
|
|
|
|
scope = scope->parent();
|
|
|
|
|
}
|
2001-12-03 05:47:14 +01:00
|
|
|
|
|
|
|
|
delete key;
|
|
|
|
|
return 0;
|
2000-04-28 18:50:53 +02:00
|
|
|
}
|
|
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
|
|
|
|
|
NetFuncDef* Design::find_function(NetScope*scope, const hname_t&name)
|
2000-03-08 05:36:53 +01:00
|
|
|
{
|
2000-07-30 20:25:43 +02:00
|
|
|
assert(scope);
|
|
|
|
|
NetScope*func = find_scope(scope, name);
|
2000-09-24 19:41:13 +02:00
|
|
|
if (func && (func->type() == NetScope::FUNC))
|
2000-07-30 20:25:43 +02:00
|
|
|
return func->func_def();
|
2000-03-08 05:36:53 +01:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
NetFuncDef* Design::find_function(const hname_t&key)
|
2000-03-08 05:36:53 +01:00
|
|
|
{
|
2000-07-30 20:25:43 +02:00
|
|
|
NetScope*func = find_scope(key);
|
|
|
|
|
if (func && (func->type() == NetScope::FUNC))
|
|
|
|
|
return func->func_def();
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2000-07-30 20:25:43 +02:00
|
|
|
return 0;
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
NetScope* Design::find_task(NetScope*scope, const hname_t&name)
|
2000-03-08 05:36:53 +01:00
|
|
|
{
|
2000-07-30 20:25:43 +02:00
|
|
|
NetScope*task = find_scope(scope, name);
|
2000-09-24 19:41:13 +02:00
|
|
|
if (task && (task->type() == NetScope::TASK))
|
2001-04-02 04:28:12 +02:00
|
|
|
return task;
|
2000-03-08 05:36:53 +01:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-03 05:47:14 +01:00
|
|
|
NetScope* Design::find_task(const hname_t&key)
|
2000-03-08 05:36:53 +01:00
|
|
|
{
|
2000-07-30 20:25:43 +02:00
|
|
|
NetScope*task = find_scope(key);
|
|
|
|
|
if (task && (task->type() == NetScope::TASK))
|
2001-04-02 04:28:12 +02:00
|
|
|
return task;
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2000-07-30 20:25:43 +02:00
|
|
|
return 0;
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
2002-12-07 03:49:24 +01:00
|
|
|
NetEvent* Design::find_event(NetScope*scope, const hname_t&p)
|
2002-07-03 07:34:59 +02:00
|
|
|
{
|
2002-12-07 03:49:24 +01:00
|
|
|
hname_t path = p;
|
2002-07-03 07:34:59 +02:00
|
|
|
assert(scope);
|
|
|
|
|
|
2002-12-07 03:49:24 +01:00
|
|
|
char*key = path.remove_tail_name();
|
|
|
|
|
if (path.peek_name(0))
|
|
|
|
|
scope = find_scope(scope, path);
|
|
|
|
|
|
2002-07-03 07:34:59 +02:00
|
|
|
while (scope) {
|
2002-12-07 03:49:24 +01:00
|
|
|
if (NetEvent*ev = scope->find_event(key)) {
|
|
|
|
|
delete key;
|
2002-07-03 07:34:59 +02:00
|
|
|
return ev;
|
|
|
|
|
}
|
|
|
|
|
|
2002-12-07 03:49:24 +01:00
|
|
|
if (scope->type() == NetScope::MODULE)
|
2002-07-03 07:34:59 +02:00
|
|
|
break;
|
|
|
|
|
scope = scope->parent();
|
|
|
|
|
}
|
|
|
|
|
|
2002-12-07 03:49:24 +01:00
|
|
|
delete key;
|
2002-07-03 07:34:59 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2000-03-08 05:36:53 +01:00
|
|
|
void Design::add_node(NetNode*net)
|
|
|
|
|
{
|
|
|
|
|
assert(net->design_ == 0);
|
|
|
|
|
if (nodes_ == 0) {
|
|
|
|
|
net->node_next_ = net;
|
|
|
|
|
net->node_prev_ = net;
|
|
|
|
|
} else {
|
|
|
|
|
net->node_next_ = nodes_->node_next_;
|
|
|
|
|
net->node_prev_ = nodes_;
|
|
|
|
|
net->node_next_->node_prev_ = net;
|
|
|
|
|
net->node_prev_->node_next_ = net;
|
|
|
|
|
}
|
|
|
|
|
nodes_ = net;
|
|
|
|
|
net->design_ = this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Design::del_node(NetNode*net)
|
|
|
|
|
{
|
|
|
|
|
assert(net->design_ == this);
|
2002-08-16 07:18:27 +02:00
|
|
|
assert(net != 0);
|
|
|
|
|
|
|
|
|
|
/* Interact with the Design::functor method by manipulate the
|
|
|
|
|
cur and nxt pointers that is is using. */
|
|
|
|
|
if (net == nodes_functor_nxt_)
|
|
|
|
|
nodes_functor_nxt_ = nodes_functor_nxt_->node_next_;
|
|
|
|
|
if (net == nodes_functor_nxt_)
|
|
|
|
|
nodes_functor_nxt_ = 0;
|
|
|
|
|
|
|
|
|
|
if (net == nodes_functor_cur_)
|
|
|
|
|
nodes_functor_cur_ = 0;
|
|
|
|
|
|
|
|
|
|
/* Now perform the actual delete. */
|
2000-03-08 05:36:53 +01:00
|
|
|
if (nodes_ == net)
|
|
|
|
|
nodes_ = net->node_prev_;
|
|
|
|
|
|
|
|
|
|
if (nodes_ == net) {
|
|
|
|
|
nodes_ = 0;
|
|
|
|
|
} else {
|
|
|
|
|
net->node_next_->node_prev_ = net->node_prev_;
|
|
|
|
|
net->node_prev_->node_next_ = net->node_next_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
net->design_ = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Design::add_process(NetProcTop*pro)
|
|
|
|
|
{
|
|
|
|
|
pro->next_ = procs_;
|
|
|
|
|
procs_ = pro;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Design::delete_process(NetProcTop*top)
|
|
|
|
|
{
|
|
|
|
|
assert(top);
|
|
|
|
|
if (procs_ == top) {
|
|
|
|
|
procs_ = top->next_;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
NetProcTop*cur = procs_;
|
|
|
|
|
while (cur->next_ != top) {
|
|
|
|
|
assert(cur->next_);
|
|
|
|
|
cur = cur->next_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cur->next_ = top->next_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (procs_idx_ == top)
|
|
|
|
|
procs_idx_ = top->next_;
|
|
|
|
|
|
|
|
|
|
delete top;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* $Log: net_design.cc,v $
|
2002-12-07 03:49:24 +01:00
|
|
|
* Revision 1.30 2002/12/07 02:49:24 steve
|
|
|
|
|
* Named event triggers can take hierarchical names.
|
|
|
|
|
*
|
2002-11-02 04:27:51 +01:00
|
|
|
* Revision 1.29 2002/11/02 03:27:52 steve
|
|
|
|
|
* Allow named events to be referenced by
|
|
|
|
|
* hierarchical names.
|
|
|
|
|
*
|
2002-10-20 00:59:49 +02:00
|
|
|
* Revision 1.28 2002/10/19 22:59:49 steve
|
|
|
|
|
* Redo the parameter vector support to allow
|
|
|
|
|
* parameter names in range expressions.
|
|
|
|
|
*
|
2002-08-16 07:18:27 +02:00
|
|
|
* Revision 1.27 2002/08/16 05:18:27 steve
|
|
|
|
|
* Fix intermix of node functors and node delete.
|
|
|
|
|
*
|
2002-08-12 03:34:58 +02:00
|
|
|
* Revision 1.26 2002/08/12 01:34:59 steve
|
|
|
|
|
* conditional ident string using autoconfig.
|
|
|
|
|
*
|
2002-07-03 07:34:59 +02:00
|
|
|
* Revision 1.25 2002/07/03 05:34:59 steve
|
|
|
|
|
* Fix scope search for events.
|
|
|
|
|
*
|
2002-06-25 04:39:34 +02:00
|
|
|
* Revision 1.24 2002/06/25 02:39:34 steve
|
|
|
|
|
* Fix mishandling of incorect defparam error message.
|
|
|
|
|
*
|
2001-12-03 05:47:14 +01:00
|
|
|
* Revision 1.23 2001/12/03 04:47:15 steve
|
|
|
|
|
* Parser and pform use hierarchical names as hname_t
|
|
|
|
|
* objects instead of encoded strings.
|
|
|
|
|
*
|
2001-10-20 07:21:51 +02:00
|
|
|
* Revision 1.22 2001/10/20 05:21:51 steve
|
|
|
|
|
* Scope/module names are char* instead of string.
|
2000-03-08 05:36:53 +01:00
|
|
|
*/
|
|
|
|
|
|