Fix part selects in l-values.
This commit is contained in:
parent
fc5cf55400
commit
707af782b3
9
PExpr.h
9
PExpr.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PExpr.h,v 1.78 2006/03/25 02:36:26 steve Exp $"
|
||||
#ident "$Id: PExpr.h,v 1.79 2006/04/16 00:15:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
|
|
@ -253,6 +253,10 @@ class PEIdent : public PExpr {
|
|||
|
||||
const hname_t& path() const;
|
||||
|
||||
private:
|
||||
NetAssign_*elaborate_lval_net_idx_up_(Design*, NetScope*, NetNet*) const;
|
||||
NetAssign_*elaborate_lval_net_idx_do_(Design*, NetScope*, NetNet*) const;
|
||||
|
||||
private:
|
||||
NetExpr*elaborate_expr_param(Design*des,
|
||||
NetScope*scope,
|
||||
|
|
@ -548,6 +552,9 @@ class PECallFunction : public PExpr {
|
|||
|
||||
/*
|
||||
* $Log: PExpr.h,v $
|
||||
* Revision 1.79 2006/04/16 00:15:43 steve
|
||||
* Fix part selects in l-values.
|
||||
*
|
||||
* Revision 1.78 2006/03/25 02:36:26 steve
|
||||
* Get rid of excess PESTring:: prefix within class declaration.
|
||||
*
|
||||
|
|
|
|||
85
elab_lval.cc
85
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.33 2006/02/02 02:43:57 steve Exp $"
|
||||
#ident "$Id: elab_lval.cc,v 1.34 2006/04/16 00:15:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -179,6 +179,12 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
|
||||
assert(reg);
|
||||
|
||||
if (sel_ == SEL_IDX_UP)
|
||||
return elaborate_lval_net_idx_up_(des, scope, reg);
|
||||
|
||||
if (sel_ == SEL_IDX_DO)
|
||||
return elaborate_lval_net_idx_do_(des, scope, reg);
|
||||
|
||||
/* Get the signal referenced by the identifier, and make sure
|
||||
it is a register. Wires are not allows in this context,
|
||||
unless this is the l-value of a force. */
|
||||
|
|
@ -197,6 +203,11 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
|
||||
if (msb_ || lsb_) {
|
||||
assert(msb_ && lsb_);
|
||||
if (sel_ != SEL_PART)
|
||||
cerr << get_line() << ": internal error: not a part select?"
|
||||
<< endl;
|
||||
|
||||
assert(sel_ == SEL_PART);
|
||||
|
||||
/* This handles part selects. In this case, there are
|
||||
two bit select expressions, and both must be
|
||||
|
|
@ -273,7 +284,13 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
bmux to select the target bit. */
|
||||
lv = new NetAssign_(reg);
|
||||
|
||||
lv->set_bmux(mux);
|
||||
/* Correct the mux for the range of the vector. */
|
||||
if (reg->msb() < reg->lsb())
|
||||
mux = make_sub_expr(reg->lsb(), mux);
|
||||
else if (reg->lsb() != 0)
|
||||
mux = make_add_expr(mux, - reg->lsb());
|
||||
|
||||
lv->set_part(mux, 1);
|
||||
|
||||
} else if (msb == reg->msb() && lsb == reg->lsb()) {
|
||||
|
||||
|
|
@ -319,6 +336,65 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
return lv;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_lval_net_idx_up_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*reg) const
|
||||
{
|
||||
assert(lsb_);
|
||||
assert(msb_);
|
||||
|
||||
if (reg->type() != NetNet::REG) {
|
||||
cerr << get_line() << ": error: " << path_ <<
|
||||
" is not a reg/integer/time in " << scope->name() <<
|
||||
"." << endl;
|
||||
cerr << reg->get_line() << ": : " << path_ <<
|
||||
" is declared here as " << reg->type() << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate the width expression (in the lsb_ position)
|
||||
first. If the expression is not constant, error but guess 1
|
||||
so we can keep going and find more errors. */
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_);
|
||||
NetEConst*wid_c = dynamic_cast<NetEConst*>(wid_ex);
|
||||
|
||||
if (wid_c == 0) {
|
||||
cerr << get_line() << ": error: Indexed part width must be "
|
||||
<< "constant. Expression in question is..." << endl;
|
||||
cerr << get_line() << ": : " << *wid_ex << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
unsigned wid = wid_c? wid_c->value().as_ulong() : 1;
|
||||
delete wid_ex;
|
||||
|
||||
NetExpr*base = elab_and_eval(des, scope, msb_);
|
||||
|
||||
/* Correct the mux for the range of the vector. */
|
||||
if (reg->msb() < reg->lsb())
|
||||
base = make_sub_expr(reg->lsb(), base);
|
||||
else if (reg->lsb() != 0)
|
||||
base = make_add_expr(base, - reg->lsb());
|
||||
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
lv->set_part(base, wid);
|
||||
|
||||
return lv;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_lval_net_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*reg) const
|
||||
{
|
||||
assert(lsb_);
|
||||
assert(msb_);
|
||||
cerr << get_line() << ": internal error: don't know how to "
|
||||
"deal with SEL_IDX_DO in lval?" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
NetMemory*mem) const
|
||||
{
|
||||
|
|
@ -352,7 +428,7 @@ NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
|||
|
||||
/* If there is no extra part select, then we are done. */
|
||||
if (msb_ == 0 && lsb_ == 0) {
|
||||
lv->set_part(0U, mem->width());
|
||||
lv->set_part(0, mem->width());
|
||||
return lv;
|
||||
}
|
||||
|
||||
|
|
@ -419,6 +495,9 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
|
|||
|
||||
/*
|
||||
* $Log: elab_lval.cc,v $
|
||||
* Revision 1.34 2006/04/16 00:15:43 steve
|
||||
* Fix part selects in l-values.
|
||||
*
|
||||
* Revision 1.33 2006/02/02 02:43:57 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
|
|
|||
13
ivl_target.h
13
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.166 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: ivl_target.h,v 1.167 2006/04/16 00:15:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -1108,10 +1108,8 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
|||
* signal (or even 1) if only a part of the l-value signal is to be
|
||||
* assigned.
|
||||
*
|
||||
* The ivl_lval_part_off is the canonical base of a constant part or
|
||||
* bit select. If the bit select base is non-constant, then the
|
||||
* ivl_lval_mux will contain an expression. If there is a mux
|
||||
* expression, then the ivl_lval_part_off result can be ignored.
|
||||
* The ivl_lval_part_off is the canonical base of a part or
|
||||
* bit select.
|
||||
*
|
||||
* - Memory words
|
||||
* If the l-value is a memory word, the ivl_lval_mem function returns
|
||||
|
|
@ -1122,7 +1120,7 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
|||
*/
|
||||
|
||||
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); // XXXX Obsolete?
|
||||
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
|
||||
extern ivl_memory_t ivl_lval_mem(ivl_lval_t net);
|
||||
extern ivl_expr_t ivl_lval_part_off(ivl_lval_t net);
|
||||
|
|
@ -1708,6 +1706,9 @@ _END_DECL
|
|||
|
||||
/*
|
||||
* $Log: ivl_target.h,v $
|
||||
* Revision 1.167 2006/04/16 00:15:43 steve
|
||||
* Fix part selects in l-values.
|
||||
*
|
||||
* Revision 1.166 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_nex_input.cc,v 1.14 2005/07/11 16:56:50 steve Exp $"
|
||||
#ident "$Id: net_nex_input.cc,v 1.15 2006/04/16 00:15:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -170,10 +170,19 @@ NexusSet* NetEUnary::nex_input()
|
|||
|
||||
NexusSet* NetAssign_::nex_input()
|
||||
{
|
||||
if (bmux_ == 0)
|
||||
return new NexusSet;
|
||||
else
|
||||
return bmux_->nex_input();
|
||||
NexusSet*result = new NexusSet;
|
||||
if (bmux_) {
|
||||
NexusSet*tmp = bmux_->nex_input();
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
if (base_) {
|
||||
NexusSet*tmp = base_->nex_input();
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetAssignBase::nex_input()
|
||||
|
|
@ -384,6 +393,9 @@ NexusSet* NetWhile::nex_input()
|
|||
|
||||
/*
|
||||
* $Log: net_nex_input.cc,v $
|
||||
* Revision 1.15 2006/04/16 00:15:43 steve
|
||||
* Fix part selects in l-values.
|
||||
*
|
||||
* Revision 1.14 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
|
|
|
|||
3
parse.y
3
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.213 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.214 2006/04/16 00:15:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -1480,6 +1480,7 @@ lpvalue
|
|||
{ PEIdent*tmp = $1;
|
||||
tmp->msb_ = $3;
|
||||
tmp->lsb_ = $5;
|
||||
tmp->sel_ = PEIdent::SEL_PART;
|
||||
$$ = tmp;
|
||||
}
|
||||
| indexed_identifier '[' expression K_PO_POS expression ']'
|
||||
|
|
|
|||
|
|
@ -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.122 2006/02/02 02:43:59 steve Exp $"
|
||||
#ident "$Id: vvp_process.c,v 1.123 2006/04/16 00:15:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
|
|
@ -76,24 +76,27 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
{
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
||||
unsigned part_off;
|
||||
unsigned part_off = 0;
|
||||
|
||||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
} else {
|
||||
assert(number_is_immediate(part_off_ex, 64));
|
||||
} else if (number_is_immediate(part_off_ex, 64)) {
|
||||
part_off = get_number_immediate(part_off_ex);
|
||||
part_off_ex = 0;
|
||||
}
|
||||
|
||||
if (ivl_lval_mux(lval)) {
|
||||
if (ivl_lval_mux(lval))
|
||||
part_off_ex = ivl_lval_mux(lval);
|
||||
|
||||
if (part_off_ex) {
|
||||
unsigned skip_set = transient_id++;
|
||||
|
||||
/* There is a mux expression, so this must be a write to
|
||||
a bit-select leval. Presumably, the x0 index register
|
||||
a bit-select l-val. Presumably, the x0 index register
|
||||
has been loaded wit the result of the evaluated
|
||||
ivl_lval_mux expression. */
|
||||
part select base expression. */
|
||||
|
||||
draw_eval_expr_into_integer(ivl_lval_mux(lval), 0);
|
||||
draw_eval_expr_into_integer(part_off_ex, 0);
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
|
||||
fprintf(vvp_out, " %%set/x0 V_%s, %u, %u;\n",
|
||||
|
|
@ -103,7 +106,7 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
} else if (part_off>0 || ivl_lval_width(lval)!=ivl_signal_width(sig)) {
|
||||
/* There is no mux expression, but a constant part
|
||||
offset. Load that into index x0 and generate a
|
||||
single-bit set instruction. */
|
||||
vector set instruction. */
|
||||
assert(ivl_lval_width(lval) == wid);
|
||||
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", part_off);
|
||||
|
|
@ -152,20 +155,22 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
{
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
||||
ivl_expr_t mux = ivl_lval_mux(lval);
|
||||
unsigned part_off;
|
||||
unsigned part_off = 0;
|
||||
|
||||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
} else {
|
||||
assert(number_is_immediate(part_off_ex, 64));
|
||||
} else if (number_is_immediate(part_off_ex, 64)) {
|
||||
part_off = get_number_immediate(part_off_ex);
|
||||
part_off_ex = 0;
|
||||
}
|
||||
|
||||
if (mux != 0) {
|
||||
if (ivl_lval_mux(lval))
|
||||
part_off_ex = ivl_lval_mux(lval);
|
||||
|
||||
if (part_off_ex) {
|
||||
unsigned skip_assign = transient_id++;
|
||||
assert(dexp == 0);
|
||||
draw_eval_expr_into_integer(mux, 1);
|
||||
draw_eval_expr_into_integer(part_off_ex, 1);
|
||||
/* If the index expression has XZ bits, skip the assign. */
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
|
|
@ -1479,6 +1484,9 @@ int draw_func_definition(ivl_scope_t scope)
|
|||
|
||||
/*
|
||||
* $Log: vvp_process.c,v $
|
||||
* Revision 1.123 2006/04/16 00:15:43 steve
|
||||
* Fix part selects in l-values.
|
||||
*
|
||||
* Revision 1.122 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue