elaborate complex l-values
This commit is contained in:
parent
b6ce313e91
commit
8a69c54886
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT) && !defined(macintosh)
|
#if !defined(WINNT) && !defined(macintosh)
|
||||||
#ident "$Id: design_dump.cc,v 1.95 2000/09/02 20:54:20 steve Exp $"
|
#ident "$Id: design_dump.cc,v 1.96 2000/09/10 02:18:16 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -422,41 +422,43 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
|
||||||
statement_->dump(o, ind+2);
|
statement_->dump(o, ind+2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetAssignBase::dump_lval(ostream&o) const
|
||||||
|
{
|
||||||
|
o << "" << "{" << lval_->name();
|
||||||
|
if (lval_->bmux())
|
||||||
|
o << "[" << *lval_->bmux() << "]";
|
||||||
|
|
||||||
|
for (NetAssign_*cur = lval_->more ; cur ; cur = cur->more) {
|
||||||
|
o << ", " << cur->name();
|
||||||
|
if (cur->bmux())
|
||||||
|
o << "[" << *cur->bmux() << "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
o << "}";
|
||||||
|
}
|
||||||
|
|
||||||
/* Dump an assignment statement */
|
/* Dump an assignment statement */
|
||||||
void NetAssign::dump(ostream&o, unsigned ind) const
|
void NetAssign::dump(ostream&o, unsigned ind) const
|
||||||
{
|
{
|
||||||
o << setw(ind) << "";
|
o << setw(ind) << "";
|
||||||
|
dump_lval(o);
|
||||||
|
|
||||||
if (l_val(0)->bmux()) {
|
o << " = ";
|
||||||
o << l_val(0)->name() << "[" << *l_val(0)->bmux() << "] = ";
|
if (l_val(0)->rise_time())
|
||||||
if (l_val(0)->rise_time())
|
o << "#" << l_val(0)->rise_time() << " ";
|
||||||
o << "#" << l_val(0)->rise_time() << " ";
|
o << *rval() << ";" << endl;
|
||||||
o << *rval() << ";" << endl;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
o << l_val(0)->name() << " = ";
|
|
||||||
if (l_val(0)->rise_time())
|
|
||||||
o << "#" << l_val(0)->rise_time() << " ";
|
|
||||||
o << *rval() << ";" << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetAssignNB::dump(ostream&o, unsigned ind) const
|
void NetAssignNB::dump(ostream&o, unsigned ind) const
|
||||||
{
|
{
|
||||||
o << setw(ind) << "";
|
o << setw(ind) << "";
|
||||||
|
dump_lval(o);
|
||||||
|
|
||||||
if (l_val(0)->bmux()) {
|
o << " <= ";
|
||||||
o << l_val(0)->name() << "[" << *l_val(0)->bmux() << "] <= ";
|
if (l_val(0)->rise_time())
|
||||||
if (l_val(0)->rise_time())
|
o << "#" << l_val(0)->rise_time() << " ";
|
||||||
o << "#" << l_val(0)->rise_time() << " ";
|
o << *rval() << ";" << endl;
|
||||||
o << *rval() << ";" << endl;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
o << l_val(0)->name() << " <= ";
|
|
||||||
if (l_val(0)->rise_time())
|
|
||||||
o << "#" << l_val(0)->rise_time() << " ";
|
|
||||||
o << *rval() << ";" << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetAssignMem::dump(ostream&o, unsigned ind) const
|
void NetAssignMem::dump(ostream&o, unsigned ind) const
|
||||||
|
|
@ -967,6 +969,9 @@ void Design::dump(ostream&o) const
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: design_dump.cc,v $
|
* $Log: design_dump.cc,v $
|
||||||
|
* Revision 1.96 2000/09/10 02:18:16 steve
|
||||||
|
* elaborate complex l-values
|
||||||
|
*
|
||||||
* Revision 1.95 2000/09/02 20:54:20 steve
|
* Revision 1.95 2000/09/02 20:54:20 steve
|
||||||
* Rearrange NetAssign to make NetAssign_ separate.
|
* Rearrange NetAssign to make NetAssign_ separate.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
37
elab_lval.cc
37
elab_lval.cc
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT) && !defined(macintosh)
|
#if !defined(WINNT) && !defined(macintosh)
|
||||||
#ident "$Id: elab_lval.cc,v 1.1 2000/09/09 15:21:26 steve Exp $"
|
#ident "$Id: elab_lval.cc,v 1.2 2000/09/10 02:18:16 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "PExpr.h"
|
# include "PExpr.h"
|
||||||
|
|
@ -79,23 +79,31 @@ NetAssign_* PExpr::elaborate_lval(Design*des, NetScope*scope) const
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Concatenation expressions can appear as l-values. Handle them here.
|
* Concatenation expressions can appear as l-values. Handle them here.
|
||||||
* XXXX For now, cheat and use elaborate_net to cope.
|
|
||||||
*/
|
*/
|
||||||
NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
|
NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
NetNet*ll = elaborate_net(des, scope->name(), 0, 0, 0, 0,
|
NetNet*ll = elaborate_net(des, scope->name(), 0, 0, 0, 0,
|
||||||
Link::STRONG, Link::STRONG);
|
Link::STRONG, Link::STRONG);
|
||||||
if (ll == 0) {
|
if (ll != 0) {
|
||||||
cerr << get_line() << ": Assignment l-value too complex."
|
NetAssign_*lv = new NetAssign_(scope->local_symbol(),
|
||||||
<< endl;
|
ll->pin_count());
|
||||||
return 0;
|
for (unsigned idx = 0 ; idx < ll->pin_count() ; idx += 1)
|
||||||
|
connect(lv->pin(idx), ll->pin(idx));
|
||||||
|
des->add_node(lv);
|
||||||
|
return lv;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
NetAssign_*res = 0;
|
||||||
|
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||||
|
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope);
|
||||||
|
assert(tmp);
|
||||||
|
|
||||||
|
tmp->more = res;
|
||||||
|
res = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetAssign_*lv = new NetAssign_(scope->local_symbol(), ll->pin_count());
|
return res;
|
||||||
for (unsigned idx = 0 ; idx < ll->pin_count() ; idx += 1)
|
|
||||||
connect(lv->pin(idx), ll->pin(idx));
|
|
||||||
des->add_node(lv);
|
|
||||||
return lv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -195,7 +203,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||||
NetAssign_ the width of the target reg and attach a
|
NetAssign_ the width of the target reg and attach a
|
||||||
bmux to select the target bit. */
|
bmux to select the target bit. */
|
||||||
unsigned wid = reg->pin_count();
|
unsigned wid = reg->pin_count();
|
||||||
lv = new NetAssign_(scope->local_symbol(), wid);
|
lv = new NetAssign_(des->local_symbol(scope->name()), wid);
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||||
connect(lv->pin(idx), reg->pin(idx));
|
connect(lv->pin(idx), reg->pin(idx));
|
||||||
|
|
@ -210,7 +218,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||||
unsigned wid = (msb >= lsb)? (msb-lsb+1) : (lsb-msb+1);
|
unsigned wid = (msb >= lsb)? (msb-lsb+1) : (lsb-msb+1);
|
||||||
assert(wid <= reg->pin_count());
|
assert(wid <= reg->pin_count());
|
||||||
|
|
||||||
lv = new NetAssign_(scope->local_symbol(), wid);
|
lv = new NetAssign_(des->local_symbol(scope->name()), wid);
|
||||||
unsigned off = reg->sb_to_idx(lsb);
|
unsigned off = reg->sb_to_idx(lsb);
|
||||||
assert((off+wid) <= reg->pin_count());
|
assert((off+wid) <= reg->pin_count());
|
||||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||||
|
|
@ -226,6 +234,9 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: elab_lval.cc,v $
|
* $Log: elab_lval.cc,v $
|
||||||
|
* Revision 1.2 2000/09/10 02:18:16 steve
|
||||||
|
* elaborate complex l-values
|
||||||
|
*
|
||||||
* Revision 1.1 2000/09/09 15:21:26 steve
|
* Revision 1.1 2000/09/09 15:21:26 steve
|
||||||
* move lval elaboration to PExpr virtual methods.
|
* move lval elaboration to PExpr virtual methods.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT) && !defined(macintosh)
|
#if !defined(WINNT) && !defined(macintosh)
|
||||||
#ident "$Id: net_assign.cc,v 1.3 2000/09/07 00:06:53 steve Exp $"
|
#ident "$Id: net_assign.cc,v 1.4 2000/09/10 02:18:16 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
|
|
@ -34,10 +34,12 @@ NetAssign_::NetAssign_(const string&n, unsigned w)
|
||||||
pin(idx).set_name("P", idx);
|
pin(idx).set_name("P", idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
more = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetAssign_::~NetAssign_()
|
NetAssign_::~NetAssign_()
|
||||||
{
|
{
|
||||||
|
assert( more == 0 );
|
||||||
if (bmux_) delete bmux_;
|
if (bmux_) delete bmux_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,7 +68,12 @@ NetAssignBase::NetAssignBase(NetAssign_*lv, NetExpr*rv)
|
||||||
NetAssignBase::~NetAssignBase()
|
NetAssignBase::~NetAssignBase()
|
||||||
{
|
{
|
||||||
if (rval_) delete rval_;
|
if (rval_) delete rval_;
|
||||||
if (lval_) delete lval_;
|
while (lval_) {
|
||||||
|
NetAssign_*tmp = lval_;
|
||||||
|
lval_ = tmp->more;
|
||||||
|
tmp->more = 0;
|
||||||
|
delete tmp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* NetAssignBase::rval()
|
NetExpr* NetAssignBase::rval()
|
||||||
|
|
@ -87,20 +94,40 @@ void NetAssignBase::set_rval(NetExpr*r)
|
||||||
|
|
||||||
NetAssign_* NetAssignBase::l_val(unsigned idx)
|
NetAssign_* NetAssignBase::l_val(unsigned idx)
|
||||||
{
|
{
|
||||||
|
NetAssign_*cur = lval_;
|
||||||
|
while (idx > 0) {
|
||||||
|
if (cur == 0)
|
||||||
|
return cur;
|
||||||
|
|
||||||
|
cur = cur->more;
|
||||||
|
idx -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
assert(idx == 0);
|
assert(idx == 0);
|
||||||
return lval_;
|
return cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NetAssign_* NetAssignBase::l_val(unsigned idx) const
|
const NetAssign_* NetAssignBase::l_val(unsigned idx) const
|
||||||
{
|
{
|
||||||
|
const NetAssign_*cur = lval_;
|
||||||
|
while (idx > 0) {
|
||||||
|
if (cur == 0)
|
||||||
|
return cur;
|
||||||
|
|
||||||
|
cur = cur->more;
|
||||||
|
idx -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
assert(idx == 0);
|
assert(idx == 0);
|
||||||
return lval_;
|
return cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned NetAssignBase::lwidth() const
|
unsigned NetAssignBase::lwidth() const
|
||||||
{
|
{
|
||||||
assert(lval_);
|
unsigned sum = 0;
|
||||||
return lval_->lwidth();
|
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more)
|
||||||
|
sum += cur->lwidth();
|
||||||
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -124,6 +151,9 @@ NetAssignNB::~NetAssignNB()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: net_assign.cc,v $
|
* $Log: net_assign.cc,v $
|
||||||
|
* Revision 1.4 2000/09/10 02:18:16 steve
|
||||||
|
* elaborate complex l-values
|
||||||
|
*
|
||||||
* Revision 1.3 2000/09/07 00:06:53 steve
|
* Revision 1.3 2000/09/07 00:06:53 steve
|
||||||
* encapsulate access to the l-value expected width.
|
* encapsulate access to the l-value expected width.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
15
netlist.h
15
netlist.h
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT) && !defined(macintosh)
|
#if !defined(WINNT) && !defined(macintosh)
|
||||||
#ident "$Id: netlist.h,v 1.161 2000/09/07 00:06:53 steve Exp $"
|
#ident "$Id: netlist.h,v 1.162 2000/09/10 02:18:16 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1128,6 +1128,11 @@ class NetProc : public LineInfo {
|
||||||
* assignment has its effect. The NetAssign_ class is not to be
|
* assignment has its effect. The NetAssign_ class is not to be
|
||||||
* derived from.
|
* derived from.
|
||||||
*
|
*
|
||||||
|
* The collection is arranged from lsb up to msb, and represents the
|
||||||
|
* concatenation of l-values. The elaborator may collapse some
|
||||||
|
* concatenations into a single NetAssign_. The "more" member of the
|
||||||
|
* NetAssign_ object points to the next most significant bits of l-value.
|
||||||
|
*
|
||||||
* NOTE: The elaborator will make an effort to match the width of the
|
* NOTE: The elaborator will make an effort to match the width of the
|
||||||
* r-value to the with of the l-value, but targets and functions
|
* r-value to the with of the l-value, but targets and functions
|
||||||
* should know that this is not a guarantee.
|
* should know that this is not a guarantee.
|
||||||
|
|
@ -1154,6 +1159,9 @@ class NetAssign_ : public NetNode {
|
||||||
virtual bool emit_node(struct target_t*) const;
|
virtual bool emit_node(struct target_t*) const;
|
||||||
virtual void dump_node(ostream&, unsigned ind) const;
|
virtual void dump_node(ostream&, unsigned ind) const;
|
||||||
|
|
||||||
|
// This pointer is for keeping simple lists.
|
||||||
|
NetAssign_* more;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetExpr*bmux_;
|
NetExpr*bmux_;
|
||||||
};
|
};
|
||||||
|
|
@ -1178,6 +1186,8 @@ class NetAssignBase : public NetProc {
|
||||||
// accounts for any grouping of NetAssign_ objects that might happen.
|
// accounts for any grouping of NetAssign_ objects that might happen.
|
||||||
unsigned lwidth() const;
|
unsigned lwidth() const;
|
||||||
|
|
||||||
|
void dump_lval(ostream&) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetAssign_*lval_;
|
NetAssign_*lval_;
|
||||||
NetExpr *rval_;
|
NetExpr *rval_;
|
||||||
|
|
@ -2752,6 +2762,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: netlist.h,v $
|
* $Log: netlist.h,v $
|
||||||
|
* Revision 1.162 2000/09/10 02:18:16 steve
|
||||||
|
* elaborate complex l-values
|
||||||
|
*
|
||||||
* Revision 1.161 2000/09/07 00:06:53 steve
|
* Revision 1.161 2000/09/07 00:06:53 steve
|
||||||
* encapsulate access to the l-value expected width.
|
* encapsulate access to the l-value expected width.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
265
t-vvm.cc
265
t-vvm.cc
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT) && !defined(macintosh)
|
#if !defined(WINNT) && !defined(macintosh)
|
||||||
#ident "$Id: t-vvm.cc,v 1.172 2000/09/08 17:08:10 steve Exp $"
|
#ident "$Id: t-vvm.cc,v 1.173 2000/09/10 02:18:16 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include <iostream>
|
# include <iostream>
|
||||||
|
|
@ -174,6 +174,10 @@ class target_vvm : public target_t {
|
||||||
virtual void net_probe(const NetEvProbe*);
|
virtual void net_probe(const NetEvProbe*);
|
||||||
virtual bool process(const NetProcTop*);
|
virtual bool process(const NetProcTop*);
|
||||||
virtual void proc_assign(const NetAssign*);
|
virtual void proc_assign(const NetAssign*);
|
||||||
|
void proc_assign_rval(const NetAssign_*, const NetEConst*,
|
||||||
|
unsigned off);
|
||||||
|
void proc_assign_rval(const NetAssign_*, const string&,
|
||||||
|
unsigned wid, unsigned off);
|
||||||
virtual void proc_assign_mem(const NetAssignMem*);
|
virtual void proc_assign_mem(const NetAssignMem*);
|
||||||
virtual void proc_assign_nb(const NetAssignNB*);
|
virtual void proc_assign_nb(const NetAssignNB*);
|
||||||
virtual void proc_assign_mem_nb(const NetAssignMemNB*);
|
virtual void proc_assign_mem_nb(const NetAssignMemNB*);
|
||||||
|
|
@ -2139,6 +2143,140 @@ void target_vvm::start_process(ostream&os, const NetProcTop*proc)
|
||||||
<< endl << "{" << endl;
|
<< endl << "{" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method handles the special case of the assignment of a
|
||||||
|
* constant r-value to the l-value. In this case, I can set specific
|
||||||
|
* values to each of the bits instead of calculating bit values or
|
||||||
|
* even reading values from a vpip_bit_t elsewhere.
|
||||||
|
*/
|
||||||
|
void target_vvm::proc_assign_rval(const NetAssign_*lv,
|
||||||
|
const NetEConst*rv,
|
||||||
|
unsigned off)
|
||||||
|
{
|
||||||
|
const verinum value = rv->value();
|
||||||
|
|
||||||
|
/* This condition catches the special case of assigning to a
|
||||||
|
non-constant bit select. This cal be something like:
|
||||||
|
|
||||||
|
a[idx] = x;
|
||||||
|
|
||||||
|
For this sort of assignment, I only need a single bit of
|
||||||
|
the r-value. That bit is written into a single bit of the
|
||||||
|
target using a generated switch statement, where each case
|
||||||
|
of the switch assignes to a specific nexus. This is not
|
||||||
|
unreasonable because there aren't typically all that many
|
||||||
|
bits in the l-value. */
|
||||||
|
|
||||||
|
if (lv->bmux()) {
|
||||||
|
|
||||||
|
// This is a bit select. Assign the low bit of the
|
||||||
|
// constant to the selected bit of the lval.
|
||||||
|
|
||||||
|
const char*rval = vvm_val_name(value.get(off),
|
||||||
|
Link::STRONG,
|
||||||
|
Link::STRONG);
|
||||||
|
|
||||||
|
string bval = emit_proc_rval(this, lv->bmux());
|
||||||
|
|
||||||
|
defn << " switch (" << bval
|
||||||
|
<< ".as_unsigned()) {" << endl;
|
||||||
|
|
||||||
|
for (unsigned idx = 0; idx < lv->pin_count(); idx += 1) {
|
||||||
|
|
||||||
|
string nexus = lv->pin(idx).nexus()->name();
|
||||||
|
unsigned ncode = nexus_wire_map[nexus];
|
||||||
|
|
||||||
|
defn << " case " << idx << ":" << endl;
|
||||||
|
|
||||||
|
defn << " nexus_wire_table["<<ncode<<"]"
|
||||||
|
<< ".reg_assign(" << rval << ");" << endl;
|
||||||
|
defn << " break;" << endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
defn << " }" << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* We've handled the case of bit selects, so here we know that
|
||||||
|
we are doing a good ol' assignment to an l-value. So for
|
||||||
|
the entire width of the l-value, assign constant bit values
|
||||||
|
to the appropriate nexus. */
|
||||||
|
|
||||||
|
for (unsigned idx = 0 ; idx < lv->pin_count() ; idx += 1) {
|
||||||
|
string nexus = lv->pin(idx).nexus()->name();
|
||||||
|
unsigned ncode = nexus_wire_map[nexus];
|
||||||
|
|
||||||
|
verinum::V val = (idx+off) < value.len()
|
||||||
|
? value.get(idx+off)
|
||||||
|
: verinum::V0;
|
||||||
|
const char*rval = vvm_val_name(val, Link::STRONG, Link::STRONG);
|
||||||
|
|
||||||
|
defn << " nexus_wire_table[" <<ncode<< "]"
|
||||||
|
<< ".reg_assign(" << rval << ");" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method does the grunt work of generating an assignment given a
|
||||||
|
* generated rval result.
|
||||||
|
*/
|
||||||
|
void target_vvm::proc_assign_rval(const NetAssign_*lv,
|
||||||
|
const string&rval,
|
||||||
|
unsigned wid, unsigned off)
|
||||||
|
{
|
||||||
|
assert(lv);
|
||||||
|
|
||||||
|
/* Now, if there is a mux on the l-value, generate a code to
|
||||||
|
assign a single bit to one of the bits of the
|
||||||
|
l-value. Otherwise, generate code for a complete
|
||||||
|
assignment. */
|
||||||
|
|
||||||
|
if (lv->bmux()) {
|
||||||
|
|
||||||
|
// This is a bit select. Assign the low bit of the rval
|
||||||
|
// to the selected bit of the lval.
|
||||||
|
string bval = emit_proc_rval(this, lv->bmux());
|
||||||
|
|
||||||
|
defn << " switch (" << bval << ".as_unsigned()) {" << endl;
|
||||||
|
|
||||||
|
for (unsigned idx = 0 ; idx < lv->pin_count() ; idx += 1) {
|
||||||
|
|
||||||
|
string nexus = lv->pin(idx).nexus()->name();
|
||||||
|
unsigned ncode = nexus_wire_map[nexus];
|
||||||
|
|
||||||
|
defn << " case " << idx << ":" << endl;
|
||||||
|
|
||||||
|
defn << " nexus_wire_table["<<ncode<<"]"
|
||||||
|
<< ".reg_assign(" << rval << "["<<off<<"]);" << endl;
|
||||||
|
defn << " break;" << endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
defn << " }" << endl;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
unsigned min_count = lv->pin_count();
|
||||||
|
if ((wid-off) < min_count)
|
||||||
|
min_count = wid - off;
|
||||||
|
|
||||||
|
for (unsigned idx = 0 ; idx < min_count ; idx += 1) {
|
||||||
|
string nexus = lv->pin(idx).nexus()->name();
|
||||||
|
unsigned ncode = nexus_wire_map[nexus];
|
||||||
|
defn << " nexus_wire_table["<<ncode<<"].reg_assign("
|
||||||
|
<< rval << "[" << (idx+off) << "]);" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned idx = min_count; idx < lv->pin_count(); idx += 1) {
|
||||||
|
string nexus = lv->pin(idx).nexus()->name();
|
||||||
|
unsigned ncode = nexus_wire_map[nexus];
|
||||||
|
defn << " nexus_wire_table["<<ncode<<"]"
|
||||||
|
<< ".reg_assign(St0);" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This method generates code for a procedural assignment. The lval is
|
* This method generates code for a procedural assignment. The lval is
|
||||||
* a signal, but the assignment should generate code to go to all the
|
* a signal, but the assignment should generate code to go to all the
|
||||||
|
|
@ -2148,59 +2286,22 @@ void target_vvm::proc_assign(const NetAssign*net)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Detect the very special (and very common) case that the
|
/* Detect the very special (and very common) case that the
|
||||||
rvalue is a constant in this assignment. I this case, there
|
rvalue is a constant value. In this case, there is no
|
||||||
is no reason to go scan the expression, and in the process
|
reason to go scan the expression, and in the process
|
||||||
generate bunches of temporaries. */
|
generate bunches of temporaries. */
|
||||||
|
|
||||||
if (const NetEConst*rc = dynamic_cast<const NetEConst*>(net->rval())) {
|
if (const NetEConst*rc = dynamic_cast<const NetEConst*>(net->rval())) {
|
||||||
|
|
||||||
const verinum value = rc->value();
|
const NetAssign_*cur = net->l_val(0);
|
||||||
|
unsigned off = 0;
|
||||||
if (net->l_val(0)->bmux()) {
|
unsigned idx = 0;
|
||||||
|
while (cur != 0) {
|
||||||
// This is a bit select. Assign the low bit of the
|
proc_assign_rval(cur, rc, off);
|
||||||
// constant to the selected bit of the lval.
|
off += cur->lwidth();
|
||||||
|
idx += 1;
|
||||||
const char*rval = vvm_val_name(value.get(0),
|
cur = net->l_val(idx);
|
||||||
Link::STRONG,
|
|
||||||
Link::STRONG);
|
|
||||||
|
|
||||||
string bval = emit_proc_rval(this, net->l_val(0)->bmux());
|
|
||||||
|
|
||||||
defn << " switch (" << bval
|
|
||||||
<< ".as_unsigned()) {" << endl;
|
|
||||||
|
|
||||||
for (unsigned idx = 0; idx < net->l_val(0)->pin_count(); idx += 1) {
|
|
||||||
|
|
||||||
string nexus = net->l_val(0)->pin(idx).nexus()->name();
|
|
||||||
unsigned ncode = nexus_wire_map[nexus];
|
|
||||||
|
|
||||||
defn << " case " << idx << ":" << endl;
|
|
||||||
|
|
||||||
defn << " nexus_wire_table["<<ncode<<"]"
|
|
||||||
<< ".reg_assign(" << rval << ");" << endl;
|
|
||||||
defn << " break;" << endl;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
defn << " }" << endl;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < net->l_val(0)->pin_count() ; idx += 1) {
|
|
||||||
string nexus = net->l_val(0)->pin(idx).nexus()->name();
|
|
||||||
unsigned ncode = nexus_wire_map[nexus];
|
|
||||||
|
|
||||||
verinum::V val = idx < value.len()
|
|
||||||
? value.get(idx)
|
|
||||||
: verinum::V0;
|
|
||||||
const char*rval = vvm_val_name(val,
|
|
||||||
Link::STRONG,
|
|
||||||
Link::STRONG);
|
|
||||||
|
|
||||||
defn << " nexus_wire_table[" <<ncode<< "]"
|
|
||||||
<< ".reg_assign(" << rval << ");" << endl;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2218,12 +2319,11 @@ void target_vvm::proc_assign(const NetAssign*net)
|
||||||
|
|
||||||
if (const NetESignal*rs = dynamic_cast<const NetESignal*>(net->rval())) {
|
if (const NetESignal*rs = dynamic_cast<const NetESignal*>(net->rval())) {
|
||||||
|
|
||||||
if (net->l_val(0)->pin_count() > rs->pin_count()) {
|
if (net->lwidth() > rs->pin_count()) {
|
||||||
rval = emit_proc_rval(this, net->rval());
|
rval = emit_proc_rval(this, net->rval());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
assert((net->l_val(0)->pin_count() <= rs->pin_count())
|
|
||||||
|| (net->l_val(0)->bmux() && (rs->pin_count() >= 1)));
|
|
||||||
rval = mangle(rs->name()) + ".bits";
|
rval = mangle(rs->name()) + ".bits";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2235,53 +2335,16 @@ void target_vvm::proc_assign(const NetAssign*net)
|
||||||
|
|
||||||
defn << " // " << net->get_line() << ": " << endl;
|
defn << " // " << net->get_line() << ": " << endl;
|
||||||
|
|
||||||
|
{ const NetAssign_*cur = net->l_val(0);
|
||||||
/* Now, if there is a mux on the l-value, generate a code to
|
unsigned wid = net->rval()->expr_width();
|
||||||
assign a single bit to one of the bits of the
|
unsigned off = 0;
|
||||||
l-value. Otherwise, generate code for a complete
|
unsigned idx = 0;
|
||||||
assignment. */
|
while (cur != 0) {
|
||||||
|
proc_assign_rval(cur, rval, wid, off);
|
||||||
if (net->l_val(0)->bmux()) {
|
off += cur->lwidth();
|
||||||
|
idx += 1;
|
||||||
// This is a bit select. Assign the low bit of the rval
|
cur = net->l_val(idx);
|
||||||
// to the selected bit of the lval.
|
}
|
||||||
string bval = emit_proc_rval(this, net->l_val(0)->bmux());
|
|
||||||
|
|
||||||
defn << " switch (" << bval << ".as_unsigned()) {" << endl;
|
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < net->l_val(0)->pin_count() ; idx += 1) {
|
|
||||||
|
|
||||||
string nexus = net->l_val(0)->pin(idx).nexus()->name();
|
|
||||||
unsigned ncode = nexus_wire_map[nexus];
|
|
||||||
|
|
||||||
defn << " case " << idx << ":" << endl;
|
|
||||||
|
|
||||||
defn << " nexus_wire_table["<<ncode<<"]"
|
|
||||||
<< ".reg_assign(" << rval << "[0]);" << endl;
|
|
||||||
defn << " break;" << endl;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
defn << " }" << endl;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
unsigned min_count = net->l_val(0)->pin_count();
|
|
||||||
if (net->rval()->expr_width() < min_count)
|
|
||||||
min_count = net->rval()->expr_width();
|
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < min_count ; idx += 1) {
|
|
||||||
string nexus = net->l_val(0)->pin(idx).nexus()->name();
|
|
||||||
unsigned ncode = nexus_wire_map[nexus];
|
|
||||||
defn << " nexus_wire_table["<<ncode<<"].reg_assign("
|
|
||||||
<< rval << "[" << idx << "]);" << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned idx = min_count; idx < net->l_val(0)->pin_count(); idx += 1) {
|
|
||||||
string nexus = net->l_val(0)->pin(idx).nexus()->name();
|
|
||||||
unsigned ncode = nexus_wire_map[nexus];
|
|
||||||
defn << " nexus_wire_table["<<ncode<<"]"
|
|
||||||
<< ".reg_assign(St0);" << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2320,6 +2383,9 @@ void target_vvm::proc_assign_nb(const NetAssignNB*net)
|
||||||
string rval = emit_proc_rval(this, net->rval());
|
string rval = emit_proc_rval(this, net->rval());
|
||||||
const unsigned long delay = net->l_val(0)->rise_time();
|
const unsigned long delay = net->l_val(0)->rise_time();
|
||||||
|
|
||||||
|
// XXXX I cannot handle this yet.
|
||||||
|
assert(net->l_val(1) == 0);
|
||||||
|
|
||||||
if (net->l_val(0)->bmux()) {
|
if (net->l_val(0)->bmux()) {
|
||||||
/* If the l-value has a bit select, set the output bit
|
/* If the l-value has a bit select, set the output bit
|
||||||
to only the desired bit. Evaluate the index and use
|
to only the desired bit. Evaluate the index and use
|
||||||
|
|
@ -3116,6 +3182,9 @@ extern const struct target tgt_vvm = {
|
||||||
};
|
};
|
||||||
/*
|
/*
|
||||||
* $Log: t-vvm.cc,v $
|
* $Log: t-vvm.cc,v $
|
||||||
|
* Revision 1.173 2000/09/10 02:18:16 steve
|
||||||
|
* elaborate complex l-values
|
||||||
|
*
|
||||||
* Revision 1.172 2000/09/08 17:08:10 steve
|
* Revision 1.172 2000/09/08 17:08:10 steve
|
||||||
* initialize vlog info.
|
* initialize vlog info.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue