Reorganize signal part select handling, and add support for
indexed part selects. Expand expression constant propagation to eliminate extra sums in certain cases.
This commit is contained in:
parent
bebcc05aab
commit
c02b3b8ac6
29
PExpr.h
29
PExpr.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PExpr.h,v 1.71 2005/10/04 04:09:25 steve Exp $"
|
||||
#ident "$Id: PExpr.h,v 1.72 2005/11/10 13:28:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
|
|
@ -256,6 +256,26 @@ class PEIdent : public PExpr {
|
|||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net_part_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net_idx_up_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net_bit_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found) const;
|
||||
hname_t path_;
|
||||
|
||||
public:
|
||||
|
|
@ -523,6 +543,13 @@ class PECallFunction : public PExpr {
|
|||
|
||||
/*
|
||||
* $Log: PExpr.h,v $
|
||||
* Revision 1.72 2005/11/10 13:28:11 steve
|
||||
* Reorganize signal part select handling, and add support for
|
||||
* indexed part selects.
|
||||
*
|
||||
* Expand expression constant propagation to eliminate extra
|
||||
* sums in certain cases.
|
||||
*
|
||||
* Revision 1.71 2005/10/04 04:09:25 steve
|
||||
* Add support for indexed select attached to parameters.
|
||||
*
|
||||
|
|
|
|||
448
elab_expr.cc
448
elab_expr.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2005 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
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_expr.cc,v 1.98 2005/10/04 04:09:25 steve Exp $"
|
||||
#ident "$Id: elab_expr.cc,v 1.99 2005/11/10 13:28:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -504,157 +504,9 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
// If the identifier names a signal (a register or wire)
|
||||
// then create a NetESignal node to handle it.
|
||||
if (net != 0) {
|
||||
if (net != 0)
|
||||
return elaborate_expr_net(des, scope, net, found_in);
|
||||
|
||||
// If this is a part select of a signal, then make a new
|
||||
// temporary signal that is connected to just the
|
||||
// selected bits. The lsb_ and msb_ expressions are from
|
||||
// the foo[msb:lsb] expression in the original.
|
||||
if (lsb_) {
|
||||
assert(msb_);
|
||||
assert(sel_ == SEL_PART);
|
||||
verinum*lsn = lsb_->eval_const(des, scope);
|
||||
verinum*msn = msb_->eval_const(des, scope);
|
||||
if ((lsn == 0) || (msn == 0)) {
|
||||
cerr << get_line() << ": error: "
|
||||
"Part select expressions must be "
|
||||
"constant expressions." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(lsn);
|
||||
assert(msn);
|
||||
|
||||
/* The indices of part selects are signed
|
||||
integers, so allow negative values. However,
|
||||
the width that they represent is
|
||||
unsigned. Remember that any order is possible,
|
||||
i.e., [1:0], [-4,6], etc. */
|
||||
|
||||
long lsv = lsn->as_long();
|
||||
long msv = msn->as_long();
|
||||
unsigned long wid = 1 + ((msv>lsv)? (msv-lsv) : (lsv-msv));
|
||||
if (wid > net->vector_width()) {
|
||||
cerr << get_line() << ": error: part select ["
|
||||
<< msv << ":" << lsv << "] out of range."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
delete lsn;
|
||||
delete msn;
|
||||
return 0;
|
||||
}
|
||||
assert(wid <= net->vector_width());
|
||||
|
||||
if (net->sb_to_idx(msv) < net->sb_to_idx(lsv)) {
|
||||
cerr << get_line() << ": error: part select ["
|
||||
<< msv << ":" << lsv << "] out of order."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
delete lsn;
|
||||
delete msn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (net->sb_to_idx(msv) >= net->vector_width()) {
|
||||
cerr << get_line() << ": error: part select ["
|
||||
<< msv << ":" << lsv << "] out of range."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
delete lsn;
|
||||
delete msn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetESignal*tmp = new NetESignal(net);
|
||||
tmp->set_line(*this);
|
||||
|
||||
// If the part select convers exactly the entire
|
||||
// vector, then do not bother with it. Return the
|
||||
// signal itself.
|
||||
if (net->sb_to_idx(lsv) == 0 && wid == net->vector_width())
|
||||
return tmp;
|
||||
|
||||
NetExpr*ex = new NetEConst(verinum(net->sb_to_idx(lsv)));
|
||||
NetESelect*ss = new NetESelect(tmp, ex, wid);
|
||||
ss->set_line(*this);
|
||||
|
||||
return ss;
|
||||
}
|
||||
|
||||
// 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, scope))) {
|
||||
assert(idx_ == 0);
|
||||
long msv = msn->as_long();
|
||||
unsigned idx = net->sb_to_idx(msv);
|
||||
|
||||
if (idx >= net->vector_width()) {
|
||||
/* The bit select is out of range of the
|
||||
vector. This is legal, but returns a
|
||||
constant 1'bx value. */
|
||||
verinum x (verinum::Vx);
|
||||
NetEConst*tmp = new NetEConst(x);
|
||||
tmp->set_line(*this);
|
||||
|
||||
cerr << get_line() << ": warning: Bit select ["
|
||||
<< msv << "] out of range of vector "
|
||||
<< net->name() << "[" << net->msb()
|
||||
<< ":" << net->lsb() << "]." << endl;
|
||||
cerr << get_line() << ": : Replacing "
|
||||
<< "expression with a constant 1'bx." << endl;
|
||||
delete msn;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetESignal*tmp = new NetESignal(net);
|
||||
tmp->set_line(*this);
|
||||
// If the vector is only one bit, we are done. The
|
||||
// bit select will return the scaler itself.
|
||||
if (net->vector_width() == 1)
|
||||
return tmp;
|
||||
|
||||
// Make an expression out of the index
|
||||
NetEConst*idx_c = new NetEConst(verinum(idx));
|
||||
idx_c->set_line(*net);
|
||||
|
||||
// Make a bit select with the canonical index
|
||||
NetESelect*res = new NetESelect(tmp, idx_c, 1);
|
||||
res->set_line(*net);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
NetESignal*node = new NetESignal(net);
|
||||
assert(idx_ == 0);
|
||||
|
||||
// Non-constant bit select? punt and make a subsignal
|
||||
// device to mux the bit in the net. This is a fairly
|
||||
// complicated task because we need to generate
|
||||
// expressions to convert calculated bit select
|
||||
// values to canonical values that are used internally.
|
||||
if (msb_) {
|
||||
NetExpr*ex = msb_->elaborate_expr(des, scope);
|
||||
|
||||
if (net->msb() < net->lsb()) {
|
||||
ex = make_sub_expr(net->lsb(), ex);
|
||||
} else {
|
||||
ex = make_add_expr(ex, - net->lsb());
|
||||
}
|
||||
|
||||
NetESelect*ss = new NetESelect(node, ex, 1);
|
||||
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
|
||||
|
|
@ -915,6 +767,291 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle part selects of NetNet identifiers.
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in)const
|
||||
{
|
||||
assert(lsb_ != 0);
|
||||
assert(msb_ != 0);
|
||||
assert(idx_ == 0);
|
||||
|
||||
verinum*lsn = lsb_->eval_const(des, scope);
|
||||
verinum*msn = msb_->eval_const(des, scope);
|
||||
if ((lsn == 0) || (msn == 0)) {
|
||||
cerr << get_line() << ": error: "
|
||||
"Part select expressions must be "
|
||||
"constant expressions." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(lsn);
|
||||
assert(msn);
|
||||
|
||||
/* The indices of part selects are signed integers, so allow
|
||||
negative values. However, the width that they represent is
|
||||
unsigned. Remember that any order is possible,
|
||||
i.e., [1:0], [-4:6], etc. */
|
||||
|
||||
long lsv = lsn->as_long();
|
||||
long msv = msn->as_long();
|
||||
unsigned long wid = 1 + ((msv>lsv)? (msv-lsv) : (lsv-msv));
|
||||
if (wid > net->vector_width()) {
|
||||
cerr << get_line() << ": error: part select ["
|
||||
<< msv << ":" << lsv << "] out of range." << endl;
|
||||
des->errors += 1;
|
||||
delete lsn;
|
||||
delete msn;
|
||||
return 0;
|
||||
}
|
||||
assert(wid <= net->vector_width());
|
||||
|
||||
if (net->sb_to_idx(msv) < net->sb_to_idx(lsv)) {
|
||||
cerr << get_line() << ": error: part select ["
|
||||
<< msv << ":" << lsv << "] out of order." << endl;
|
||||
des->errors += 1;
|
||||
delete lsn;
|
||||
delete msn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (net->sb_to_idx(msv) >= net->vector_width()) {
|
||||
cerr << get_line() << ": error: part select ["
|
||||
<< msv << ":" << lsv << "] out of range." << endl;
|
||||
des->errors += 1;
|
||||
delete lsn;
|
||||
delete msn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetESignal*tmp = new NetESignal(net);
|
||||
tmp->set_line(*this);
|
||||
|
||||
// If the part select convers exactly the entire
|
||||
// vector, then do not bother with it. Return the
|
||||
// signal itself.
|
||||
if (net->sb_to_idx(lsv) == 0 && wid == net->vector_width())
|
||||
return tmp;
|
||||
|
||||
NetExpr*ex = new NetEConst(verinum(net->sb_to_idx(lsv)));
|
||||
NetESelect*ss = new NetESelect(tmp, ex, wid);
|
||||
ss->set_line(*this);
|
||||
|
||||
return ss;
|
||||
}
|
||||
|
||||
/*
|
||||
* Part select indexed up, i.e. net[<m> +: <l>]
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in)const
|
||||
{
|
||||
assert(lsb_ != 0);
|
||||
assert(msb_ != 0);
|
||||
assert(idx_ == 0);
|
||||
|
||||
NetESignal*sig = new NetESignal(net);
|
||||
sig->set_line(*this);
|
||||
|
||||
NetExpr*base = elab_and_eval(des, scope, msb_);
|
||||
|
||||
NetExpr*wid_e = elab_and_eval(des, scope, lsb_);
|
||||
NetEConst*wid_c = dynamic_cast<NetEConst*> (wid_e);
|
||||
if (wid_c == 0) {
|
||||
cerr << get_line() << ": error: Width of indexed part select "
|
||||
<< "must be constant." << endl;
|
||||
cerr << get_line() << ": : Width expression is: "
|
||||
<< *wid_e << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(wid_c != 0);
|
||||
long wid = wid_c->value().as_long();
|
||||
|
||||
// Handle the special case that the base is constant as
|
||||
// well. In this case it can be converted to a conventional
|
||||
// part select.
|
||||
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
|
||||
long lsv = base_c->value().as_long();
|
||||
|
||||
// If the part select convers exactly the entire
|
||||
// vector, then do not bother with it. Return the
|
||||
// signal itself.
|
||||
if (net->sb_to_idx(lsv) == 0 && wid == net->vector_width())
|
||||
return sig;
|
||||
}
|
||||
|
||||
NetESelect*ss = new NetESelect(sig, base, wid);
|
||||
ss->set_line(*this);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Elaborate part "
|
||||
<< "select base="<< *base << ", wid="<< wid << endl;
|
||||
}
|
||||
|
||||
return ss;
|
||||
}
|
||||
|
||||
/*
|
||||
* Part select up, i.e. net[<m> +: <l>]
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in)const
|
||||
{
|
||||
assert(lsb_ != 0);
|
||||
assert(msb_ != 0);
|
||||
assert(idx_ == 0);
|
||||
|
||||
NetESignal*sig = new NetESignal(net);
|
||||
sig->set_line(*this);
|
||||
|
||||
NetExpr*base = elab_and_eval(des, scope, msb_);
|
||||
|
||||
NetExpr*wid_e = elab_and_eval(des, scope, lsb_);
|
||||
NetEConst*wid_c = dynamic_cast<NetEConst*> (wid_e);
|
||||
if (wid_c == 0) {
|
||||
cerr << get_line() << ": error: Width of indexed part select "
|
||||
<< "must be constant." << endl;
|
||||
cerr << get_line() << ": : Width expression is: "
|
||||
<< *wid_e << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(wid_c != 0);
|
||||
long wid = wid_c->value().as_long();
|
||||
|
||||
// Handle the special case that the base is constant as
|
||||
// well. In this case it can be converted to a conventional
|
||||
// part select.
|
||||
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
|
||||
long lsv = base_c->value().as_long();
|
||||
|
||||
// If the part select convers exactly the entire
|
||||
// vector, then do not bother with it. Return the
|
||||
// signal itself.
|
||||
if (net->sb_to_idx(lsv) == (wid-1) && wid == net->vector_width())
|
||||
return sig;
|
||||
}
|
||||
|
||||
NetExpr*base_adjusted = wid > 1? make_add_expr(base,1-wid) : base;
|
||||
NetESelect*ss = new NetESelect(sig, base_adjusted, wid);
|
||||
ss->set_line(*this);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Elaborate part "
|
||||
<< "select base="<< *base << ", wid="<< wid << endl;
|
||||
}
|
||||
|
||||
return ss;
|
||||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in) const
|
||||
{
|
||||
assert(msb_ != 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_ == 0);
|
||||
|
||||
// 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.
|
||||
if (verinum*msn = msb_->eval_const(des, scope)) {
|
||||
long msv = msn->as_long();
|
||||
unsigned idx = net->sb_to_idx(msv);
|
||||
|
||||
if (idx >= net->vector_width()) {
|
||||
/* The bit select is out of range of the
|
||||
vector. This is legal, but returns a
|
||||
constant 1'bx value. */
|
||||
verinum x (verinum::Vx);
|
||||
NetEConst*tmp = new NetEConst(x);
|
||||
tmp->set_line(*this);
|
||||
|
||||
cerr << get_line() << ": warning: Bit select ["
|
||||
<< msv << "] out of range of vector "
|
||||
<< net->name() << "[" << net->msb()
|
||||
<< ":" << net->lsb() << "]." << endl;
|
||||
cerr << get_line() << ": : Replacing "
|
||||
<< "expression with a constant 1'bx." << endl;
|
||||
delete msn;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetESignal*tmp = new NetESignal(net);
|
||||
tmp->set_line(*this);
|
||||
// If the vector is only one bit, we are done. The
|
||||
// bit select will return the scaler itself.
|
||||
if (net->vector_width() == 1)
|
||||
return tmp;
|
||||
|
||||
// Make an expression out of the index
|
||||
NetEConst*idx_c = new NetEConst(verinum(idx));
|
||||
idx_c->set_line(*net);
|
||||
|
||||
// Make a bit select with the canonical index
|
||||
NetESelect*res = new NetESelect(tmp, idx_c, 1);
|
||||
res->set_line(*net);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
NetESignal*node = new NetESignal(net);
|
||||
|
||||
// Non-constant bit select? punt and make a subsignal
|
||||
// device to mux the bit in the net. This is a fairly
|
||||
// complicated task because we need to generate
|
||||
// expressions to convert calculated bit select
|
||||
// values to canonical values that are used internally.
|
||||
NetExpr*ex = msb_->elaborate_expr(des, scope);
|
||||
|
||||
if (net->msb() < net->lsb()) {
|
||||
ex = make_sub_expr(net->lsb(), ex);
|
||||
} else {
|
||||
ex = make_add_expr(ex, - net->lsb());
|
||||
}
|
||||
|
||||
NetESelect*ss = new NetESelect(node, ex, 1);
|
||||
ss->set_line(*this);
|
||||
return ss;
|
||||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in) const
|
||||
{
|
||||
// If this is a part select of a signal, then make a new
|
||||
// temporary signal that is connected to just the
|
||||
// selected bits. The lsb_ and msb_ expressions are from
|
||||
// the foo[msb:lsb] expression in the original.
|
||||
if (sel_ == SEL_PART)
|
||||
return elaborate_expr_net_part_(des, scope, net, found_in);
|
||||
|
||||
if (sel_ == SEL_BIT)
|
||||
return elaborate_expr_net_bit_(des, scope, net, found_in);
|
||||
|
||||
if (sel_ == SEL_IDX_UP)
|
||||
return elaborate_expr_net_idx_up_(des, scope, net, found_in);
|
||||
|
||||
if (sel_ == SEL_IDX_DO)
|
||||
return elaborate_expr_net_idx_do_(des, scope, net, found_in);
|
||||
|
||||
// It's not anything else, so this must be a simple identifier
|
||||
// expression with no part or bit select. Return the signal
|
||||
// itself as the expression.
|
||||
assert(sel_ == SEL_NONE);
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_ == 0);
|
||||
|
||||
NetESignal*node = new NetESignal(net);
|
||||
node->set_line(*this);
|
||||
return node;
|
||||
}
|
||||
|
||||
NetEConst* PENumber::elaborate_expr(Design*des, NetScope*, bool) const
|
||||
{
|
||||
assert(value_);
|
||||
|
|
@ -1091,6 +1228,13 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
|||
|
||||
/*
|
||||
* $Log: elab_expr.cc,v $
|
||||
* Revision 1.99 2005/11/10 13:28:11 steve
|
||||
* Reorganize signal part select handling, and add support for
|
||||
* indexed part selects.
|
||||
*
|
||||
* Expand expression constant propagation to eliminate extra
|
||||
* sums in certain cases.
|
||||
*
|
||||
* Revision 1.98 2005/10/04 04:09:25 steve
|
||||
* Add support for indexed select attached to parameters.
|
||||
*
|
||||
|
|
|
|||
11
elaborate.cc
11
elaborate.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elaborate.cc,v 1.330 2005/09/27 04:51:37 steve Exp $"
|
||||
#ident "$Id: elaborate.cc,v 1.331 2005/11/10 13:28:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -587,7 +587,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Instantiate module "
|
||||
<< rmod->mod_name() << " With instance name "
|
||||
<< rmod->mod_name() << " with instance name "
|
||||
<< get_name() << " in scope " << scope->name() << endl;
|
||||
}
|
||||
|
||||
|
|
@ -3028,6 +3028,13 @@ Design* elaborate(list<perm_string>roots)
|
|||
|
||||
/*
|
||||
* $Log: elaborate.cc,v $
|
||||
* Revision 1.331 2005/11/10 13:28:11 steve
|
||||
* Reorganize signal part select handling, and add support for
|
||||
* indexed part selects.
|
||||
*
|
||||
* Expand expression constant propagation to eliminate extra
|
||||
* sums in certain cases.
|
||||
*
|
||||
* Revision 1.330 2005/09/27 04:51:37 steve
|
||||
* Error message for invalid for-loop index variable.
|
||||
*
|
||||
|
|
|
|||
51
eval_tree.cc
51
eval_tree.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_tree.cc,v 1.65 2005/09/14 02:53:14 steve Exp $"
|
||||
#ident "$Id: eval_tree.cc,v 1.66 2005/11/10 13:28:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -55,10 +55,11 @@ NetEConst* NetEBAdd::eval_tree()
|
|||
{
|
||||
eval_sub_tree_();
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
|
||||
/* If both operands are constant, then replace the entire
|
||||
expression with a constant value. */
|
||||
if (lc != 0 && rc != 0) {
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
|
||||
|
|
@ -77,6 +78,43 @@ NetEConst* NetEBAdd::eval_tree()
|
|||
return new NetEConst(val);
|
||||
}
|
||||
|
||||
/* Try to combine a right constant value with the right
|
||||
constant value of a sub-expression add. For example, the
|
||||
expression (a + 2) - 1 can be rewritten as a + 1. */
|
||||
|
||||
NetEBAdd*se = dynamic_cast<NetEBAdd*>(left_);
|
||||
lc = se? dynamic_cast<NetEConst*>(se->right_) : 0;
|
||||
|
||||
if (lc != 0 && rc != 0) {
|
||||
assert(se != 0);
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
|
||||
verinum val;
|
||||
if (op_ == se->op_) {
|
||||
/* (a + lval) + rval --> a + (rval+lval) */
|
||||
/* (a - lval) - rval --> a - (rval+lval) */
|
||||
val = rval + lval;
|
||||
} else {
|
||||
/* (a - lval) + rval --> a + (rval-lval) */
|
||||
/* (a + lval) - rval --> a - (rval-lval) */
|
||||
val = rval - lval;
|
||||
}
|
||||
|
||||
NetEConst*tmp = new NetEConst(val);
|
||||
left_ = se->left_->dup_expr();
|
||||
delete se;
|
||||
delete right_;
|
||||
right_ = tmp;
|
||||
/* We've changed the subexpression, but the result is
|
||||
still not constant, so return nil here anyhow. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Nothing more to be done, the value is not constant. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst* NetEBBits::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
|
@ -1561,6 +1599,13 @@ NetEConst* NetEUReduce::eval_tree()
|
|||
|
||||
/*
|
||||
* $Log: eval_tree.cc,v $
|
||||
* Revision 1.66 2005/11/10 13:28:12 steve
|
||||
* Reorganize signal part select handling, and add support for
|
||||
* indexed part selects.
|
||||
*
|
||||
* Expand expression constant propagation to eliminate extra
|
||||
* sums in certain cases.
|
||||
*
|
||||
* Revision 1.65 2005/09/14 02:53:14 steve
|
||||
* Support bool expressions and compares handle them optimally.
|
||||
*
|
||||
|
|
|
|||
7
parse.y
7
parse.y
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-2004 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2005 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
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: parse.y,v 1.206 2005/10/04 04:09:25 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.207 2005/11/10 13:28:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -985,6 +985,7 @@ expr_primary
|
|||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
tmp->msb_ = $3;
|
||||
tmp->sel_ = PEIdent::SEL_BIT;
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
@ -1455,6 +1456,7 @@ lavalue
|
|||
} else {
|
||||
tmp->msb_ = sel;
|
||||
}
|
||||
tmp->sel_ = PEIdent::SEL_BIT;
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
delete $1;
|
||||
|
|
@ -1465,6 +1467,7 @@ lavalue
|
|||
assert($2->count() == 2);
|
||||
tmp->msb_ = (*$2)[0];
|
||||
tmp->lsb_ = (*$2)[1];
|
||||
tmp->sel_ = PEIdent::SEL_PART;
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
delete $1;
|
||||
|
|
|
|||
Loading…
Reference in New Issue