Allow part selects of memory words in l-values.

This commit is contained in:
steve 2006-02-02 02:43:57 +00:00
parent 3158e2caa1
commit d434dd7296
27 changed files with 610 additions and 337 deletions

17
PExpr.h
View File

@ -19,10 +19,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include <string> # include <string>
# include <vector>
# include "netlist.h" # include "netlist.h"
# include "verinum.h" # include "verinum.h"
# include "LineInfo.h" # include "LineInfo.h"
@ -282,15 +283,16 @@ class PEIdent : public PExpr {
hname_t path_; hname_t path_;
public: public:
// Use these to support bit- and part-select operators. // Use these to support part-select operators.
PExpr*msb_; PExpr*msb_;
PExpr*lsb_; 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 // If this is a reference to a memory/array, this is the index
// expression. // expression. If this is a reference to a vector, this is a
PExpr*idx_; // bit select.
std::vector<PExpr*> idx_;
NetNet* elaborate_net_ram_(Design*des, NetScope*scope, NetNet* elaborate_net_ram_(Design*des, NetScope*scope,
NetMemory*mem, unsigned lwidth, NetMemory*mem, unsigned lwidth,
@ -546,6 +548,9 @@ class PECallFunction : public PExpr {
/* /*
* $Log: PExpr.h,v $ * $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 * Revision 1.76 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts. * Node delays can be more general expressions in structural contexts.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -537,8 +537,8 @@ void NetAssign_::dump_lval(ostream&o) const
if (bmux_) { if (bmux_) {
o << "[" << *bmux_ << "]"; o << "[" << *bmux_ << "]";
} else { } else if (base_) {
o << "[" << (loff_+lwid_-1) << ":" << loff_ << "]"; o << "[" << *base_ << " +: " << lwid_ << "]";
} }
} else if (mem_) { } else if (mem_) {
// Is there an obvious way to flag memories in the dump // 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_; if (bmux_) o << *bmux_;
else o << "**oops**"; else o << "**oops**";
o << "]"; o << "]";
if (base_) {
o << "[" << *base_ << " +: " << lwid_ << "]";
}
} else { } else {
o << ""; o << "";
} }
@ -1166,6 +1170,9 @@ void Design::dump(ostream&o) const
/* /*
* $Log: design_dump.cc,v $ * $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 * Revision 1.163 2005/08/27 04:32:08 steve
* Handle synthesis of fully packed case statements. * Handle synthesis of fully packed case statements.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -515,7 +515,15 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
// memory reference and I must generate a NetEMemory // memory reference and I must generate a NetEMemory
// object to handle it. // object to handle it.
if (mem != 0) { 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, // If this memory is an argument to a system task,
// then it is OK for it to not have an index. // 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; return 0;
} }
assert(msb_ != 0); if (idx_.size() != mem->dimensions()) {
if (lsb_) { cerr << get_line() << ": error: " << idx_.size()
cerr << get_line() << ": error: part select of a memory: " << " indices do not properly address a "
<< mem->name() << endl; << mem->dimensions() << "-dimension memory/array."
<< endl;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }
assert(lsb_ == 0); // XXXX For now, only support single word index.
assert(idx_ == 0); assert(idx_.size() == 1);
NetExpr*i = msb_->elaborate_expr(des, scope); PExpr*addr = idx_[0];
if (msb_ && i == 0) { assert(addr);
NetExpr*i = addr->elaborate_expr(des, scope);
if (i == 0) {
cerr << get_line() << ": error: Unable to elaborate " cerr << get_line() << ": error: Unable to elaborate "
"index expression `" << *msb_ << "'" << endl; "index expression `" << *addr << "'" << endl;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }
NetEMemory*node = new NetEMemory(mem, i); NetEMemory*node = new NetEMemory(mem, i);
node->set_line(*this); node->set_line(*this);
if (msb_ == 0 && lsb_ == 0)
return node; 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. // If the identifier is a named event.
@ -613,6 +686,7 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
if (sel_ == SEL_PART) { if (sel_ == SEL_PART) {
assert(msb_ && lsb_); assert(msb_ && lsb_);
assert(idx_.empty());
/* If the identifier has a part select, we support /* If the identifier has a part select, we support
it by pulling the right bits out and making a 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) { } else if (sel_ == SEL_IDX_UP || sel_ == SEL_IDX_DO) {
assert(msb_); assert(msb_);
assert(lsb_); assert(lsb_);
assert(idx_.empty());
/* Get and evaluate the width of the index /* Get and evaluate the width of the index
select. This must be constant. */ select. This must be constant. */
@ -710,14 +785,16 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
tmp = new NetESelect(tmp, idx_ex, wid); tmp = new NetESelect(tmp, idx_ex, wid);
} else if (sel_ == SEL_BIT) { } else if (!idx_.empty()) {
assert(msb_); assert(!msb_);
assert(!lsb_); assert(!lsb_);
assert(idx_.size() == 1);
assert(sel_ == SEL_NONE);
/* Handle the case where a parameter has a bit /* Handle the case where a parameter has a bit
select attached to it. Generate a NetESelect select attached to it. Generate a NetESelect
object to select the bit as desired. */ 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)) { if (! dynamic_cast<NetEConst*>(mtmp)) {
NetExpr*re = mtmp->eval_tree(); NetExpr*re = mtmp->eval_tree();
if (re) { if (re) {
@ -815,7 +892,7 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
{ {
assert(lsb_ != 0); assert(lsb_ != 0);
assert(msb_ != 0); assert(msb_ != 0);
assert(idx_ == 0); assert(idx_.empty());
verinum*lsn = lsb_->eval_const(des, scope); verinum*lsn = lsb_->eval_const(des, scope);
verinum*msn = msb_->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(lsb_ != 0);
assert(msb_ != 0); assert(msb_ != 0);
assert(idx_ == 0); assert(idx_.empty());
NetESignal*sig = new NetESignal(net); NetESignal*sig = new NetESignal(net);
sig->set_line(*this); sig->set_line(*this);
@ -944,7 +1021,7 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
{ {
assert(lsb_ != 0); assert(lsb_ != 0);
assert(msb_ != 0); assert(msb_ != 0);
assert(idx_ == 0); assert(idx_.empty());
NetESignal*sig = new NetESignal(net); NetESignal*sig = new NetESignal(net);
sig->set_line(*this); 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, NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
NetNet*net, NetScope*found_in) const NetNet*net, NetScope*found_in) const
{ {
assert(msb_ != 0); assert(msb_ == 0);
assert(lsb_ == 0); assert(lsb_ == 0);
assert(idx_ == 0); assert(idx_.size() == 1);
// If the bit select is constant, then treat it similar // If the bit select is constant, then treat it similar
// to the part select, so that I save the effort of // to the part select, so that I save the effort of
// making a mux part in the netlist. // 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(); long msv = msn->as_long();
unsigned idx = net->sb_to_idx(msv); 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 // complicated task because we need to generate
// expressions to convert calculated bit select // expressions to convert calculated bit select
// values to canonical values that are used internally. // 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()) { if (net->msb() < net->lsb()) {
ex = make_sub_expr(net->lsb(), ex); ex = make_sub_expr(net->lsb(), ex);
@ -1070,22 +1147,22 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
if (sel_ == SEL_PART) if (sel_ == SEL_PART)
return elaborate_expr_net_part_(des, scope, net, found_in); 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) if (sel_ == SEL_IDX_UP)
return elaborate_expr_net_idx_up_(des, scope, net, found_in); return elaborate_expr_net_idx_up_(des, scope, net, found_in);
if (sel_ == SEL_IDX_DO) if (sel_ == SEL_IDX_DO)
return elaborate_expr_net_idx_do_(des, scope, net, found_in); 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 // It's not anything else, so this must be a simple identifier
// expression with no part or bit select. Return the signal // expression with no part or bit select. Return the signal
// itself as the expression. // itself as the expression.
assert(sel_ == SEL_NONE); assert(sel_ == SEL_NONE);
assert(msb_ == 0); assert(msb_ == 0);
assert(lsb_ == 0); assert(lsb_ == 0);
assert(idx_ == 0); assert(idx_.empty());
NetESignal*node = new NetESignal(net); NetESignal*node = new NetESignal(net);
node->set_line(*this); node->set_line(*this);
@ -1268,6 +1345,9 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
/* /*
* $Log: elab_expr.cc,v $ * $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 * Revision 1.101 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges. * Handle bit select of parameter with ranges.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -195,7 +195,9 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
long msb, lsb; long msb, lsb;
NetExpr*mux; NetExpr*mux;
if (msb_ && lsb_) { if (msb_ || lsb_) {
assert(msb_ && lsb_);
/* This handles part selects. In this case, there are /* This handles part selects. In this case, there are
two bit select expressions, and both must be two bit select expressions, and both must be
constant. Evaluate them and pass the results back to constant. Evaluate them and pass the results back to
@ -225,17 +227,19 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
lsb = vl->as_long(); lsb = vl->as_long();
mux = 0; mux = 0;
} else if (msb_) { } else if (! idx_.empty()) {
/* If there is only a single select expression, it is a /* If there is only a single select expression, it is a
bit select. Evaluate the constant value and treat it bit select. Evaluate the constant value and treat it
as a part select with a bit width of 1. If the as a part select with a bit width of 1. If the
expression it not constant, then return the expression it not constant, then return the
expression as a mux. */ expression as a mux. */
assert(msb_ == 0);
assert(lsb_ == 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) { if (v == 0) {
NetExpr*m = msb_->elaborate_expr(des, scope); NetExpr*m = idx_[0]->elaborate_expr(des, scope);
assert(m); assert(m);
msb = 0; msb = 0;
lsb = 0; lsb = 0;
@ -271,6 +275,12 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
lv->set_bmux(mux); 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 { } else {
/* If the bit/part select is constant, then make the /* 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 = 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, NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
NetMemory*mem) const NetMemory*mem) const
{ {
if (msb_ == 0) { if (idx_.empty()) {
cerr << get_line() << ": error: Assign to memory \"" cerr << get_line() << ": error: Assign to memory \""
<< mem->name() << "\" requires a word select index." << mem->name() << "\" requires a word select index."
<< endl; << endl;
@ -320,33 +330,82 @@ NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
return 0; return 0;
} }
if (msb_ && lsb_) { if (idx_.size() != mem->dimensions()) {
cerr << get_line() << ": error: Cannot use part select on " cerr << get_line() << ": error: " << idx_.size()
<< "memory \"" << mem->name() << ".\"" << endl; << " indices do not properly address a "
<< mem->dimensions() << "-dimension memory/array."
<< endl;
des->errors += 1; des->errors += 1;
return 0; 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) if (ix == 0)
return 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); NetAssign_*lv = new NetAssign_(mem);
lv->set_bmux(ix); 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; return lv;
} }
@ -360,6 +419,9 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
/* /*
* $Log: elab_lval.cc,v $ * $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 * Revision 1.32 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures. * Remove NetVariable and ivl_variable_t structures.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -1466,11 +1466,15 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
Link::strength_t drive0, Link::strength_t drive0,
Link::strength_t drive1) const Link::strength_t drive1) const
{ {
assert(msb_ == 0);
assert(lsb_ == 0);
assert(idx_.size() == 1);
/* Elaborate the selector. */ /* Elaborate the selector. */
NetNet*sel; NetNet*sel;
if (sig->msb() < sig->lsb()) { 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); sel_expr = make_sub_expr(sig->lsb(), sel_expr);
if (NetExpr*tmp = sel_expr->eval_tree()) { if (NetExpr*tmp = sel_expr->eval_tree()) {
delete sel_expr; delete sel_expr;
@ -1480,7 +1484,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
sel = sel_expr->synthesize(des); sel = sel_expr->synthesize(des);
} else if (sig->lsb() != 0) { } 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()); sel_expr = make_add_expr(sel_expr, - sig->lsb());
if (NetExpr*tmp = sel_expr->eval_tree()) { if (NetExpr*tmp = sel_expr->eval_tree()) {
delete sel_expr; delete sel_expr;
@ -1490,7 +1494,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
sel = sel_expr->synthesize(des); sel = sel_expr->synthesize(des);
} else { } 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) { 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 /* Catch the case of a non-constant bit select. That should be
handled elsewhere. */ handled elsewhere. */
if (msb_ && !lsb_) { if (! idx_.empty()) {
verinum*mval = msb_->eval_const(des, scope); assert(msb_ == 0);
assert(lsb_ == 0);
assert(idx_.size() == 1);
verinum*mval = idx_[0]->eval_const(des, scope);
if (mval == 0) { if (mval == 0) {
return elaborate_net_bitmux_(des, scope, sig, rise, return elaborate_net_bitmux_(des, scope, sig, rise,
fall, decay, drive0, drive1); fall, decay, drive0, drive1);
@ -1666,20 +1674,24 @@ NetNet* PEIdent::elaborate_net_ram_(Design*des, NetScope*scope,
{ {
assert(scope); assert(scope);
if (msb_ == 0) { if (idx_.empty()) {
cerr << get_line() << ": error: memory reference without" cerr << get_line() << ": error: memory reference without"
" the required index expression." << endl; " the required index expression." << endl;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }
assert(msb_ == 0);
assert(lsb_ == 0);
assert(idx_.size() == 1);
/* Even if this expression must be fully self determined, the /* Even if this expression must be fully self determined, the
index expression does not, so make sure this flag is off index expression does not, so make sure this flag is off
while elaborating the address expression. */ while elaborating the address expression. */
const bool must_be_self_determined_save = must_be_self_determined_flag; const bool must_be_self_determined_save = must_be_self_determined_flag;
must_be_self_determined_flag = false; 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 /* If an offset is needed, subtract it from the address to get
an expression for the canonical address. */ an expression for the canonical address. */
@ -1905,8 +1917,11 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
des->errors += 1; des->errors += 1;
} }
} else if (msb_) { } else if (!idx_.empty()) {
verinum*mval = msb_->eval_const(des, scope); assert(msb_ == 0);
assert(lsb_ == 0);
assert(idx_.size() == 1);
verinum*mval = idx_[0]->eval_const(des, scope);
if (mval == 0) { if (mval == 0) {
cerr << get_line() << ": index of " << path_ << cerr << get_line() << ": index of " << path_ <<
" needs to be constant in this context." << " needs to be constant in this context." <<
@ -2645,6 +2660,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/* /*
* $Log: elab_net.cc,v $ * $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 * Revision 1.177 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts. * Node delays can be more general expressions in structural contexts.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -154,17 +154,20 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
res->set_line(*this); res->set_line(*this);
assert(res); assert(res);
assert(idx_ == 0);
if (msb_ && lsb_) { if (msb_ && lsb_) {
assert(idx_.empty());
cerr << get_line() << ": sorry: Cannot part select " cerr << get_line() << ": sorry: Cannot part select "
"bits of parameters." << endl; "bits of parameters." << endl;
des->errors += 1; 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 /* We have here a bit select. Insert a NetESelect node
to handle it. */ to handle it. */
NetExpr*tmp = msb_->elaborate_pexpr(des, scope); NetExpr*tmp = idx_[0]->elaborate_pexpr(des, scope);
if (tmp != 0) { if (tmp != 0) {
res = new NetESelect(res, tmp, 1); res = new NetESelect(res, tmp, 1);
} }
@ -233,6 +236,9 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
/* /*
* $Log: elab_pexpr.cc,v $ * $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 * Revision 1.22 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges. * Handle bit select of parameter with ranges.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
#ifdef __cplusplus #ifdef __cplusplus
@ -324,10 +324,10 @@ typedef enum ivl_statement_type_e {
expression. */ expression. */
typedef enum ivl_variable_type_e { typedef enum ivl_variable_type_e {
IVL_VT_VOID = 0, /* Not used */ IVL_VT_VOID = 0, /* Not used */
IVL_VT_NO_TYPE, /* Place holder for missing/unknown type. */ IVL_VT_NO_TYPE = 1, /* Place holder for missing/unknown type. */
IVL_VT_REAL, IVL_VT_REAL = 2,
IVL_VT_BOOL, IVL_VT_BOOL = 3,
IVL_VT_LOGIC, IVL_VT_LOGIC = 4,
IVL_VT_VECTOR = IVL_VT_LOGIC /* For compatibility */ IVL_VT_VECTOR = IVL_VT_LOGIC /* For compatibility */
} ivl_variable_type_t; } 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 * returns an ivl_expr_t that represents that
* expression. Otherwise, it returns 0. * expression. Otherwise, it returns 0.
* *
* (Should this be combined with ivl_lval_idx? -Ed)
*
* ivl_lval_mem * ivl_lval_mem
* If the l-value is a memory, this method returns an * If the l-value is a memory, this method returns an
* ivl_memory_t that represents that memory. Otherwise, it * 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 * ivl_lval_part_off
* The part select of the signal is based here. This is the * 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 * ivl_lval_idx
* If the l-value is a memory, this method returns an * 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_mux(ivl_lval_t net);
extern ivl_expr_t ivl_lval_idx(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 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); extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
@ -1703,6 +1707,9 @@ _END_DECL
/* /*
* $Log: ivl_target.h,v $ * $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 * Revision 1.164 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts. * Node delays can be more general expressions in structural contexts.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -39,18 +39,16 @@ unsigned count_lval_width(const NetAssign_*idx)
} }
NetAssign_::NetAssign_(NetNet*s) NetAssign_::NetAssign_(NetNet*s)
: sig_(s), mem_(0), bmux_(0) : sig_(s), mem_(0), bmux_(0), base_(0)
{ {
loff_ = 0;
lwid_ = sig_->vector_width(); lwid_ = sig_->vector_width();
sig_->incr_lref(); sig_->incr_lref();
more = 0; more = 0;
} }
NetAssign_::NetAssign_(NetMemory*s) NetAssign_::NetAssign_(NetMemory*s)
: sig_(0), mem_(s), bmux_(0) : sig_(0), mem_(s), bmux_(0), base_(0)
{ {
loff_ = 0;
lwid_ = mem_->width(); lwid_ = mem_->width();
more = 0; more = 0;
} }
@ -83,6 +81,11 @@ const NetExpr* NetAssign_::bmux() const
return bmux_; return bmux_;
} }
const NetExpr* NetAssign_::get_base() const
{
return base_;
}
unsigned NetAssign_::lwidth() const unsigned NetAssign_::lwidth() const
{ {
if (mem_) return lwid_; if (mem_) return lwid_;
@ -111,21 +114,10 @@ NetMemory* NetAssign_::mem() const
return mem_; return mem_;
} }
void NetAssign_::set_part(unsigned lo, unsigned lw) void NetAssign_::set_part(NetExpr*base, unsigned wid)
{ {
loff_ = lo; base_ = base;
lwid_ = lw; lwid_ = wid;
if (sig_) {
assert(sig_->vector_width() >= (lo + lw));
} else {
assert(mem_);
assert(lwid_ == mem_->width());
}
}
unsigned NetAssign_::get_loff() const
{
return loff_;
} }
/* /*
@ -283,6 +275,9 @@ NetRelease::~NetRelease()
/* /*
* $Log: net_assign.cc,v $ * $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 * Revision 1.20 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures. * Remove NetVariable and ivl_variable_t structures.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -58,6 +58,9 @@ void connect(Nexus*l, Link&r)
void connect(Link&l, Link&r) void connect(Link&l, Link&r)
{ {
assert(&l != &r); assert(&l != &r);
if (r.is_linked() && !l.is_linked())
connect(r.nexus_, l);
else
connect(l.nexus_, r); connect(l.nexus_, r);
} }
@ -522,6 +525,9 @@ bool NexusSet::intersect(const NexusSet&that) const
/* /*
* $Log: net_link.cc,v $ * $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 * Revision 1.18 2005/09/25 23:40:11 steve
* Simplify NexusSet set handling. * Simplify NexusSet set handling.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
/* /*
@ -791,7 +791,11 @@ class NetMemory {
// This is the width (in bits) of a single memory position. // This is the width (in bits) of a single memory position.
unsigned width() const { return width_; } 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_; }; const NetScope*scope() const { return scope_; };
// This is the number of memory positions. // This is the number of memory positions.
@ -1644,10 +1648,12 @@ class NetAssign_ {
NetExpr*bmux(); NetExpr*bmux();
const NetExpr*bmux() const; 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_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 // Get the width of the r-value that this node expects. This
// method accounts for the presence of the mux, so it not // method accounts for the presence of the mux, so it not
@ -1679,10 +1685,12 @@ class NetAssign_ {
private: private:
NetNet *sig_; NetNet *sig_;
NetMemory*mem_; NetMemory*mem_;
// Memory word index
NetExpr*bmux_; NetExpr*bmux_;
bool turn_sig_to_wire_on_release_; bool turn_sig_to_wire_on_release_;
unsigned loff_; // indexed part select base
NetExpr*base_;
unsigned lwid_; unsigned lwid_;
}; };
@ -3451,6 +3459,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/* /*
* $Log: netlist.h,v $ * $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 * Revision 1.354 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts. * Node delays can be more general expressions in structural contexts.
* *

176
parse.y
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -104,6 +104,8 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
svector<PEEvent*>*event_expr; svector<PEEvent*>*event_expr;
PEIdent*indexed_identifier;
NetNet::Type nettype; NetNet::Type nettype;
PGBuiltin::Type gatetype; PGBuiltin::Type gatetype;
NetNet::PortType porttype; 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 <gates> gate_instance_list
%type <expr> expression expr_primary %type <expr> expression expr_primary
%type <expr> lavalue lpvalue %type <expr> lpvalue
%type <expr> delay_value delay_value_simple %type <expr> delay_value delay_value_simple
%type <exprs> delay1 delay3 delay3_opt %type <exprs> delay1 delay3 delay3_opt
%type <exprs> expression_list %type <exprs> expression_list
%type <exprs> assign assign_list %type <exprs> assign assign_list
%type <indexed_identifier> indexed_identifier
%type <exprs> range range_opt %type <exprs> range range_opt
%type <nettype> net_type var_type net_type_opt %type <nettype> net_type var_type net_type_opt
@ -967,13 +970,6 @@ expr_primary
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
$$ = tmp; $$ = tmp;
} }
| identifier
{ PEIdent*tmp = new PEIdent(*$1);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
delete $1;
}
| SYSTEM_IDENTIFIER | SYSTEM_IDENTIFIER
{ PECallFunction*tmp = new PECallFunction(hname_t($1)); { PECallFunction*tmp = new PECallFunction(hname_t($1));
tmp->set_file(@1.text); tmp->set_file(@1.text);
@ -981,13 +977,12 @@ expr_primary
$$ = tmp; $$ = tmp;
delete $1; delete $1;
} }
| identifier '[' expression ']'
{ PEIdent*tmp = new PEIdent(*$1); /* The indexed_identifier rule matches simple identifiers as well as
tmp->set_file(@1.text); indexed arrays. Part selects are handled below. */
tmp->set_lineno(@1.first_line);
tmp->msb_ = $3; | indexed_identifier
tmp->sel_ = PEIdent::SEL_BIT; { PEIdent*tmp = $1;
delete $1;
$$ = tmp; $$ = tmp;
} }
@ -996,34 +991,25 @@ expr_primary
place of the : in the basic part select, and the first expression place of the : in the basic part select, and the first expression
is not limited to constant values. */ is not limited to constant values. */
| identifier '[' expression ':' expression ']' | indexed_identifier '[' expression ':' expression ']'
{ PEIdent*tmp = new PEIdent(*$1); { PEIdent*tmp = $1;
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
tmp->msb_ = $3; tmp->msb_ = $3;
tmp->lsb_ = $5; tmp->lsb_ = $5;
tmp->sel_ = PEIdent::SEL_PART; tmp->sel_ = PEIdent::SEL_PART;
delete $1;
$$ = tmp; $$ = tmp;
} }
| identifier '[' expression K_PO_POS expression ']' | indexed_identifier '[' expression K_PO_POS expression ']'
{ PEIdent*tmp = new PEIdent(*$1); { PEIdent*tmp = $1;
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
tmp->msb_ = $3; tmp->msb_ = $3;
tmp->lsb_ = $5; tmp->lsb_ = $5;
tmp->sel_ = PEIdent::SEL_IDX_UP; tmp->sel_ = PEIdent::SEL_IDX_UP;
delete $1;
$$ = tmp; $$ = tmp;
} }
| identifier '[' expression K_PO_NEG expression ']' | indexed_identifier '[' expression K_PO_NEG expression ']'
{ PEIdent*tmp = new PEIdent(*$1); { PEIdent*tmp = $1;
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
tmp->msb_ = $3; tmp->msb_ = $3;
tmp->lsb_ = $5; tmp->lsb_ = $5;
tmp->sel_ = PEIdent::SEL_IDX_DO; tmp->sel_ = PEIdent::SEL_IDX_DO;
delete $1;
$$ = tmp; $$ = tmp;
} }
@ -1075,7 +1061,6 @@ expr_primary
} }
; ;
/* A function_item is either a block item (i.e. a reg or integer /* A function_item is either a block item (i.e. a reg or integer
declaration) or an input declaration. There are no output or declaration) or an input declaration. There are no output or
inout ports. */ 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, /* This is a list of identifiers. The result is a list of strings,
each one of the identifiers in the list. These are simple, each one of the identifiers in the list. These are simple,
non-hierarchical names separated by ',' characters. */ non-hierarchical names separated by ',' characters. */
@ -1436,80 +1439,33 @@ net_type_opt
signed_opt : K_signed { $$ = true; } | {$$ = false; } ; 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 /* 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 lpvalue
: identifier : indexed_identifier
{ PEIdent*tmp = new PEIdent(*$1); { PEIdent*tmp = $1;
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
delete $1;
$$ = tmp; $$ = tmp;
} }
| identifier '[' expression ']' | indexed_identifier '[' expression ':' expression ']'
{ PEIdent*tmp = new PEIdent(*$1); { PEIdent*tmp = $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);
tmp->msb_ = $3; tmp->msb_ = $3;
tmp->lsb_ = $5; tmp->lsb_ = $5;
tmp->set_file(@1.text); $$ = tmp;
tmp->set_lineno(@1.first_line); }
delete $1; | 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; $$ = tmp;
} }
| '{' expression_list '}' | '{' expression_list '}'
@ -1522,7 +1478,7 @@ lpvalue
; ;
assign assign
: lavalue '=' expression : lpvalue '=' expression
{ svector<PExpr*>*tmp = new svector<PExpr*>(2); { svector<PExpr*>*tmp = new svector<PExpr*>(2);
(*tmp)[0] = $1; (*tmp)[0] = $1;
(*tmp)[1] = $3; (*tmp)[1] = $3;
@ -2595,14 +2551,14 @@ statement
off. This stronger then any other assign, but weaker then the off. This stronger then any other assign, but weaker then the
force assignments. */ force assignments. */
: K_assign lavalue '=' expression ';' : K_assign lpvalue '=' expression ';'
{ PCAssign*tmp = new PCAssign($2, $4); { PCAssign*tmp = new PCAssign($2, $4);
tmp->set_file(@1.text); tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
$$ = tmp; $$ = tmp;
} }
| K_deassign lavalue ';' | K_deassign lpvalue ';'
{ PDeassign*tmp = new PDeassign($2); { PDeassign*tmp = new PDeassign($2);
tmp->set_file(@1.text); tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
@ -2613,13 +2569,13 @@ statement
/* Force and release statements are similar to assignments, /* Force and release statements are similar to assignments,
syntactically, but they will be elaborated differently. */ syntactically, but they will be elaborated differently. */
| K_force lavalue '=' expression ';' | K_force lpvalue '=' expression ';'
{ PForce*tmp = new PForce($2, $4); { PForce*tmp = new PForce($2, $4);
tmp->set_file(@1.text); tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
$$ = tmp; $$ = tmp;
} }
| K_release lavalue ';' | K_release lpvalue ';'
{ PRelease*tmp = new PRelease($2); { PRelease*tmp = new PRelease($2);
tmp->set_file(@1.text); tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
@ -2843,12 +2799,22 @@ statement
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
$$ = tmp; $$ = tmp;
} }
| error '=' expression ';'
{ yyerror(@1, "Syntax in assignment statement l-value.");
yyerrok;
$$ = new PNoop;
}
| lpvalue K_LE expression ';' | lpvalue K_LE expression ';'
{ PAssignNB*tmp = new PAssignNB($1,$3); { PAssignNB*tmp = new PAssignNB($1,$3);
tmp->set_file(@1.text); tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line); tmp->set_lineno(@1.first_line);
$$ = tmp; $$ = tmp;
} }
| error K_LE expression ';'
{ yyerror(@1, "Syntax in assignment statement l-value.");
yyerrok;
$$ = new PNoop;
}
| lpvalue '=' delay1 expression ';' | lpvalue '=' delay1 expression ';'
{ assert($3->count() == 1); { assert($3->count() == 1);
PExpr*del = (*$3)[0]; PExpr*del = (*$3)[0];

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -1217,10 +1217,10 @@ extern "C" ivl_memory_t ivl_lval_mem(ivl_lval_t net)
return 0x0; 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); assert(net);
return net->loff_; return net->loff;
} }
extern "C" unsigned ivl_lval_width(ivl_lval_t net) 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 $ * $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 * Revision 1.132 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts. * Node delays can be more general expressions in structural contexts.
* *

View File

@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -154,9 +154,18 @@ void dll_target::make_assign_lvals_(const NetAssignBase*net)
for (unsigned idx = 0 ; idx < cnt ; idx += 1) { for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
struct ivl_lval_s*cur = stmt_cur_->u_.assign_.lval_ + idx; struct ivl_lval_s*cur = stmt_cur_->u_.assign_.lval_ + idx;
const NetAssign_*asn = net->l_val(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->width_ = asn->lwidth();
cur->loff_ = asn->get_loff();
if (asn->sig()) { if (asn->sig()) {
cur->type_ = IVL_LVAL_REG; cur->type_ = IVL_LVAL_REG;
cur->n.sig = find_signal(des_, asn->sig()); 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 $ * $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 * Revision 1.67 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures. * Remove NetVariable and ivl_variable_t structures.
* *

11
t-dll.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "target.h" # include "target.h"
@ -379,10 +379,10 @@ enum ivl_lval_type_t {
}; };
struct ivl_lval_s { struct ivl_lval_s {
unsigned width_; ivl_expr_t loff;
unsigned loff_;
unsigned type_ : 8;
ivl_expr_t idx; ivl_expr_t idx;
unsigned width_;
unsigned type_ : 8;
union { union {
ivl_signal_t sig; ivl_signal_t sig;
ivl_memory_t mem; ivl_memory_t mem;
@ -671,6 +671,9 @@ struct ivl_statement_s {
/* /*
* $Log: t-dll.h,v $ * $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 * Revision 1.129 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts. * Node delays can be more general expressions in structural contexts.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -32,11 +32,18 @@ static unsigned show_assign_lval(ivl_lval_t lval, unsigned ind)
if ( (mem = ivl_lval_mem(lval)) ) { if ( (mem = ivl_lval_mem(lval)) ) {
ivl_scope_t scope = ivl_memory_scope(mem); 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_scope_name(scope),
ivl_memory_basename(mem)); ivl_memory_basename(mem),
show_expression(ivl_lval_idx(lval), ind+4); ivl_lval_width(lval));
fprintf(out, "%*s] width=%u }\n", ind, "", 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 /* When the l-value is a memory word, the lval_width
must exactly match the word width. */ must exactly match the word width. */
@ -50,16 +57,20 @@ static unsigned show_assign_lval(ivl_lval_t lval, unsigned ind)
} else { } else {
ivl_signal_t sig = ivl_lval_sig(lval); 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, "", ind, "",
ivl_signal_name(sig), ivl_signal_name(sig),
ivl_signal_width(sig), ivl_signal_width(sig),
ivl_lval_part_off(lval),
ivl_lval_width(lval)); ivl_lval_width(lval));
if (ivl_lval_mux(lval)) { if (ivl_lval_mux(lval)) {
fprintf(out, "%*sBit select expression:\n", ind+4, ""); fprintf(out, "%*sBit select expression:\n", ind+4, "");
show_expression(ivl_lval_mux(lval), ind+8); 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); wid = ivl_lval_width(lval);
} }

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "vvp_priv.h" # include "vvp_priv.h"
@ -101,6 +101,38 @@ unsigned long get_number_immediate(ivl_expr_t ex)
return imm; 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 * 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 * 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 $ * $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 * Revision 1.129 2006/01/02 05:33:20 steve
* Node delays can be more general expressions in structural contexts. * Node delays can be more general expressions in structural contexts.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "vvp_config.h" # 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); 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 * These functions manage vector allocation in the thread register
* space. They presume that we work on one thread at a time, to * 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 $ * $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 * Revision 1.39 2005/10/12 17:26:17 steve
* MUX nodes get inputs from nets, not from net inputs, * MUX nodes get inputs from nets, not from net inputs,
* Detect and draw alias nodes to reduce net size and * Detect and draw alias nodes to reduce net size and

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "vvp_priv.h" # include "vvp_priv.h"
@ -29,7 +29,6 @@
# include <stdlib.h> # include <stdlib.h>
static int show_statement(ivl_statement_t net, ivl_scope_t sscope); 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 local_count = 0;
unsigned thread_count = 0; unsigned thread_count = 0;
@ -76,7 +75,15 @@ static void set_to_lvariable(ivl_lval_t lval,
unsigned bit, unsigned wid) unsigned bit, unsigned wid)
{ {
ivl_signal_t sig = ivl_lval_sig(lval); 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)) { if (ivl_lval_mux(lval)) {
unsigned skip_set = transient_id++; 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 memory, and bit is the base of the thread vector. The wid is
* the width of the vector to be written to the word. * 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 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, " %%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, 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) unsigned width)
{ {
ivl_signal_t sig = ivl_lval_sig(lval); 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); 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) { if (mux != 0) {
unsigned skip_assign = transient_id++; 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) 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, " %%ix/load 0, %u;\n", wid);
fprintf(vvp_out, " %%assign/mv M_%p, %u, %u;\n", mem, delay, bit); fprintf(vvp_out, " %%assign/mv M_%p, %u, %u;\n", mem, delay, bit);
} fprintf(vvp_out, "t_%u ;\n", skip_set);
/* clear_expression_lookaside();
* 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);
}
} }
static void calculate_into_x1(ivl_expr_t expr) 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; unsigned cur_rbit = 0;
for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) { for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
unsigned skip_set = transient_id++;
unsigned skip_set_flag = 0;
unsigned bidx; unsigned bidx;
unsigned bit_limit = wid - cur_rbit; unsigned bit_limit = wid - cur_rbit;
lval = ivl_stmt_lval(net, lidx); lval = ivl_stmt_lval(net, lidx);
mem = ivl_lval_mem(lval); 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. */ /* Reduce bit_limit to the width of this l-value. */
if (bit_limit > ivl_lval_width(lval)) 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); bidx = res.base < 4? res.base : (res.base+cur_rbit);
if (mem) { if (mem) {
set_to_memory_word(mem, 3, bidx, bit_limit); set_to_memory_word(lval, 3, bidx, bit_limit);
} else { } else {
set_to_lvariable(lval, bidx, bit_limit); 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 /* Now we've consumed this many r-value bits for the
current l-value. */ current l-value. */
cur_rbit += bit_limit; 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); calculate_into_x1(del);
for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) { 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; unsigned bit_limit = wid - cur_rbit;
lval = ivl_stmt_lval(net, lidx); lval = ivl_stmt_lval(net, lidx);
mem = ivl_lval_mem(lval); 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)) if (bit_limit > ivl_lval_width(lval))
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 { } else {
unsigned bidx; unsigned bidx;
assert(mem); /* XXXX don't yet know what to do with a
/* XXXX don't yet know what to do with a delay non-constant delay exprssion. */
in an index variable. */
assert(del == 0); assert(del == 0);
bidx = res.base < 4? res.base : (res.base+cur_rbit); 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; cur_rbit += bit_limit;
if (skip_set_flag) {
fprintf(vvp_out, "t_%u ;\n", skip_set);
clear_expression_lookaside();
}
} }
if (res.base > 3) 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); ivl_signal_t lsig = ivl_lval_sig(lval);
unsigned use_wid = ivl_lval_width(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 */ /* L-Value must be a signal: reg or wire */
assert(lsig != 0); assert(lsig != 0);
@ -1479,6 +1479,9 @@ int draw_func_definition(ivl_scope_t scope)
/* /*
* $Log: vvp_process.c,v $ * $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 * Revision 1.121 2005/11/26 17:23:17 steve
* Handle indexed l-value to force. * Handle indexed l-value to force.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #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_AND(vthread_t thr, vvp_code_t code);
extern bool of_ANDR(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_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_MV(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_V0(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); 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 $ * $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 * Revision 1.77 2005/11/26 17:16:05 steve
* Force instruction that can be indexed. * Force instruction that can be indexed.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "arith.h" # 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} }, { "%addi", of_ADDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%and", of_AND, 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} }, { "%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/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",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} }, { "%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 $ * $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 * Revision 1.216 2006/01/02 05:32:06 steve
* Require explicit delay node from source. * Require explicit delay node from source.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
#include "memory.h" #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; 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 for (vvp_fun_memport*cur = mem->port_list
; cur ; cur = cur->next_) { ; cur ; cur = cur->next_) {
@ -249,6 +264,9 @@ void vvp_fun_memport::check_word_change(unsigned long addr)
/* /*
* $Log: memory.cc,v $ * $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 * Revision 1.27 2005/06/22 00:04:49 steve
* Reduce vvp_vector4 copies by using const references. * Reduce vvp_vector4 copies by using const references.
* *

View File

@ -20,7 +20,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
#include "vvp_net.h" #include "vvp_net.h"
@ -69,6 +69,7 @@ extern void memory_init_word(vvp_memory_t mem,
vvp_vector4_t val); vvp_vector4_t val);
extern void memory_set_word(vvp_memory_t mem, extern void memory_set_word(vvp_memory_t mem,
unsigned idx, unsigned idx,
unsigned off,
vvp_vector4_t val); vvp_vector4_t val);
/* /*
@ -129,7 +130,8 @@ class vvp_fun_memport : public vvp_net_fun_t {
private: private:
vvp_memory_t mem_; 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); void check_word_change(unsigned long address);
class vvp_fun_memport*next_; class vvp_fun_memport*next_;
@ -152,6 +154,9 @@ vvp_memory_t memory_create(char *label);
/* /*
* $Log: memory.h,v $ * $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 * Revision 1.10 2005/06/22 00:04:49 steve
* Reduce vvp_vector4 copies by using const references. * Reduce vvp_vector4 copies by using const references.
* *

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com) * 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 1 and 1 --> 1
otherwise x 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> * %assign/mv <memory-label>, <delay>, <bit>
the %assign/mv instruction assigns a vector value to a word in the 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 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 The address of the word in the memory is from index register 3. The
address is canonical form. address is canonical form.
@ -540,8 +535,12 @@ signal.
This sets a thread vector to a memory word. The <memory-label> 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 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 written. Index register 3 contains the address of the word within the
memory. The address (in canonical form) is precalculated and loaded memory.
into index register 3.
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> * %set/wr <vpi-label>, <bit>

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "schedule.h" # include "schedule.h"
@ -136,13 +136,14 @@ struct assign_memory_word_s : public event_s {
vvp_memory_t mem; vvp_memory_t mem;
unsigned adr; unsigned adr;
vvp_vector4_t val; vvp_vector4_t val;
unsigned off;
void run_run(void); void run_run(void);
}; };
void assign_memory_word_s::run_run(void) void assign_memory_word_s::run_run(void)
{ {
count_assign_events += 1; count_assign_events += 1;
memory_set_word(mem, adr, val); memory_set_word(mem, adr, off, val);
} }
struct generic_event_s : public event_s { 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, void schedule_assign_memory_word(vvp_memory_t mem,
unsigned word_addr, unsigned word_addr,
unsigned off,
vvp_vector4_t val, vvp_vector4_t val,
vvp_time64_t delay) vvp_time64_t delay)
{ {
struct assign_memory_word_s*cur = new struct assign_memory_word_s; struct assign_memory_word_s*cur = new struct assign_memory_word_s;
cur->mem = mem; cur->mem = mem;
cur->adr = word_addr; cur->adr = word_addr;
cur->off = off;
cur->val = val; cur->val = val;
schedule_event_(cur, delay, SEQ_NBASSIGN); schedule_event_(cur, delay, SEQ_NBASSIGN);
} }
@ -605,6 +608,9 @@ void schedule_simulate(void)
/* /*
* $Log: schedule.cc,v $ * $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 * Revision 1.40 2005/09/20 18:34:02 steve
* Clean up compiler warnings. * Clean up compiler warnings.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "vthread.h" # 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, extern void schedule_assign_memory_word(vvp_memory_t mem,
unsigned word_address, unsigned word_address,
unsigned off,
vvp_vector4_t val, vvp_vector4_t val,
vvp_time64_t delay); vvp_time64_t delay);
/* /*
@ -133,6 +134,9 @@ extern unsigned long count_event_pool;
/* /*
* $Log: schedule.h,v $ * $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 * Revision 1.26 2005/09/20 18:34:02 steve
* Clean up compiler warnings. * Clean up compiler warnings.
* *

View File

@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "vpi_priv.h" # include "vpi_priv.h"
@ -346,7 +346,7 @@ static vpiHandle memory_word_put(vpiHandle ref, p_vpi_value val)
assert(0); 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; return 0;
} }
@ -557,6 +557,9 @@ vpiHandle vpip_make_memory(vvp_memory_t mem, const char*name)
/* /*
* $Log: vpi_memory.cc,v $ * $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 * Revision 1.27 2005/06/17 05:13:07 steve
* Support set of IntVal to memory words. * Support set of IntVal to memory words.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #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 #endif
# include "config.h" # include "config.h"
@ -606,17 +606,6 @@ bool of_ASSIGN_X0(vthread_t thr, vvp_code_t cp)
return true; 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> /* %assign/mv <memory>, <delay>, <bit>
* This generates an assignment event to a memory. Index register 0 * This generates an assignment event to a memory. Index register 0
* contains the width of the vector (and the word) and index register * 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) bool of_ASSIGN_MV(vthread_t thr, vvp_code_t cp)
{ {
unsigned wid = thr->words[0].w_int; unsigned wid = thr->words[0].w_int;
unsigned off = thr->words[1].w_int;
unsigned adr = thr->words[3].w_int; unsigned adr = thr->words[3].w_int;
assert(wid > 0); 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); 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; return true;
} }
@ -2789,12 +2779,13 @@ bool of_SET_MV(vthread_t thr, vvp_code_t cp)
{ {
unsigned bit = cp->bit_idx[0]; unsigned bit = cp->bit_idx[0];
unsigned wid = cp->bit_idx[1]; unsigned wid = cp->bit_idx[1];
unsigned off = thr->words[1].w_int;
unsigned adr = thr->words[3].w_int; unsigned adr = thr->words[3].w_int;
/* Make a vector of the desired width. */ /* Make a vector of the desired width. */
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid); 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; return true;
} }
@ -3228,6 +3219,9 @@ bool of_JOIN_UFUNC(vthread_t thr, vvp_code_t cp)
/* /*
* $Log: vthread.cc,v $ * $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 * Revision 1.150 2005/11/26 17:16:05 steve
* Force instruction that can be indexed. * Force instruction that can be indexed.
* *