diff --git a/PExpr.h b/PExpr.h index 17491d304..d6038f282 100644 --- a/PExpr.h +++ b/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 +# include # 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 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. * diff --git a/design_dump.cc b/design_dump.cc index ad2b3fcbb..4d4c45b9e 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -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. * diff --git a/elab_expr.cc b/elab_expr.cc index 3b53622cc..d0ca45cbb 100644 --- a/elab_expr.cc +++ b/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(le); + NetEConst*mec = dynamic_cast(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 (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(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. * diff --git a/elab_lval.cc b/elab_lval.cc index aeac32032..cfdb39cc5 100644 --- a/elab_lval.cc +++ b/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(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(le); + NetEConst*mec = dynamic_cast(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 (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. * diff --git a/elab_net.cc b/elab_net.cc index cc539b891..f093be3ea 100644 --- a/elab_net.cc +++ b/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. * diff --git a/elab_pexpr.cc b/elab_pexpr.cc index 8588f2bed..8d80a3376 100644 --- a/elab_pexpr.cc +++ b/elab_pexpr.cc @@ -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. * diff --git a/ivl_target.h b/ivl_target.h index a865abafd..0e5ee9ccd 100644 --- a/ivl_target.h +++ b/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. * diff --git a/net_assign.cc b/net_assign.cc index f1620ee34..8926482ec 100644 --- a/net_assign.cc +++ b/net_assign.cc @@ -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. * diff --git a/net_link.cc b/net_link.cc index 5d6d2b292..de5a677ee 100644 --- a/net_link.cc +++ b/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. * diff --git a/netlist.h b/netlist.h index 1bbb3b83a..dfc64ad9d 100644 --- a/netlist.h +++ b/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. * diff --git a/parse.y b/parse.y index 61aba973e..040ee8445 100644 --- a/parse.y +++ b/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*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 gate_instance_list %type expression expr_primary -%type lavalue lpvalue +%type lpvalue %type delay_value delay_value_simple %type delay1 delay3 delay3_opt %type expression_list %type assign assign_list +%type indexed_identifier %type range range_opt %type 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*tmp = new svector(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]; diff --git a/t-dll-api.cc b/t-dll-api.cc index f3db3bb1c..6759e772c 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -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. * diff --git a/t-dll-proc.cc b/t-dll-proc.cc index 0835a26c4..82b1e63e8 100644 --- a/t-dll-proc.cc +++ b/t-dll-proc.cc @@ -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. * diff --git a/t-dll.h b/t-dll.h index e985c90fe..8331e5dc5 100644 --- a/t-dll.h +++ b/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. * diff --git a/tgt-stub/statement.c b/tgt-stub/statement.c index 96fe6820b..a68f7b0f7 100644 --- a/tgt-stub/statement.c +++ b/tgt-stub/statement.c @@ -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); } diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index e02628bc2..5391b7615 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -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. * diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index f88af087b..4eb016508 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -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 diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index bb25550c3..0d202093a 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -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 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. * diff --git a/vvp/codes.h b/vvp/codes.h index 1e19a31d7..fac20c9aa 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -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. * diff --git a/vvp/compile.cc b/vvp/compile.cc index 534c7a088..24a402503 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -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. * diff --git a/vvp/memory.cc b/vvp/memory.cc index 3ea1be318..a453bc0ed 100644 --- a/vvp/memory.cc +++ b/vvp/memory.cc @@ -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. * diff --git a/vvp/memory.h b/vvp/memory.h index 0b98df252..39b2d7771 100644 --- a/vvp/memory.h +++ b/vvp/memory.h @@ -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. * diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 0fe9b9820..9c58061b1 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -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 , , (OBSOLETE) - -This instruction does a non-blocking assignment to a bit in a memory -from the specified thread register . The memory bit is addressed -by index register 3. Bit address zero is the LSB of the first memory -word. - * %assign/mv , , 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 addresses a memory device, and the , 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 , diff --git a/vvp/schedule.cc b/vvp/schedule.cc index 67620de0d..2079651cd 100644 --- a/vvp/schedule.cc +++ b/vvp/schedule.cc @@ -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. * diff --git a/vvp/schedule.h b/vvp/schedule.h index 001e0988e..d31a85f71 100644 --- a/vvp/schedule.h +++ b/vvp/schedule.h @@ -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. * diff --git a/vvp/vpi_memory.cc b/vvp/vpi_memory.cc index bdf3abf09..db0705f02 100644 --- a/vvp/vpi_memory.cc +++ b/vvp/vpi_memory.cc @@ -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. * diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 63c2ab49d..f4bdfdad5 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -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 , , * 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. *