Elaborate parameters in phases.
This commit is contained in:
parent
1f44822510
commit
3a5e55b229
|
|
@ -18,7 +18,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.16 1999/09/04 19:11:45 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.17 1999/09/20 02:21:10 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -60,7 +60,8 @@ clean:
|
|||
TT = t-null.o t-verilog.o t-vvm.o t-xnf.o
|
||||
FF = nobufz.o propinit.o sigfold.o xnfio.o xnfsyn.o
|
||||
|
||||
O = main.o cprop.o design_dump.o elaborate.o emit.o eval.o functor.o \
|
||||
O = main.o cprop.o design_dump.o elaborate.o elab_expr.o emit.o eval.o \
|
||||
eval_tree.o functor.o \
|
||||
lexor.o mangle.o netlist.o parse.o parse_misc.o pform.o pform_dump.o \
|
||||
verinum.o verireal.o target.o targets.o Module.o PDelays.o PExpr.o PGate.o \
|
||||
PTask.o PFunction.o PWire.o Statement.o \
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: design_dump.cc,v 1.41 1999/09/19 01:06:36 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.42 1999/09/20 02:21:10 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -644,6 +644,11 @@ void NetEMemory::dump(ostream&o) const
|
|||
o << "]";
|
||||
}
|
||||
|
||||
void NetEParam::dump(ostream&o) const
|
||||
{
|
||||
o << "<" << path_ << "." << name_ << ">";
|
||||
}
|
||||
|
||||
void NetESignal::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Expression Node (NetESignal): " <<
|
||||
|
|
@ -748,6 +753,9 @@ void Design::dump(ostream&o) const
|
|||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.42 1999/09/20 02:21:10 steve
|
||||
* Elaborate parameters in phases.
|
||||
*
|
||||
* Revision 1.41 1999/09/19 01:06:36 steve
|
||||
* dump the repeat count, if applicable.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: elab_expr.cc,v 1.1 1999/09/20 02:21:10 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
# include "pform.h"
|
||||
# include "netlist.h"
|
||||
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const
|
||||
{
|
||||
// System identifiers show up in the netlist as identifiers.
|
||||
if (text_[0] == '$')
|
||||
return new NetEIdent(text_, 64);
|
||||
|
||||
string name = path+"."+text_;
|
||||
|
||||
// If the identifier name is a parameter name, then return
|
||||
// a reference to the parameter expression.
|
||||
if (const NetExpr*ex = des->find_parameter(path, text_)) {
|
||||
NetExpr*tmp;
|
||||
if (dynamic_cast<const NetExpr*>(ex))
|
||||
tmp = ex->dup_expr();
|
||||
else
|
||||
tmp = new NetEParam(path, text_);
|
||||
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// If the identifier names a signal (a register or wire)
|
||||
// then create a NetESignal node to handle it.
|
||||
if (NetNet*net = des->find_signal(path, text_)) {
|
||||
|
||||
// If this is a part select of a signal, then make a new
|
||||
// temporary signal that is connected to just the
|
||||
// selected bits.
|
||||
if (lsb_) {
|
||||
assert(msb_);
|
||||
verinum*lsn = lsb_->eval_const(des, path);
|
||||
verinum*msn = msb_->eval_const(des, path);
|
||||
if ((lsn == 0) || (msn == 0)) {
|
||||
cerr << get_line() << ": Part select expresions "
|
||||
" must be constant expressions." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(lsn);
|
||||
assert(msn);
|
||||
unsigned long lsv = lsn->as_ulong();
|
||||
unsigned long msv = msn->as_ulong();
|
||||
unsigned long wid = 1 + ((msv>lsv)? (msv-lsv) : (lsv-msv));
|
||||
assert(wid <= net->pin_count());
|
||||
assert(net->sb_to_idx(msv) >= net->sb_to_idx(lsv));
|
||||
|
||||
string tname = des->local_symbol(path);
|
||||
NetESignal*tmp = new NetESignal(tname, wid);
|
||||
tmp->set_line(*this);
|
||||
|
||||
// Connect the pins from the lsb up to the msb.
|
||||
unsigned off = net->sb_to_idx(lsv);
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
connect(tmp->pin(idx), net->pin(idx+off));
|
||||
|
||||
des->add_node(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// If the bit select is constant, then treat it similar
|
||||
// to the part select, so that I save the effort of
|
||||
// making a mux part in the netlist.
|
||||
verinum*msn;
|
||||
if (msb_ && (msn = msb_->eval_const(des, path))) {
|
||||
assert(idx_ == 0);
|
||||
unsigned long msv = msn->as_ulong();
|
||||
|
||||
string tname = des->local_symbol(path);
|
||||
NetESignal*tmp = new NetESignal(tname, 1);
|
||||
tmp->set_line(*this);
|
||||
connect(tmp->pin(0), net->pin(msv));
|
||||
|
||||
des->add_node(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetESignal*node = new NetESignal(net);
|
||||
des->add_node(node);
|
||||
assert(idx_ == 0);
|
||||
|
||||
// Non-constant bit select? punt and make a subsignal
|
||||
// device to mux the bit in the net.
|
||||
if (msb_) {
|
||||
NetExpr*ex = msb_->elaborate_expr(des, path);
|
||||
NetESubSignal*ss = new NetESubSignal(node, ex);
|
||||
ss->set_line(*this);
|
||||
return ss;
|
||||
}
|
||||
|
||||
// All else fails, return the signal itself as the
|
||||
// expression.
|
||||
assert(msb_ == 0);
|
||||
return node;
|
||||
}
|
||||
|
||||
// If the identifier names a memory, then this is a
|
||||
// memory reference and I must generate a NetEMemory
|
||||
// object to handle it.
|
||||
if (NetMemory*mem = des->find_memory(name)) {
|
||||
assert(msb_ != 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_ == 0);
|
||||
NetExpr*i = msb_->elaborate_expr(des, path);
|
||||
if (i == 0) {
|
||||
cerr << get_line() << ": Unable to exaborate "
|
||||
"index expression `" << *msb_ << "'" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEMemory*node = new NetEMemory(mem, i);
|
||||
node->set_line(*this);
|
||||
return node;
|
||||
}
|
||||
|
||||
// I cannot interpret this identifier. Error message.
|
||||
cerr << get_line() << ": Unable to bind wire/reg/memory "
|
||||
"`" << path << "." << text_ << "'" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: elab_expr.cc,v $
|
||||
* Revision 1.1 1999/09/20 02:21:10 steve
|
||||
* Elaborate parameters in phases.
|
||||
*
|
||||
*/
|
||||
|
||||
178
elaborate.cc
178
elaborate.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: elaborate.cc,v 1.92 1999/09/18 22:23:50 steve Exp $"
|
||||
#ident "$Id: elaborate.cc,v 1.93 1999/09/20 02:21:10 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -1377,8 +1377,9 @@ NetExpr* PEConcat::elaborate_expr(Design*des, const string&path) const
|
|||
if (repeat_) {
|
||||
verinum*vrep = repeat_->eval_const(des, path);
|
||||
if (vrep == 0) {
|
||||
cerr << get_line() << ": concatenation repeat expression"
|
||||
" cannot be evaluated." << endl;
|
||||
cerr << get_line() << ": error: "
|
||||
"concatenation repeat expression cannot be evaluated."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1417,121 +1418,6 @@ NetExpr* PEString::elaborate_expr(Design*des, const string&path) const
|
|||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const
|
||||
{
|
||||
// System identifiers show up in the netlist as identifiers.
|
||||
if (text_[0] == '$')
|
||||
return new NetEIdent(text_, 64);
|
||||
|
||||
string name = path+"."+text_;
|
||||
|
||||
// If the identifier name a parameter name, then return
|
||||
// the expression that it represents.
|
||||
if (const NetExpr*ex = des->find_parameter(path, text_))
|
||||
return ex->dup_expr();
|
||||
|
||||
// If the identifier names a signal (a register or wire)
|
||||
// then create a NetESignal node to handle it.
|
||||
if (NetNet*net = des->find_signal(path, text_)) {
|
||||
|
||||
// If this is a part select of a signal, then make a new
|
||||
// temporary signal that is connected to just the
|
||||
// selected bits.
|
||||
if (lsb_) {
|
||||
assert(msb_);
|
||||
verinum*lsn = lsb_->eval_const(des, path);
|
||||
verinum*msn = msb_->eval_const(des, path);
|
||||
if ((lsn == 0) || (msn == 0)) {
|
||||
cerr << get_line() << ": Part select expresions "
|
||||
" must be constant expressions." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(lsn);
|
||||
assert(msn);
|
||||
unsigned long lsv = lsn->as_ulong();
|
||||
unsigned long msv = msn->as_ulong();
|
||||
unsigned long wid = 1 + ((msv>lsv)? (msv-lsv) : (lsv-msv));
|
||||
assert(wid <= net->pin_count());
|
||||
assert(net->sb_to_idx(msv) >= net->sb_to_idx(lsv));
|
||||
|
||||
string tname = des->local_symbol(path);
|
||||
NetESignal*tmp = new NetESignal(tname, wid);
|
||||
tmp->set_line(*this);
|
||||
|
||||
// Connect the pins from the lsb up to the msb.
|
||||
unsigned off = net->sb_to_idx(lsv);
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
connect(tmp->pin(idx), net->pin(idx+off));
|
||||
|
||||
des->add_node(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// If the bit select is constant, then treat it similar
|
||||
// to the part select, so that I save the effort of
|
||||
// making a mux part in the netlist.
|
||||
verinum*msn;
|
||||
if (msb_ && (msn = msb_->eval_const(des, path))) {
|
||||
assert(idx_ == 0);
|
||||
unsigned long msv = msn->as_ulong();
|
||||
|
||||
string tname = des->local_symbol(path);
|
||||
NetESignal*tmp = new NetESignal(tname, 1);
|
||||
tmp->set_line(*this);
|
||||
connect(tmp->pin(0), net->pin(msv));
|
||||
|
||||
des->add_node(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetESignal*node = new NetESignal(net);
|
||||
des->add_node(node);
|
||||
assert(idx_ == 0);
|
||||
|
||||
// Non-constant bit select? punt and make a subsignal
|
||||
// device to mux the bit in the net.
|
||||
if (msb_) {
|
||||
NetExpr*ex = msb_->elaborate_expr(des, path);
|
||||
NetESubSignal*ss = new NetESubSignal(node, ex);
|
||||
ss->set_line(*this);
|
||||
return ss;
|
||||
}
|
||||
|
||||
// All else fails, return the signal itself as the
|
||||
// expression.
|
||||
assert(msb_ == 0);
|
||||
return node;
|
||||
}
|
||||
|
||||
// If the identifier names a memory, then this is a
|
||||
// memory reference and I must generate a NetEMemory
|
||||
// object to handle it.
|
||||
if (NetMemory*mem = des->find_memory(name)) {
|
||||
assert(msb_ != 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_ == 0);
|
||||
NetExpr*i = msb_->elaborate_expr(des, path);
|
||||
if (i == 0) {
|
||||
cerr << get_line() << ": Unable to exaborate "
|
||||
"index expression `" << *msb_ << "'" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEMemory*node = new NetEMemory(mem, i);
|
||||
node->set_line(*this);
|
||||
return node;
|
||||
}
|
||||
|
||||
// I cannot interpret this identifier. Error message.
|
||||
cerr << get_line() << ": Unable to bind wire/reg/memory "
|
||||
"`" << path << "." << text_ << "'" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* PExpr::elaborate_expr(Design*des, const string&path) const
|
||||
{
|
||||
cerr << get_line() << ": I do not know how to elaborate expression: "
|
||||
|
|
@ -2513,8 +2399,20 @@ bool Module::elaborate(Design*des, const string&path, svector<PExpr*>*overrides_
|
|||
bool result_flag = true;
|
||||
|
||||
// Generate all the parameters that this instance of this
|
||||
// module introduce to the design.
|
||||
// module introduce to the design. This needs to be done in
|
||||
// two passes. The first pass marks the parameter names as
|
||||
// available so that they can be discovered when the second
|
||||
// pass references them during elaboration.
|
||||
typedef map<string,PExpr*>::const_iterator mparm_it_t;
|
||||
|
||||
// So this loop elaborates the parameters, ...
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
string pname = path + "." + (*cur).first;
|
||||
des->set_parameter(pname, new NetEParam);
|
||||
}
|
||||
|
||||
// and this loop elaborates the expressions.
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
string pname = path + "." + (*cur).first;
|
||||
|
|
@ -2535,6 +2433,45 @@ bool Module::elaborate(Design*des, const string&path, svector<PExpr*>*overrides_
|
|||
}
|
||||
}
|
||||
|
||||
// Finally, evaluate the parameter value. This step collapses
|
||||
// the parameters to NetEConst values.
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
|
||||
// Get the NetExpr for the parameter.
|
||||
string pname = path + "." + (*cur).first;
|
||||
const NetExpr*expr = des->find_parameter(path, (*cur).first);
|
||||
assert(expr);
|
||||
|
||||
// If it's already a NetEConst, then this parameter is done.
|
||||
if (dynamic_cast<const NetEConst*>(expr))
|
||||
continue;
|
||||
|
||||
// Get a non-constant copy of the expression to evaluate...
|
||||
NetExpr*nexpr = expr->dup_expr();
|
||||
if (nexpr == 0) {
|
||||
cerr << (*cur).second->get_line() << ": internal error: "
|
||||
"unable to dup expression: " << *expr << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Try to evaluate the expression.
|
||||
nexpr = nexpr->eval_tree();
|
||||
if (nexpr == 0) {
|
||||
cerr << (*cur).second->get_line() << ": internal error: "
|
||||
"unable to evaluate parm expression: " <<
|
||||
*expr << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// The evaluate worked, replace the old expression with
|
||||
// this constant value.
|
||||
assert(nexpr);
|
||||
des->set_parameter(pname, nexpr);
|
||||
}
|
||||
|
||||
// Get all the explicitly declared wires of the module and
|
||||
// start the signals list with them.
|
||||
const list<PWire*>&wl = get_wires();
|
||||
|
|
@ -2646,6 +2583,9 @@ Design* elaborate(const map<string,Module*>&modules,
|
|||
|
||||
/*
|
||||
* $Log: elaborate.cc,v $
|
||||
* Revision 1.93 1999/09/20 02:21:10 steve
|
||||
* Elaborate parameters in phases.
|
||||
*
|
||||
* Revision 1.92 1999/09/18 22:23:50 steve
|
||||
* Match bit widths comming out of task output ports.
|
||||
*
|
||||
|
|
|
|||
11
emit.cc
11
emit.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: emit.cc,v 1.21 1999/09/15 01:55:06 steve Exp $"
|
||||
#ident "$Id: emit.cc,v 1.22 1999/09/20 02:21:10 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -287,6 +287,12 @@ void NetEMemory::expr_scan(struct expr_scan_t*tgt) const
|
|||
tgt->expr_memory(this);
|
||||
}
|
||||
|
||||
void NetEParam::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
cerr << get_line() << ":internal error: unexpected NetEParam."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
void NetEUFunc::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_ufunc(this);
|
||||
|
|
@ -331,6 +337,9 @@ void emit(ostream&o, const Design*des, const char*type)
|
|||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.22 1999/09/20 02:21:10 steve
|
||||
* Elaborate parameters in phases.
|
||||
*
|
||||
* Revision 1.21 1999/09/15 01:55:06 steve
|
||||
* Elaborate non-blocking assignment to memories.
|
||||
*
|
||||
|
|
|
|||
11
eval.cc
11
eval.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: eval.cc,v 1.7 1999/09/18 01:52:48 steve Exp $"
|
||||
#ident "$Id: eval.cc,v 1.8 1999/09/20 02:21:10 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PExpr.h"
|
||||
|
|
@ -68,6 +68,12 @@ verinum* PEIdent::eval_const(const Design*des, const string&path) const
|
|||
if (expr == 0)
|
||||
return 0;
|
||||
|
||||
if (dynamic_cast<const NetEParam*>(expr)) {
|
||||
cerr << get_line() << ": sorry: I cannot evaluate ``" <<
|
||||
text_ << "'' in this context." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const NetEConst*eval = dynamic_cast<const NetEConst*>(expr);
|
||||
assert(eval);
|
||||
return new verinum(eval->value());
|
||||
|
|
@ -86,6 +92,9 @@ verinum* PETernary::eval_const(const Design*, const string&) const
|
|||
|
||||
/*
|
||||
* $Log: eval.cc,v $
|
||||
* Revision 1.8 1999/09/20 02:21:10 steve
|
||||
* Elaborate parameters in phases.
|
||||
*
|
||||
* Revision 1.7 1999/09/18 01:52:48 steve
|
||||
* Remove spurious message.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: eval_tree.cc,v 1.1 1999/09/20 02:21:10 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
||||
NetExpr* NetExpr::eval_tree()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
|
||||
* Some of the derived classes can be evaluated by the compiler, this
|
||||
* method provides the common aid of evaluating the parameter
|
||||
* expressions.
|
||||
*/
|
||||
void NetEBinary::eval_sub_tree_()
|
||||
{
|
||||
NetExpr*tmp = left_->eval_tree();
|
||||
if (tmp) {
|
||||
delete left_;
|
||||
left_ = tmp;
|
||||
}
|
||||
tmp = right_->eval_tree();
|
||||
if (tmp){
|
||||
delete right_;
|
||||
right_ = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NetExpr* NetEBComp::eval_eqeq_()
|
||||
{
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
||||
const verinum&lv = l->value();
|
||||
const verinum&rv = r->value();
|
||||
|
||||
if (lv.len() < rv.len())
|
||||
return 0;
|
||||
|
||||
verinum result(verinum::V1, 1);
|
||||
for (unsigned idx = 0 ; idx < lv.len(); idx += 1) {
|
||||
if (lv[idx] != rv[idx])
|
||||
result = verinum::V0;
|
||||
}
|
||||
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
|
||||
NetExpr* NetEBComp::eval_leeq_()
|
||||
{
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
||||
verinum rv = r->value();
|
||||
|
||||
/* Detect the case where the right side is greater that or
|
||||
equal to the largest value the left side can possibly
|
||||
have. */
|
||||
unsigned long lv = (1 << left_->expr_width()) - 1;
|
||||
if (lv <= rv.as_ulong()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
NetExpr* NetEBComp::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
switch (op_) {
|
||||
case 'e':
|
||||
return eval_eqeq_();
|
||||
|
||||
case 'L':
|
||||
return eval_leeq_();
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
NetExpr* NetEConcat::eval_tree()
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
// If this parameter is already a constant, go on.
|
||||
if (dynamic_cast<NetEConst*>(parms_[idx]))
|
||||
continue;
|
||||
|
||||
assert(parms_[idx]);
|
||||
NetExpr*expr = parms_[idx]->eval_tree();
|
||||
if (expr) {
|
||||
delete parms_[idx];
|
||||
parms_[idx] = expr;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned gap = expr_width() / repeat_;
|
||||
verinum val (verinum::Vx, repeat_ * gap);
|
||||
|
||||
|
||||
// build up the result from least significant to most.
|
||||
|
||||
unsigned cur = 0;
|
||||
for (unsigned idx = parms_.count() ; idx > 0 ; idx -= 1) {
|
||||
NetEConst*expr = dynamic_cast<NetEConst*>(parms_[idx-1]);
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
|
||||
verinum tmp = expr->value();
|
||||
for (unsigned bit = 0 ; bit < tmp.len() ; bit += 1, cur += 1)
|
||||
for (unsigned rep = 0 ; rep < repeat_ ; rep += 1)
|
||||
val.set(rep*gap+cur, tmp[bit]);
|
||||
}
|
||||
|
||||
NetEConst*res = new NetEConst(val);
|
||||
res->set_width(val.len());
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: eval_tree.cc,v $
|
||||
* Revision 1.1 1999/09/20 02:21:10 steve
|
||||
* Elaborate parameters in phases.
|
||||
*
|
||||
*/
|
||||
|
||||
131
netlist.cc
131
netlist.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: netlist.cc,v 1.65 1999/09/18 01:53:08 steve Exp $"
|
||||
#ident "$Id: netlist.cc,v 1.66 1999/09/20 02:21:10 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <cassert>
|
||||
|
|
@ -729,6 +729,11 @@ NetUTask::~NetUTask()
|
|||
{
|
||||
}
|
||||
|
||||
NetExpr::NetExpr(unsigned w)
|
||||
: width_(w)
|
||||
{
|
||||
}
|
||||
|
||||
NetExpr::~NetExpr()
|
||||
{
|
||||
}
|
||||
|
|
@ -741,11 +746,6 @@ bool NetExpr::set_width(unsigned w)
|
|||
return false;
|
||||
}
|
||||
|
||||
NetExpr* NetExpr::eval_tree()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
|
|
@ -920,84 +920,6 @@ NetEBinary* NetEBinary::dup_expr() const
|
|||
assert(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Some of the derived classes can be evaluated by the compiler, this
|
||||
* method provides the common aid of evaluating the parameter
|
||||
* expressions.
|
||||
*/
|
||||
void NetEBinary::eval_sub_tree_()
|
||||
{
|
||||
NetExpr*tmp = left_->eval_tree();
|
||||
if (tmp) {
|
||||
delete left_;
|
||||
left_ = tmp;
|
||||
}
|
||||
tmp = right_->eval_tree();
|
||||
if (tmp){
|
||||
delete right_;
|
||||
right_ = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NetExpr* NetEBComp::eval_eqeq_()
|
||||
{
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
||||
const verinum&lv = l->value();
|
||||
const verinum&rv = r->value();
|
||||
|
||||
if (lv.len() < rv.len())
|
||||
return 0;
|
||||
|
||||
verinum result(verinum::V1, 1);
|
||||
for (unsigned idx = 0 ; idx < lv.len(); idx += 1) {
|
||||
if (lv[idx] != rv[idx])
|
||||
result = verinum::V0;
|
||||
}
|
||||
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
NetExpr* NetEBComp::eval_leeq_()
|
||||
{
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
||||
verinum rv = r->value();
|
||||
|
||||
/* Detect the case where the right side is greater that or
|
||||
equal to the largest value the left side can possibly
|
||||
have. */
|
||||
unsigned long lv = (1 << left_->expr_width()) - 1;
|
||||
if (lv <= rv.as_ulong()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
NetExpr* NetEBComp::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
switch (op_) {
|
||||
case 'e':
|
||||
return eval_eqeq_();
|
||||
|
||||
case 'L':
|
||||
return eval_leeq_();
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
NetEConcat::NetEConcat(unsigned cnt, unsigned r)
|
||||
: parms_(cnt), repeat_(r)
|
||||
{
|
||||
|
|
@ -1015,7 +937,7 @@ void NetEConcat::set(unsigned idx, NetExpr*e)
|
|||
assert(idx < parms_.count());
|
||||
assert(parms_[idx] == 0);
|
||||
parms_[idx] = e;
|
||||
expr_width( expr_width() + e->expr_width() );
|
||||
expr_width( expr_width() + repeat_*e->expr_width() );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1043,7 +965,7 @@ bool NetEConcat::set_width(unsigned w)
|
|||
|
||||
NetEConcat* NetEConcat::dup_expr() const
|
||||
{
|
||||
NetEConcat*dup = new NetEConcat(parms_.count());
|
||||
NetEConcat*dup = new NetEConcat(parms_.count(), repeat_);
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
|
||||
if (parms_[idx]) {
|
||||
assert(parms_[idx]->dup_expr());
|
||||
|
|
@ -1055,17 +977,20 @@ NetEConcat* NetEConcat::dup_expr() const
|
|||
return dup;
|
||||
}
|
||||
|
||||
NetEConst::NetEConst(const verinum&val)
|
||||
: NetExpr(val.len()), value_(val)
|
||||
{
|
||||
}
|
||||
|
||||
NetEConst::~NetEConst()
|
||||
{
|
||||
}
|
||||
|
||||
bool NetEConst::set_width(unsigned w)
|
||||
{
|
||||
if (w > value_.len()) {
|
||||
cerr << get_line() << ": Cannot expand " << *this
|
||||
<< " to " << w << " bits." << endl;
|
||||
if (w > value_.len())
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(w <= value_.len());
|
||||
value_ = verinum(value_, w);
|
||||
expr_width(w);
|
||||
|
|
@ -1135,6 +1060,29 @@ NetEMemory* NetEMemory::dup_expr() const
|
|||
assert(0);
|
||||
}
|
||||
|
||||
NetEParam::NetEParam()
|
||||
{
|
||||
}
|
||||
|
||||
NetEParam::NetEParam(const string&p, const string&n)
|
||||
: path_(p), name_(n)
|
||||
{
|
||||
}
|
||||
|
||||
NetEParam::~NetEParam()
|
||||
{
|
||||
}
|
||||
|
||||
bool NetEParam::set_width(unsigned)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
NetEParam* NetEParam::dup_expr() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetESignal::NetESignal(NetNet*n)
|
||||
: NetExpr(n->pin_count()), NetNode(n->name(), n->pin_count())
|
||||
{
|
||||
|
|
@ -1870,6 +1818,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
|
|||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* Revision 1.66 1999/09/20 02:21:10 steve
|
||||
* Elaborate parameters in phases.
|
||||
*
|
||||
* Revision 1.65 1999/09/18 01:53:08 steve
|
||||
* Detect constant lessthen-equal expressions.
|
||||
*
|
||||
|
|
|
|||
37
netlist.h
37
netlist.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: netlist.h,v 1.66 1999/09/18 01:53:08 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.67 1999/09/20 02:21:10 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -364,7 +364,7 @@ class NetMemory {
|
|||
*/
|
||||
class NetExpr : public LineInfo {
|
||||
public:
|
||||
explicit NetExpr(unsigned w =0) : width_(w) { }
|
||||
explicit NetExpr(unsigned w =0);
|
||||
virtual ~NetExpr() =0;
|
||||
|
||||
virtual void expr_scan(struct expr_scan_t*) const =0;
|
||||
|
|
@ -1249,6 +1249,7 @@ class NetEConcat : public NetExpr {
|
|||
|
||||
virtual bool set_width(unsigned w);
|
||||
virtual NetEConcat* dup_expr() const;
|
||||
virtual NetExpr* eval_tree();
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
|
|
@ -1260,8 +1261,7 @@ class NetEConcat : public NetExpr {
|
|||
class NetEConst : public NetExpr {
|
||||
|
||||
public:
|
||||
NetEConst(const verinum&val)
|
||||
: NetExpr(val.len()), value_(val) { }
|
||||
explicit NetEConst(const verinum&val);
|
||||
~NetEConst();
|
||||
|
||||
const verinum&value() const { return value_; }
|
||||
|
|
@ -1276,6 +1276,32 @@ class NetEConst : public NetExpr {
|
|||
verinum value_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This clas is a placeholder for a parameter expression. When
|
||||
* parameters are first created, an instance of this object is used to
|
||||
* hold the place where the parameter exression goes. Then, when the
|
||||
* parameters are resolved, these objects are removed.
|
||||
*
|
||||
* If the parameter object is created with a path and name, then the
|
||||
* object represents a reference to a parameter that is known to exist.
|
||||
*/
|
||||
class NetEParam : public NetExpr {
|
||||
public:
|
||||
NetEParam();
|
||||
NetEParam(const string&path, const string&name);
|
||||
~NetEParam();
|
||||
|
||||
virtual bool set_width(unsigned w);
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetEParam* dup_expr() const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
private:
|
||||
string path_;
|
||||
string name_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This class represents the ternary (?:) operator. It has 3
|
||||
* expressions, one of which is a condition used to select which of
|
||||
|
|
@ -1585,6 +1611,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.67 1999/09/20 02:21:10 steve
|
||||
* Elaborate parameters in phases.
|
||||
*
|
||||
* Revision 1.66 1999/09/18 01:53:08 steve
|
||||
* Detect constant lessthen-equal expressions.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue