Allow part selects of memory words in l-values.
This commit is contained in:
parent
3158e2caa1
commit
d434dd7296
17
PExpr.h
17
PExpr.h
|
|
@ -19,10 +19,11 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PExpr.h,v 1.76 2006/01/02 05:33:19 steve Exp $"
|
||||
#ident "$Id: PExpr.h,v 1.77 2006/02/02 02:43:57 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
# include <vector>
|
||||
# include "netlist.h"
|
||||
# include "verinum.h"
|
||||
# include "LineInfo.h"
|
||||
|
|
@ -282,15 +283,16 @@ class PEIdent : public PExpr {
|
|||
hname_t path_;
|
||||
|
||||
public:
|
||||
// Use these to support bit- and part-select operators.
|
||||
// Use these to support part-select operators.
|
||||
PExpr*msb_;
|
||||
PExpr*lsb_;
|
||||
|
||||
enum { SEL_NONE, SEL_BIT, SEL_PART, SEL_IDX_UP, SEL_IDX_DO } sel_;
|
||||
enum { SEL_NONE, SEL_PART, SEL_IDX_UP, SEL_IDX_DO } sel_;
|
||||
|
||||
// If this is a reference to a memory, this is the index
|
||||
// expression.
|
||||
PExpr*idx_;
|
||||
// If this is a reference to a memory/array, this is the index
|
||||
// expression. If this is a reference to a vector, this is a
|
||||
// bit select.
|
||||
std::vector<PExpr*> idx_;
|
||||
|
||||
NetNet* elaborate_net_ram_(Design*des, NetScope*scope,
|
||||
NetMemory*mem, unsigned lwidth,
|
||||
|
|
@ -546,6 +548,9 @@ class PECallFunction : public PExpr {
|
|||
|
||||
/*
|
||||
* $Log: PExpr.h,v $
|
||||
* Revision 1.77 2006/02/02 02:43:57 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.76 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: design_dump.cc,v 1.163 2005/08/27 04:32:08 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.164 2006/02/02 02:43:57 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -537,8 +537,8 @@ void NetAssign_::dump_lval(ostream&o) const
|
|||
if (bmux_) {
|
||||
o << "[" << *bmux_ << "]";
|
||||
|
||||
} else {
|
||||
o << "[" << (loff_+lwid_-1) << ":" << loff_ << "]";
|
||||
} else if (base_) {
|
||||
o << "[" << *base_ << " +: " << lwid_ << "]";
|
||||
}
|
||||
} else if (mem_) {
|
||||
// Is there an obvious way to flag memories in the dump
|
||||
|
|
@ -548,6 +548,10 @@ void NetAssign_::dump_lval(ostream&o) const
|
|||
if (bmux_) o << *bmux_;
|
||||
else o << "**oops**";
|
||||
o << "]";
|
||||
|
||||
if (base_) {
|
||||
o << "[" << *base_ << " +: " << lwid_ << "]";
|
||||
}
|
||||
} else {
|
||||
o << "";
|
||||
}
|
||||
|
|
@ -1166,6 +1170,9 @@ void Design::dump(ostream&o) const
|
|||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.164 2006/02/02 02:43:57 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.163 2005/08/27 04:32:08 steve
|
||||
* Handle synthesis of fully packed case statements.
|
||||
*
|
||||
|
|
|
|||
132
elab_expr.cc
132
elab_expr.cc
|
|
@ -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.101 2005/11/27 05:56:20 steve Exp $"
|
||||
#ident "$Id: elab_expr.cc,v 1.102 2006/02/02 02:43:57 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -515,7 +515,15 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
// memory reference and I must generate a NetEMemory
|
||||
// object to handle it.
|
||||
if (mem != 0) {
|
||||
if (msb_ == 0) {
|
||||
|
||||
if (idx_.empty()) {
|
||||
|
||||
if (msb_ || lsb_) {
|
||||
cerr << get_line() << ": error: "
|
||||
<< "Part select of a memory: "
|
||||
<< mem->name() << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
// If this memory is an argument to a system task,
|
||||
// then it is OK for it to not have an index.
|
||||
|
|
@ -533,27 +541,92 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
return 0;
|
||||
}
|
||||
|
||||
assert(msb_ != 0);
|
||||
if (lsb_) {
|
||||
cerr << get_line() << ": error: part select of a memory: "
|
||||
<< mem->name() << endl;
|
||||
if (idx_.size() != mem->dimensions()) {
|
||||
cerr << get_line() << ": error: " << idx_.size()
|
||||
<< " indices do not properly address a "
|
||||
<< mem->dimensions() << "-dimension memory/array."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_ == 0);
|
||||
NetExpr*i = msb_->elaborate_expr(des, scope);
|
||||
if (msb_ && i == 0) {
|
||||
// XXXX For now, only support single word index.
|
||||
assert(idx_.size() == 1);
|
||||
PExpr*addr = idx_[0];
|
||||
assert(addr);
|
||||
|
||||
NetExpr*i = addr->elaborate_expr(des, scope);
|
||||
if (i == 0) {
|
||||
cerr << get_line() << ": error: Unable to elaborate "
|
||||
"index expression `" << *msb_ << "'" << endl;
|
||||
"index expression `" << *addr << "'" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEMemory*node = new NetEMemory(mem, i);
|
||||
node->set_line(*this);
|
||||
return node;
|
||||
|
||||
if (msb_ == 0 && lsb_ == 0)
|
||||
return node;
|
||||
|
||||
assert(msb_ && lsb_);
|
||||
|
||||
assert(sel_ != SEL_NONE);
|
||||
|
||||
if (sel_ == SEL_PART) {
|
||||
|
||||
NetExpr*le = elab_and_eval(des, scope, lsb_);
|
||||
NetExpr*me = elab_and_eval(des, scope, msb_);
|
||||
|
||||
NetEConst*lec = dynamic_cast<NetEConst*>(le);
|
||||
NetEConst*mec = dynamic_cast<NetEConst*>(me);
|
||||
|
||||
if (lec == 0 || mec == 0) {
|
||||
cerr << get_line() << ": error: Part select "
|
||||
<< "expressions must be constant." << endl;
|
||||
des->errors += 1;
|
||||
delete le;
|
||||
delete me;
|
||||
return node;
|
||||
}
|
||||
|
||||
verinum wedv = mec->value() - lec->value();
|
||||
unsigned wid = wedv.as_long() + 1;
|
||||
|
||||
NetESelect*se = new NetESelect(node, le, wid);
|
||||
|
||||
delete me;
|
||||
return se;
|
||||
}
|
||||
|
||||
assert(sel_ == SEL_IDX_UP || sel_ == SEL_IDX_DO);
|
||||
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_);
|
||||
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
|
||||
if (wid_ec == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
<< "Second expression of indexed part select "
|
||||
<< "most be constant." << endl;
|
||||
des->errors += 1;
|
||||
return node;
|
||||
}
|
||||
|
||||
unsigned wid = wid_ec->value().as_ulong();
|
||||
|
||||
NetExpr*idx_ex = elab_and_eval(des, scope, msb_);
|
||||
if (idx_ex == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sel_ == SEL_IDX_DO && wid > 1) {
|
||||
idx_ex = make_add_expr(idx_ex, 1-(long)wid);
|
||||
}
|
||||
|
||||
|
||||
/* Wrap the param expression with a part select. */
|
||||
NetESelect*se = new NetESelect(node, idx_ex, wid);
|
||||
se->set_line(*this);
|
||||
return se;
|
||||
}
|
||||
|
||||
// If the identifier is a named event.
|
||||
|
|
@ -613,6 +686,7 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
|||
|
||||
if (sel_ == SEL_PART) {
|
||||
assert(msb_ && lsb_);
|
||||
assert(idx_.empty());
|
||||
|
||||
/* If the identifier has a part select, we support
|
||||
it by pulling the right bits out and making a
|
||||
|
|
@ -681,6 +755,7 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
|||
} else if (sel_ == SEL_IDX_UP || sel_ == SEL_IDX_DO) {
|
||||
assert(msb_);
|
||||
assert(lsb_);
|
||||
assert(idx_.empty());
|
||||
|
||||
/* Get and evaluate the width of the index
|
||||
select. This must be constant. */
|
||||
|
|
@ -710,14 +785,16 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
|||
tmp = new NetESelect(tmp, idx_ex, wid);
|
||||
|
||||
|
||||
} else if (sel_ == SEL_BIT) {
|
||||
assert(msb_);
|
||||
} else if (!idx_.empty()) {
|
||||
assert(!msb_);
|
||||
assert(!lsb_);
|
||||
assert(idx_.size() == 1);
|
||||
assert(sel_ == SEL_NONE);
|
||||
|
||||
/* Handle the case where a parameter has a bit
|
||||
select attached to it. Generate a NetESelect
|
||||
object to select the bit as desired. */
|
||||
NetExpr*mtmp = msb_->elaborate_expr(des, scope);
|
||||
NetExpr*mtmp = idx_[0]->elaborate_expr(des, scope);
|
||||
if (! dynamic_cast<NetEConst*>(mtmp)) {
|
||||
NetExpr*re = mtmp->eval_tree();
|
||||
if (re) {
|
||||
|
|
@ -815,7 +892,7 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
|||
{
|
||||
assert(lsb_ != 0);
|
||||
assert(msb_ != 0);
|
||||
assert(idx_ == 0);
|
||||
assert(idx_.empty());
|
||||
|
||||
verinum*lsn = lsb_->eval_const(des, scope);
|
||||
verinum*msn = msb_->eval_const(des, scope);
|
||||
|
|
@ -891,7 +968,7 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
|||
{
|
||||
assert(lsb_ != 0);
|
||||
assert(msb_ != 0);
|
||||
assert(idx_ == 0);
|
||||
assert(idx_.empty());
|
||||
|
||||
NetESignal*sig = new NetESignal(net);
|
||||
sig->set_line(*this);
|
||||
|
|
@ -944,7 +1021,7 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
|||
{
|
||||
assert(lsb_ != 0);
|
||||
assert(msb_ != 0);
|
||||
assert(idx_ == 0);
|
||||
assert(idx_.empty());
|
||||
|
||||
NetESignal*sig = new NetESignal(net);
|
||||
sig->set_line(*this);
|
||||
|
|
@ -993,14 +1070,14 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
|||
NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in) const
|
||||
{
|
||||
assert(msb_ != 0);
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_ == 0);
|
||||
assert(idx_.size() == 1);
|
||||
|
||||
// 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)) {
|
||||
if (verinum*msn = idx_[0]->eval_const(des, scope)) {
|
||||
long msv = msn->as_long();
|
||||
unsigned idx = net->sb_to_idx(msv);
|
||||
|
||||
|
|
@ -1047,7 +1124,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
// 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);
|
||||
NetExpr*ex = idx_[0]->elaborate_expr(des, scope);
|
||||
|
||||
if (net->msb() < net->lsb()) {
|
||||
ex = make_sub_expr(net->lsb(), ex);
|
||||
|
|
@ -1070,22 +1147,22 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
|
|||
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);
|
||||
|
||||
if (!idx_.empty())
|
||||
return elaborate_expr_net_bit_(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);
|
||||
assert(idx_.empty());
|
||||
|
||||
NetESignal*node = new NetESignal(net);
|
||||
node->set_line(*this);
|
||||
|
|
@ -1268,6 +1345,9 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
|||
|
||||
/*
|
||||
* $Log: elab_expr.cc,v $
|
||||
* Revision 1.102 2006/02/02 02:43:57 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.101 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
|
|
|
|||
110
elab_lval.cc
110
elab_lval.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_lval.cc,v 1.32 2005/07/11 16:56:50 steve Exp $"
|
||||
#ident "$Id: elab_lval.cc,v 1.33 2006/02/02 02:43:57 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -195,7 +195,9 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
long msb, lsb;
|
||||
NetExpr*mux;
|
||||
|
||||
if (msb_ && lsb_) {
|
||||
if (msb_ || lsb_) {
|
||||
assert(msb_ && lsb_);
|
||||
|
||||
/* This handles part selects. In this case, there are
|
||||
two bit select expressions, and both must be
|
||||
constant. Evaluate them and pass the results back to
|
||||
|
|
@ -225,17 +227,19 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
lsb = vl->as_long();
|
||||
mux = 0;
|
||||
|
||||
} else if (msb_) {
|
||||
} else if (! idx_.empty()) {
|
||||
|
||||
/* If there is only a single select expression, it is a
|
||||
bit select. Evaluate the constant value and treat it
|
||||
as a part select with a bit width of 1. If the
|
||||
expression it not constant, then return the
|
||||
expression as a mux. */
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
verinum*v = msb_->eval_const(des, scope);
|
||||
assert(idx_.size() == 1);
|
||||
verinum*v = idx_[0]->eval_const(des, scope);
|
||||
if (v == 0) {
|
||||
NetExpr*m = msb_->elaborate_expr(des, scope);
|
||||
NetExpr*m = idx_[0]->elaborate_expr(des, scope);
|
||||
assert(m);
|
||||
msb = 0;
|
||||
lsb = 0;
|
||||
|
|
@ -271,6 +275,12 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
|
||||
lv->set_bmux(mux);
|
||||
|
||||
} else if (msb == reg->msb() && lsb == reg->lsb()) {
|
||||
|
||||
/* No bit select, and part select covers the entire
|
||||
vector. Simplest case. */
|
||||
lv = new NetAssign_(reg);
|
||||
|
||||
} else {
|
||||
|
||||
/* If the bit/part select is constant, then make the
|
||||
|
|
@ -302,7 +312,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
}
|
||||
|
||||
lv = new NetAssign_(reg);
|
||||
lv->set_part(loff, wid);
|
||||
lv->set_part(new NetEConst(verinum(loff)), wid);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -312,7 +322,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
NetMemory*mem) const
|
||||
{
|
||||
if (msb_ == 0) {
|
||||
if (idx_.empty()) {
|
||||
cerr << get_line() << ": error: Assign to memory \""
|
||||
<< mem->name() << "\" requires a word select index."
|
||||
<< endl;
|
||||
|
|
@ -320,33 +330,82 @@ NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (msb_ && lsb_) {
|
||||
cerr << get_line() << ": error: Cannot use part select on "
|
||||
<< "memory \"" << mem->name() << ".\"" << endl;
|
||||
if (idx_.size() != mem->dimensions()) {
|
||||
cerr << get_line() << ": error: " << idx_.size()
|
||||
<< " indices do not properly address a "
|
||||
<< mem->dimensions() << "-dimension memory/array."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(msb_ && !lsb_);
|
||||
// XXXX For now, require exactly 1 index.
|
||||
assert(idx_.size() == 1);
|
||||
|
||||
NetExpr*ix = msb_->elaborate_expr(des, scope);
|
||||
/* Elaborate the address expression. */
|
||||
NetExpr*ix = elab_and_eval(des, scope, idx_[0]);
|
||||
if (ix == 0)
|
||||
return 0;
|
||||
|
||||
/* Evaluate the memory index expression down as must as
|
||||
possible. Ideally, we can get it down to a constant. */
|
||||
if (! dynamic_cast<NetEConst*>(ix)) {
|
||||
NetExpr*tmp = ix->eval_tree();
|
||||
if (tmp) {
|
||||
tmp->set_line(*ix);
|
||||
delete ix;
|
||||
ix = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
NetAssign_*lv = new NetAssign_(mem);
|
||||
lv->set_bmux(ix);
|
||||
lv->set_part(0, mem->width());
|
||||
|
||||
/* If there is no extra part select, then we are done. */
|
||||
if (msb_ == 0 && lsb_ == 0) {
|
||||
lv->set_part(0U, mem->width());
|
||||
return lv;
|
||||
}
|
||||
|
||||
assert(sel_ != SEL_NONE);
|
||||
assert(msb_ && lsb_);
|
||||
|
||||
if (sel_ == SEL_PART) {
|
||||
NetExpr*le = elab_and_eval(des, scope, lsb_);
|
||||
NetExpr*me = elab_and_eval(des, scope, msb_);
|
||||
|
||||
NetEConst*lec = dynamic_cast<NetEConst*>(le);
|
||||
NetEConst*mec = dynamic_cast<NetEConst*>(me);
|
||||
|
||||
if (lec == 0 || mec == 0) {
|
||||
cerr << get_line() << ": error: Part select "
|
||||
<< "expressions must be constant." << endl;
|
||||
des->errors += 1;
|
||||
delete le;
|
||||
delete me;
|
||||
return lv;
|
||||
}
|
||||
|
||||
verinum wedv = mec->value() - lec->value();
|
||||
unsigned wid = wedv.as_long() + 1;
|
||||
|
||||
lv->set_part(lec, wid);
|
||||
return lv;
|
||||
}
|
||||
|
||||
assert(sel_ == SEL_IDX_UP || sel_ == SEL_IDX_DO);
|
||||
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_);
|
||||
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
|
||||
if (wid_ec == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
<< "Second expression of indexed part select "
|
||||
<< "most be constant." << endl;
|
||||
des->errors += 1;
|
||||
return lv;
|
||||
}
|
||||
|
||||
unsigned wid = wid_ec->value().as_ulong();
|
||||
|
||||
NetExpr*base_ex = elab_and_eval(des, scope, msb_);
|
||||
if (base_ex == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sel_ == SEL_IDX_DO && wid > 1) {
|
||||
base_ex = make_add_expr(base_ex, 1-(long)wid);
|
||||
}
|
||||
|
||||
lv->set_part(base_ex, wid);
|
||||
return lv;
|
||||
}
|
||||
|
||||
|
|
@ -360,6 +419,9 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
|
|||
|
||||
/*
|
||||
* $Log: elab_lval.cc,v $
|
||||
* Revision 1.33 2006/02/02 02:43:57 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.32 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
|
|
|
|||
38
elab_net.cc
38
elab_net.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_net.cc,v 1.177 2006/01/02 05:33:19 steve Exp $"
|
||||
#ident "$Id: elab_net.cc,v 1.178 2006/02/02 02:43:57 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -1466,11 +1466,15 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
|
|||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const
|
||||
{
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_.size() == 1);
|
||||
|
||||
/* Elaborate the selector. */
|
||||
NetNet*sel;
|
||||
|
||||
if (sig->msb() < sig->lsb()) {
|
||||
NetExpr*sel_expr = msb_->elaborate_expr(des, scope);
|
||||
NetExpr*sel_expr = idx_[0]->elaborate_expr(des, scope);
|
||||
sel_expr = make_sub_expr(sig->lsb(), sel_expr);
|
||||
if (NetExpr*tmp = sel_expr->eval_tree()) {
|
||||
delete sel_expr;
|
||||
|
|
@ -1480,7 +1484,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
|
|||
sel = sel_expr->synthesize(des);
|
||||
|
||||
} else if (sig->lsb() != 0) {
|
||||
NetExpr*sel_expr = msb_->elaborate_expr(des, scope);
|
||||
NetExpr*sel_expr = idx_[0]->elaborate_expr(des, scope);
|
||||
sel_expr = make_add_expr(sel_expr, - sig->lsb());
|
||||
if (NetExpr*tmp = sel_expr->eval_tree()) {
|
||||
delete sel_expr;
|
||||
|
|
@ -1490,7 +1494,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
|
|||
sel = sel_expr->synthesize(des);
|
||||
|
||||
} else {
|
||||
sel = msb_->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
sel = idx_[0]->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
|
|
@ -1613,8 +1617,12 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
|||
|
||||
/* Catch the case of a non-constant bit select. That should be
|
||||
handled elsewhere. */
|
||||
if (msb_ && !lsb_) {
|
||||
verinum*mval = msb_->eval_const(des, scope);
|
||||
if (! idx_.empty()) {
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_.size() == 1);
|
||||
|
||||
verinum*mval = idx_[0]->eval_const(des, scope);
|
||||
if (mval == 0) {
|
||||
return elaborate_net_bitmux_(des, scope, sig, rise,
|
||||
fall, decay, drive0, drive1);
|
||||
|
|
@ -1666,20 +1674,24 @@ NetNet* PEIdent::elaborate_net_ram_(Design*des, NetScope*scope,
|
|||
{
|
||||
assert(scope);
|
||||
|
||||
if (msb_ == 0) {
|
||||
if (idx_.empty()) {
|
||||
cerr << get_line() << ": error: memory reference without"
|
||||
" the required index expression." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_.size() == 1);
|
||||
|
||||
/* Even if this expression must be fully self determined, the
|
||||
index expression does not, so make sure this flag is off
|
||||
while elaborating the address expression. */
|
||||
const bool must_be_self_determined_save = must_be_self_determined_flag;
|
||||
must_be_self_determined_flag = false;
|
||||
|
||||
NetExpr*adr_expr = elab_and_eval(des, scope, msb_);
|
||||
NetExpr*adr_expr = elab_and_eval(des, scope, idx_[0]);
|
||||
|
||||
/* If an offset is needed, subtract it from the address to get
|
||||
an expression for the canonical address. */
|
||||
|
|
@ -1905,8 +1917,11 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
|||
des->errors += 1;
|
||||
}
|
||||
|
||||
} else if (msb_) {
|
||||
verinum*mval = msb_->eval_const(des, scope);
|
||||
} else if (!idx_.empty()) {
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_.size() == 1);
|
||||
verinum*mval = idx_[0]->eval_const(des, scope);
|
||||
if (mval == 0) {
|
||||
cerr << get_line() << ": index of " << path_ <<
|
||||
" needs to be constant in this context." <<
|
||||
|
|
@ -2645,6 +2660,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
|
||||
/*
|
||||
* $Log: elab_net.cc,v $
|
||||
* Revision 1.178 2006/02/02 02:43:57 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.177 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_pexpr.cc,v 1.22 2005/11/27 05:56:20 steve Exp $"
|
||||
#ident "$Id: elab_pexpr.cc,v 1.23 2006/02/02 02:43:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -154,17 +154,20 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
|
|||
res->set_line(*this);
|
||||
assert(res);
|
||||
|
||||
assert(idx_ == 0);
|
||||
if (msb_ && lsb_) {
|
||||
assert(idx_.empty());
|
||||
cerr << get_line() << ": sorry: Cannot part select "
|
||||
"bits of parameters." << endl;
|
||||
des->errors += 1;
|
||||
|
||||
} else if (msb_) {
|
||||
} else if (!idx_.empty()) {
|
||||
assert(msb_==0);
|
||||
assert(lsb_==0);
|
||||
assert(idx_.size() == 1);
|
||||
|
||||
/* We have here a bit select. Insert a NetESelect node
|
||||
to handle it. */
|
||||
NetExpr*tmp = msb_->elaborate_pexpr(des, scope);
|
||||
NetExpr*tmp = idx_[0]->elaborate_pexpr(des, scope);
|
||||
if (tmp != 0) {
|
||||
res = new NetESelect(res, tmp, 1);
|
||||
}
|
||||
|
|
@ -233,6 +236,9 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
|
|||
|
||||
/*
|
||||
* $Log: elab_pexpr.cc,v $
|
||||
* Revision 1.23 2006/02/02 02:43:58 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.22 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
|
|
|
|||
23
ivl_target.h
23
ivl_target.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: ivl_target.h,v 1.164 2006/01/02 05:33:19 steve Exp $"
|
||||
#ident "$Id: ivl_target.h,v 1.165 2006/02/02 02:43:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -323,11 +323,11 @@ typedef enum ivl_statement_type_e {
|
|||
/* This is the type of a variable, and also used as the type for an
|
||||
expression. */
|
||||
typedef enum ivl_variable_type_e {
|
||||
IVL_VT_VOID = 0, /* Not used */
|
||||
IVL_VT_NO_TYPE, /* Place holder for missing/unknown type. */
|
||||
IVL_VT_REAL,
|
||||
IVL_VT_BOOL,
|
||||
IVL_VT_LOGIC,
|
||||
IVL_VT_VOID = 0, /* Not used */
|
||||
IVL_VT_NO_TYPE = 1, /* Place holder for missing/unknown type. */
|
||||
IVL_VT_REAL = 2,
|
||||
IVL_VT_BOOL = 3,
|
||||
IVL_VT_LOGIC = 4,
|
||||
IVL_VT_VECTOR = IVL_VT_LOGIC /* For compatibility */
|
||||
} ivl_variable_type_t;
|
||||
|
||||
|
|
@ -1078,6 +1078,8 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
|||
* returns an ivl_expr_t that represents that
|
||||
* expression. Otherwise, it returns 0.
|
||||
*
|
||||
* (Should this be combined with ivl_lval_idx? -Ed)
|
||||
*
|
||||
* ivl_lval_mem
|
||||
* If the l-value is a memory, this method returns an
|
||||
* ivl_memory_t that represents that memory. Otherwise, it
|
||||
|
|
@ -1089,7 +1091,9 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
|||
*
|
||||
* ivl_lval_part_off
|
||||
* The part select of the signal is based here. This is the
|
||||
* canonical index of bit-0 of the part select.
|
||||
* canonical index of bit-0 of the part select. The return value is
|
||||
* an ivl_expr_t. If the return value is nil, then take the offset
|
||||
* as zero. Otherwise, evaluate the expression to get the offset.
|
||||
*
|
||||
* ivl_lval_idx
|
||||
* If the l-value is a memory, this method returns an
|
||||
|
|
@ -1120,7 +1124,7 @@ extern unsigned ivl_lval_width(ivl_lval_t net);
|
|||
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net);
|
||||
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
|
||||
extern ivl_memory_t ivl_lval_mem(ivl_lval_t net);
|
||||
extern unsigned ivl_lval_part_off(ivl_lval_t net);
|
||||
extern ivl_expr_t ivl_lval_part_off(ivl_lval_t net);
|
||||
extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
|
||||
|
||||
|
||||
|
|
@ -1703,6 +1707,9 @@ _END_DECL
|
|||
|
||||
/*
|
||||
* $Log: ivl_target.h,v $
|
||||
* Revision 1.165 2006/02/02 02:43:58 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.164 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_assign.cc,v 1.20 2005/07/11 16:56:50 steve Exp $"
|
||||
#ident "$Id: net_assign.cc,v 1.21 2006/02/02 02:43:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -39,18 +39,16 @@ unsigned count_lval_width(const NetAssign_*idx)
|
|||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetNet*s)
|
||||
: sig_(s), mem_(0), bmux_(0)
|
||||
: sig_(s), mem_(0), bmux_(0), base_(0)
|
||||
{
|
||||
loff_ = 0;
|
||||
lwid_ = sig_->vector_width();
|
||||
sig_->incr_lref();
|
||||
more = 0;
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetMemory*s)
|
||||
: sig_(0), mem_(s), bmux_(0)
|
||||
: sig_(0), mem_(s), bmux_(0), base_(0)
|
||||
{
|
||||
loff_ = 0;
|
||||
lwid_ = mem_->width();
|
||||
more = 0;
|
||||
}
|
||||
|
|
@ -83,6 +81,11 @@ const NetExpr* NetAssign_::bmux() const
|
|||
return bmux_;
|
||||
}
|
||||
|
||||
const NetExpr* NetAssign_::get_base() const
|
||||
{
|
||||
return base_;
|
||||
}
|
||||
|
||||
unsigned NetAssign_::lwidth() const
|
||||
{
|
||||
if (mem_) return lwid_;
|
||||
|
|
@ -111,21 +114,10 @@ NetMemory* NetAssign_::mem() const
|
|||
return mem_;
|
||||
}
|
||||
|
||||
void NetAssign_::set_part(unsigned lo, unsigned lw)
|
||||
void NetAssign_::set_part(NetExpr*base, unsigned wid)
|
||||
{
|
||||
loff_ = lo;
|
||||
lwid_ = lw;
|
||||
if (sig_) {
|
||||
assert(sig_->vector_width() >= (lo + lw));
|
||||
} else {
|
||||
assert(mem_);
|
||||
assert(lwid_ == mem_->width());
|
||||
}
|
||||
}
|
||||
|
||||
unsigned NetAssign_::get_loff() const
|
||||
{
|
||||
return loff_;
|
||||
base_ = base;
|
||||
lwid_ = wid;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -283,6 +275,9 @@ NetRelease::~NetRelease()
|
|||
|
||||
/*
|
||||
* $Log: net_assign.cc,v $
|
||||
* Revision 1.21 2006/02/02 02:43:58 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.20 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
|
|
|
|||
10
net_link.cc
10
net_link.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_link.cc,v 1.18 2005/09/25 23:40:11 steve Exp $"
|
||||
#ident "$Id: net_link.cc,v 1.19 2006/02/02 02:43:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -58,7 +58,10 @@ void connect(Nexus*l, Link&r)
|
|||
void connect(Link&l, Link&r)
|
||||
{
|
||||
assert(&l != &r);
|
||||
connect(l.nexus_, r);
|
||||
if (r.is_linked() && !l.is_linked())
|
||||
connect(r.nexus_, l);
|
||||
else
|
||||
connect(l.nexus_, r);
|
||||
}
|
||||
|
||||
Link::Link()
|
||||
|
|
@ -522,6 +525,9 @@ bool NexusSet::intersect(const NexusSet&that) const
|
|||
|
||||
/*
|
||||
* $Log: net_link.cc,v $
|
||||
* Revision 1.19 2006/02/02 02:43:58 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.18 2005/09/25 23:40:11 steve
|
||||
* Simplify NexusSet set handling.
|
||||
*
|
||||
|
|
|
|||
21
netlist.h
21
netlist.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netlist.h,v 1.354 2006/01/02 05:33:19 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.355 2006/02/02 02:43:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -791,7 +791,11 @@ class NetMemory {
|
|||
// This is the width (in bits) of a single memory position.
|
||||
unsigned width() const { return width_; }
|
||||
|
||||
// NetScope*scope();
|
||||
// This is the number of dimensions for the memory. A baseline
|
||||
// verilog memory has always 1 dimension, but N-dimensional
|
||||
// arrays have N.
|
||||
unsigned dimensions() const { return 1; }
|
||||
|
||||
const NetScope*scope() const { return scope_; };
|
||||
|
||||
// This is the number of memory positions.
|
||||
|
|
@ -1644,10 +1648,12 @@ class NetAssign_ {
|
|||
NetExpr*bmux();
|
||||
const NetExpr*bmux() const;
|
||||
|
||||
unsigned get_loff() const;
|
||||
// Get the base index of the part select, or 0 if there is no
|
||||
// part select.
|
||||
const NetExpr* get_base() const;
|
||||
|
||||
void set_bmux(NetExpr*);
|
||||
void set_part(unsigned loff, unsigned wid);
|
||||
void set_part(NetExpr* loff, unsigned wid);
|
||||
|
||||
// Get the width of the r-value that this node expects. This
|
||||
// method accounts for the presence of the mux, so it not
|
||||
|
|
@ -1679,10 +1685,12 @@ class NetAssign_ {
|
|||
private:
|
||||
NetNet *sig_;
|
||||
NetMemory*mem_;
|
||||
// Memory word index
|
||||
NetExpr*bmux_;
|
||||
|
||||
bool turn_sig_to_wire_on_release_;
|
||||
unsigned loff_;
|
||||
// indexed part select base
|
||||
NetExpr*base_;
|
||||
unsigned lwid_;
|
||||
};
|
||||
|
||||
|
|
@ -3451,6 +3459,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.355 2006/02/02 02:43:58 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.354 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
|
|
|
|||
176
parse.y
176
parse.y
|
|
@ -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.208 2005/12/05 21:21:18 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.209 2006/02/02 02:43:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -104,6 +104,8 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
|
|||
|
||||
svector<PEEvent*>*event_expr;
|
||||
|
||||
PEIdent*indexed_identifier;
|
||||
|
||||
NetNet::Type nettype;
|
||||
PGBuiltin::Type gatetype;
|
||||
NetNet::PortType porttype;
|
||||
|
|
@ -193,11 +195,12 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
|
|||
%type <gates> gate_instance_list
|
||||
|
||||
%type <expr> expression expr_primary
|
||||
%type <expr> lavalue lpvalue
|
||||
%type <expr> lpvalue
|
||||
%type <expr> delay_value delay_value_simple
|
||||
%type <exprs> delay1 delay3 delay3_opt
|
||||
%type <exprs> expression_list
|
||||
%type <exprs> assign assign_list
|
||||
%type <indexed_identifier> indexed_identifier
|
||||
|
||||
%type <exprs> range range_opt
|
||||
%type <nettype> net_type var_type net_type_opt
|
||||
|
|
@ -967,13 +970,6 @@ expr_primary
|
|||
tmp->set_lineno(@1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| identifier
|
||||
{ PEIdent*tmp = new PEIdent(*$1);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
$$ = tmp;
|
||||
delete $1;
|
||||
}
|
||||
| SYSTEM_IDENTIFIER
|
||||
{ PECallFunction*tmp = new PECallFunction(hname_t($1));
|
||||
tmp->set_file(@1.text);
|
||||
|
|
@ -981,13 +977,12 @@ expr_primary
|
|||
$$ = tmp;
|
||||
delete $1;
|
||||
}
|
||||
| identifier '[' expression ']'
|
||||
{ PEIdent*tmp = new PEIdent(*$1);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
tmp->msb_ = $3;
|
||||
tmp->sel_ = PEIdent::SEL_BIT;
|
||||
delete $1;
|
||||
|
||||
/* The indexed_identifier rule matches simple identifiers as well as
|
||||
indexed arrays. Part selects are handled below. */
|
||||
|
||||
| indexed_identifier
|
||||
{ PEIdent*tmp = $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
|
|
@ -996,34 +991,25 @@ expr_primary
|
|||
place of the : in the basic part select, and the first expression
|
||||
is not limited to constant values. */
|
||||
|
||||
| identifier '[' expression ':' expression ']'
|
||||
{ PEIdent*tmp = new PEIdent(*$1);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
| indexed_identifier '[' expression ':' expression ']'
|
||||
{ PEIdent*tmp = $1;
|
||||
tmp->msb_ = $3;
|
||||
tmp->lsb_ = $5;
|
||||
tmp->sel_ = PEIdent::SEL_PART;
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| identifier '[' expression K_PO_POS expression ']'
|
||||
{ PEIdent*tmp = new PEIdent(*$1);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
| indexed_identifier '[' expression K_PO_POS expression ']'
|
||||
{ PEIdent*tmp = $1;
|
||||
tmp->msb_ = $3;
|
||||
tmp->lsb_ = $5;
|
||||
tmp->sel_ = PEIdent::SEL_IDX_UP;
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| identifier '[' expression K_PO_NEG expression ']'
|
||||
{ PEIdent*tmp = new PEIdent(*$1);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
| indexed_identifier '[' expression K_PO_NEG expression ']'
|
||||
{ PEIdent*tmp = $1;
|
||||
tmp->msb_ = $3;
|
||||
tmp->lsb_ = $5;
|
||||
tmp->sel_ = PEIdent::SEL_IDX_DO;
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
|
|
@ -1075,7 +1061,6 @@ expr_primary
|
|||
}
|
||||
;
|
||||
|
||||
|
||||
/* A function_item is either a block item (i.e. a reg or integer
|
||||
declaration) or an input declaration. There are no output or
|
||||
inout ports. */
|
||||
|
|
@ -1260,6 +1245,24 @@ identifier
|
|||
}
|
||||
;
|
||||
|
||||
/* An indexed_identifier is an identifier with a bit-select
|
||||
expression. This bit select may be an array index or bit index,
|
||||
to be sorted out later. */
|
||||
indexed_identifier
|
||||
: identifier
|
||||
{ PEIdent*tmp = new PEIdent(*$1);
|
||||
tmp->sel_ = PEIdent::SEL_NONE;
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| indexed_identifier '[' expression ']'
|
||||
{ PEIdent*tmp = $1;
|
||||
tmp->idx_.push_back($3);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/* This is a list of identifiers. The result is a list of strings,
|
||||
each one of the identifiers in the list. These are simple,
|
||||
non-hierarchical names separated by ',' characters. */
|
||||
|
|
@ -1436,80 +1439,33 @@ net_type_opt
|
|||
|
||||
signed_opt : K_signed { $$ = true; } | {$$ = false; } ;
|
||||
|
||||
/* An lavalue is the expression that can go on the left side of a
|
||||
continuous assign statement. This checks (where it can) that the
|
||||
expression meets the constraints of continuous assignments. */
|
||||
lavalue
|
||||
: identifier
|
||||
{ PEIdent*tmp = new PEIdent(*$1);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| identifier '[' expression ']'
|
||||
{ PEIdent*tmp = new PEIdent(*$1);
|
||||
PExpr*sel = $3;
|
||||
if (! pform_expression_is_constant(sel)) {
|
||||
yyerror(@2, "error: Bit select in lvalue must "
|
||||
"contain a constant expression.");
|
||||
delete sel;
|
||||
} else {
|
||||
tmp->msb_ = sel;
|
||||
}
|
||||
tmp->sel_ = PEIdent::SEL_BIT;
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| identifier range
|
||||
{ PEIdent*tmp = new PEIdent(*$1);
|
||||
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;
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
| '{' expression_list '}'
|
||||
{ PEConcat*tmp = new PEConcat(*$2);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
/* An lpvalue is the expression that can go on the left side of a
|
||||
procedural assignment. This rule handles only procedural assignments. */
|
||||
procedural assignment. This rule handles only procedural
|
||||
assignments. It is more limited then the general expr_primary
|
||||
rule to reflect the rules for assignment l-values. */
|
||||
lpvalue
|
||||
: identifier
|
||||
{ PEIdent*tmp = new PEIdent(*$1);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
delete $1;
|
||||
: indexed_identifier
|
||||
{ PEIdent*tmp = $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| identifier '[' expression ']'
|
||||
{ PEIdent*tmp = new PEIdent(*$1);
|
||||
tmp->msb_ = $3;
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
delete $1;
|
||||
|
||||
$$ = tmp;
|
||||
}
|
||||
| identifier '[' expression ':' expression ']'
|
||||
{ PEIdent*tmp = new PEIdent(*$1);
|
||||
| indexed_identifier '[' expression ':' expression ']'
|
||||
{ PEIdent*tmp = $1;
|
||||
tmp->msb_ = $3;
|
||||
tmp->lsb_ = $5;
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| indexed_identifier '[' expression K_PO_POS expression ']'
|
||||
{ PEIdent*tmp = $1;
|
||||
tmp->msb_ = $3;
|
||||
tmp->lsb_ = $5;
|
||||
tmp->sel_ = PEIdent::SEL_IDX_UP;
|
||||
$$ = tmp;
|
||||
}
|
||||
| indexed_identifier '[' expression K_PO_NEG expression ']'
|
||||
{ PEIdent*tmp = $1;
|
||||
tmp->msb_ = $3;
|
||||
tmp->lsb_ = $5;
|
||||
tmp->sel_ = PEIdent::SEL_IDX_DO;
|
||||
$$ = tmp;
|
||||
}
|
||||
| '{' expression_list '}'
|
||||
|
|
@ -1522,7 +1478,7 @@ lpvalue
|
|||
;
|
||||
|
||||
assign
|
||||
: lavalue '=' expression
|
||||
: lpvalue '=' expression
|
||||
{ svector<PExpr*>*tmp = new svector<PExpr*>(2);
|
||||
(*tmp)[0] = $1;
|
||||
(*tmp)[1] = $3;
|
||||
|
|
@ -2595,14 +2551,14 @@ statement
|
|||
off. This stronger then any other assign, but weaker then the
|
||||
force assignments. */
|
||||
|
||||
: K_assign lavalue '=' expression ';'
|
||||
: K_assign lpvalue '=' expression ';'
|
||||
{ PCAssign*tmp = new PCAssign($2, $4);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
| K_deassign lavalue ';'
|
||||
| K_deassign lpvalue ';'
|
||||
{ PDeassign*tmp = new PDeassign($2);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
|
|
@ -2613,13 +2569,13 @@ statement
|
|||
/* Force and release statements are similar to assignments,
|
||||
syntactically, but they will be elaborated differently. */
|
||||
|
||||
| K_force lavalue '=' expression ';'
|
||||
| K_force lpvalue '=' expression ';'
|
||||
{ PForce*tmp = new PForce($2, $4);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_release lavalue ';'
|
||||
| K_release lpvalue ';'
|
||||
{ PRelease*tmp = new PRelease($2);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
|
|
@ -2843,12 +2799,22 @@ statement
|
|||
tmp->set_lineno(@1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| error '=' expression ';'
|
||||
{ yyerror(@1, "Syntax in assignment statement l-value.");
|
||||
yyerrok;
|
||||
$$ = new PNoop;
|
||||
}
|
||||
| lpvalue K_LE expression ';'
|
||||
{ PAssignNB*tmp = new PAssignNB($1,$3);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| error K_LE expression ';'
|
||||
{ yyerror(@1, "Syntax in assignment statement l-value.");
|
||||
yyerrok;
|
||||
$$ = new PNoop;
|
||||
}
|
||||
| lpvalue '=' delay1 expression ';'
|
||||
{ assert($3->count() == 1);
|
||||
PExpr*del = (*$3)[0];
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-api.cc,v 1.132 2006/01/02 05:33:19 steve Exp $"
|
||||
#ident "$Id: t-dll-api.cc,v 1.133 2006/02/02 02:43:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -1217,10 +1217,10 @@ extern "C" ivl_memory_t ivl_lval_mem(ivl_lval_t net)
|
|||
return 0x0;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_lval_part_off(ivl_lval_t net)
|
||||
extern "C" ivl_expr_t ivl_lval_part_off(ivl_lval_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->loff_;
|
||||
return net->loff;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_lval_width(ivl_lval_t net)
|
||||
|
|
@ -2033,6 +2033,9 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
|
|||
|
||||
/*
|
||||
* $Log: t-dll-api.cc,v $
|
||||
* Revision 1.133 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.132 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-proc.cc,v 1.67 2005/07/11 16:56:51 steve Exp $"
|
||||
#ident "$Id: t-dll-proc.cc,v 1.68 2006/02/02 02:43:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -154,9 +154,18 @@ void dll_target::make_assign_lvals_(const NetAssignBase*net)
|
|||
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
|
||||
struct ivl_lval_s*cur = stmt_cur_->u_.assign_.lval_ + idx;
|
||||
const NetAssign_*asn = net->l_val(idx);
|
||||
const NetExpr*loff = asn->get_base();
|
||||
|
||||
if (loff == 0) {
|
||||
cur->loff = 0;
|
||||
} else {
|
||||
loff->expr_scan(this);
|
||||
cur->loff = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
|
||||
cur->width_ = asn->lwidth();
|
||||
cur->loff_ = asn->get_loff();
|
||||
|
||||
if (asn->sig()) {
|
||||
cur->type_ = IVL_LVAL_REG;
|
||||
cur->n.sig = find_signal(des_, asn->sig());
|
||||
|
|
@ -732,6 +741,9 @@ void dll_target::proc_while(const NetWhile*net)
|
|||
|
||||
/*
|
||||
* $Log: t-dll-proc.cc,v $
|
||||
* Revision 1.68 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.67 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
|
|
|
|||
11
t-dll.h
11
t-dll.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll.h,v 1.129 2006/01/02 05:33:19 steve Exp $"
|
||||
#ident "$Id: t-dll.h,v 1.130 2006/02/02 02:43:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
|
|
@ -379,10 +379,10 @@ enum ivl_lval_type_t {
|
|||
};
|
||||
|
||||
struct ivl_lval_s {
|
||||
unsigned width_;
|
||||
unsigned loff_;
|
||||
unsigned type_ : 8;
|
||||
ivl_expr_t loff;
|
||||
ivl_expr_t idx;
|
||||
unsigned width_;
|
||||
unsigned type_ : 8;
|
||||
union {
|
||||
ivl_signal_t sig;
|
||||
ivl_memory_t mem;
|
||||
|
|
@ -671,6 +671,9 @@ struct ivl_statement_s {
|
|||
|
||||
/*
|
||||
* $Log: t-dll.h,v $
|
||||
* Revision 1.130 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.129 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: statement.c,v 1.8 2005/11/20 15:58:53 steve Exp $"
|
||||
#ident "$Id: statement.c,v 1.9 2006/02/02 02:43:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -32,11 +32,18 @@ static unsigned show_assign_lval(ivl_lval_t lval, unsigned ind)
|
|||
if ( (mem = ivl_lval_mem(lval)) ) {
|
||||
|
||||
ivl_scope_t scope = ivl_memory_scope(mem);
|
||||
fprintf(out, "%*s{ %s . %s [\n", ind, "",
|
||||
fprintf(out, "%*s{ %s.%s width=%u }\n", ind, "",
|
||||
ivl_scope_name(scope),
|
||||
ivl_memory_basename(mem));
|
||||
show_expression(ivl_lval_idx(lval), ind+4);
|
||||
fprintf(out, "%*s] width=%u }\n", ind, "", ivl_lval_width(lval));
|
||||
ivl_memory_basename(mem),
|
||||
ivl_lval_width(lval));
|
||||
|
||||
fprintf(out, "%*sAddress-0 expression:\n", ind+4, "");
|
||||
show_expression(ivl_lval_idx(lval), ind+8);
|
||||
|
||||
if (ivl_lval_part_off(lval)) {
|
||||
fprintf(out, "%*sPart select base:\n", ind+4, "");
|
||||
show_expression(ivl_lval_part_off(lval), ind+8);
|
||||
}
|
||||
|
||||
/* When the l-value is a memory word, the lval_width
|
||||
must exactly match the word width. */
|
||||
|
|
@ -50,16 +57,20 @@ static unsigned show_assign_lval(ivl_lval_t lval, unsigned ind)
|
|||
} else {
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
|
||||
fprintf(out, "%*s{name=%s width=%u part_off=%u lvwidth=%u}\n",
|
||||
fprintf(out, "%*s{name=%s width=%u lvwidth=%u}\n",
|
||||
ind, "",
|
||||
ivl_signal_name(sig),
|
||||
ivl_signal_width(sig),
|
||||
ivl_lval_part_off(lval),
|
||||
ivl_lval_width(lval));
|
||||
if (ivl_lval_mux(lval)) {
|
||||
fprintf(out, "%*sBit select expression:\n", ind+4, "");
|
||||
show_expression(ivl_lval_mux(lval), ind+8);
|
||||
}
|
||||
if (ivl_lval_part_off(lval)) {
|
||||
fprintf(out, "%*sPart select base:\n", ind+4, "");
|
||||
show_expression(ivl_lval_part_off(lval), ind+8);
|
||||
}
|
||||
|
||||
wid = ivl_lval_width(lval);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_expr.c,v 1.129 2006/01/02 05:33:20 steve Exp $"
|
||||
#ident "$Id: eval_expr.c,v 1.130 2006/02/02 02:43:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
|
|
@ -101,6 +101,38 @@ unsigned long get_number_immediate(ivl_expr_t ex)
|
|||
return imm;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function, in addition to setting the value into index 0, sets
|
||||
* bit 4 to 1 if the value is unknown.
|
||||
*/
|
||||
void draw_eval_expr_into_integer(ivl_expr_t expr, unsigned ix)
|
||||
{
|
||||
struct vector_info vec;
|
||||
int word;
|
||||
|
||||
switch (ivl_expr_value(expr)) {
|
||||
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC:
|
||||
vec = draw_eval_expr(expr, 0);
|
||||
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
|
||||
ix, vec.base, vec.wid);
|
||||
clr_vector(vec);
|
||||
break;
|
||||
|
||||
case IVL_VT_REAL:
|
||||
word = draw_eval_real(expr);
|
||||
clr_word(word);
|
||||
fprintf(vvp_out, " %%cvt/ir %u, %u;\n", ix, word);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "XXXX ivl_expr_value == %d\n",
|
||||
ivl_expr_value(expr));
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The STUFF_OK_XZ bit is true if the output is going to be further
|
||||
* processed so that x and z values are equivilent. This may allow for
|
||||
|
|
@ -2177,6 +2209,9 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
|
|||
|
||||
/*
|
||||
* $Log: eval_expr.c,v $
|
||||
* Revision 1.130 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.129 2006/01/02 05:33:20 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vvp_priv.h,v 1.39 2005/10/12 17:26:17 steve Exp $"
|
||||
#ident "$Id: vvp_priv.h,v 1.40 2006/02/02 02:43:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_config.h"
|
||||
|
|
@ -150,6 +150,13 @@ extern struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned w,
|
|||
*/
|
||||
extern void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t exp);
|
||||
|
||||
/*
|
||||
* This evaluates an expression and leaves the result in the numbered
|
||||
* integer index register. It also will set bit-4 to 1 if the value is
|
||||
* not fully defined (i.e. contains x or z).
|
||||
*/
|
||||
extern void draw_eval_expr_into_integer(ivl_expr_t expr, unsigned ix);
|
||||
|
||||
/*
|
||||
* These functions manage vector allocation in the thread register
|
||||
* space. They presume that we work on one thread at a time, to
|
||||
|
|
@ -245,6 +252,9 @@ extern unsigned thread_count;
|
|||
|
||||
/*
|
||||
* $Log: vvp_priv.h,v $
|
||||
* Revision 1.40 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.39 2005/10/12 17:26:17 steve
|
||||
* MUX nodes get inputs from nets, not from net inputs,
|
||||
* Detect and draw alias nodes to reduce net size and
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vvp_process.c,v 1.121 2005/11/26 17:23:17 steve Exp $"
|
||||
#ident "$Id: vvp_process.c,v 1.122 2006/02/02 02:43:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
|
|
@ -29,7 +29,6 @@
|
|||
# include <stdlib.h>
|
||||
|
||||
static int show_statement(ivl_statement_t net, ivl_scope_t sscope);
|
||||
static void draw_eval_expr_into_integer(ivl_expr_t expr, unsigned ix);
|
||||
|
||||
unsigned local_count = 0;
|
||||
unsigned thread_count = 0;
|
||||
|
|
@ -76,7 +75,15 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
unsigned bit, unsigned wid)
|
||||
{
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
unsigned part_off = ivl_lval_part_off(lval);
|
||||
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
||||
unsigned part_off;
|
||||
|
||||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
} else {
|
||||
assert(number_is_immediate(part_off_ex, 64));
|
||||
part_off = get_number_immediate(part_off_ex);
|
||||
}
|
||||
|
||||
if (ivl_lval_mux(lval)) {
|
||||
unsigned skip_set = transient_id++;
|
||||
|
|
@ -117,10 +124,26 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
* the memory, and bit is the base of the thread vector. The wid is
|
||||
* the width of the vector to be written to the word.
|
||||
*/
|
||||
static void set_to_memory_word(ivl_memory_t mem, unsigned idx,
|
||||
static void set_to_memory_word(ivl_lval_t lval, unsigned idx,
|
||||
unsigned bit, unsigned wid)
|
||||
{
|
||||
unsigned skip_set = transient_id++;
|
||||
ivl_memory_t mem = ivl_lval_mem(lval);
|
||||
|
||||
/* Calculate the word part select into index-1 */
|
||||
if (ivl_lval_part_off(lval)) {
|
||||
draw_eval_expr_into_integer(ivl_lval_part_off(lval), 1);
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%ix/load 1, 0;\n");
|
||||
}
|
||||
|
||||
/* Calculate the memory address into index-3 */
|
||||
draw_memory_index_expr(mem, ivl_lval_idx(lval));
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
|
||||
fprintf(vvp_out, " %%set/mv M_%p, %u, %u;\n", mem, bit, wid);
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_set);
|
||||
}
|
||||
|
||||
static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
||||
|
|
@ -128,8 +151,16 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
unsigned width)
|
||||
{
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
unsigned part_off = ivl_lval_part_off(lval);
|
||||
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
||||
ivl_expr_t mux = ivl_lval_mux(lval);
|
||||
unsigned part_off;
|
||||
|
||||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
} else {
|
||||
assert(number_is_immediate(part_off_ex, 64));
|
||||
part_off = get_number_immediate(part_off_ex);
|
||||
}
|
||||
|
||||
if (mux != 0) {
|
||||
unsigned skip_assign = transient_id++;
|
||||
|
|
@ -166,42 +197,31 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
}
|
||||
}
|
||||
|
||||
static void assign_to_memory_word(ivl_memory_t mem, unsigned bit,
|
||||
static void assign_to_memory_word(ivl_lval_t lval, unsigned bit,
|
||||
unsigned delay, unsigned wid)
|
||||
{
|
||||
assert(wid = ivl_memory_width(mem));
|
||||
unsigned skip_set = transient_id++;
|
||||
ivl_memory_t mem = ivl_lval_mem(lval);
|
||||
//assert(wid == ivl_memory_width(mem));
|
||||
|
||||
/* Calculate the word part select into index-1 */
|
||||
if (ivl_lval_part_off(lval)) {
|
||||
draw_eval_expr_into_integer(ivl_lval_part_off(lval), 1);
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%ix/load 1, 0;\n");
|
||||
}
|
||||
|
||||
/* Calculate the memory address into index-3 */
|
||||
draw_memory_index_expr(mem, ivl_lval_idx(lval));
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
|
||||
/* Load the word/part-select width into index-0 */
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", wid);
|
||||
fprintf(vvp_out, " %%assign/mv M_%p, %u, %u;\n", mem, delay, bit);
|
||||
}
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_set);
|
||||
|
||||
/*
|
||||
* This function, in addition to setting the value into index 0, sets
|
||||
* bit 4 to 1 if the value is unknown.
|
||||
*/
|
||||
static void draw_eval_expr_into_integer(ivl_expr_t expr, unsigned ix)
|
||||
{
|
||||
struct vector_info vec;
|
||||
int word;
|
||||
|
||||
switch (ivl_expr_value(expr)) {
|
||||
|
||||
case IVL_VT_VECTOR:
|
||||
vec = draw_eval_expr(expr, 0);
|
||||
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
|
||||
ix, vec.base, vec.wid);
|
||||
clr_vector(vec);
|
||||
break;
|
||||
|
||||
case IVL_VT_REAL:
|
||||
word = draw_eval_real(expr);
|
||||
clr_word(word);
|
||||
fprintf(vvp_out, " %%cvt/ir %u, %u;\n", ix, word);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
clear_expression_lookaside();
|
||||
}
|
||||
|
||||
static void calculate_into_x1(ivl_expr_t expr)
|
||||
|
|
@ -225,23 +245,12 @@ static void set_vec_to_lval(ivl_statement_t net, struct vector_info res)
|
|||
unsigned cur_rbit = 0;
|
||||
|
||||
for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
|
||||
unsigned skip_set = transient_id++;
|
||||
unsigned skip_set_flag = 0;
|
||||
unsigned bidx;
|
||||
unsigned bit_limit = wid - cur_rbit;
|
||||
|
||||
lval = ivl_stmt_lval(net, lidx);
|
||||
|
||||
|
||||
mem = ivl_lval_mem(lval);
|
||||
if (mem) {
|
||||
/* If a memory, then the idx expression is the
|
||||
memory index, and the ivl_lval_mux should be
|
||||
absent. */
|
||||
assert(! ivl_lval_mux(lval));
|
||||
draw_memory_index_expr(mem, ivl_lval_idx(lval));
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
skip_set_flag = 1;
|
||||
}
|
||||
|
||||
/* Reduce bit_limit to the width of this l-value. */
|
||||
if (bit_limit > ivl_lval_width(lval))
|
||||
|
|
@ -252,7 +261,7 @@ static void set_vec_to_lval(ivl_statement_t net, struct vector_info res)
|
|||
bidx = res.base < 4? res.base : (res.base+cur_rbit);
|
||||
|
||||
if (mem) {
|
||||
set_to_memory_word(mem, 3, bidx, bit_limit);
|
||||
set_to_memory_word(lval, 3, bidx, bit_limit);
|
||||
|
||||
} else {
|
||||
set_to_lvariable(lval, bidx, bit_limit);
|
||||
|
|
@ -261,11 +270,6 @@ static void set_vec_to_lval(ivl_statement_t net, struct vector_info res)
|
|||
/* Now we've consumed this many r-value bits for the
|
||||
current l-value. */
|
||||
cur_rbit += bit_limit;
|
||||
|
||||
if (skip_set_flag) {
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_set);
|
||||
clear_expression_lookaside();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -440,17 +444,10 @@ static int show_stmt_assign_nb(ivl_statement_t net)
|
|||
calculate_into_x1(del);
|
||||
|
||||
for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
|
||||
unsigned skip_set = transient_id++;
|
||||
unsigned skip_set_flag = 0;
|
||||
unsigned bit_limit = wid - cur_rbit;
|
||||
lval = ivl_stmt_lval(net, lidx);
|
||||
|
||||
mem = ivl_lval_mem(lval);
|
||||
if (mem) {
|
||||
draw_memory_index_expr(mem, ivl_lval_idx(lval));
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
skip_set_flag = 1;
|
||||
}
|
||||
|
||||
if (bit_limit > ivl_lval_width(lval))
|
||||
bit_limit = ivl_lval_width(lval);
|
||||
|
|
@ -464,21 +461,16 @@ static int show_stmt_assign_nb(ivl_statement_t net)
|
|||
} else {
|
||||
unsigned bidx;
|
||||
|
||||
assert(mem);
|
||||
/* XXXX don't yet know what to do with a delay
|
||||
in an index variable. */
|
||||
/* XXXX don't yet know what to do with a
|
||||
non-constant delay exprssion. */
|
||||
assert(del == 0);
|
||||
|
||||
bidx = res.base < 4? res.base : (res.base+cur_rbit);
|
||||
assign_to_memory_word(mem, bidx, delay, bit_limit);
|
||||
assign_to_memory_word(lval, bidx, delay, bit_limit);
|
||||
}
|
||||
|
||||
cur_rbit += bit_limit;
|
||||
|
||||
if (skip_set_flag) {
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_set);
|
||||
clear_expression_lookaside();
|
||||
}
|
||||
}
|
||||
|
||||
if (res.base > 3)
|
||||
|
|
@ -747,7 +739,15 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
|
|||
ivl_signal_t lsig = ivl_lval_sig(lval);
|
||||
|
||||
unsigned use_wid = ivl_lval_width(lval);
|
||||
unsigned part_off = ivl_lval_part_off(lval);
|
||||
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
||||
unsigned part_off;
|
||||
|
||||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
} else {
|
||||
assert(number_is_immediate(part_off_ex, 64));
|
||||
part_off = get_number_immediate(part_off_ex);
|
||||
}
|
||||
|
||||
/* L-Value must be a signal: reg or wire */
|
||||
assert(lsig != 0);
|
||||
|
|
@ -1479,6 +1479,9 @@ int draw_func_definition(ivl_scope_t scope)
|
|||
|
||||
/*
|
||||
* $Log: vvp_process.c,v $
|
||||
* Revision 1.122 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.121 2005/11/26 17:23:17 steve
|
||||
* Handle indexed l-value to force.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: codes.h,v 1.77 2005/11/26 17:16:05 steve Exp $"
|
||||
#ident "$Id: codes.h,v 1.78 2006/02/02 02:44:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -41,7 +41,6 @@ extern bool of_ADDI(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_AND(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ANDR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_D(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_MEM(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_MV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_V0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_V0D(vthread_t thr, vvp_code_t code);
|
||||
|
|
@ -179,6 +178,9 @@ extern vvp_code_t codespace_null(void);
|
|||
|
||||
/*
|
||||
* $Log: codes.h,v $
|
||||
* Revision 1.78 2006/02/02 02:44:00 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.77 2005/11/26 17:16:05 steve
|
||||
* Force instruction that can be indexed.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: compile.cc,v 1.216 2006/01/02 05:32:06 steve Exp $"
|
||||
#ident "$Id: compile.cc,v 1.217 2006/02/02 02:44:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "arith.h"
|
||||
|
|
@ -87,7 +87,6 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%addi", of_ADDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%assign/m",of_ASSIGN_MEM,3,{OA_MEM_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/mv",of_ASSIGN_MV,3,{OA_MEM_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/v0",of_ASSIGN_V0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/v0/d",of_ASSIGN_V0D,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
||||
|
|
@ -1511,6 +1510,9 @@ void compile_param_string(char*label, char*name, char*str, char*value)
|
|||
|
||||
/*
|
||||
* $Log: compile.cc,v $
|
||||
* Revision 1.217 2006/02/02 02:44:00 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.216 2006/01/02 05:32:06 steve
|
||||
* Require explicit delay node from source.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: memory.cc,v 1.27 2005/06/22 00:04:49 steve Exp $"
|
||||
#ident "$Id: memory.cc,v 1.28 2006/02/02 02:44:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include "memory.h"
|
||||
|
|
@ -185,9 +185,24 @@ void memory_init_word(vvp_memory_t mem, unsigned addr, vvp_vector4_t val)
|
|||
mem->words[addr] = val;
|
||||
}
|
||||
|
||||
void memory_set_word(vvp_memory_t mem, unsigned addr, vvp_vector4_t val)
|
||||
void memory_set_word(vvp_memory_t mem, unsigned addr,
|
||||
unsigned off, vvp_vector4_t val)
|
||||
{
|
||||
memory_init_word(mem, addr, val);
|
||||
if (addr >= mem->word_count)
|
||||
return;
|
||||
|
||||
if (off >= mem->width)
|
||||
return;
|
||||
|
||||
if (off == 0 && val.size() == mem->width) {
|
||||
mem->words[addr] = val;
|
||||
|
||||
} else {
|
||||
if ((off + val.size()) > mem->width)
|
||||
val = val.subvalue(0, mem->width - off);
|
||||
|
||||
mem->words[addr].set_vec(off, val);
|
||||
}
|
||||
|
||||
for (vvp_fun_memport*cur = mem->port_list
|
||||
; cur ; cur = cur->next_) {
|
||||
|
|
@ -249,6 +264,9 @@ void vvp_fun_memport::check_word_change(unsigned long addr)
|
|||
|
||||
/*
|
||||
* $Log: memory.cc,v $
|
||||
* Revision 1.28 2006/02/02 02:44:00 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.27 2005/06/22 00:04:49 steve
|
||||
* Reduce vvp_vector4 copies by using const references.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: memory.h,v 1.10 2005/06/22 00:04:49 steve Exp $"
|
||||
#ident "$Id: memory.h,v 1.11 2006/02/02 02:44:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include "vvp_net.h"
|
||||
|
|
@ -69,6 +69,7 @@ extern void memory_init_word(vvp_memory_t mem,
|
|||
vvp_vector4_t val);
|
||||
extern void memory_set_word(vvp_memory_t mem,
|
||||
unsigned idx,
|
||||
unsigned off,
|
||||
vvp_vector4_t val);
|
||||
|
||||
/*
|
||||
|
|
@ -129,7 +130,8 @@ class vvp_fun_memport : public vvp_net_fun_t {
|
|||
private:
|
||||
vvp_memory_t mem_;
|
||||
|
||||
friend void memory_set_word(vvp_memory_t, unsigned, vvp_vector4_t);
|
||||
friend void memory_set_word(vvp_memory_t, unsigned,
|
||||
unsigned, vvp_vector4_t);
|
||||
void check_word_change(unsigned long address);
|
||||
class vvp_fun_memport*next_;
|
||||
|
||||
|
|
@ -152,6 +154,9 @@ vvp_memory_t memory_create(char *label);
|
|||
|
||||
/*
|
||||
* $Log: memory.h,v $
|
||||
* Revision 1.11 2006/02/02 02:44:00 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.10 2005/06/22 00:04:49 steve
|
||||
* Reduce vvp_vector4 copies by using const references.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* $Id: opcodes.txt,v 1.69 2005/11/26 17:16:05 steve Exp $
|
||||
* $Id: opcodes.txt,v 1.70 2006/02/02 02:44:00 steve Exp $
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -57,13 +57,6 @@ means the following:
|
|||
1 and 1 --> 1
|
||||
otherwise x
|
||||
|
||||
* %assign/m <memory-label>, <delay>, <bit> (OBSOLETE)
|
||||
|
||||
This instruction does a non-blocking assignment to a bit in a memory
|
||||
from the specified thread register <bit>. The memory bit is addressed
|
||||
by index register 3. Bit address zero is the LSB of the first memory
|
||||
word.
|
||||
|
||||
* %assign/mv <memory-label>, <delay>, <bit>
|
||||
|
||||
the %assign/mv instruction assigns a vector value to a word in the
|
||||
|
|
@ -73,6 +66,8 @@ of the vector to write.
|
|||
|
||||
The width of the word is retrieved from index register 0.
|
||||
|
||||
The base of a part select is retrieved from index register 1.
|
||||
|
||||
The address of the word in the memory is from index register 3. The
|
||||
address is canonical form.
|
||||
|
||||
|
|
@ -540,8 +535,12 @@ signal.
|
|||
This sets a thread vector to a memory word. The <memory-label>
|
||||
addresses a memory device, and the <bit>,<wid> describe a vector to be
|
||||
written. Index register 3 contains the address of the word within the
|
||||
memory. The address (in canonical form) is precalculated and loaded
|
||||
into index register 3.
|
||||
memory.
|
||||
|
||||
The base of a part select is retrieved from index register 1.
|
||||
|
||||
The address (in canonical form) is precalculated and loaded into index
|
||||
register 3.
|
||||
|
||||
|
||||
* %set/wr <vpi-label>, <bit>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: schedule.cc,v 1.40 2005/09/20 18:34:02 steve Exp $"
|
||||
#ident "$Id: schedule.cc,v 1.41 2006/02/02 02:44:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "schedule.h"
|
||||
|
|
@ -136,13 +136,14 @@ struct assign_memory_word_s : public event_s {
|
|||
vvp_memory_t mem;
|
||||
unsigned adr;
|
||||
vvp_vector4_t val;
|
||||
unsigned off;
|
||||
void run_run(void);
|
||||
};
|
||||
|
||||
void assign_memory_word_s::run_run(void)
|
||||
{
|
||||
count_assign_events += 1;
|
||||
memory_set_word(mem, adr, val);
|
||||
memory_set_word(mem, adr, off, val);
|
||||
}
|
||||
|
||||
struct generic_event_s : public event_s {
|
||||
|
|
@ -463,12 +464,14 @@ void schedule_assign_vector(vvp_net_ptr_t ptr,
|
|||
|
||||
void schedule_assign_memory_word(vvp_memory_t mem,
|
||||
unsigned word_addr,
|
||||
unsigned off,
|
||||
vvp_vector4_t val,
|
||||
vvp_time64_t delay)
|
||||
{
|
||||
struct assign_memory_word_s*cur = new struct assign_memory_word_s;
|
||||
cur->mem = mem;
|
||||
cur->adr = word_addr;
|
||||
cur->off = off;
|
||||
cur->val = val;
|
||||
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
||||
}
|
||||
|
|
@ -605,6 +608,9 @@ void schedule_simulate(void)
|
|||
|
||||
/*
|
||||
* $Log: schedule.cc,v $
|
||||
* Revision 1.41 2006/02/02 02:44:00 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.40 2005/09/20 18:34:02 steve
|
||||
* Clean up compiler warnings.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: schedule.h,v 1.26 2005/09/20 18:34:02 steve Exp $"
|
||||
#ident "$Id: schedule.h,v 1.27 2006/02/02 02:44:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vthread.h"
|
||||
|
|
@ -56,6 +56,7 @@ extern void schedule_assign_vector(vvp_net_ptr_t ptr,
|
|||
|
||||
extern void schedule_assign_memory_word(vvp_memory_t mem,
|
||||
unsigned word_address,
|
||||
unsigned off,
|
||||
vvp_vector4_t val,
|
||||
vvp_time64_t delay);
|
||||
/*
|
||||
|
|
@ -133,6 +134,9 @@ extern unsigned long count_event_pool;
|
|||
|
||||
/*
|
||||
* $Log: schedule.h,v $
|
||||
* Revision 1.27 2006/02/02 02:44:00 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.26 2005/09/20 18:34:02 steve
|
||||
* Clean up compiler warnings.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_memory.cc,v 1.27 2005/06/17 05:13:07 steve Exp $"
|
||||
#ident "$Id: vpi_memory.cc,v 1.28 2006/02/02 02:44:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
|
|
@ -346,7 +346,7 @@ static vpiHandle memory_word_put(vpiHandle ref, p_vpi_value val)
|
|||
assert(0);
|
||||
}
|
||||
|
||||
memory_set_word(rfp->mem->mem, word_addr, put_val);
|
||||
memory_set_word(rfp->mem->mem, word_addr, 0, put_val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -557,6 +557,9 @@ vpiHandle vpip_make_memory(vvp_memory_t mem, const char*name)
|
|||
|
||||
/*
|
||||
* $Log: vpi_memory.cc,v $
|
||||
* Revision 1.28 2006/02/02 02:44:00 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.27 2005/06/17 05:13:07 steve
|
||||
* Support set of IntVal to memory words.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vthread.cc,v 1.150 2005/11/26 17:16:05 steve Exp $"
|
||||
#ident "$Id: vthread.cc,v 1.151 2006/02/02 02:44:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -606,17 +606,6 @@ bool of_ASSIGN_X0(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool of_ASSIGN_MEM(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
#if 0
|
||||
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[1]);
|
||||
schedule_memory(cp->mem, thr->words[3].w_int, bit_val, cp->bit_idx[0]);
|
||||
#else
|
||||
fprintf(stderr, "XXXX %%assign/m is obsolete.\n");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/* %assign/mv <memory>, <delay>, <bit>
|
||||
* This generates an assignment event to a memory. Index register 0
|
||||
* contains the width of the vector (and the word) and index register
|
||||
|
|
@ -625,6 +614,7 @@ bool of_ASSIGN_MEM(vthread_t thr, vvp_code_t cp)
|
|||
bool of_ASSIGN_MV(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned wid = thr->words[0].w_int;
|
||||
unsigned off = thr->words[1].w_int;
|
||||
unsigned adr = thr->words[3].w_int;
|
||||
|
||||
assert(wid > 0);
|
||||
|
|
@ -634,7 +624,7 @@ bool of_ASSIGN_MV(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
|
||||
|
||||
schedule_assign_memory_word(cp->mem, adr, value, delay);
|
||||
schedule_assign_memory_word(cp->mem, adr, off, value, delay);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2789,12 +2779,13 @@ bool of_SET_MV(vthread_t thr, vvp_code_t cp)
|
|||
{
|
||||
unsigned bit = cp->bit_idx[0];
|
||||
unsigned wid = cp->bit_idx[1];
|
||||
unsigned off = thr->words[1].w_int;
|
||||
unsigned adr = thr->words[3].w_int;
|
||||
|
||||
/* Make a vector of the desired width. */
|
||||
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
|
||||
|
||||
memory_set_word(cp->mem, adr, value);
|
||||
memory_set_word(cp->mem, adr, off, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -3228,6 +3219,9 @@ bool of_JOIN_UFUNC(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
/*
|
||||
* $Log: vthread.cc,v $
|
||||
* Revision 1.151 2006/02/02 02:44:00 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.150 2005/11/26 17:16:05 steve
|
||||
* Force instruction that can be indexed.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue