Major rework of array handling. Memories are replaced with the
more general concept of arrays. The NetMemory and NetEMemory classes are removed from the ivl core program, and the IVL_LPM_RAM lpm type is removed from the ivl_target API.
This commit is contained in:
parent
5c3b2f4193
commit
91d84e7dc7
51
PExpr.h
51
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.86 2006/11/10 04:54:26 steve Exp $"
|
||||
#ident "$Id: PExpr.h,v 1.87 2007/01/16 05:44:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
|
|
@ -294,9 +294,10 @@ class PEIdent : public PExpr {
|
|||
bool calculate_up_do_width_(Design*, NetScope*, unsigned long&wid) const;
|
||||
|
||||
private:
|
||||
NetAssign_*elaborate_lval_net_part_(Design*, NetScope*, NetNet*) const;
|
||||
NetAssign_*elaborate_lval_net_idx_up_(Design*, NetScope*, NetNet*) const;
|
||||
NetAssign_*elaborate_lval_net_idx_do_(Design*, NetScope*, NetNet*) const;
|
||||
NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*) const;
|
||||
bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
|
||||
bool elaborate_lval_net_idx_up_(Design*, NetScope*, NetAssign_*) const;
|
||||
bool elaborate_lval_net_idx_do_(Design*, NetScope*, NetAssign_*) const;
|
||||
|
||||
private:
|
||||
NetExpr*elaborate_expr_param(Design*des,
|
||||
|
|
@ -306,24 +307,30 @@ class PEIdent : public PExpr {
|
|||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const;
|
||||
NetExpr*elaborate_expr_net(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found) const;
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found,
|
||||
bool sys_task_arg) const;
|
||||
NetExpr*elaborate_expr_net_word_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found,
|
||||
bool sys_task_arg) const;
|
||||
NetExpr*elaborate_expr_net_part_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net_idx_up_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net_bit_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
hname_t path_;
|
||||
|
||||
|
|
@ -338,12 +345,13 @@ class PEIdent : public PExpr {
|
|||
// expression. If this is a reference to a vector, this is a
|
||||
// bit select.
|
||||
std::vector<PExpr*> idx_;
|
||||
|
||||
NetNet* elaborate_net_ram_(Design*des, NetScope*scope,
|
||||
NetMemory*mem, unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_array_(Design*des, NetScope*scope,
|
||||
NetNet*sig, unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
NetNet* elaborate_net_bitmux_(Design*des, NetScope*scope,
|
||||
NetNet*sig,
|
||||
|
|
@ -354,9 +362,6 @@ class PEIdent : public PExpr {
|
|||
Link::strength_t drive1) const;
|
||||
|
||||
private:
|
||||
NetAssign_* elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
NetMemory*mem) const;
|
||||
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok,
|
||||
bool bidirectional_flag) const;
|
||||
|
|
@ -650,6 +655,12 @@ class PECallFunction : public PExpr {
|
|||
|
||||
/*
|
||||
* $Log: PExpr.h,v $
|
||||
* Revision 1.87 2007/01/16 05:44:14 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.86 2006/11/10 04:54:26 steve
|
||||
* Add test_width methods for PETernary and PEString.
|
||||
*
|
||||
|
|
|
|||
9
PWire.cc
9
PWire.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PWire.cc,v 1.11 2005/07/07 16:22:49 steve Exp $"
|
||||
#ident "$Id: PWire.cc,v 1.12 2007/01/16 05:44:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -154,13 +154,18 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
|
|||
{
|
||||
assert(lidx_ == 0);
|
||||
assert(ridx_ == 0);
|
||||
assert(type_ == NetNet::REG);
|
||||
lidx_ = ldx;
|
||||
ridx_ = rdx;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PWire.cc,v $
|
||||
* Revision 1.12 2007/01/16 05:44:14 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.11 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.171 2006/10/30 05:44:49 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.172 2007/01/16 05:44:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -112,8 +112,8 @@ void NetDelaySrc::dump(ostream&o, unsigned ind) const
|
|||
/* Dump a net. This can be a wire or register. */
|
||||
void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << type() << ": " << name() << "[" <<
|
||||
pin_count() << "]";
|
||||
o << setw(ind) << "" << type() << ": " << name()
|
||||
<< "[" << s0_ << ":" << e0_ << " count=" << pin_count() << "]";
|
||||
if (local_flag_)
|
||||
o << " (local)";
|
||||
o << " " << data_type_;
|
||||
|
|
@ -167,13 +167,6 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
|||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetMemory::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << name_ << "[" << width_ << "] " <<
|
||||
"[" << idxh_ << ":" << idxl_ << "]" << endl;
|
||||
}
|
||||
|
||||
|
||||
/* Dump a NetNode and its pins. Dump what I know about the netnode on
|
||||
the first line, then list all the pins, with the name of the
|
||||
connected signal. */
|
||||
|
|
@ -239,6 +232,15 @@ void NetAddSub::dump_node(ostream&o, unsigned ind) const
|
|||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetArrayDq::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetArrayDq: " << name()
|
||||
<< " array=" << mem_->name()
|
||||
<< endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCLShift::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Combinatorial shift (NetCLShift): " <<
|
||||
|
|
@ -427,14 +429,6 @@ void NetPartSelect::dump_node(ostream&o, unsigned ind) const
|
|||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetRamDq::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_RAM_DQ (" << mem_->name() << "): "
|
||||
<< name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetReplicate::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetReplicate: "
|
||||
|
|
@ -566,21 +560,9 @@ void NetAssign_::dump_lval(ostream&o) const
|
|||
{
|
||||
if (sig_) {
|
||||
o << sig_->name();
|
||||
if (bmux_) {
|
||||
o << "[" << *bmux_ << "]";
|
||||
|
||||
} else if (base_) {
|
||||
o << "[" << *base_ << " +: " << lwid_ << "]";
|
||||
if (word_) {
|
||||
o << "[word=" << *word_ << "]";
|
||||
}
|
||||
} else if (mem_) {
|
||||
// Is there an obvious way to flag memories in the dump
|
||||
// as different from the _real_ bit mux case?
|
||||
// o << "**memory**";
|
||||
o << mem_->name() << "[";
|
||||
if (bmux_) o << *bmux_;
|
||||
else o << "**oops**";
|
||||
o << "]";
|
||||
|
||||
if (base_) {
|
||||
o << "[" << *base_ << " +: " << lwid_ << "]";
|
||||
}
|
||||
|
|
@ -906,15 +888,6 @@ void NetScope::dump(ostream&o) const
|
|||
} while (cur != signals_->sig_next_);
|
||||
}
|
||||
|
||||
// Dump the memories,
|
||||
if (memories_) {
|
||||
NetMemory*cur = memories_->snext_;
|
||||
do {
|
||||
cur->dump(o, 4);
|
||||
cur = cur->snext_;
|
||||
} while (cur != memories_->snext_);
|
||||
}
|
||||
|
||||
// Dump specparams
|
||||
typedef map<perm_string,spec_val_t>::const_iterator specparam_it_t;
|
||||
for (specparam_it_t cur = specparams.begin()
|
||||
|
|
@ -1148,14 +1121,9 @@ void NetESignal::dump(ostream&o) const
|
|||
{
|
||||
if (has_sign())
|
||||
o << "+";
|
||||
o << name() << "[" << msi()<<":"<<lsi() << "]";
|
||||
}
|
||||
|
||||
void NetEMemory::dump(ostream&o) const
|
||||
{
|
||||
o << mem_->name() << "[";
|
||||
if (idx_) idx_->dump(o);
|
||||
o << "]";
|
||||
o << name();
|
||||
if (word_) o << "[word=" << *word_ << "]";
|
||||
o << "[" << msi()<<":"<<lsi() << "]";
|
||||
}
|
||||
|
||||
void NetEParam::dump(ostream&o) const
|
||||
|
|
@ -1165,7 +1133,7 @@ void NetEParam::dump(ostream&o) const
|
|||
else if (name_)
|
||||
o << "<" << name_ << ">";
|
||||
else
|
||||
o << "<???>";
|
||||
o << "<" "???" ">";
|
||||
}
|
||||
|
||||
void NetETernary::dump(ostream&o) const
|
||||
|
|
@ -1231,6 +1199,12 @@ void Design::dump(ostream&o) const
|
|||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.172 2007/01/16 05:44:14 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.171 2006/10/30 05:44:49 steve
|
||||
* Expression widths with unsized literals are pseudo-infinite width.
|
||||
*
|
||||
|
|
|
|||
279
elab_expr.cc
279
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.116 2006/11/10 04:54:26 steve Exp $"
|
||||
#ident "$Id: elab_expr.cc,v 1.117 2007/01/16 05:44:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -687,14 +687,13 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
|
|||
bool&unsized_flag) const
|
||||
{
|
||||
NetNet* net = 0;
|
||||
NetMemory* mem = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
const NetExpr*ex1, *ex2;
|
||||
|
||||
NetScope*found_in = symbol_search(des, scope, path_,
|
||||
net, mem, par, eve,
|
||||
net, par, eve,
|
||||
ex1, ex2);
|
||||
|
||||
if (net != 0) {
|
||||
|
|
@ -741,14 +740,13 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
assert(scope);
|
||||
|
||||
NetNet* net = 0;
|
||||
NetMemory* mem = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
const NetExpr*ex1, *ex2;
|
||||
|
||||
NetScope*found_in = symbol_search(des, scope, path_,
|
||||
net, mem, par, eve,
|
||||
net, par, eve,
|
||||
ex1, ex2);
|
||||
|
||||
// If the identifier name is a parameter name, then return
|
||||
|
|
@ -760,126 +758,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
// If the identifier names a signal (a register or wire)
|
||||
// then create a NetESignal node to handle it.
|
||||
if (net != 0)
|
||||
return elaborate_expr_net(des, scope, net, found_in);
|
||||
|
||||
|
||||
// If the identifier names a memory, then this is a
|
||||
// memory reference and I must generate a NetEMemory
|
||||
// object to handle it.
|
||||
if (mem != 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.
|
||||
if (sys_task_arg) {
|
||||
NetEMemory*node = new NetEMemory(mem);
|
||||
node->set_line(*this);
|
||||
return node;
|
||||
}
|
||||
|
||||
// If it is not a simple system task argument,
|
||||
// this a missing index is an error.
|
||||
cerr << get_line() << ": error: memory " << mem->name()
|
||||
<< " needs an index in this context." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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, -1, false);
|
||||
if (i == 0) {
|
||||
cerr << get_line() << ": error: Unable to elaborate "
|
||||
"index expression `" << *addr << "'" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEMemory*node = new NetEMemory(mem, i);
|
||||
node->set_line(*this);
|
||||
|
||||
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_, -1);
|
||||
NetExpr*me = elab_and_eval(des, scope, msb_, -1);
|
||||
|
||||
NetEConst*lec = dynamic_cast<NetEConst*>(le);
|
||||
NetEConst*mec = dynamic_cast<NetEConst*>(me);
|
||||
|
||||
if (lec == 0 || mec == 0) {
|
||||
cerr << get_line() << ": error: Part select "
|
||||
<< "expressions must be constant." << endl;
|
||||
des->errors += 1;
|
||||
delete le;
|
||||
delete me;
|
||||
return node;
|
||||
}
|
||||
|
||||
verinum wedv = mec->value() - lec->value();
|
||||
unsigned wid = wedv.as_long() + 1;
|
||||
|
||||
NetESelect*se = new NetESelect(node, le, wid);
|
||||
|
||||
delete me;
|
||||
return se;
|
||||
}
|
||||
|
||||
assert(sel_ == SEL_IDX_UP || sel_ == SEL_IDX_DO);
|
||||
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
|
||||
if (wid_ec == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
<< "Second expression of indexed part select "
|
||||
<< "most be constant." << endl;
|
||||
des->errors += 1;
|
||||
return node;
|
||||
}
|
||||
|
||||
unsigned wid = wid_ec->value().as_ulong();
|
||||
|
||||
NetExpr*idx_ex = elab_and_eval(des, scope, msb_, -1);
|
||||
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;
|
||||
}
|
||||
return elaborate_expr_net(des, scope, net, found_in, sys_task_arg);
|
||||
|
||||
// If the identifier is a named event.
|
||||
// is a variable reference.
|
||||
|
|
@ -1176,11 +1055,64 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle word selects of vector arrays.
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in,
|
||||
bool sys_task_arg) const
|
||||
{
|
||||
assert(sys_task_arg || !idx_.empty());
|
||||
NetExpr*word_index = idx_.empty()
|
||||
? 0
|
||||
: elab_and_eval(des, scope, idx_[0], -1);
|
||||
if (word_index == 0 && !sys_task_arg)
|
||||
return 0;
|
||||
|
||||
if (NetEConst*word_addr = dynamic_cast<NetEConst*>(word_index)) {
|
||||
long addr = word_addr->value().as_long();
|
||||
|
||||
// Special case: The index is out of range, so the value
|
||||
// of this expression is a 'bx vector the width of a word.
|
||||
if (!net->array_index_is_valid(addr)) {
|
||||
verinum xxx (verinum::Vx, net->vector_width());
|
||||
NetEConst*resx = new NetEConst(xxx);
|
||||
resx->set_line(*this);
|
||||
delete word_index;
|
||||
return resx;
|
||||
}
|
||||
|
||||
// Recalculate the constant address with the adjusted base.
|
||||
unsigned use_addr = net->array_index_to_address(addr);
|
||||
if (use_addr != addr) {
|
||||
verinum val (use_addr, 8*sizeof(use_addr));
|
||||
NetEConst*tmp = new NetEConst(val);
|
||||
tmp->set_line(*this);
|
||||
delete word_index;
|
||||
word_index = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
NetESignal*res = new NetESignal(net, word_index);
|
||||
res->set_line(*this);
|
||||
|
||||
if (sel_ == SEL_PART)
|
||||
return elaborate_expr_net_part_(des, scope, res, found_in);
|
||||
|
||||
if (sel_ == SEL_IDX_UP)
|
||||
return elaborate_expr_net_idx_up_(des, scope, res, found_in);
|
||||
|
||||
if (sel_ == SEL_IDX_DO)
|
||||
return elaborate_expr_net_idx_do_(des, scope, res, found_in);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle part selects of NetNet identifiers.
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in)const
|
||||
NetESignal*net, NetScope*found_in) const
|
||||
{
|
||||
long msv, lsv;
|
||||
assert(idx_.empty());
|
||||
|
|
@ -1199,40 +1131,37 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
|||
des->errors += 1;
|
||||
//delete lsn;
|
||||
//delete msn;
|
||||
return 0;
|
||||
return net;
|
||||
}
|
||||
assert(wid <= net->vector_width());
|
||||
|
||||
if (net->sb_to_idx(msv) < net->sb_to_idx(lsv)) {
|
||||
if (net->sig()->sb_to_idx(msv) < net->sig()->sb_to_idx(lsv)) {
|
||||
cerr << get_line() << ": error: part select ["
|
||||
<< msv << ":" << lsv << "] out of order." << endl;
|
||||
des->errors += 1;
|
||||
//delete lsn;
|
||||
//delete msn;
|
||||
return 0;
|
||||
return net;
|
||||
}
|
||||
|
||||
|
||||
if (net->sb_to_idx(msv) >= net->vector_width()) {
|
||||
if (net->sig()->sb_to_idx(msv) >= net->vector_width()) {
|
||||
cerr << get_line() << ": error: part select ["
|
||||
<< msv << ":" << lsv << "] out of range." << endl;
|
||||
des->errors += 1;
|
||||
//delete lsn;
|
||||
//delete msn;
|
||||
return 0;
|
||||
return net;
|
||||
}
|
||||
|
||||
NetESignal*tmp = new NetESignal(net);
|
||||
tmp->set_line(*this);
|
||||
|
||||
// If the part select convers exactly the entire
|
||||
// vector, then do not bother with it. Return the
|
||||
// signal itself.
|
||||
if (net->sb_to_idx(lsv) == 0 && wid == net->vector_width())
|
||||
return tmp;
|
||||
if (net->sig()->sb_to_idx(lsv) == 0 && wid == net->vector_width())
|
||||
return net;
|
||||
|
||||
NetExpr*ex = new NetEConst(verinum(net->sb_to_idx(lsv)));
|
||||
NetESelect*ss = new NetESelect(tmp, ex, wid);
|
||||
NetExpr*ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv)));
|
||||
NetESelect*ss = new NetESelect(net, ex, wid);
|
||||
ss->set_line(*this);
|
||||
|
||||
return ss;
|
||||
|
|
@ -1242,14 +1171,10 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
|||
* Part select indexed up, i.e. net[<m> +: <l>]
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in)const
|
||||
NetESignal*net, NetScope*found_in) const
|
||||
{
|
||||
assert(lsb_ != 0);
|
||||
assert(msb_ != 0);
|
||||
assert(idx_.empty());
|
||||
|
||||
NetESignal*sig = new NetESignal(net);
|
||||
sig->set_line(*this);
|
||||
|
||||
NetExpr*base = elab_and_eval(des, scope, msb_, -1);
|
||||
|
||||
|
|
@ -1266,11 +1191,11 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
|||
// If the part select convers exactly the entire
|
||||
// vector, then do not bother with it. Return the
|
||||
// signal itself.
|
||||
if (net->sb_to_idx(lsv) == 0 && wid == net->vector_width())
|
||||
return sig;
|
||||
if (net->sig()->sb_to_idx(lsv) == 0 && wid == net->vector_width())
|
||||
return net;
|
||||
}
|
||||
|
||||
NetESelect*ss = new NetESelect(sig, base, wid);
|
||||
NetESelect*ss = new NetESelect(net, base, wid);
|
||||
ss->set_line(*this);
|
||||
|
||||
if (debug_elaborate) {
|
||||
|
|
@ -1285,14 +1210,10 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
|||
* Part select up, i.e. net[<m> +: <l>]
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in)const
|
||||
NetESignal*net, NetScope*found_in)const
|
||||
{
|
||||
assert(lsb_ != 0);
|
||||
assert(msb_ != 0);
|
||||
assert(idx_.empty());
|
||||
|
||||
NetESignal*sig = new NetESignal(net);
|
||||
sig->set_line(*this);
|
||||
|
||||
NetExpr*base = elab_and_eval(des, scope, msb_, -1);
|
||||
|
||||
|
|
@ -1308,12 +1229,13 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
|||
// If the part select convers exactly the entire
|
||||
// vector, then do not bother with it. Return the
|
||||
// signal itself.
|
||||
if (net->sb_to_idx(lsv) == (wid-1) && wid == net->vector_width())
|
||||
return sig;
|
||||
if (net->sig()->sb_to_idx(lsv) == (wid-1)
|
||||
&& wid == net->vector_width())
|
||||
return net;
|
||||
}
|
||||
|
||||
NetExpr*base_adjusted = wid > 1? make_add_expr(base,1-wid) : base;
|
||||
NetESelect*ss = new NetESelect(sig, base_adjusted, wid);
|
||||
NetESelect*ss = new NetESelect(net, base_adjusted, wid);
|
||||
ss->set_line(*this);
|
||||
|
||||
if (debug_elaborate) {
|
||||
|
|
@ -1325,7 +1247,7 @@ 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
|
||||
NetESignal*net, NetScope*found_in) const
|
||||
{
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
|
|
@ -1338,7 +1260,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
// making a mux part in the netlist.
|
||||
if (NetEConst*msc = dynamic_cast<NetEConst*> (ex)) {
|
||||
long msv = msc->value().as_long();
|
||||
unsigned idx = net->sb_to_idx(msv);
|
||||
unsigned idx = net->sig()->sb_to_idx(msv);
|
||||
|
||||
if (idx >= net->vector_width()) {
|
||||
/* The bit select is out of range of the
|
||||
|
|
@ -1350,69 +1272,72 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
|
||||
cerr << get_line() << ": warning: Bit select ["
|
||||
<< msv << "] out of range of vector "
|
||||
<< net->name() << "[" << net->msb()
|
||||
<< ":" << net->lsb() << "]." << endl;
|
||||
<< net->name() << "[" << net->sig()->msb()
|
||||
<< ":" << net->sig()->lsb() << "]." << endl;
|
||||
cerr << get_line() << ": : Replacing "
|
||||
<< "expression with a constant 1'bx." << endl;
|
||||
delete ex;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetESignal*tmp = new NetESignal(net);
|
||||
tmp->set_line(*this);
|
||||
// If the vector is only one bit, we are done. The
|
||||
// bit select will return the scaler itself.
|
||||
if (net->vector_width() == 1)
|
||||
return tmp;
|
||||
return net;
|
||||
|
||||
// Make an expression out of the index
|
||||
NetEConst*idx_c = new NetEConst(verinum(idx));
|
||||
idx_c->set_line(*net);
|
||||
|
||||
// Make a bit select with the canonical index
|
||||
NetESelect*res = new NetESelect(tmp, idx_c, 1);
|
||||
NetESelect*res = new NetESelect(net, idx_c, 1);
|
||||
res->set_line(*net);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
NetESignal*node = new NetESignal(net);
|
||||
|
||||
// Non-constant bit select? punt and make a subsignal
|
||||
// device to mux the bit in the net. This is a fairly
|
||||
// complicated task because we need to generate
|
||||
// expressions to convert calculated bit select
|
||||
// values to canonical values that are used internally.
|
||||
|
||||
if (net->msb() < net->lsb()) {
|
||||
ex = make_sub_expr(net->lsb(), ex);
|
||||
if (net->sig()->msb() < net->sig()->lsb()) {
|
||||
ex = make_sub_expr(net->sig()->lsb(), ex);
|
||||
} else {
|
||||
ex = make_add_expr(ex, - net->lsb());
|
||||
ex = make_add_expr(ex, - net->sig()->lsb());
|
||||
}
|
||||
|
||||
NetESelect*ss = new NetESelect(node, ex, 1);
|
||||
NetESelect*ss = new NetESelect(net, ex, 1);
|
||||
ss->set_line(*this);
|
||||
return ss;
|
||||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in) const
|
||||
NetNet*net, NetScope*found_in,
|
||||
bool sys_task_arg) const
|
||||
{
|
||||
if (net->array_dimensions() > 0)
|
||||
return elaborate_expr_net_word_(des, scope, net, found_in, sys_task_arg);
|
||||
|
||||
NetESignal*node = new NetESignal(net);
|
||||
node->set_line(*this);
|
||||
|
||||
// If this is a part select of a signal, then make a new
|
||||
// temporary signal that is connected to just the
|
||||
// selected bits. The lsb_ and msb_ expressions are from
|
||||
// the foo[msb:lsb] expression in the original.
|
||||
if (sel_ == SEL_PART)
|
||||
return elaborate_expr_net_part_(des, scope, net, found_in);
|
||||
return elaborate_expr_net_part_(des, scope, node, found_in);
|
||||
|
||||
if (sel_ == SEL_IDX_UP)
|
||||
return elaborate_expr_net_idx_up_(des, scope, net, found_in);
|
||||
return elaborate_expr_net_idx_up_(des, scope, node, found_in);
|
||||
|
||||
if (sel_ == SEL_IDX_DO)
|
||||
return elaborate_expr_net_idx_do_(des, scope, net, found_in);
|
||||
return elaborate_expr_net_idx_do_(des, scope, node, found_in);
|
||||
|
||||
if (!idx_.empty())
|
||||
return elaborate_expr_net_bit_(des, scope, net, found_in);
|
||||
return elaborate_expr_net_bit_(des, scope, node, found_in);
|
||||
|
||||
// It's not anything else, so this must be a simple identifier
|
||||
// expression with no part or bit select. Return the signal
|
||||
|
|
@ -1422,8 +1347,6 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
|
|||
assert(lsb_ == 0);
|
||||
assert(idx_.empty());
|
||||
|
||||
NetESignal*node = new NetESignal(net);
|
||||
node->set_line(*this);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
|
@ -1675,6 +1598,12 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
/*
|
||||
* $Log: elab_expr.cc,v $
|
||||
* Revision 1.117 2007/01/16 05:44:14 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.116 2006/11/10 04:54:26 steve
|
||||
* Add test_width methods for PETernary and PEString.
|
||||
*
|
||||
|
|
|
|||
222
elab_lval.cc
222
elab_lval.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2006 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -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.37 2006/11/04 06:19:25 steve Exp $"
|
||||
#ident "$Id: elab_lval.cc,v 1.38 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
# include "PExpr.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
|
||||
# include "compiler.h"
|
||||
# include <iostream>
|
||||
|
||||
/*
|
||||
|
|
@ -149,25 +149,10 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
bool is_force) const
|
||||
{
|
||||
NetNet* reg = 0;
|
||||
NetMemory* mem = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(des, scope, path_, reg, mem, par, eve);
|
||||
|
||||
if (mem) {
|
||||
if (is_force) {
|
||||
cerr << get_line() << ": error: Memories "
|
||||
<< "(" << path_ << " in this case)"
|
||||
<< " are not allowed"
|
||||
<< " as l-values to force statements." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return elaborate_mem_lval_(des, scope, mem);
|
||||
}
|
||||
|
||||
symbol_search(des, scope, path_, reg, par, eve);
|
||||
if (reg == 0) {
|
||||
cerr << get_line() << ": error: Could not find variable ``"
|
||||
<< path_ << "'' in ``" << scope->name() <<
|
||||
|
|
@ -179,14 +164,26 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
|
||||
assert(reg);
|
||||
|
||||
if (sel_ == SEL_PART)
|
||||
return elaborate_lval_net_part_(des, scope, reg);
|
||||
if (reg->array_dimensions() > 0)
|
||||
return elaborate_lval_net_word_(des, scope, reg);
|
||||
|
||||
if (sel_ == SEL_IDX_UP)
|
||||
return elaborate_lval_net_idx_up_(des, scope, reg);
|
||||
if (sel_ == SEL_PART) {
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_part_(des, scope, lv);
|
||||
return lv;
|
||||
}
|
||||
|
||||
if (sel_ == SEL_IDX_DO)
|
||||
return elaborate_lval_net_idx_do_(des, scope, reg);
|
||||
if (sel_ == SEL_IDX_UP) {
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_idx_up_(des, scope, lv);
|
||||
return lv;
|
||||
}
|
||||
|
||||
if (sel_ == SEL_IDX_DO) {
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_idx_do_(des, scope, lv);
|
||||
return lv;
|
||||
}
|
||||
|
||||
/* Get the signal referenced by the identifier, and make sure
|
||||
it is a register. Wires are not allows in this context,
|
||||
|
|
@ -300,22 +297,60 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
return lv;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*reg) const
|
||||
{
|
||||
assert(idx_.size() == 1);
|
||||
|
||||
NetExpr*word = elab_and_eval(des, scope, idx_[0], -1);
|
||||
|
||||
// If there is a non-zero base to the memory, then build an
|
||||
// expression to calculate the canonical address.
|
||||
if (long base = reg->array_first()) {
|
||||
|
||||
word = make_add_expr(word, 0-base);
|
||||
if (NetExpr*tmp = word->eval_tree()) {
|
||||
word = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
lv->set_word(word);
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: Set array word=" << *word << endl;
|
||||
|
||||
/* An array word may also have part selects applied to them. */
|
||||
|
||||
if (sel_ == SEL_PART)
|
||||
elaborate_lval_net_part_(des, scope, lv);
|
||||
|
||||
if (sel_ == SEL_IDX_UP)
|
||||
elaborate_lval_net_idx_up_(des, scope, lv);
|
||||
|
||||
if (sel_ == SEL_IDX_DO)
|
||||
elaborate_lval_net_idx_do_(des, scope, lv);
|
||||
|
||||
return lv;
|
||||
}
|
||||
|
||||
bool PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
NetScope*scope,
|
||||
NetAssign_*lv) const
|
||||
{
|
||||
long msb, lsb;
|
||||
bool flag = calculate_parts_(des, scope, msb, lsb);
|
||||
if (!flag)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
NetAssign_*lv = 0;
|
||||
NetNet*reg = lv->sig();
|
||||
assert(reg);
|
||||
|
||||
if (msb == reg->msb() && lsb == reg->lsb()) {
|
||||
|
||||
/* No bit select, and part select covers the entire
|
||||
vector. Simplest case. */
|
||||
lv = new NetAssign_(reg);
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -331,7 +366,7 @@ NetAssign_* PEIdent::elaborate_lval_net_part_(Design*des,
|
|||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is reversed." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If the part select extends beyond the extreme of the
|
||||
|
|
@ -344,23 +379,25 @@ NetAssign_* PEIdent::elaborate_lval_net_part_(Design*des,
|
|||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
lv = new NetAssign_(reg);
|
||||
lv->set_part(new NetEConst(verinum(loff)), wid);
|
||||
}
|
||||
|
||||
return lv;
|
||||
return true;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_lval_net_idx_up_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*reg) const
|
||||
bool PEIdent::elaborate_lval_net_idx_up_(Design*des,
|
||||
NetScope*scope,
|
||||
NetAssign_*lv) const
|
||||
{
|
||||
assert(lsb_);
|
||||
assert(msb_);
|
||||
|
||||
NetNet*reg = lv->sig();
|
||||
assert(reg);
|
||||
|
||||
if (reg->type() != NetNet::REG) {
|
||||
cerr << get_line() << ": error: " << path_ <<
|
||||
" is not a reg/integer/time in " << scope->name() <<
|
||||
|
|
@ -368,7 +405,7 @@ NetAssign_* PEIdent::elaborate_lval_net_idx_up_(Design*des,
|
|||
cerr << reg->get_line() << ": : " << path_ <<
|
||||
" is declared here as " << reg->type() << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long wid;
|
||||
|
|
@ -382,112 +419,25 @@ NetAssign_* PEIdent::elaborate_lval_net_idx_up_(Design*des,
|
|||
else if (reg->lsb() != 0)
|
||||
base = make_add_expr(base, - reg->lsb());
|
||||
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: Set part select width="
|
||||
<< wid << ", base=" << *base << endl;
|
||||
|
||||
lv->set_part(base, wid);
|
||||
|
||||
return lv;
|
||||
return true;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_lval_net_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*reg) const
|
||||
bool PEIdent::elaborate_lval_net_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
NetAssign_*lv) 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
|
||||
{
|
||||
if (idx_.empty()) {
|
||||
cerr << get_line() << ": error: Assign to memory \""
|
||||
<< mem->name() << "\" requires a word select index."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// XXXX For now, require exactly 1 index.
|
||||
assert(idx_.size() == 1);
|
||||
|
||||
/* Elaborate the address expression. */
|
||||
NetExpr*ix = elab_and_eval(des, scope, idx_[0], -1);
|
||||
if (ix == 0)
|
||||
return 0;
|
||||
|
||||
NetAssign_*lv = new NetAssign_(mem);
|
||||
lv->set_bmux(ix);
|
||||
|
||||
/* If there is no extra part select, then we are done. */
|
||||
if (msb_ == 0 && lsb_ == 0) {
|
||||
lv->set_part(0, mem->width());
|
||||
return lv;
|
||||
}
|
||||
|
||||
assert(sel_ != SEL_NONE);
|
||||
assert(msb_ && lsb_);
|
||||
|
||||
if (sel_ == SEL_PART) {
|
||||
NetExpr*le = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetExpr*me = elab_and_eval(des, scope, msb_, -1);
|
||||
|
||||
NetEConst*lec = dynamic_cast<NetEConst*>(le);
|
||||
NetEConst*mec = dynamic_cast<NetEConst*>(me);
|
||||
|
||||
if (lec == 0 || mec == 0) {
|
||||
cerr << get_line() << ": error: Part select "
|
||||
<< "expressions must be constant." << endl;
|
||||
des->errors += 1;
|
||||
delete le;
|
||||
delete me;
|
||||
return lv;
|
||||
}
|
||||
|
||||
verinum wedv = mec->value() - lec->value();
|
||||
unsigned wid = wedv.as_long() + 1;
|
||||
|
||||
lv->set_part(lec, wid);
|
||||
return lv;
|
||||
}
|
||||
|
||||
assert(sel_ == SEL_IDX_UP || sel_ == SEL_IDX_DO);
|
||||
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
|
||||
if (wid_ec == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
<< "Second expression of indexed part select "
|
||||
<< "most be constant." << endl;
|
||||
des->errors += 1;
|
||||
return lv;
|
||||
}
|
||||
|
||||
unsigned wid = wid_ec->value().as_ulong();
|
||||
|
||||
NetExpr*base_ex = elab_and_eval(des, scope, msb_, -1);
|
||||
if (base_ex == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sel_ == SEL_IDX_DO && wid > 1) {
|
||||
base_ex = make_add_expr(base_ex, 1-(long)wid);
|
||||
}
|
||||
|
||||
lv->set_part(base_ex, wid);
|
||||
return lv;
|
||||
return false;
|
||||
}
|
||||
|
||||
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
|
||||
|
|
@ -500,6 +450,12 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
|
|||
|
||||
/*
|
||||
* $Log: elab_lval.cc,v $
|
||||
* Revision 1.38 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.37 2006/11/04 06:19:25 steve
|
||||
* Remove last bits of relax_width methods, and use test_width
|
||||
* to calculate the width of an r-value expression that may
|
||||
|
|
|
|||
189
elab_net.cc
189
elab_net.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2005 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -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.191 2006/12/08 03:43:26 steve Exp $"
|
||||
#ident "$Id: elab_net.cc,v 1.192 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -1594,18 +1594,10 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
|||
assert(scope);
|
||||
|
||||
NetNet* sig = 0;
|
||||
NetMemory* mem = 0;
|
||||
const NetExpr*par = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(des, scope, path_, sig, mem, par, eve);
|
||||
|
||||
/* If the identifier is a memory instead of a signal,
|
||||
then handle it elsewhere. Create a RAM. */
|
||||
if (mem != 0) {
|
||||
return elaborate_net_ram_(des, scope, mem, lwidth,
|
||||
rise, fall, decay);
|
||||
}
|
||||
symbol_search(des, scope, path_, sig, par, eve);
|
||||
|
||||
/* If this is a parameter name, then create a constant node
|
||||
that connects to a signal with the correct name. */
|
||||
|
|
@ -1681,6 +1673,13 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
|||
|
||||
assert(sig);
|
||||
|
||||
/* Handle the case that this is an array elsewhere. */
|
||||
if (sig->array_dimensions() > 0) {
|
||||
return elaborate_net_array_(des, scope, sig, lwidth,
|
||||
rise, fall, decay,
|
||||
drive0, drive1);
|
||||
}
|
||||
|
||||
/* Catch the case of a non-constant bit select. That should be
|
||||
handled elsewhere. */
|
||||
if (! idx_.empty()) {
|
||||
|
|
@ -1728,68 +1727,77 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
|||
return sig;
|
||||
}
|
||||
|
||||
/*
|
||||
* When I run into an identifier in an expression that refers to a
|
||||
* memory, create a RAM port object.
|
||||
*/
|
||||
NetNet* PEIdent::elaborate_net_ram_(Design*des, NetScope*scope,
|
||||
NetMemory*mem, unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const
|
||||
NetNet* PEIdent::elaborate_net_array_(Design*des, NetScope*scope,
|
||||
NetNet*sig, unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
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, idx_[0], -1);
|
||||
|
||||
/* If an offset is needed, subtract it from the address to get
|
||||
an expression for the canonical address. */
|
||||
if (mem->index_to_address(0) != 0) {
|
||||
adr_expr = make_add_expr(adr_expr, mem->index_to_address(0));
|
||||
if (NetExpr*tmp = adr_expr->eval_tree()) {
|
||||
delete adr_expr;
|
||||
adr_expr = tmp;
|
||||
}
|
||||
}
|
||||
NetNet*adr = adr_expr->synthesize(des);
|
||||
delete adr_expr;
|
||||
|
||||
must_be_self_determined_flag = must_be_self_determined_save;
|
||||
|
||||
if (adr == 0)
|
||||
NetExpr*index_ex = elab_and_eval(des, scope, idx_[0], -1);
|
||||
if (index_ex == 0)
|
||||
return 0;
|
||||
|
||||
NetRamDq*ram = new NetRamDq(scope, scope->local_symbol(),
|
||||
mem, adr->vector_width());
|
||||
des->add_node(ram);
|
||||
if (NetEConst*index_co = dynamic_cast<NetEConst*> (index_ex)) {
|
||||
long index = index_co->value().as_long();
|
||||
|
||||
connect(ram->pin_Address(), adr->pin(0));
|
||||
if (!sig->array_index_is_valid(index)) {
|
||||
// Oops! The index is a constant known to be
|
||||
// outside the array. Change the expression to a
|
||||
// constant X vector.
|
||||
verinum xxx (verinum::Vx, sig->vector_width());
|
||||
NetConst*con_n = new NetConst(scope, scope->local_symbol(), xxx);
|
||||
des->add_node(con_n);
|
||||
con_n->set_line(*index_co);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, ram->width());
|
||||
osig->data_type(IVL_VT_LOGIC);
|
||||
osig->local_flag(true);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, sig->vector_width());
|
||||
tmp->set_line(*this);
|
||||
tmp->local_flag(true);
|
||||
tmp->data_type(sig->data_type());
|
||||
connect(tmp->pin(0), con_n->pin(0));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
connect(ram->pin_Q(), osig->pin(0));
|
||||
assert(sig->array_index_is_valid(index));
|
||||
index = sig->array_index_to_address(index);
|
||||
|
||||
return osig;
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, sig->vector_width());
|
||||
tmp->set_line(*this);
|
||||
tmp->local_flag(true);
|
||||
connect(tmp->pin(0), sig->pin(index));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
unsigned selwid = index_ex->expr_width();
|
||||
|
||||
NetArrayDq*mux = new NetArrayDq(scope, scope->local_symbol(),
|
||||
sig, selwid);
|
||||
mux->set_line(*this);
|
||||
des->add_node(mux);
|
||||
|
||||
// Adjust the expression to calculate the canonical offset?
|
||||
if (long array_base = sig->array_first()) {
|
||||
index_ex = make_add_expr(index_ex, 0-array_base);
|
||||
}
|
||||
|
||||
NetNet*index_net = index_ex->synthesize(des);
|
||||
connect(mux->pin_Address(), index_net->pin(0));
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, sig->vector_width());
|
||||
tmp->set_line(*this);
|
||||
tmp->local_flag(true);
|
||||
tmp->data_type(sig->data_type());
|
||||
connect(tmp->pin(0), mux->pin_Result());
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2127,19 +2135,10 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
assert(scope);
|
||||
|
||||
NetNet* sig = 0;
|
||||
NetMemory* mem = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(des, scope, path_, sig, mem, par, eve);
|
||||
|
||||
if (mem != 0) {
|
||||
cerr << get_line() << ": error: memories (" << path_
|
||||
<< ") cannot be l-values in continuous "
|
||||
<< "assignments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
symbol_search(des, scope, path_, sig, par, eve);
|
||||
|
||||
if (eve != 0) {
|
||||
cerr << get_line() << ": error: named events (" << path_
|
||||
|
|
@ -2184,12 +2183,44 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
sig->port_type(NetNet::PINOUT);
|
||||
}
|
||||
|
||||
unsigned midx, lidx;
|
||||
if (! eval_part_select_(des, scope, sig, midx, lidx))
|
||||
return 0;
|
||||
// Default part select is the entire word.
|
||||
unsigned midx = sig->vector_width()-1, lidx = 0;
|
||||
// The default word select is the first.
|
||||
unsigned widx = 0;
|
||||
|
||||
if (sig->array_dimensions() > 0) {
|
||||
assert(!idx_.empty());
|
||||
|
||||
NetExpr*tmp_ex = elab_and_eval(des, scope, idx_[0], -1);
|
||||
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||
assert(tmp);
|
||||
|
||||
long widx_val = tmp->value().as_long();
|
||||
widx = sig->array_index_to_address(widx_val);
|
||||
delete tmp_ex;
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: Use [" << widx << "]"
|
||||
<< " to index l-value array." << endl;
|
||||
|
||||
} else {
|
||||
if (! eval_part_select_(des, scope, sig, midx, lidx))
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned subnet_wid = midx-lidx+1;
|
||||
|
||||
if (sig->pin_count() > 1) {
|
||||
assert(widx < sig->pin_count());
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
sig->type(), sig->vector_width());
|
||||
tmp->set_line(*this);
|
||||
tmp->local_flag(true);
|
||||
connect(sig->pin(widx), tmp->pin(0));
|
||||
sig = tmp;
|
||||
}
|
||||
|
||||
/* If the desired l-value vector is narrower then the
|
||||
signal itself, then use a NetPartSelect node to
|
||||
arrange for connection to the desired bits. All this
|
||||
|
|
@ -2850,6 +2881,12 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
|
||||
/*
|
||||
* $Log: elab_net.cc,v $
|
||||
* Revision 1.192 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.191 2006/12/08 03:43:26 steve
|
||||
* Prevent name clash when processing parameter in net.
|
||||
*
|
||||
|
|
|
|||
132
elab_sig.cc
132
elab_sig.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_sig.cc,v 1.42 2006/06/02 04:48:50 steve Exp $"
|
||||
#ident "$Id: elab_sig.cc,v 1.43 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -616,6 +616,9 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
attrib_list_t*attrib_list = evaluate_attributes(attributes, nattrib,
|
||||
des, scope);
|
||||
|
||||
long array_s0 = 0;
|
||||
long array_e0 = 0;
|
||||
|
||||
/* If the ident has idx expressions, then this is a
|
||||
memory. It can only have the idx registers after the msb
|
||||
and lsb expressions are filled. And, if it has one index,
|
||||
|
|
@ -639,7 +642,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
if ((lcon == 0) || (rcon == 0)) {
|
||||
cerr << get_line() << ": internal error: The indices "
|
||||
<< "are not constant for memory ``"
|
||||
<< "are not constant for array ``"
|
||||
<< hname_.peek_tail_name() << "''." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
|
|
@ -653,73 +656,74 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
perm_string name = lex_strings.make(hname_.peek_tail_name());
|
||||
|
||||
long lnum = lval.as_long();
|
||||
long rnum = rval.as_long();
|
||||
|
||||
new NetMemory(scope, name, wid, lnum, rnum);
|
||||
// The constructor automatically adds the memory object
|
||||
// to the scope. Do I need to set line number information?
|
||||
|
||||
} else {
|
||||
|
||||
/* If the net type is supply0 or supply1, replace it
|
||||
with a simple wire with a pulldown/pullup with supply
|
||||
strength. In other words, transform:
|
||||
|
||||
supply0 foo;
|
||||
|
||||
to:
|
||||
|
||||
wire foo;
|
||||
pulldown #(supply0) (foo);
|
||||
|
||||
This reduces the backend burden, and behaves exactly
|
||||
the same. */
|
||||
|
||||
NetLogic*pull = 0;
|
||||
if (wtype == NetNet::SUPPLY0 || wtype == NetNet::SUPPLY1) {
|
||||
NetLogic::TYPE pull_type = (wtype==NetNet::SUPPLY1)
|
||||
? NetLogic::PULLUP
|
||||
: NetLogic::PULLDOWN;
|
||||
pull = new NetLogic(scope, scope->local_symbol(),
|
||||
1, pull_type, wid);
|
||||
pull->set_line(*this);
|
||||
pull->pin(0).drive0(Link::SUPPLY);
|
||||
pull->pin(0).drive1(Link::SUPPLY);
|
||||
des->add_node(pull);
|
||||
wtype = NetNet::WIRE;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Generate a SUPPLY pulldown for the "
|
||||
<< "supply0 net." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
perm_string name = lex_strings.make(hname_.peek_tail_name());
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Create signal "
|
||||
<< name << "["<<msb<<":"<<lsb<<"]"
|
||||
<< " in scope " << scope->name() << endl;
|
||||
}
|
||||
|
||||
NetNet*sig = new NetNet(scope, name, wtype, msb, lsb);
|
||||
sig->data_type(data_type_);
|
||||
sig->set_line(*this);
|
||||
sig->port_type(port_type_);
|
||||
sig->set_signed(get_signed());
|
||||
sig->set_isint(get_isint());
|
||||
|
||||
if (pull)
|
||||
connect(sig->pin(0), pull->pin(0));
|
||||
|
||||
for (unsigned idx = 0 ; idx < nattrib ; idx += 1)
|
||||
sig->attribute(attrib_list[idx].key, attrib_list[idx].val);
|
||||
array_s0 = lval.as_long();
|
||||
array_e0 = rval.as_long();
|
||||
}
|
||||
|
||||
/* If the net type is supply0 or supply1, replace it
|
||||
with a simple wire with a pulldown/pullup with supply
|
||||
strength. In other words, transform:
|
||||
|
||||
supply0 foo;
|
||||
|
||||
to:
|
||||
|
||||
wire foo;
|
||||
pulldown #(supply0) (foo);
|
||||
|
||||
This reduces the backend burden, and behaves exactly
|
||||
the same. */
|
||||
|
||||
NetLogic*pull = 0;
|
||||
if (wtype == NetNet::SUPPLY0 || wtype == NetNet::SUPPLY1) {
|
||||
NetLogic::TYPE pull_type = (wtype==NetNet::SUPPLY1)
|
||||
? NetLogic::PULLUP
|
||||
: NetLogic::PULLDOWN;
|
||||
pull = new NetLogic(scope, scope->local_symbol(),
|
||||
1, pull_type, wid);
|
||||
pull->set_line(*this);
|
||||
pull->pin(0).drive0(Link::SUPPLY);
|
||||
pull->pin(0).drive1(Link::SUPPLY);
|
||||
des->add_node(pull);
|
||||
wtype = NetNet::WIRE;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Generate a SUPPLY pulldown for the "
|
||||
<< "supply0 net." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
perm_string name = lex_strings.make(hname_.peek_tail_name());
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Create signal "
|
||||
<< name << "["<<msb<<":"<<lsb<<"]"
|
||||
<< " in scope " << scope->name() << endl;
|
||||
}
|
||||
|
||||
NetNet*sig = new NetNet(scope, name, wtype, msb, lsb,
|
||||
array_s0, array_e0);
|
||||
sig->data_type(data_type_);
|
||||
sig->set_line(*this);
|
||||
sig->port_type(port_type_);
|
||||
sig->set_signed(get_signed());
|
||||
sig->set_isint(get_isint());
|
||||
|
||||
if (pull)
|
||||
connect(sig->pin(0), pull->pin(0));
|
||||
|
||||
for (unsigned idx = 0 ; idx < nattrib ; idx += 1)
|
||||
sig->attribute(attrib_list[idx].key, attrib_list[idx].val);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: elab_sig.cc,v $
|
||||
* Revision 1.43 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.42 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
|
|
|
|||
14
elaborate.cc
14
elaborate.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elaborate.cc,v 1.354 2006/12/09 01:59:35 steve Exp $"
|
||||
#ident "$Id: elaborate.cc,v 1.355 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -2295,12 +2295,11 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
|
|||
|
||||
if (PEIdent*id = dynamic_cast<PEIdent*>(expr_[idx]->expr())) {
|
||||
NetNet* sig = 0;
|
||||
NetMemory* mem = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
NetScope*found_in = symbol_search(des, scope, id->path(),
|
||||
sig, mem, par, eve);
|
||||
sig, par, eve);
|
||||
|
||||
if (found_in && eve) {
|
||||
wa->add_event(eve);
|
||||
|
|
@ -2874,12 +2873,11 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
|
|||
assert(scope);
|
||||
|
||||
NetNet* sig = 0;
|
||||
NetMemory* mem = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
NetScope*found_in = symbol_search(des, scope, event_,
|
||||
sig, mem, par, eve);
|
||||
sig, par, eve);
|
||||
|
||||
if (found_in == 0) {
|
||||
cerr << get_line() << ": error: event <" << event_ << ">"
|
||||
|
|
@ -3349,6 +3347,12 @@ Design* elaborate(list<perm_string>roots)
|
|||
|
||||
/*
|
||||
* $Log: elaborate.cc,v $
|
||||
* Revision 1.355 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.354 2006/12/09 01:59:35 steve
|
||||
* Fix an uninitialized variable warning.
|
||||
*
|
||||
|
|
|
|||
31
emit.cc
31
emit.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: emit.cc,v 1.88 2006/11/10 05:44:44 steve Exp $"
|
||||
#ident "$Id: emit.cc,v 1.89 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -57,6 +57,11 @@ bool NetAddSub::emit_node(struct target_t*tgt) const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NetArrayDq::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->lpm_array_dq(this);
|
||||
}
|
||||
|
||||
bool NetCaseCmp::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_case_cmp(this);
|
||||
|
|
@ -125,12 +130,6 @@ bool NetPartSelect::emit_node(struct target_t*tgt) const
|
|||
return tgt->part_select(this);
|
||||
}
|
||||
|
||||
bool NetRamDq::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_ram_dq(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetReplicate::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->replicate(this);
|
||||
|
|
@ -357,13 +356,6 @@ void NetScope::emit_scope(struct target_t*tgt) const
|
|||
} while (cur != signals_->sig_next_);
|
||||
}
|
||||
|
||||
if (memories_) {
|
||||
NetMemory*cur = memories_->snext_;
|
||||
do {
|
||||
tgt->memory(cur);
|
||||
cur = cur->snext_;
|
||||
} while (cur != memories_->snext_);
|
||||
}
|
||||
}
|
||||
|
||||
bool NetScope::emit_defs(struct target_t*tgt) const
|
||||
|
|
@ -472,11 +464,6 @@ void NetECRealParam::expr_scan(struct expr_scan_t*tgt) const
|
|||
tgt->expr_rparam(this);
|
||||
}
|
||||
|
||||
void NetEMemory::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_memory(this);
|
||||
}
|
||||
|
||||
void NetEParam::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
cerr << get_line() << ":internal error: unexpected NetEParam."
|
||||
|
|
@ -540,6 +527,12 @@ int emit(const Design*des, const char*type)
|
|||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.89 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.88 2006/11/10 05:44:44 steve
|
||||
* Process delay paths in second path over signals.
|
||||
*
|
||||
|
|
|
|||
11
eval.cc
11
eval.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval.cc,v 1.43 2006/08/08 05:11:37 steve Exp $"
|
||||
#ident "$Id: eval.cc,v 1.44 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -174,7 +174,6 @@ verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const
|
|||
{
|
||||
assert(scope);
|
||||
NetNet*net;
|
||||
NetMemory*mem;
|
||||
NetEvent*eve;
|
||||
const NetExpr*expr;
|
||||
|
||||
|
|
@ -187,7 +186,7 @@ verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const
|
|||
}
|
||||
|
||||
NetScope*found_in = symbol_search(des, scope, path_,
|
||||
net, mem, expr, eve);
|
||||
net, expr, eve);
|
||||
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
|
|
@ -276,6 +275,12 @@ verinum* PEUnary::eval_const(const Design*des, NetScope*scope) const
|
|||
|
||||
/*
|
||||
* $Log: eval.cc,v $
|
||||
* Revision 1.44 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.43 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
|
|
|
|||
52
eval_tree.cc
52
eval_tree.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_tree.cc,v 1.72 2006/11/04 06:16:27 steve Exp $"
|
||||
#ident "$Id: eval_tree.cc,v 1.73 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -1190,50 +1190,6 @@ NetEConst* NetEConcat::eval_tree()
|
|||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* There are limits to our ability to evaluate a memory reference
|
||||
* expression, because the content of a memory is never
|
||||
* constant. However, the index expression may be precalculated, and
|
||||
* there are certain index values that do give us constant results.
|
||||
*/
|
||||
NetExpr* NetEMemory::eval_tree()
|
||||
{
|
||||
/* Attempt to evaluate the index expression to a constant, if
|
||||
it is not already. */
|
||||
if (idx_ && !dynamic_cast<NetEConst*>(idx_)) {
|
||||
NetExpr* tmp = idx_->eval_tree();
|
||||
if (tmp) {
|
||||
delete idx_;
|
||||
idx_ = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
NetEConst*itmp = dynamic_cast<NetEConst*>(idx_);
|
||||
if (itmp == 0)
|
||||
return 0;
|
||||
|
||||
verinum ival = itmp->value();
|
||||
|
||||
/* If the index expression has any x or z bits, then we know
|
||||
already that the expression result is a constant x. */
|
||||
if (! ival.is_defined()) {
|
||||
verinum xres (verinum::Vx, mem_->width(), false);
|
||||
NetEConst*res = new NetEConst(xres);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* If the index expression is outside the range of the memory,
|
||||
then the result is a constant x. */
|
||||
unsigned norm_idx = mem_->index_to_address(ival.as_long());
|
||||
if (norm_idx >= mem_->count()) {
|
||||
verinum xres (verinum::Vx, mem_->width(), false);
|
||||
NetEConst*res = new NetEConst(xres);
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* NetEParam::eval_tree()
|
||||
{
|
||||
if (des_ == 0) {
|
||||
|
|
@ -1696,6 +1652,12 @@ NetEConst* NetEUReduce::eval_tree()
|
|||
|
||||
/*
|
||||
* $Log: eval_tree.cc,v $
|
||||
* Revision 1.73 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.72 2006/11/04 06:16:27 steve
|
||||
* Fix padding of constant eval of NetESelect.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: expr_synth.cc,v 1.80 2006/08/08 05:11:37 steve Exp $"
|
||||
#ident "$Id: expr_synth.cc,v 1.81 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -692,7 +692,7 @@ NetNet* NetEUReduce::synthesize(Design*des)
|
|||
|
||||
return osig;
|
||||
}
|
||||
|
||||
#if 0
|
||||
NetNet* NetEMemory::synthesize(Design *des)
|
||||
{
|
||||
NetNet*adr = idx_->synthesize(des);
|
||||
|
|
@ -719,7 +719,7 @@ NetNet* NetEMemory::synthesize(Design *des)
|
|||
return osig;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
NetNet* NetESelect::synthesize(Design *des)
|
||||
{
|
||||
|
||||
|
|
@ -890,6 +890,12 @@ NetNet* NetESignal::synthesize(Design*des)
|
|||
|
||||
/*
|
||||
* $Log: expr_synth.cc,v $
|
||||
* Revision 1.81 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.80 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
|
|
|
|||
1
ivl.def
1
ivl.def
|
|
@ -62,6 +62,7 @@ ivl_logic_type
|
|||
ivl_logic_udp
|
||||
ivl_logic_width
|
||||
|
||||
ivl_lpm_array
|
||||
ivl_lpm_aset_value
|
||||
ivl_lpm_async_clr
|
||||
ivl_lpm_async_set
|
||||
|
|
|
|||
278
ivl_target.h
278
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.171 2006/09/23 04:57:19 steve Exp $"
|
||||
#ident "$Id: ivl_target.h,v 1.172 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdint.h>
|
||||
|
|
@ -59,6 +59,10 @@ _BEGIN_DECL
|
|||
* The following typedefs list the various cookies that may be passed
|
||||
* around.
|
||||
*
|
||||
* ivl_array_t
|
||||
* This object represent an array that can be a memory or a net
|
||||
* array. (They are the same from the perspective of ivl_target.h.)
|
||||
*
|
||||
* ivl_design_t
|
||||
* This object represents the entire elaborated design. Various
|
||||
* global properties and methods are available from this.
|
||||
|
|
@ -137,6 +141,7 @@ _BEGIN_DECL
|
|||
* scope. These names are unique within a scope, but not necessarily
|
||||
* throughout the design.
|
||||
*/
|
||||
typedef struct ivl_array_s *ivl_array_t;
|
||||
typedef struct ivl_delaypath_s*ivl_delaypath_t;
|
||||
typedef struct ivl_design_s *ivl_design_t;
|
||||
typedef struct ivl_event_s *ivl_event_t;
|
||||
|
|
@ -153,7 +158,7 @@ typedef struct ivl_parameter_s*ivl_parameter_t;
|
|||
typedef struct ivl_process_s *ivl_process_t;
|
||||
typedef struct ivl_scope_s *ivl_scope_t;
|
||||
typedef struct ivl_signal_s *ivl_signal_t;
|
||||
typedef struct ivl_memory_s *ivl_memory_t;
|
||||
typedef struct ivl_memory_s *ivl_memory_t; /* DEPRECATED */
|
||||
typedef struct ivl_statement_s*ivl_statement_t;
|
||||
|
||||
/*
|
||||
|
|
@ -178,7 +183,7 @@ typedef enum ivl_drive_e {
|
|||
and incompatibilities to be introduced. */
|
||||
typedef enum ivl_expr_type_e {
|
||||
IVL_EX_NONE = 0,
|
||||
/* IVL_EX_BITSEL = 1, */
|
||||
IVL_EX_ARRAY = 18,
|
||||
IVL_EX_BINARY = 2,
|
||||
IVL_EX_CONCAT = 3,
|
||||
IVL_EX_EVENT = 17,
|
||||
|
|
@ -225,6 +230,7 @@ typedef enum ivl_logic_e {
|
|||
/* This is the type of an LPM object. */
|
||||
typedef enum ivl_lpm_type_e {
|
||||
IVL_LPM_ADD = 0,
|
||||
IVL_LPM_ARRAY = 30,
|
||||
IVL_LPM_CONCAT = 16,
|
||||
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
|
||||
IVL_LPM_CMP_EQ = 10,
|
||||
|
|
@ -252,7 +258,7 @@ typedef enum ivl_lpm_type_e {
|
|||
IVL_LPM_SHIFTR = 7,
|
||||
IVL_LPM_SIGN_EXT=27,
|
||||
IVL_LPM_SUB = 8,
|
||||
IVL_LPM_RAM = 9,
|
||||
_IVL_LPM_RAM = 9, /* obsolete */
|
||||
IVL_LPM_UFUNC = 14
|
||||
} ivl_lpm_type_t;
|
||||
|
||||
|
|
@ -574,6 +580,14 @@ extern ivl_nexus_t ivl_event_pos(ivl_event_t net, unsigned idx);
|
|||
*
|
||||
* SEMANTIC NOTES
|
||||
*
|
||||
* - IVL_EX_ARRAY
|
||||
* This expression type is a special case of the IVL_EX_SIGNAL where
|
||||
* the target is an array (ivl_signal_t with an array_count) but there
|
||||
* is no index expression. This is used only in the special situation
|
||||
* where the array is passed to a system task/function. The function
|
||||
* ivl_expr_signal returns the ivl_signal_t of the array object, and
|
||||
* from that all the properties of the array can be determined.
|
||||
*
|
||||
* - IVL_EX_BINARY
|
||||
*
|
||||
* - IVL_EX_SELECT
|
||||
|
|
@ -583,6 +597,21 @@ extern ivl_nexus_t ivl_event_pos(ivl_event_t net, unsigned idx);
|
|||
* is the base of a vector. The compiler has already figured out any
|
||||
* conversion from signal units to vector units, so the result of
|
||||
* ivl_expr_oper1 should range from 0 to ivl_expr_width().
|
||||
*
|
||||
* - IVL_EX_SIGNAL
|
||||
* This expression references a signal vector. The ivl_expr_signal
|
||||
* function gets a handle for the signal that is referenced. The
|
||||
* signal may be an array (see the ivl_signal_array_count function)
|
||||
* that is addressed by the expression returned by the ivl_expr_oper1
|
||||
* function. This expression returns a *canonical* address. The core
|
||||
* compiler already corrected the expression to account for index
|
||||
* bases.
|
||||
*
|
||||
* The ivl_expr_width function returns the vector width of the signal
|
||||
* word. The ivl_expr_value returns the data type of the word.
|
||||
*
|
||||
* Bit and part selects are not done here. The IVL_EX_SELECT
|
||||
* expression does bit/part selects on the word read from the signal.
|
||||
*/
|
||||
|
||||
extern ivl_expr_type_t ivl_expr_type(ivl_expr_t net);
|
||||
|
|
@ -975,7 +1004,7 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
|||
* single ivl_lpm_data input are the same with, ivl_lpm_width. This
|
||||
* device carries a vector like other LPM devices.
|
||||
*
|
||||
* - Memory port (IVL_LPM_RAM)
|
||||
* - Memory port (IVL_LPM_RAM) (deprecated in favor of IVL_LPM_ARRAY)
|
||||
* These are structural ports into a memory device. They represent
|
||||
* address/data ports of a memory device that the context can hook to
|
||||
* for read or write. Read devices have an ivl_lpm_q output port that
|
||||
|
|
@ -1069,34 +1098,33 @@ extern ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net);
|
|||
extern ivl_nexus_t ivl_lpm_sync_clr(ivl_lpm_t net);
|
||||
extern ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net);
|
||||
extern ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net);
|
||||
/* IVL_LPM_ARRAY */
|
||||
extern ivl_signal_t ivl_lpm_array(ivl_lpm_t net);
|
||||
/* IVL_LPM_PART */
|
||||
extern unsigned ivl_lpm_base(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF IVL_LPM_RAM */
|
||||
/* IVL_LPM_FF */
|
||||
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
|
||||
/* IVL_LPM_UFUNC */
|
||||
extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF IVL_LPM_RAM */
|
||||
/* IVL_LPM_FF */
|
||||
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
|
||||
/* IVL_LPM_ADD IVL_LPM_CONCAT IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT
|
||||
IVL_LPM_MUX IVL_LPM_RAM IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB
|
||||
IVL_LPM_MUX IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB
|
||||
IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */
|
||||
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_RAM
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART
|
||||
IVL_LPM_SUB IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_MUX IVL_LPM_RAM */
|
||||
/* IVL_LPM_MUX */
|
||||
extern unsigned ivl_lpm_selects(ivl_lpm_t net);
|
||||
/* IVL_LPM_MUX IVL_LPM_RAM */
|
||||
/* IVL_LPM_MUX */
|
||||
extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net);
|
||||
/* IVL_LPM_CONCAT IVL_LPM_MUX IVL_LPM_REPEAT IVL_LPM_UFUNC */
|
||||
extern unsigned ivl_lpm_size(ivl_lpm_t net);
|
||||
/* IVL_LPM_SFUNC */
|
||||
extern const char*ivl_lpm_string(ivl_lpm_t net);
|
||||
/* IVL_LPM_RAM */
|
||||
extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
||||
|
||||
|
||||
/* LVAL
|
||||
* The l-values of assignments are concatenation of ivl_lval_t
|
||||
|
|
@ -1149,12 +1177,21 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
|||
* The ivl_lval_part_off is the canonical base of a part or
|
||||
* bit select.
|
||||
*
|
||||
* - Memory words
|
||||
* - Memory words (Replace this with Array words below)
|
||||
* If the l-value is a memory word, the ivl_lval_mem function returns
|
||||
* a non-nil value. The ivl_lval_idx function will return an
|
||||
* expression that calculates an address for the memory. The compiler
|
||||
* will assure that the ivl_lval_width will exactly match the
|
||||
* ivl_memory_width of the memory word.
|
||||
*
|
||||
* - Array words
|
||||
* If the l-value is an array, then ivl_lval_idx function will return
|
||||
* an expression that calculates the address of the array word. If
|
||||
* the referenced signal has more then one word, this expression must
|
||||
* be present. If the signal has exactly one word (it is not an array)
|
||||
* then the ivl_lval_idx exression must *not* be present.
|
||||
*
|
||||
* For array words, the ivl_lval_width is the width of the word.
|
||||
*/
|
||||
|
||||
extern unsigned ivl_lval_width(ivl_lval_t net);
|
||||
|
|
@ -1432,17 +1469,22 @@ extern int ivl_scope_time_units(ivl_scope_t net);
|
|||
* Signals have a name (obviously) and types. A signal may also be
|
||||
* signed or unsigned.
|
||||
*
|
||||
* ivl_signal_pins (replace these with ivl_signal_nex)
|
||||
* ivl_signal_pin
|
||||
* The ivl_signal_pin function returns the nexus connected to the
|
||||
* signal. If the signal is a vector, the idx can be a non-zero
|
||||
* value, and the result is the nexus for the specified bit.
|
||||
*
|
||||
* ivl_signal_nex
|
||||
* This is the nexus of the signal. This is used for managing
|
||||
* connections to the rest of the net. There is exactly one pin for
|
||||
* a signal. If the signal represents a vector, then the entire
|
||||
* vector is carried through the single output.
|
||||
* each word of a signal. Each word may in turn be a vector. The
|
||||
* word address is the zero-based index for the word. It is up to
|
||||
* the context to translate different bases to the canonical address.
|
||||
*
|
||||
* ivl_signal_array_base
|
||||
* ivl_signal_array_count
|
||||
* The signal may be arrayed. If so, the array_count is >1. Each
|
||||
* word of the array has its own nexus. The array_base is the
|
||||
* address is the Verilg source for the canonical zero word. This
|
||||
* may be negative, positive or zero.
|
||||
*
|
||||
* Note that arraying of the signal into words is distinct from the
|
||||
* vectors. The width of a signal is the width of a WORD.
|
||||
*
|
||||
* ivl_signal_msb
|
||||
* ivl_signal_lsb
|
||||
|
|
@ -1503,7 +1545,9 @@ extern int ivl_scope_time_units(ivl_scope_t net);
|
|||
* key does not exist, the function returns 0.
|
||||
*/
|
||||
|
||||
extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net);
|
||||
extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word);
|
||||
extern int ivl_signal_array_base(ivl_signal_t net);
|
||||
extern unsigned ivl_signal_array_count(ivl_signal_t net);
|
||||
extern int ivl_signal_msb(ivl_signal_t net);
|
||||
extern int ivl_signal_lsb(ivl_signal_t net);
|
||||
extern unsigned ivl_signal_width(ivl_signal_t net);
|
||||
|
|
@ -1706,10 +1750,6 @@ extern unsigned ivl_stmt_lvals(ivl_statement_t net);
|
|||
extern unsigned ivl_stmt_lwidth(ivl_statement_t net);
|
||||
/* IVL_ST_STASK */
|
||||
extern const char* ivl_stmt_name(ivl_statement_t net);
|
||||
#if 0
|
||||
extern ivl_nexus_t ivl_stmt_nexus(ivl_statement_t net, unsigned idx);
|
||||
extern unsigned ivl_stmt_nexus_count(ivl_statement_t net);
|
||||
#endif
|
||||
/* IVL_ST_STASK */
|
||||
extern ivl_expr_t ivl_stmt_parm(ivl_statement_t net, unsigned idx);
|
||||
/* IVL_ST_STASK */
|
||||
|
|
@ -1752,6 +1792,12 @@ _END_DECL
|
|||
|
||||
/*
|
||||
* $Log: ivl_target.h,v $
|
||||
* Revision 1.172 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.171 2006/09/23 04:57:19 steve
|
||||
* Basic support for specify timing.
|
||||
*
|
||||
|
|
@ -1781,181 +1827,5 @@ _END_DECL
|
|||
*
|
||||
* Revision 1.162 2005/11/20 15:58:25 steve
|
||||
* Document the IVL_ST_DELAY statements.
|
||||
*
|
||||
* Revision 1.161 2005/09/19 21:45:35 steve
|
||||
* Spelling patches from Larry.
|
||||
*
|
||||
* Revision 1.160 2005/09/01 04:11:37 steve
|
||||
* Generate code to handle real valued muxes.
|
||||
*
|
||||
* Revision 1.159 2005/08/06 17:58:16 steve
|
||||
* Implement bi-directional part selects.
|
||||
*
|
||||
* Revision 1.158 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.157 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.156 2005/06/13 22:25:37 steve
|
||||
* Document ivl_logic_delay function.
|
||||
*
|
||||
* Revision 1.155 2005/05/24 01:44:28 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.154 2005/05/08 23:44:08 steve
|
||||
* Add support for variable part select.
|
||||
*
|
||||
* Revision 1.153 2005/05/07 03:14:00 steve
|
||||
* Clarify internal delays for assignments.
|
||||
*
|
||||
* Revision 1.152 2005/04/24 23:44:02 steve
|
||||
* Update DFF support to new data flow.
|
||||
*
|
||||
* Revision 1.151 2005/04/13 06:35:11 steve
|
||||
* Make logic aware of strength.
|
||||
*
|
||||
* Revision 1.150 2005/04/08 04:52:31 steve
|
||||
* Make clear that memory addresses are cannonical.
|
||||
*
|
||||
* Revision 1.149 2005/04/06 05:29:08 steve
|
||||
* Rework NetRamDq and IVL_LPM_RAM nodes.
|
||||
*
|
||||
* Revision 1.148 2005/04/01 06:04:30 steve
|
||||
* Clean up handle of UDPs.
|
||||
*
|
||||
* Revision 1.147 2005/03/18 02:56:03 steve
|
||||
* Add support for LPM_UFUNC user defined functions.
|
||||
*
|
||||
* Revision 1.146 2005/03/09 04:53:40 steve
|
||||
* Generate code for new form of memory ports.
|
||||
*
|
||||
* Revision 1.145 2005/03/05 05:47:42 steve
|
||||
* Handle memory words in l-value concatenations.
|
||||
*
|
||||
* Revision 1.144 2005/03/03 04:34:42 steve
|
||||
* Rearrange how memories are supported as vvp_vector4 arrays.
|
||||
*
|
||||
* Revision 1.143 2005/02/19 02:43:38 steve
|
||||
* Support shifts and divide.
|
||||
*
|
||||
* Revision 1.142 2005/02/14 01:51:39 steve
|
||||
* Handle bit selects in l-values to assignments.
|
||||
*
|
||||
* Revision 1.141 2005/02/13 01:15:07 steve
|
||||
* Replace supply nets with wires connected to pullup/down supply devices.
|
||||
*
|
||||
* Revision 1.140 2005/02/12 06:25:40 steve
|
||||
* Restructure NetMux devices to pass vectors.
|
||||
* Generate NetMux devices from ternary expressions,
|
||||
* Reduce NetMux devices to bufif when appropriate.
|
||||
*
|
||||
* Revision 1.139 2005/02/08 00:12:36 steve
|
||||
* Add the NetRepeat node, and code generator support.
|
||||
*
|
||||
* Revision 1.138 2005/02/03 04:56:20 steve
|
||||
* laborate reduction gates into LPM_RED_ nodes.
|
||||
*
|
||||
* Revision 1.137 2005/01/29 18:46:18 steve
|
||||
* Netlist boolean expressions generate gate vectors.
|
||||
*
|
||||
* Revision 1.136 2005/01/29 16:47:20 steve
|
||||
* Clarify width of nexus.
|
||||
*
|
||||
* Revision 1.135 2005/01/28 05:39:33 steve
|
||||
* Simplified NetMult and IVL_LPM_MULT.
|
||||
*
|
||||
* Revision 1.134 2005/01/24 05:28:30 steve
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
*
|
||||
* Revision 1.133 2005/01/22 17:36:59 steve
|
||||
* stub dump signed flags of magnitude compare.
|
||||
*
|
||||
* Revision 1.132 2005/01/22 01:06:55 steve
|
||||
* Change case compare from logic to an LPM node.
|
||||
*
|
||||
* Revision 1.131 2005/01/09 20:16:01 steve
|
||||
* Use PartSelect/PV and VP to handle part selects through ports.
|
||||
*
|
||||
* Revision 1.130 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.129 2004/12/18 18:56:18 steve
|
||||
* Add ivl_event_scope, and better document ivl_event_X methods.
|
||||
*
|
||||
* Revision 1.128 2004/12/15 17:10:40 steve
|
||||
* Fixup force statement elaboration.
|
||||
*
|
||||
* Revision 1.127 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.126 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.125 2004/09/25 01:58:12 steve
|
||||
* Some commentary on ivl_logic_pin.
|
||||
*
|
||||
* Revision 1.124 2003/12/03 02:46:24 steve
|
||||
* Add support for wait on list of named events.
|
||||
*
|
||||
* Revision 1.123 2003/11/08 20:06:21 steve
|
||||
* Spelling fixes in comments.
|
||||
*
|
||||
* Revision 1.122 2003/08/22 23:14:26 steve
|
||||
* Preserve variable ranges all the way to the vpi.
|
||||
*
|
||||
* Revision 1.121 2003/08/15 02:23:52 steve
|
||||
* Add synthesis support for synchronous reset.
|
||||
*
|
||||
* Revision 1.120 2003/07/30 01:13:28 steve
|
||||
* Add support for triand and trior.
|
||||
*
|
||||
* Revision 1.119 2003/06/23 01:25:44 steve
|
||||
* Module attributes make it al the way to ivl_target.
|
||||
*
|
||||
* Revision 1.118 2003/05/14 05:26:41 steve
|
||||
* Support real expressions in case statements.
|
||||
*
|
||||
* Revision 1.117 2003/04/22 04:48:29 steve
|
||||
* Support event names as expressions elements.
|
||||
*
|
||||
* Revision 1.116 2003/04/11 05:18:08 steve
|
||||
* Handle signed magnitude compare all the
|
||||
* way through to the vvp code generator.
|
||||
*
|
||||
* Revision 1.115 2003/03/10 23:40:53 steve
|
||||
* Keep parameter constants for the ivl_target API.
|
||||
*
|
||||
* Revision 1.114 2003/03/06 01:24:37 steve
|
||||
* Obsolete the ivl_event_name function.
|
||||
*
|
||||
* Revision 1.113 2003/03/06 00:28:41 steve
|
||||
* All NetObj objects have lex_string base names.
|
||||
*
|
||||
* Revision 1.112 2003/02/26 01:29:24 steve
|
||||
* LPM objects store only their base names.
|
||||
*
|
||||
* Revision 1.111 2003/01/30 16:23:07 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.110 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.109 2002/12/21 00:55:58 steve
|
||||
* The $time system task returns the integer time
|
||||
* scaled to the local units. Change the internal
|
||||
* implementation of vpiSystemTime the $time functions
|
||||
* to properly account for this. Also add $simtime
|
||||
* to get the simulation time.
|
||||
*/
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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.21 2006/02/02 02:43:58 steve Exp $"
|
||||
#ident "$Id: net_assign.cc,v 1.22 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -39,20 +39,13 @@ unsigned count_lval_width(const NetAssign_*idx)
|
|||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetNet*s)
|
||||
: sig_(s), mem_(0), bmux_(0), base_(0)
|
||||
: sig_(s), word_(0), base_(0)
|
||||
{
|
||||
lwid_ = sig_->vector_width();
|
||||
sig_->incr_lref();
|
||||
more = 0;
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetMemory*s)
|
||||
: sig_(0), mem_(s), bmux_(0), base_(0)
|
||||
{
|
||||
lwid_ = mem_->width();
|
||||
more = 0;
|
||||
}
|
||||
|
||||
NetAssign_::~NetAssign_()
|
||||
{
|
||||
if (sig_) {
|
||||
|
|
@ -62,23 +55,23 @@ NetAssign_::~NetAssign_()
|
|||
}
|
||||
|
||||
assert( more == 0 );
|
||||
if (bmux_) delete bmux_;
|
||||
if (word_) delete word_;
|
||||
}
|
||||
|
||||
void NetAssign_::set_bmux(NetExpr*r)
|
||||
void NetAssign_::set_word(NetExpr*r)
|
||||
{
|
||||
assert(bmux_ == 0);
|
||||
bmux_ = r;
|
||||
assert(word_ == 0);
|
||||
word_ = r;
|
||||
}
|
||||
|
||||
NetExpr* NetAssign_::bmux()
|
||||
NetExpr* NetAssign_::word()
|
||||
{
|
||||
return bmux_;
|
||||
return word_;
|
||||
}
|
||||
|
||||
const NetExpr* NetAssign_::bmux() const
|
||||
const NetExpr* NetAssign_::word() const
|
||||
{
|
||||
return bmux_;
|
||||
return word_;
|
||||
}
|
||||
|
||||
const NetExpr* NetAssign_::get_base() const
|
||||
|
|
@ -88,17 +81,13 @@ const NetExpr* NetAssign_::get_base() const
|
|||
|
||||
unsigned NetAssign_::lwidth() const
|
||||
{
|
||||
if (mem_) return lwid_;
|
||||
else if (bmux_) return 1;
|
||||
else return lwid_;
|
||||
return lwid_;
|
||||
}
|
||||
|
||||
perm_string NetAssign_::name() const
|
||||
{
|
||||
if (sig_) {
|
||||
return sig_->name();
|
||||
} else if (mem_) {
|
||||
return mem_->name();
|
||||
} else {
|
||||
return perm_string::literal("");
|
||||
}
|
||||
|
|
@ -109,11 +98,6 @@ NetNet* NetAssign_::sig() const
|
|||
return sig_;
|
||||
}
|
||||
|
||||
NetMemory* NetAssign_::mem() const
|
||||
{
|
||||
return mem_;
|
||||
}
|
||||
|
||||
void NetAssign_::set_part(NetExpr*base, unsigned wid)
|
||||
{
|
||||
base_ = base;
|
||||
|
|
@ -275,6 +259,12 @@ NetRelease::~NetRelease()
|
|||
|
||||
/*
|
||||
* $Log: net_assign.cc,v $
|
||||
* Revision 1.22 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.21 2006/02/02 02:43:58 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.15 2006/04/16 00:15:43 steve Exp $"
|
||||
#ident "$Id: net_nex_input.cc,v 1.16 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -78,12 +78,6 @@ NexusSet* NetECReal::nex_input()
|
|||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetEMemory::nex_input()
|
||||
{
|
||||
NexusSet*result = idx_->nex_input();
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* A parameter by definition has no inputs. It represents a constant
|
||||
* value, even if that value is a constant expression.
|
||||
|
|
@ -171,8 +165,8 @@ NexusSet* NetEUnary::nex_input()
|
|||
NexusSet* NetAssign_::nex_input()
|
||||
{
|
||||
NexusSet*result = new NexusSet;
|
||||
if (bmux_) {
|
||||
NexusSet*tmp = bmux_->nex_input();
|
||||
if (word_) {
|
||||
NexusSet*tmp = word_->nex_input();
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
|
|
@ -393,6 +387,12 @@ NexusSet* NetWhile::nex_input()
|
|||
|
||||
/*
|
||||
* $Log: net_nex_input.cc,v $
|
||||
* Revision 1.16 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.15 2006/04/16 00:15:43 steve
|
||||
* Fix part selects in l-values.
|
||||
*
|
||||
|
|
|
|||
53
net_scope.cc
53
net_scope.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_scope.cc,v 1.35 2005/11/27 05:56:20 steve Exp $"
|
||||
#ident "$Id: net_scope.cc,v 1.36 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -38,7 +38,6 @@
|
|||
NetScope::NetScope(NetScope*up, perm_string n, NetScope::TYPE t)
|
||||
: type_(t), up_(up), sib_(0), sub_(0)
|
||||
{
|
||||
memories_ = 0;
|
||||
signals_ = 0;
|
||||
events_ = 0;
|
||||
lcounter_ = 0;
|
||||
|
|
@ -358,50 +357,6 @@ NetNet* NetScope::find_signal_in_child(const hname_t&path)
|
|||
return cur->find_signal(path.peek_name(idx));
|
||||
}
|
||||
|
||||
void NetScope::add_memory(NetMemory*mem)
|
||||
{
|
||||
if (memories_ == 0) {
|
||||
mem->snext_ = mem;
|
||||
mem->sprev_ = mem;
|
||||
} else {
|
||||
mem->snext_ = memories_->snext_;
|
||||
mem->sprev_ = memories_;
|
||||
mem->snext_->sprev_ = mem;
|
||||
mem->sprev_->snext_ = mem;
|
||||
}
|
||||
memories_ = mem;
|
||||
mem->scope_ = this;
|
||||
}
|
||||
|
||||
void NetScope::rem_memory(NetMemory*mem)
|
||||
{
|
||||
assert(mem->scope_ == this);
|
||||
if (memories_ == mem)
|
||||
memories_ = mem->sprev_;
|
||||
|
||||
if (memories_ == mem) {
|
||||
memories_ = 0;
|
||||
} else {
|
||||
mem->sprev_->snext_ = mem->snext_;
|
||||
mem->snext_->sprev_ = mem->sprev_;
|
||||
}
|
||||
mem->scope_ = 0;
|
||||
}
|
||||
|
||||
NetMemory* NetScope::find_memory(const string&key)
|
||||
{
|
||||
if (memories_ == 0)
|
||||
return 0;
|
||||
|
||||
NetMemory*cur = memories_;
|
||||
do {
|
||||
if (cur->name() == key.c_str())
|
||||
return cur;
|
||||
cur = cur->sprev_;
|
||||
} while (cur != memories_);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method locates a child scope by name. The name is the simple
|
||||
* name of the child, no hierarchy is searched.
|
||||
|
|
@ -457,6 +412,12 @@ string NetScope::local_hsymbol()
|
|||
|
||||
/*
|
||||
* $Log: net_scope.cc,v $
|
||||
* Revision 1.36 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.35 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
|
|
|
|||
382
netlist.cc
382
netlist.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netlist.cc,v 1.250 2006/11/10 04:54:26 steve Exp $"
|
||||
#ident "$Id: netlist.cc,v 1.251 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -333,7 +333,7 @@ uint64_t NetDelaySrc::get_delay(unsigned idx) const
|
|||
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
||||
: NetObj(s, n, 1), sig_next_(0), sig_prev_(0),
|
||||
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
|
||||
signed_(false), msb_(npins-1), lsb_(0),
|
||||
signed_(false), msb_(npins-1), lsb_(0), s0_(0), e0_(0),
|
||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
{
|
||||
assert(s);
|
||||
|
|
@ -367,11 +367,20 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
|||
s->add_signal(this);
|
||||
}
|
||||
|
||||
NetNet::NetNet(NetScope*s, perm_string n, Type t, long ms, long ls)
|
||||
: NetObj(s, n, 1),
|
||||
static unsigned calculate_count(long s, long e)
|
||||
{
|
||||
if (s >= e)
|
||||
return s - e + 1;
|
||||
else
|
||||
return e - s + 1;
|
||||
}
|
||||
|
||||
NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||
long ms, long ls, long array_s, long array_e)
|
||||
: NetObj(s, n, calculate_count(array_s, array_e)),
|
||||
sig_next_(0), sig_prev_(0), type_(t),
|
||||
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
|
||||
msb_(ms), lsb_(ls),
|
||||
msb_(ms), lsb_(ls), s0_(array_s), e0_(array_e),
|
||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
{
|
||||
assert(s);
|
||||
|
|
@ -533,6 +542,43 @@ unsigned NetNet::sb_to_idx(long sb) const
|
|||
return lsb_ - sb;
|
||||
}
|
||||
|
||||
unsigned NetNet::array_dimensions() const
|
||||
{
|
||||
if (s0_ == e0_)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
long NetNet::array_first() const
|
||||
{
|
||||
if (s0_ < e0_)
|
||||
return s0_;
|
||||
else
|
||||
return e0_;
|
||||
}
|
||||
|
||||
unsigned NetNet::array_count() const
|
||||
{
|
||||
return calculate_count(s0_, e0_);
|
||||
}
|
||||
|
||||
bool NetNet::array_index_is_valid(long sb) const
|
||||
{
|
||||
if (sb < s0_ && sb < e0_)
|
||||
return false;
|
||||
if (sb > e0_ && sb > s0_)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned NetNet::array_index_to_address(long sb) const
|
||||
{
|
||||
if (s0_ <= e0_)
|
||||
return sb - s0_;
|
||||
else
|
||||
return sb - e0_;
|
||||
}
|
||||
|
||||
void NetNet::incr_eref()
|
||||
{
|
||||
eref_count_ += 1;
|
||||
|
|
@ -973,6 +1019,55 @@ const Link& NetAddSub::pin_Result() const
|
|||
return pin(8);
|
||||
}
|
||||
|
||||
NetArrayDq::NetArrayDq(NetScope*s, perm_string n, NetNet*mem, unsigned awid)
|
||||
: NetNode(s, n, 2),
|
||||
mem_(mem), awidth_(awid)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Result"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("Address"), 0);
|
||||
}
|
||||
|
||||
NetArrayDq::~NetArrayDq()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned NetArrayDq::width() const
|
||||
{
|
||||
return mem_->vector_width();
|
||||
}
|
||||
|
||||
unsigned NetArrayDq::awidth() const
|
||||
{
|
||||
return awidth_;
|
||||
}
|
||||
|
||||
const NetNet* NetArrayDq::mem() const
|
||||
{
|
||||
return mem_;
|
||||
}
|
||||
|
||||
Link& NetArrayDq::pin_Result()
|
||||
{
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
Link& NetArrayDq::pin_Address()
|
||||
{
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
const Link& NetArrayDq::pin_Result() const
|
||||
{
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
const Link& NetArrayDq::pin_Address() const
|
||||
{
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* The pinout for the NetCLShift is:
|
||||
* 0 -- Result
|
||||
|
|
@ -1428,190 +1523,6 @@ const Link& NetMux::pin_Data(unsigned s) const
|
|||
return pin(2+s);
|
||||
}
|
||||
|
||||
|
||||
NetRamDq::NetRamDq(NetScope*s, perm_string n, NetMemory*mem, unsigned awid)
|
||||
: NetNode(s, n, 6),
|
||||
mem_(mem), awidth_(awid)
|
||||
{
|
||||
pin(0).set_dir(Link::INPUT);
|
||||
pin(0).set_name(perm_string::literal("InClock"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("OutClock"), 0);
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
pin(2).set_name(perm_string::literal("WE"), 0);
|
||||
pin(3).set_dir(Link::INPUT);
|
||||
pin(3).set_name(perm_string::literal("Address"), 0);
|
||||
pin(4).set_dir(Link::INPUT);
|
||||
pin(4).set_name(perm_string::literal("Data"), 0);
|
||||
pin(5).set_dir(Link::OUTPUT);
|
||||
pin(5).set_name(perm_string::literal("Q"), 0);
|
||||
|
||||
next_ = mem_->ram_list_;
|
||||
mem_->ram_list_ = this;
|
||||
}
|
||||
|
||||
NetRamDq::~NetRamDq()
|
||||
{
|
||||
if (mem_->ram_list_ == this) {
|
||||
mem_->ram_list_ = next_;
|
||||
|
||||
} else {
|
||||
NetRamDq*cur = mem_->ram_list_;
|
||||
while (cur->next_ != this) {
|
||||
assert(cur->next_);
|
||||
cur = cur->next_;
|
||||
}
|
||||
assert(cur->next_ == this);
|
||||
cur->next_ = next_;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned NetRamDq::width() const
|
||||
{
|
||||
return mem_->width();
|
||||
}
|
||||
|
||||
unsigned NetRamDq::awidth() const
|
||||
{
|
||||
return awidth_;
|
||||
}
|
||||
|
||||
unsigned NetRamDq::size() const
|
||||
{
|
||||
return mem_->count();
|
||||
}
|
||||
|
||||
const NetMemory* NetRamDq::mem() const
|
||||
{
|
||||
return mem_;
|
||||
}
|
||||
|
||||
unsigned NetRamDq::count_partners() const
|
||||
{
|
||||
unsigned count = 0;
|
||||
for (NetRamDq*cur = mem_->ram_list_ ; cur ; cur = cur->next_)
|
||||
count += 1;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void NetRamDq::absorb_partners()
|
||||
{
|
||||
NetRamDq*cur, *tmp;
|
||||
for (cur = mem_->ram_list_, tmp = 0
|
||||
; cur||tmp ; cur = cur? cur->next_ : tmp) {
|
||||
tmp = 0;
|
||||
if (cur == this) continue;
|
||||
|
||||
bool ok_flag = true;
|
||||
ok_flag &= pin_Address().is_linked(cur->pin_Address());
|
||||
|
||||
if (!ok_flag) continue;
|
||||
|
||||
if (pin_InClock().is_linked()
|
||||
&& cur->pin_InClock().is_linked()
|
||||
&& ! pin_InClock().is_linked(cur->pin_InClock()))
|
||||
continue;
|
||||
|
||||
if (pin_OutClock().is_linked()
|
||||
&& cur->pin_OutClock().is_linked()
|
||||
&& ! pin_OutClock().is_linked(cur->pin_OutClock()))
|
||||
continue;
|
||||
|
||||
if (pin_WE().is_linked()
|
||||
&& cur->pin_WE().is_linked()
|
||||
&& ! pin_WE().is_linked(cur->pin_WE()))
|
||||
continue;
|
||||
|
||||
if (pin_Data().is_linked() && cur->pin_Data().is_linked()) {
|
||||
ok_flag &= pin_Data().is_linked(cur->pin_Data());
|
||||
}
|
||||
|
||||
if (! ok_flag) continue;
|
||||
|
||||
if (pin_Q().is_linked() && cur->pin_Q().is_linked()) {
|
||||
|
||||
ok_flag &= pin_Q().is_linked(cur->pin_Q());
|
||||
}
|
||||
|
||||
if (! ok_flag) continue;
|
||||
|
||||
// I see no other reason to reject cur, so link up all
|
||||
// my pins and delete it.
|
||||
connect(pin_InClock(), cur->pin_InClock());
|
||||
connect(pin_OutClock(), cur->pin_OutClock());
|
||||
connect(pin_WE(), cur->pin_WE());
|
||||
|
||||
connect(pin_Address(), cur->pin_Address());
|
||||
connect(pin_Data(), cur->pin_Data());
|
||||
connect(pin_Q(), cur->pin_Q());
|
||||
|
||||
tmp = cur->next_;
|
||||
delete cur;
|
||||
cur = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Link& NetRamDq::pin_InClock()
|
||||
{
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
const Link& NetRamDq::pin_InClock() const
|
||||
{
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
Link& NetRamDq::pin_OutClock()
|
||||
{
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
const Link& NetRamDq::pin_OutClock() const
|
||||
{
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
Link& NetRamDq::pin_WE()
|
||||
{
|
||||
return pin(2);
|
||||
}
|
||||
|
||||
const Link& NetRamDq::pin_WE() const
|
||||
{
|
||||
return pin(2);
|
||||
}
|
||||
|
||||
Link& NetRamDq::pin_Address()
|
||||
{
|
||||
return pin(3);
|
||||
}
|
||||
|
||||
const Link& NetRamDq::pin_Address() const
|
||||
{
|
||||
return pin(3);
|
||||
}
|
||||
|
||||
Link& NetRamDq::pin_Data()
|
||||
{
|
||||
return pin(4);
|
||||
}
|
||||
|
||||
const Link& NetRamDq::pin_Data() const
|
||||
{
|
||||
return pin(4);
|
||||
}
|
||||
|
||||
Link& NetRamDq::pin_Q()
|
||||
{
|
||||
return pin(5);
|
||||
}
|
||||
|
||||
const Link& NetRamDq::pin_Q() const
|
||||
{
|
||||
return pin(5);
|
||||
}
|
||||
|
||||
NetSignExtend::NetSignExtend(NetScope*s, perm_string n, unsigned w)
|
||||
: NetNode(s, n, 2), width_(w)
|
||||
{
|
||||
|
|
@ -2027,68 +1938,6 @@ const NetScope* NetEConstParam::scope() const
|
|||
return scope_;
|
||||
}
|
||||
|
||||
|
||||
NetEMemory::NetEMemory(NetMemory*m, NetExpr*i)
|
||||
: NetExpr(m->width()), mem_(m), idx_(i)
|
||||
{
|
||||
}
|
||||
|
||||
NetEMemory::~NetEMemory()
|
||||
{
|
||||
}
|
||||
|
||||
perm_string NetEMemory::name() const
|
||||
{
|
||||
return mem_->name();
|
||||
}
|
||||
|
||||
const NetExpr* NetEMemory::index() const
|
||||
{
|
||||
return idx_;
|
||||
}
|
||||
|
||||
NetMemory::NetMemory(NetScope*sc, perm_string n, long w, long s, long e)
|
||||
: width_(w), idxh_(s), idxl_(e), ram_list_(0), scope_(sc)
|
||||
{
|
||||
name_ = n;
|
||||
scope_->add_memory(this);
|
||||
}
|
||||
|
||||
NetMemory::~NetMemory()
|
||||
{
|
||||
assert(scope_);
|
||||
scope_->rem_memory(this);
|
||||
}
|
||||
|
||||
unsigned NetMemory::count() const
|
||||
{
|
||||
if (idxh_ < idxl_)
|
||||
return idxl_ - idxh_ + 1;
|
||||
else
|
||||
return idxh_ - idxl_ + 1;
|
||||
}
|
||||
|
||||
perm_string NetMemory::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
long NetMemory::index_to_address(long idx) const
|
||||
{
|
||||
if (idxh_ < idxl_)
|
||||
return idx - idxh_;
|
||||
else
|
||||
return idx - idxl_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NetEMemory* NetEMemory::dup_expr() const
|
||||
{
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEEvent::NetEEvent(NetEvent*e)
|
||||
: event_(e)
|
||||
{
|
||||
|
|
@ -2119,25 +1968,20 @@ const NetScope* NetEScope::scope() const
|
|||
}
|
||||
|
||||
NetESignal::NetESignal(NetNet*n)
|
||||
: NetExpr(n->vector_width()), net_(n)
|
||||
: NetExpr(n->vector_width()), net_(n), word_(0)
|
||||
{
|
||||
net_->incr_eref();
|
||||
set_line(*n);
|
||||
cast_signed(net_->get_signed());
|
||||
}
|
||||
|
||||
#if 0
|
||||
NetESignal::NetESignal(NetNet*n, unsigned m, unsigned l)
|
||||
: NetExpr(m - l + 1), net_(n)
|
||||
NetESignal::NetESignal(NetNet*n, NetExpr*w)
|
||||
: NetExpr(n->vector_width()), net_(n), word_(w)
|
||||
{
|
||||
assert(m >= l);
|
||||
msi_ = m;
|
||||
lsi_ = l;
|
||||
net_->incr_eref();
|
||||
set_line(*n);
|
||||
cast_signed(net_->get_signed());
|
||||
}
|
||||
#endif
|
||||
|
||||
NetESignal::~NetESignal()
|
||||
{
|
||||
|
|
@ -2149,18 +1993,22 @@ perm_string NetESignal::name() const
|
|||
return net_->name();
|
||||
}
|
||||
|
||||
unsigned NetESignal::bit_count() const
|
||||
const NetExpr* NetESignal::word_index() const
|
||||
{
|
||||
return word_;
|
||||
}
|
||||
|
||||
unsigned NetESignal::vector_width() const
|
||||
{
|
||||
return net_->vector_width();
|
||||
}
|
||||
|
||||
Link& NetESignal::bit(unsigned idx)
|
||||
const NetNet* NetESignal::sig() const
|
||||
{
|
||||
assert(idx <= 0);
|
||||
return net_->pin(idx);
|
||||
return net_;
|
||||
}
|
||||
|
||||
const NetNet* NetESignal::sig() const
|
||||
NetNet* NetESignal::sig()
|
||||
{
|
||||
return net_;
|
||||
}
|
||||
|
|
@ -2342,6 +2190,12 @@ const NetProc*NetTaskDef::proc() const
|
|||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* Revision 1.251 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.250 2006/11/10 04:54:26 steve
|
||||
* Add test_width methods for PETernary and PEString.
|
||||
*
|
||||
|
|
|
|||
253
netlist.h
253
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.365 2006/11/04 06:19:25 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.366 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -447,7 +447,12 @@ class NetNet : public NetObj {
|
|||
// that passed through.
|
||||
explicit NetNet(NetScope*s, perm_string n, Type t, unsigned width =1);
|
||||
|
||||
explicit NetNet(NetScope*s, perm_string n, Type t, long ms, long ls);
|
||||
// This form supports an array of vectors. The [ms:ls] define
|
||||
// the base vector, and the [s0:e0] define the array
|
||||
// dimensions. If s0==e0, then this is not an array after
|
||||
// all.
|
||||
explicit NetNet(NetScope*s, perm_string n, Type t,
|
||||
long ms, long ls, long s0 =0, long e0 =0);
|
||||
|
||||
virtual ~NetNet();
|
||||
|
||||
|
|
@ -488,6 +493,21 @@ class NetNet : public NetObj {
|
|||
the pin# from the index. */
|
||||
bool sb_is_valid(long sb) const;
|
||||
|
||||
/* This method returns 0 for scalers and vectors, and greater
|
||||
for arrays. The value is the number of array
|
||||
indices. (Currently only one array index is supported.) */
|
||||
unsigned array_dimensions() const;
|
||||
long array_first() const;
|
||||
|
||||
// This is the number of array elements.
|
||||
unsigned array_count() const;
|
||||
|
||||
// This method returns a 0 based address of an array entry as
|
||||
// indexed by idx. The Verilog source may give index ranges
|
||||
// that are not zero based.
|
||||
bool array_index_is_valid(long idx) const;
|
||||
unsigned array_index_to_address(long idx) const;
|
||||
|
||||
bool local_flag() const { return local_flag_; }
|
||||
void local_flag(bool f) { local_flag_ = f; }
|
||||
|
||||
|
|
@ -524,6 +544,7 @@ class NetNet : public NetObj {
|
|||
bool isint_; // original type of integer
|
||||
|
||||
long msb_, lsb_;
|
||||
long s0_, e0_;
|
||||
|
||||
bool local_flag_;
|
||||
unsigned eref_count_;
|
||||
|
|
@ -571,6 +592,37 @@ class NetAddSub : public NetNode {
|
|||
unsigned width_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The NetArrayDq node represents an array dereference. The NetNet
|
||||
* that this object refers to is an array, and the Address pin selects
|
||||
* which word of the array to place on the Result.
|
||||
*/
|
||||
class NetArrayDq : public NetNode {
|
||||
|
||||
public:
|
||||
NetArrayDq(NetScope*s, perm_string name, NetNet*mem, unsigned awid);
|
||||
~NetArrayDq();
|
||||
|
||||
unsigned width() const;
|
||||
unsigned awidth() const;
|
||||
unsigned size() const;
|
||||
const NetNet*mem() const;
|
||||
|
||||
Link& pin_Address();
|
||||
Link& pin_Result();
|
||||
|
||||
const Link& pin_Address() const;
|
||||
const Link& pin_Result() const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
NetNet*mem_;
|
||||
unsigned awidth_;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* This type represents the LPM_CLSHIFT device.
|
||||
*/
|
||||
|
|
@ -819,62 +871,6 @@ class NetFF : public NetNode {
|
|||
verinum sset_value_;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This class represents the declared memory object. The parser
|
||||
* creates one of these for each declared memory in the elaborated
|
||||
* design. A reference to one of these is handled by the NetEMemory
|
||||
* object, which is derived from NetExpr. This is not a node because
|
||||
* memory objects can only be accessed by behavioral code.
|
||||
*/
|
||||
class NetMemory {
|
||||
|
||||
public:
|
||||
NetMemory(NetScope*sc, perm_string n, long w, long s, long e);
|
||||
~NetMemory();
|
||||
|
||||
// This is the BASE name of the memory object. It does not
|
||||
// include scope name, get that from the scope itself.
|
||||
perm_string name() const;
|
||||
|
||||
// This is the width (in bits) of a single memory position.
|
||||
unsigned width() const { return width_; }
|
||||
|
||||
// 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.
|
||||
unsigned count() const;
|
||||
|
||||
// This method returns a 0 based address of a memory entry as
|
||||
// indexed by idx. The Verilog source may give index ranges
|
||||
// that are not zero based.
|
||||
long index_to_address(long idx) const;
|
||||
|
||||
void dump(ostream&o, unsigned lm) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
unsigned width_;
|
||||
long idxh_;
|
||||
long idxl_;
|
||||
|
||||
friend class NetRamDq;
|
||||
NetRamDq* ram_list_;
|
||||
|
||||
friend class NetScope;
|
||||
NetMemory*snext_, *sprev_;
|
||||
NetScope*scope_;
|
||||
|
||||
private: // not implemented
|
||||
NetMemory(const NetMemory&);
|
||||
NetMemory& operator= (const NetMemory&);
|
||||
};
|
||||
|
||||
/*
|
||||
* This class implements a basic LPM_MULT combinational multiplier. It
|
||||
* is used as a structural representation of the * operator. The
|
||||
|
|
@ -965,57 +961,6 @@ class NetMux : public NetNode {
|
|||
unsigned swidth_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This device represents an LPM_RAM_DQ device. The actual content is
|
||||
* represented by a NetMemory object allocated elsewhere, but that
|
||||
* object fixes the width and size of the device. The pin count of the
|
||||
* address input is given in the constructor.
|
||||
*/
|
||||
class NetRamDq : public NetNode {
|
||||
|
||||
public:
|
||||
NetRamDq(NetScope*s, perm_string name, NetMemory*mem, unsigned awid);
|
||||
~NetRamDq();
|
||||
|
||||
unsigned width() const;
|
||||
unsigned awidth() const;
|
||||
unsigned size() const;
|
||||
const NetMemory*mem() const;
|
||||
|
||||
Link& pin_InClock();
|
||||
Link& pin_OutClock();
|
||||
Link& pin_WE();
|
||||
|
||||
Link& pin_Address();
|
||||
Link& pin_Data();
|
||||
Link& pin_Q();
|
||||
|
||||
const Link& pin_InClock() const;
|
||||
const Link& pin_OutClock() const;
|
||||
const Link& pin_WE() const;
|
||||
|
||||
const Link& pin_Address() const;
|
||||
const Link& pin_Data() const;
|
||||
const Link& pin_Q() const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
// Use this method to absorb other NetRamDq objects that are
|
||||
// connected to the same memory, and have compatible pin
|
||||
// connections.
|
||||
void absorb_partners();
|
||||
|
||||
// Use this method to count the partners (including myself)
|
||||
// that are ports to the attached memory.
|
||||
unsigned count_partners() const;
|
||||
|
||||
private:
|
||||
NetMemory*mem_;
|
||||
NetRamDq*next_;
|
||||
unsigned awidth_;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* The NetReplicate node takes a vector input and makes it into a larger
|
||||
|
|
@ -1710,20 +1655,18 @@ class NetAssign_ {
|
|||
|
||||
public:
|
||||
NetAssign_(NetNet*sig);
|
||||
NetAssign_(NetMemory*mem);
|
||||
~NetAssign_();
|
||||
|
||||
// If this expression exists, then only a single bit is to be
|
||||
// set from the rval, and the value of this expression selects
|
||||
// the pin that gets the value.
|
||||
NetExpr*bmux();
|
||||
const NetExpr*bmux() const;
|
||||
// If this expression exists, then it is used to select a word
|
||||
// from an array/memory.
|
||||
NetExpr*word();
|
||||
const NetExpr*word() 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_word(NetExpr*);
|
||||
void set_part(NetExpr* loff, unsigned wid);
|
||||
|
||||
// Get the width of the r-value that this node expects. This
|
||||
|
|
@ -1735,7 +1678,6 @@ class NetAssign_ {
|
|||
perm_string name() const;
|
||||
|
||||
NetNet* sig() const;
|
||||
NetMemory*mem() const;
|
||||
|
||||
// Mark that the synthesizer has worked with this l-value, so
|
||||
// when it is released, the l-value signal should be turned
|
||||
|
|
@ -1755,9 +1697,8 @@ class NetAssign_ {
|
|||
|
||||
private:
|
||||
NetNet *sig_;
|
||||
NetMemory*mem_;
|
||||
// Memory word index
|
||||
NetExpr*bmux_;
|
||||
NetExpr*word_;
|
||||
|
||||
bool turn_sig_to_wire_on_release_;
|
||||
// indexed part select base
|
||||
|
|
@ -3149,52 +3090,21 @@ class NetEUReduce : public NetEUnary {
|
|||
|
||||
};
|
||||
|
||||
/*
|
||||
* A reference to a memory is represented by this expression. If the
|
||||
* index is not supplied, then the node is only valid in certain
|
||||
* specific contexts.
|
||||
*/
|
||||
class NetEMemory : public NetExpr {
|
||||
|
||||
public:
|
||||
NetEMemory(NetMemory*mem, NetExpr*idx =0);
|
||||
virtual ~NetEMemory();
|
||||
|
||||
perm_string name () const;
|
||||
const NetExpr* index() const;
|
||||
|
||||
virtual bool set_width(unsigned, bool last_chance);
|
||||
virtual NetNet* synthesize(Design*des);
|
||||
|
||||
NetExpr* eval_tree();
|
||||
virtual NetEMemory*dup_expr() const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
const NetMemory*memory() const { return mem_; };
|
||||
|
||||
private:
|
||||
NetMemory*mem_;
|
||||
NetExpr* idx_;
|
||||
};
|
||||
|
||||
/*
|
||||
* When a signal shows up in an expression, this type represents
|
||||
* it. From this the expression can get any kind of access to the
|
||||
* structural signal.
|
||||
* structural signal, including arrays.
|
||||
*
|
||||
* A signal shows up as a node in the netlist so that structural
|
||||
* activity can invoke the expression. This node also supports part
|
||||
* select by indexing a range of the NetNet that is associated with
|
||||
* it. The msi() is the more significant index, and lsi() the least
|
||||
* significant index.
|
||||
* The NetESignal may refer to an array, if the word_index is
|
||||
* included. This expression calculates the index of the word in the
|
||||
* array. It may only be nil if the expression refers to the whole
|
||||
* array, and that is legal only in limited situation.
|
||||
*/
|
||||
class NetESignal : public NetExpr {
|
||||
|
||||
public:
|
||||
NetESignal(NetNet*n);
|
||||
NetESignal(NetNet*n, NetExpr*word_index);
|
||||
~NetESignal();
|
||||
|
||||
perm_string name() const;
|
||||
|
|
@ -3204,12 +3114,16 @@ class NetESignal : public NetExpr {
|
|||
NetNet* synthesize(Design*des);
|
||||
NexusSet* nex_input();
|
||||
|
||||
// These methods actually reference the properties of the
|
||||
// NetNet object that I point to.
|
||||
unsigned bit_count() const;
|
||||
Link& bit(unsigned idx);
|
||||
// This is the expression for selecting an array word, if this
|
||||
// signal refers to an array.
|
||||
const NetExpr* word_index() const;
|
||||
|
||||
// This is the width of the vector that this signal refers to.
|
||||
unsigned vector_width() const;
|
||||
// Point back to the signal that this expression node references.
|
||||
const NetNet* sig() const;
|
||||
NetNet* sig();
|
||||
// Declared vector dimensions for the signal.
|
||||
unsigned msi() const;
|
||||
unsigned lsi() const;
|
||||
|
||||
|
|
@ -3220,6 +3134,8 @@ class NetESignal : public NetExpr {
|
|||
|
||||
private:
|
||||
NetNet*net_;
|
||||
// Expression to select a word from the net.
|
||||
NetExpr*word_;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -3278,15 +3194,6 @@ class NetScope : public Attrib {
|
|||
NetNet* find_signal_in_child(const hname_t&name);
|
||||
|
||||
|
||||
/* ... and these methods manage memory the same way as signals
|
||||
are managed above. */
|
||||
|
||||
void add_memory(NetMemory*);
|
||||
void rem_memory(NetMemory*);
|
||||
|
||||
NetMemory* find_memory(const string&name);
|
||||
|
||||
|
||||
/* The parent and child() methods allow users of NetScope
|
||||
objects to locate nearby scopes. */
|
||||
NetScope* parent();
|
||||
|
|
@ -3399,8 +3306,6 @@ class NetScope : public Attrib {
|
|||
|
||||
NetEvent *events_;
|
||||
NetNet *signals_;
|
||||
NetMemory*memories_;
|
||||
|
||||
perm_string module_name_;
|
||||
union {
|
||||
NetTaskDef*task_;
|
||||
|
|
@ -3567,6 +3472,12 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.366 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.365 2006/11/04 06:19:25 steve
|
||||
* Remove last bits of relax_width methods, and use test_width
|
||||
* to calculate the width of an r-value expression that may
|
||||
|
|
|
|||
12
netmisc.h
12
netmisc.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netmisc.h,v 1.26 2006/09/28 00:29:49 steve Exp $"
|
||||
#ident "$Id: netmisc.h,v 1.27 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
|
@ -42,7 +42,6 @@
|
|||
extern NetScope* symbol_search(const Design*des,
|
||||
NetScope*start, hname_t path,
|
||||
NetNet*&net, /* net/reg */
|
||||
NetMemory*&mem, /* memory */
|
||||
const NetExpr*&par,/* parameter */
|
||||
NetEvent*&eve, /* named event */
|
||||
const NetExpr*&ex1, const NetExpr*&ex2);
|
||||
|
|
@ -50,12 +49,11 @@ extern NetScope* symbol_search(const Design*des,
|
|||
inline NetScope* symbol_search(const Design*des,
|
||||
NetScope*start, const hname_t&path,
|
||||
NetNet*&net, /* net/reg */
|
||||
NetMemory*&mem, /* memory */
|
||||
const NetExpr*&par,/* parameter */
|
||||
NetEvent*&eve /* named event */)
|
||||
{
|
||||
const NetExpr*ex1, *ex2;
|
||||
return symbol_search(des, start, path, net, mem, par, eve, ex1, ex2);
|
||||
return symbol_search(des, start, path, net, /*mem,*/ par, eve, ex1, ex2);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -122,6 +120,12 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
|||
|
||||
/*
|
||||
* $Log: netmisc.h,v $
|
||||
* Revision 1.27 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.26 2006/09/28 00:29:49 steve
|
||||
* Allow specparams as constants in expressions.
|
||||
*
|
||||
|
|
|
|||
42
parse.y
42
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.223 2006/12/06 05:32:36 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.224 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -191,8 +191,8 @@ static list<perm_string>* list_from_identifier(list<perm_string>*tmp, char*id)
|
|||
%type <expr> udp_initial_expr_opt
|
||||
|
||||
%type <hier> identifier
|
||||
%type <text> register_variable
|
||||
%type <perm_strings> register_variable_list list_of_identifiers
|
||||
%type <text> register_variable net_variable
|
||||
%type <perm_strings> register_variable_list net_variable_list list_of_identifiers
|
||||
|
||||
%type <net_decl_assign> net_decl_assign net_decl_assigns
|
||||
|
||||
|
|
@ -1629,7 +1629,7 @@ module_item
|
|||
: attribute_list_opt net_type
|
||||
primitive_type_opt signed_opt range_opt
|
||||
delay3_opt
|
||||
list_of_identifiers ';'
|
||||
net_variable_list ';'
|
||||
|
||||
{ ivl_variable_type_t dtype = $3;
|
||||
if (dtype == IVL_VT_NO_TYPE)
|
||||
|
|
@ -2477,6 +2477,40 @@ register_variable_list
|
|||
}
|
||||
;
|
||||
|
||||
net_variable
|
||||
: IDENTIFIER
|
||||
{ pform_makewire(@1, $1, NetNet::IMPLICIT,
|
||||
NetNet::NOT_A_PORT,
|
||||
IVL_VT_NO_TYPE, 0);
|
||||
$$ = $1;
|
||||
}
|
||||
| IDENTIFIER '[' expression ':' expression ']'
|
||||
{ pform_makewire(@1, $1, NetNet::IMPLICIT,
|
||||
NetNet::NOT_A_PORT,
|
||||
IVL_VT_NO_TYPE, 0);
|
||||
if (! pform_expression_is_constant($3))
|
||||
yyerror(@3, "error: msb of net range must be constant.");
|
||||
if (! pform_expression_is_constant($5))
|
||||
yyerror(@3, "error: lsb of net range must be constant.");
|
||||
pform_set_reg_idx($1, $3, $5);
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
net_variable_list
|
||||
: net_variable
|
||||
{ list<perm_string>*tmp = new list<perm_string>;
|
||||
tmp->push_back(lex_strings.make($1));
|
||||
$$ = tmp;
|
||||
delete[]$1;
|
||||
}
|
||||
| net_variable_list ',' net_variable
|
||||
{ list<perm_string>*tmp = $1;
|
||||
tmp->push_back(lex_strings.make($3));
|
||||
$$ = tmp;
|
||||
delete[]$3;
|
||||
}
|
||||
;
|
||||
|
||||
specify_item
|
||||
: K_specparam specparam_list ';'
|
||||
| specify_simple_path_decl ';'
|
||||
|
|
|
|||
33
pform.cc
33
pform.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: pform.cc,v 1.137 2006/09/23 04:57:19 steve Exp $"
|
||||
#ident "$Id: pform.cc,v 1.138 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -1197,24 +1197,21 @@ void pform_makewire(const vlltype&li, const char*nm,
|
|||
|
||||
PWire*cur = get_wire_in_module(name);
|
||||
|
||||
if (cur) {
|
||||
if ((cur->get_wire_type() != NetNet::IMPLICIT)
|
||||
&& (cur->get_wire_type() != NetNet::IMPLICIT_REG)) {
|
||||
// If this is not implicit ("implicit" meaning we don't know
|
||||
// what the type is yet) then set thay type now.
|
||||
if (cur && type != NetNet::IMPLICIT) {
|
||||
bool rc = cur->set_wire_type(type);
|
||||
if (rc == false) {
|
||||
ostringstream msg;
|
||||
msg << name << " previously defined at " <<
|
||||
cur->get_line() << ".";
|
||||
msg << name << " definition conflicts with "
|
||||
<< "definition at " << cur->get_line()
|
||||
<< ".";
|
||||
VLerror(msg.str().c_str());
|
||||
} else {
|
||||
bool rc = cur->set_wire_type(type);
|
||||
if (rc == false) {
|
||||
ostringstream msg;
|
||||
msg << name << " definition conflicts with "
|
||||
<< "definition at " << cur->get_line()
|
||||
<< ".";
|
||||
VLerror(msg.str().c_str());
|
||||
}
|
||||
cerr << "XXXX type=" << type <<", curtype=" << cur->get_wire_type() << endl;
|
||||
}
|
||||
|
||||
}
|
||||
if (cur) {
|
||||
cur->set_file(li.text);
|
||||
cur->set_lineno(li.first_line);
|
||||
return;
|
||||
|
|
@ -1747,6 +1744,12 @@ int pform_parse(const char*path, FILE*file)
|
|||
|
||||
/*
|
||||
* $Log: pform.cc,v $
|
||||
* Revision 1.138 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.137 2006/09/23 04:57:19 steve
|
||||
* Basic support for specify timing.
|
||||
*
|
||||
|
|
|
|||
14
set_width.cc
14
set_width.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: set_width.cc,v 1.41 2006/11/04 06:19:25 steve Exp $"
|
||||
#ident "$Id: set_width.cc,v 1.42 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -340,7 +340,7 @@ bool NetECReal::set_width(unsigned w, bool)
|
|||
expr_width(w);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool NetEMemory::set_width(unsigned w, bool)
|
||||
{
|
||||
if (w != mem_->width())
|
||||
|
|
@ -349,7 +349,7 @@ bool NetEMemory::set_width(unsigned w, bool)
|
|||
expr_width(w);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
bool NetEParam::set_width(unsigned, bool)
|
||||
{
|
||||
return false;
|
||||
|
|
@ -374,7 +374,7 @@ bool NetESFunc::set_width(unsigned w, bool)
|
|||
*/
|
||||
bool NetESignal::set_width(unsigned w, bool)
|
||||
{
|
||||
if (w != bit_count())
|
||||
if (w != vector_width())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
@ -441,6 +441,12 @@ bool NetEUReduce::set_width(unsigned w, bool)
|
|||
|
||||
/*
|
||||
* $Log: set_width.cc,v $
|
||||
* Revision 1.42 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.41 2006/11/04 06:19:25 steve
|
||||
* Remove last bits of relax_width methods, and use test_width
|
||||
* to calculate the width of an r-value expression that may
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: symbol_search.cc,v 1.3 2005/11/27 05:56:20 steve Exp $"
|
||||
#ident "$Id: symbol_search.cc,v 1.4 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
|
@ -29,7 +29,6 @@
|
|||
*/
|
||||
NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
|
||||
NetNet*&net,
|
||||
NetMemory*&mem,
|
||||
const NetExpr*&par,
|
||||
NetEvent*&eve,
|
||||
const NetExpr*&ex1, const NetExpr*&ex2)
|
||||
|
|
@ -41,7 +40,6 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
|
|||
|
||||
/* Initialize output argument to cleared. */
|
||||
net = 0;
|
||||
mem = 0;
|
||||
par = 0;
|
||||
eve = 0;
|
||||
|
||||
|
|
@ -56,11 +54,6 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
|
|||
return scope;
|
||||
}
|
||||
|
||||
if ( (mem = scope->find_memory(key)) ) {
|
||||
delete key;
|
||||
return scope;
|
||||
}
|
||||
|
||||
if ( (eve = scope->find_event(key)) ) {
|
||||
delete key;
|
||||
return scope;
|
||||
|
|
@ -83,6 +76,12 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
|
|||
|
||||
/*
|
||||
* $Log: symbol_search.cc,v $
|
||||
* Revision 1.4 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.3 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
|
|
|
|||
48
syn-rules.y
48
syn-rules.y
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: syn-rules.y,v 1.33 2005/04/24 23:44:02 steve Exp $"
|
||||
#ident "$Id: syn-rules.y,v 1.34 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -118,7 +118,7 @@ static void hookup_DFF_CE(NetFF*ff, NetESignal*d, NetEvProbe*pclk,
|
|||
// where lval is really a "reg [7:0]". In other words, part
|
||||
// selects in the l-value are handled by loff and the lwidth().
|
||||
|
||||
connect(ff->pin_Data(), d->bit(0));
|
||||
connect(ff->pin_Data(), d->sig()->pin(0));
|
||||
connect(ff->pin_Q(), a->sig()->pin(0));
|
||||
|
||||
connect(ff->pin_Clock(), pclk->pin(0));
|
||||
|
|
@ -137,41 +137,6 @@ static void hookup_DFF_CE(NetFF*ff, NetESignal*d, NetEvProbe*pclk,
|
|||
a->turn_sig_to_wire_on_release();
|
||||
}
|
||||
|
||||
static void hookup_RAMDQ(NetRamDq*ram, NetESignal*d, NetNet*adr,
|
||||
NetEvProbe*pclk, NetNet*ce,
|
||||
NetAssign_*a, unsigned rval_pinoffset)
|
||||
{
|
||||
assert(d);
|
||||
assert(a);
|
||||
|
||||
/* Connect the input Data bits of the RAM, from the r-value of
|
||||
the assignment. */
|
||||
connect(ram->pin_Data(), d->bit(rval_pinoffset));
|
||||
|
||||
/* Connect the Address pins from the addr net discovered by the
|
||||
caller. */
|
||||
connect(ram->pin_Address(), adr->pin(0));
|
||||
|
||||
/* Connect the input clock and the WE of the RAM. */
|
||||
assert(pclk);
|
||||
connect(ram->pin_InClock(), pclk->pin(0));
|
||||
if (ce) {
|
||||
connect(ram->pin_WE(), ce->pin(0));
|
||||
} /* XXX does ram CE default to true if not connected? */
|
||||
|
||||
/* This notices any other NetRamDq objects connected to the
|
||||
same NetMemory, that have the same address pins and are
|
||||
otherwise compatible. This absorbs them into this object. */
|
||||
ram->absorb_partners();
|
||||
|
||||
/* This lval_ represents a reg that is a WIRE in the
|
||||
synthesized results. This function signals the destructor
|
||||
to change the REG that this l-value refers to into a
|
||||
WIRE. It is done then, at the last minute, so that pending
|
||||
synthesis can continue to work with it as a WIRE. */
|
||||
a->turn_sig_to_wire_on_release();
|
||||
}
|
||||
|
||||
static void make_DFF_CE(Design*des, NetProcTop*top, NetEvWait*wclk,
|
||||
NetEvent*eclk, NetExpr*cexp, NetAssignBase*asn)
|
||||
{
|
||||
|
|
@ -207,13 +172,6 @@ static void make_DFF_CE(Design*des, NetProcTop*top, NetEvWait*wclk,
|
|||
a->sig()->vector_width());
|
||||
hookup_DFF_CE(ff, d, pclk, ce, a, rval_pinoffset);
|
||||
des->add_node(ff);
|
||||
} else if (a->mem()) {
|
||||
NetMemory *m=a->mem();
|
||||
NetNet *adr = a->bmux()->synthesize(des);
|
||||
NetRamDq*ram = new NetRamDq(top->scope(), m->name(),
|
||||
m, adr->pin_count());
|
||||
hookup_RAMDQ(ram, d, adr, pclk, ce, a, rval_pinoffset);
|
||||
des->add_node(ram);
|
||||
}
|
||||
rval_pinoffset += a->lwidth();
|
||||
}
|
||||
|
|
@ -233,7 +191,7 @@ static void make_initializer(Design*des, NetProcTop*top, NetAssignBase*asn)
|
|||
|
||||
for (unsigned idx = 0 ; idx < asn->l_val(0)->lwidth() ; idx += 1) {
|
||||
|
||||
verinum::V bit = rsig->bit(idx).nexus()->driven_value();
|
||||
verinum::V bit = rsig->sig()->pin(idx).nexus()->driven_value();
|
||||
|
||||
Nexus*nex = asn->l_val(0)->sig()->pin(idx).nexus();
|
||||
for (Link*cur = nex->first_nlink()
|
||||
|
|
|
|||
86
t-dll-api.cc
86
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.137 2006/09/23 04:57:19 steve Exp $"
|
||||
#ident "$Id: t-dll-api.cc,v 1.138 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -317,6 +317,9 @@ extern "C" ivl_expr_t ivl_expr_oper1(ivl_expr_t net)
|
|||
case IVL_EX_MEMORY:
|
||||
return net->u_.memory_.idx_;
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
return net->u_.signal_.word;
|
||||
|
||||
case IVL_EX_TERNARY:
|
||||
return net->u_.ternary_.cond;
|
||||
|
||||
|
|
@ -443,6 +446,7 @@ extern "C" ivl_signal_t ivl_expr_signal(ivl_expr_t net)
|
|||
switch (net->type_) {
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
case IVL_EX_ARRAY:
|
||||
return net->u_.signal_.sig;
|
||||
|
||||
default:
|
||||
|
|
@ -707,6 +711,18 @@ extern "C" ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net)
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_signal_t ivl_lpm_array(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_ARRAY:
|
||||
return net->u_.array.sig;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_lpm_base(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
|
|
@ -726,7 +742,6 @@ extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
|
|||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.clk;
|
||||
default:
|
||||
assert(0);
|
||||
|
|
@ -739,7 +754,6 @@ extern "C" ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net)
|
|||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.aset_value;
|
||||
default:
|
||||
assert(0);
|
||||
|
|
@ -751,7 +765,6 @@ extern "C" ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net)
|
|||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.sset_value;
|
||||
default:
|
||||
assert(0);
|
||||
|
|
@ -775,7 +788,6 @@ extern "C" ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net)
|
|||
{
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_RAM:
|
||||
case IVL_LPM_FF:
|
||||
return net->u_.ff.we;
|
||||
default:
|
||||
|
|
@ -827,10 +839,6 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
|||
else
|
||||
return net->u_.shift.s;
|
||||
|
||||
case IVL_LPM_RAM:
|
||||
assert(idx == 0);
|
||||
return net->u_.ff.d.pin;
|
||||
|
||||
case IVL_LPM_FF:
|
||||
assert(idx == 0);
|
||||
return net->u_.ff.d.pin;
|
||||
|
|
@ -945,10 +953,6 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
|
|||
assert(idx == 0);
|
||||
return net->u_.arith.q;
|
||||
|
||||
case IVL_LPM_RAM:
|
||||
assert(idx == 0);
|
||||
return net->u_.ff.q.pin;
|
||||
|
||||
case IVL_LPM_FF:
|
||||
assert(idx == 0);
|
||||
return net->u_.ff.q.pin;
|
||||
|
|
@ -993,6 +997,10 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
|
|||
assert(idx == 0);
|
||||
return net->u_.repeat.q;
|
||||
|
||||
case IVL_LPM_ARRAY:
|
||||
assert(idx == 0);
|
||||
return net->u_.array.q;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -1008,12 +1016,13 @@ extern "C" ivl_scope_t ivl_lpm_scope(ivl_lpm_t net)
|
|||
extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net)
|
||||
{
|
||||
switch (net->type) {
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.s.pin;
|
||||
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.s;
|
||||
|
||||
case IVL_LPM_ARRAY:
|
||||
return net->u_.array.a;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -1023,10 +1032,10 @@ extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net)
|
|||
extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net)
|
||||
{
|
||||
switch (net->type) {
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.swid;
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.swid;
|
||||
case IVL_LPM_ARRAY:
|
||||
return net->u_.array.swid;
|
||||
case IVL_LPM_CONCAT:
|
||||
return net->u_.concat.inputs;
|
||||
default:
|
||||
|
|
@ -1040,7 +1049,6 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
|||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
case IVL_LPM_MUX:
|
||||
return 0;
|
||||
case IVL_LPM_ADD:
|
||||
|
|
@ -1079,6 +1087,8 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
|||
return net->u_.part.signed_flag;
|
||||
case IVL_LPM_REPEAT:
|
||||
return 0;
|
||||
case IVL_LPM_ARRAY: // Array ports take the signedness of the array.
|
||||
return net->u_.array.sig->signed_;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -1119,18 +1129,6 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
|
|||
return net->width;
|
||||
}
|
||||
|
||||
extern "C" ivl_memory_t ivl_lpm_memory(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.mem;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_expr_t ivl_lval_mux(ivl_lval_t net)
|
||||
{
|
||||
assert(net);
|
||||
|
|
@ -1144,6 +1142,8 @@ extern "C" ivl_expr_t ivl_lval_idx(ivl_lval_t net)
|
|||
assert(net);
|
||||
if (net->type_ == IVL_LVAL_MEM)
|
||||
return net->idx;
|
||||
if (net->type_ == IVL_LVAL_ARR)
|
||||
return net->idx;
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
|
|
@ -1174,6 +1174,7 @@ extern "C" ivl_signal_t ivl_lval_sig(ivl_lval_t net)
|
|||
case IVL_LVAL_REG:
|
||||
case IVL_LVAL_NET:
|
||||
case IVL_LVAL_MUX:
|
||||
case IVL_LVAL_ARR:
|
||||
return net->n.sig;
|
||||
default:
|
||||
return 0;
|
||||
|
|
@ -1520,6 +1521,16 @@ extern "C" const char* ivl_scope_tname(ivl_scope_t net)
|
|||
return net->tname_;
|
||||
}
|
||||
|
||||
extern "C" int ivl_signal_array_base(ivl_signal_t net)
|
||||
{
|
||||
return net->array_base;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_signal_array_count(ivl_signal_t net)
|
||||
{
|
||||
return net->array_words;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_signal_attr(ivl_signal_t net, const char*key)
|
||||
{
|
||||
if (net->nattr == 0)
|
||||
|
|
@ -1571,9 +1582,13 @@ extern "C" const char* ivl_signal_name(ivl_signal_t net)
|
|||
return name_buffer;
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_signal_nex(ivl_signal_t net)
|
||||
extern "C" ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word)
|
||||
{
|
||||
return net->pin_;
|
||||
assert(word < net->array_words);
|
||||
if (net->array_words > 1)
|
||||
return net->pins[word];
|
||||
else
|
||||
return net->pin;
|
||||
}
|
||||
|
||||
extern "C" int ivl_signal_msb(ivl_signal_t net)
|
||||
|
|
@ -1889,6 +1904,7 @@ extern "C" unsigned ivl_stmt_lwidth(ivl_statement_t net)
|
|||
sum += 1;
|
||||
break;
|
||||
case IVL_LVAL_REG:
|
||||
case IVL_LVAL_ARR:
|
||||
sum += ivl_lval_width(cur);
|
||||
break;
|
||||
case IVL_LVAL_MEM:
|
||||
|
|
@ -1976,6 +1992,12 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
|
|||
|
||||
/*
|
||||
* $Log: t-dll-api.cc,v $
|
||||
* Revision 1.138 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.137 2006/09/23 04:57:19 steve
|
||||
* Basic support for specify timing.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-expr.cc,v 1.43 2005/09/14 02:53:15 steve Exp $"
|
||||
#ident "$Id: t-dll-expr.cc,v 1.44 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -200,27 +200,6 @@ void dll_target::expr_concat(const NetEConcat*net)
|
|||
expr_ = cur;
|
||||
}
|
||||
|
||||
void dll_target::expr_memory(const NetEMemory*net)
|
||||
{
|
||||
assert(expr_ == 0);
|
||||
if (net->index()) {
|
||||
net->index()->expr_scan(this);
|
||||
assert(expr_);
|
||||
}
|
||||
|
||||
ivl_expr_t cur = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
assert(cur);
|
||||
|
||||
cur->type_ = IVL_EX_MEMORY;
|
||||
cur->value_ = IVL_VT_VECTOR;
|
||||
cur->width_= net->expr_width();
|
||||
cur->signed_ = net->has_sign()? 1 : 0;
|
||||
cur->u_.memory_.mem_ = find_memory(des_, net->memory());
|
||||
cur->u_.memory_.idx_ = expr_;
|
||||
|
||||
expr_ = cur;
|
||||
}
|
||||
|
||||
void dll_target::expr_const(const NetEConst*net)
|
||||
{
|
||||
assert(expr_ == 0);
|
||||
|
|
@ -410,8 +389,19 @@ void dll_target::expr_ternary(const NetETernary*net)
|
|||
|
||||
void dll_target::expr_signal(const NetESignal*net)
|
||||
{
|
||||
ivl_signal_t sig = find_signal(des_, net->sig());
|
||||
|
||||
assert(expr_ == 0);
|
||||
|
||||
/* If there is a word expression, generate it. */
|
||||
ivl_expr_t word_expr = 0;
|
||||
if (const NetExpr*word = net->word_index()) {
|
||||
word->expr_scan(this);
|
||||
assert(expr_);
|
||||
word_expr = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
|
||||
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
assert(expr_);
|
||||
|
||||
|
|
@ -419,7 +409,18 @@ void dll_target::expr_signal(const NetESignal*net)
|
|||
expr_->value_= net->expr_type();
|
||||
expr_->width_= net->expr_width();
|
||||
expr_->signed_ = net->has_sign()? 1 : 0;
|
||||
expr_->u_.signal_.sig = find_signal(des_, net->sig());
|
||||
expr_->u_.signal_.word = word_expr;
|
||||
expr_->u_.signal_.sig = sig;
|
||||
|
||||
/* Make account for the special case that this is a reference
|
||||
to an array as a whole. We detect this case by noting that
|
||||
this is an array (more then 1 word) and there is no word
|
||||
select expression. In that case, this is an IVL_EX_ARRAY
|
||||
expression instead of a SIGNAL expression. */
|
||||
if (sig->array_words > 1 && word_expr == 0) {
|
||||
expr_->type_ = IVL_EX_ARRAY;
|
||||
expr_->width_ = 0; // Doesn't make much sense for arrays.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -473,6 +474,12 @@ void dll_target::expr_unary(const NetEUnary*net)
|
|||
|
||||
/*
|
||||
* $Log: t-dll-expr.cc,v $
|
||||
* Revision 1.44 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.43 2005/09/14 02:53:15 steve
|
||||
* Support bool expressions and compares handle them optimally.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.68 2006/02/02 02:43:59 steve Exp $"
|
||||
#ident "$Id: t-dll-proc.cc,v 1.69 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -171,30 +171,21 @@ void dll_target::make_assign_lvals_(const NetAssignBase*net)
|
|||
cur->n.sig = find_signal(des_, asn->sig());
|
||||
|
||||
cur->idx = 0;
|
||||
if (asn->bmux()) {
|
||||
// If there is a word select expression, it is
|
||||
// really an array index.
|
||||
if (asn->word()) {
|
||||
assert(expr_ == 0);
|
||||
asn->bmux()->expr_scan(this);
|
||||
asn->word()->expr_scan(this);
|
||||
|
||||
if (cur->n.sig->lsb_index != 0)
|
||||
sub_off_from_expr_(asn->sig()->lsb());
|
||||
if (cur->n.sig->lsb_dist != 1)
|
||||
mul_expr_by_const_(cur->n.sig->lsb_dist);
|
||||
|
||||
cur->type_ = IVL_LVAL_MUX;
|
||||
cur->type_ = IVL_LVAL_ARR;
|
||||
cur->idx = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
} else if (asn->mem()) {
|
||||
assert(asn->mem());
|
||||
cur->type_ = IVL_LVAL_MEM;
|
||||
cur->n.mem = find_memory(des_, asn->mem());
|
||||
assert(cur->n.mem);
|
||||
cur->width_ = ivl_memory_width(cur->n.mem);
|
||||
|
||||
assert(expr_ == 0);
|
||||
asn->bmux()->expr_scan(this);
|
||||
cur->idx = expr_;
|
||||
expr_ = 0;
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
|
|
@ -741,6 +732,12 @@ void dll_target::proc_while(const NetWhile*net)
|
|||
|
||||
/*
|
||||
* $Log: t-dll-proc.cc,v $
|
||||
* Revision 1.69 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.68 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
|
|
|||
181
t-dll.cc
181
t-dll.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.cc,v 1.161 2006/11/10 05:44:45 steve Exp $"
|
||||
#ident "$Id: t-dll.cc,v 1.162 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -242,27 +242,6 @@ ivl_signal_t dll_target::find_signal(ivl_design_s &des, const NetNet*net)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function locates an ivl_memory_t object that matches the
|
||||
* NetMemory object. The search works by looking for the parent scope,
|
||||
* then scanning the parent scope for the NetMemory object.
|
||||
*/
|
||||
ivl_memory_t dll_target::find_memory(ivl_design_s &des, const NetMemory*net)
|
||||
{
|
||||
ivl_scope_t scope = find_scope(des, net->scope());
|
||||
assert(scope);
|
||||
|
||||
const char*nname = net->name();
|
||||
|
||||
for (unsigned idx = 0 ; idx < scope->nmem_ ; idx += 1) {
|
||||
if (strcmp(scope->mem_[idx]->basename_, nname) == 0)
|
||||
return scope->mem_[idx];
|
||||
}
|
||||
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ivl_nexus_t nexus_sig_make(ivl_signal_t net, unsigned pin)
|
||||
{
|
||||
ivl_nexus_t tmp = new struct ivl_nexus_s;
|
||||
|
|
@ -417,14 +396,6 @@ static void scope_add_lpm(ivl_scope_t scope, ivl_lpm_t net)
|
|||
}
|
||||
}
|
||||
|
||||
static void scope_add_mem(ivl_scope_t scope, ivl_memory_t net)
|
||||
{
|
||||
scope->nmem_ += 1;
|
||||
scope->mem_ = (ivl_memory_t*)
|
||||
realloc(scope->mem_, scope->nmem_*sizeof(ivl_memory_t));
|
||||
scope->mem_[scope->nmem_-1] = net;
|
||||
}
|
||||
|
||||
ivl_parameter_t dll_target::scope_find_param(ivl_scope_t scope,
|
||||
const char*name)
|
||||
{
|
||||
|
|
@ -1186,20 +1157,6 @@ void dll_target::udp(const NetUDP*net)
|
|||
scope_add_logic(scope, obj);
|
||||
}
|
||||
|
||||
void dll_target::memory(const NetMemory*net)
|
||||
{
|
||||
ivl_memory_t obj = new struct ivl_memory_s;
|
||||
|
||||
obj->scope_ = find_scope(des_, net->scope());
|
||||
obj->basename_ = net->name();
|
||||
obj->width_ = net->width();
|
||||
obj->signed_ = 0;
|
||||
obj->size_ = net->count();
|
||||
obj->root_ = -net->index_to_address(0);
|
||||
|
||||
scope_add_mem(obj->scope_, obj);
|
||||
}
|
||||
|
||||
void dll_target::lpm_add_sub(const NetAddSub*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
|
|
@ -1252,6 +1209,35 @@ void dll_target::lpm_add_sub(const NetAddSub*net)
|
|||
scope_add_lpm(obj->scope, obj);
|
||||
}
|
||||
|
||||
bool dll_target::lpm_array_dq(const NetArrayDq*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_ARRAY;
|
||||
obj->name = net->name();
|
||||
obj->u_.array.sig = find_signal(des_, net->mem());
|
||||
assert(obj->u_.array.sig);
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
obj->width = net->width();
|
||||
obj->u_.array.swid = net->awidth();
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
|
||||
const Nexus*nex;
|
||||
|
||||
nex = net->pin_Address().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.array.a = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.array.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
nex = net->pin_Result().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.array.q = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.array.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The lpm_clshift device represents both left and right shifts,
|
||||
* depending on what is connected to the Direction pin. We convert
|
||||
|
|
@ -1578,73 +1564,6 @@ void dll_target::lpm_ff(const NetFF*net)
|
|||
|
||||
}
|
||||
|
||||
void dll_target::lpm_ram_dq(const NetRamDq*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_RAM;
|
||||
obj->name = net->name();
|
||||
obj->u_.ff.mem = find_memory(des_, net->mem());
|
||||
assert(obj->u_.ff.mem);
|
||||
obj->scope = find_scope(des_, net->mem()->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->width = net->width();
|
||||
obj->u_.ff.swid = net->awidth();
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
|
||||
const Nexus*nex;
|
||||
|
||||
// A write port is present only if something is connected to
|
||||
// the clock input.
|
||||
|
||||
bool has_write_port = net->pin_InClock().is_linked();
|
||||
|
||||
// Connect the write clock and write enable
|
||||
|
||||
if (has_write_port) {
|
||||
nex = net->pin_InClock().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.clk = (ivl_nexus_t) nex->t_cookie();
|
||||
assert(obj->u_.ff.clk);
|
||||
nexus_lpm_add(obj->u_.ff.clk, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
nex = net->pin_WE().nexus();
|
||||
if (nex && nex->t_cookie()) {
|
||||
obj->u_.ff.we = (ivl_nexus_t) nex->t_cookie();
|
||||
assert(obj->u_.ff.we);
|
||||
nexus_lpm_add(obj->u_.ff.we, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
else
|
||||
obj->u_.ff.we = 0x0;
|
||||
}
|
||||
else {
|
||||
obj->u_.ff.clk = 0x0;
|
||||
obj->u_.ff.we = 0x0;
|
||||
}
|
||||
|
||||
// Connect the address bus
|
||||
|
||||
nex = net->pin_Address().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.s.pin = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.ff.s.pin, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
// Connect the data busses
|
||||
|
||||
nex = net->pin_Q().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.q.pin = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.ff.q.pin, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
if (has_write_port) {
|
||||
nex = net->pin_Data().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.d.pin = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.ff.d.pin, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Make the NetMult object into an IVL_LPM_MULT node.
|
||||
*/
|
||||
|
|
@ -2192,18 +2111,32 @@ void dll_target::signal(const NetNet*net)
|
|||
t_cookie of the Nexus object so that I find it again when I
|
||||
next encounter the nexus. */
|
||||
|
||||
const Nexus*nex = net->pin(0).nexus();
|
||||
if (nex->t_cookie()) {
|
||||
obj->pin_ = (ivl_nexus_t)nex->t_cookie();
|
||||
nexus_sig_add(obj->pin_, obj, 0);
|
||||
obj->array_base = net->array_first();
|
||||
obj->array_words = net->array_count();
|
||||
if (obj->array_words > 1)
|
||||
obj->pins = new ivl_nexus_t[obj->array_words];
|
||||
|
||||
} else {
|
||||
ivl_nexus_t tmp = nexus_sig_make(obj, 0);
|
||||
tmp->name_ = strings_.add(nex->name());
|
||||
nex->t_cookie(tmp);
|
||||
obj->pin_ = tmp;
|
||||
for (unsigned idx = 0 ; idx < obj->array_words ; idx += 1) {
|
||||
|
||||
const Nexus*nex = net->pin(idx).nexus();
|
||||
if (nex->t_cookie()) {
|
||||
if (obj->array_words > 1) {
|
||||
obj->pins[idx] = (ivl_nexus_t)nex->t_cookie();
|
||||
nexus_sig_add(obj->pins[idx], obj, idx);
|
||||
} else {
|
||||
obj->pin = (ivl_nexus_t)nex->t_cookie();
|
||||
nexus_sig_add(obj->pin, obj, idx);
|
||||
}
|
||||
} else {
|
||||
ivl_nexus_t tmp = nexus_sig_make(obj, idx);
|
||||
tmp->name_ = strings_.add(nex->name());
|
||||
nex->t_cookie(tmp);
|
||||
if (obj->array_words > 1)
|
||||
obj->pins[idx] = tmp;
|
||||
else
|
||||
obj->pin = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool dll_target::signal_paths(const NetNet*net)
|
||||
|
|
@ -2258,6 +2191,12 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
|
|||
|
||||
/*
|
||||
* $Log: t-dll.cc,v $
|
||||
* Revision 1.162 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.161 2006/11/10 05:44:45 steve
|
||||
* Process delay paths in second path over signals.
|
||||
*
|
||||
|
|
|
|||
40
t-dll.h
40
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.134 2006/11/10 05:44:45 steve Exp $"
|
||||
#ident "$Id: t-dll.h,v 1.135 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
|
|
@ -74,6 +74,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
void net_case_cmp(const NetCaseCmp*);
|
||||
void udp(const NetUDP*);
|
||||
void lpm_add_sub(const NetAddSub*);
|
||||
bool lpm_array_dq(const NetArrayDq*);
|
||||
void lpm_clshift(const NetCLShift*);
|
||||
void lpm_compare(const NetCompare*);
|
||||
void lpm_divide(const NetDivide*);
|
||||
|
|
@ -81,7 +82,6 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
void lpm_modulo(const NetModulo*);
|
||||
void lpm_mult(const NetMult*);
|
||||
void lpm_mux(const NetMux*);
|
||||
void lpm_ram_dq(const NetRamDq*);
|
||||
bool concat(const NetConcat*);
|
||||
bool part_select(const NetPartSelect*);
|
||||
bool replicate(const NetReplicate*);
|
||||
|
|
@ -97,8 +97,6 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
void scope(const NetScope*);
|
||||
void signal(const NetNet*);
|
||||
bool signal_paths(const NetNet*);
|
||||
void memory(const NetMemory*);
|
||||
|
||||
ivl_dll_t dll_;
|
||||
|
||||
ivl_design_s des_;
|
||||
|
|
@ -134,7 +132,6 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
struct ivl_expr_s*expr_;
|
||||
void expr_binary(const NetEBinary*);
|
||||
void expr_concat(const NetEConcat*);
|
||||
void expr_memory(const NetEMemory*);
|
||||
void expr_const(const NetEConst*);
|
||||
void expr_creal(const NetECReal*);
|
||||
void expr_param(const NetEConstParam*);
|
||||
|
|
@ -157,8 +154,6 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
|
||||
static ivl_scope_t find_scope(ivl_design_s &des, const NetScope*cur);
|
||||
static ivl_signal_t find_signal(ivl_design_s &des, const NetNet*net);
|
||||
static ivl_memory_t find_memory(ivl_design_s &des, const NetMemory*net);
|
||||
|
||||
static ivl_parameter_t scope_find_param(ivl_scope_t scope,
|
||||
const char*name);
|
||||
|
||||
|
|
@ -231,6 +226,7 @@ struct ivl_expr_s {
|
|||
|
||||
struct {
|
||||
ivl_signal_t sig;
|
||||
ivl_expr_t word;
|
||||
} signal_;
|
||||
|
||||
struct {
|
||||
|
|
@ -294,7 +290,6 @@ struct ivl_lpm_s {
|
|||
|
||||
union {
|
||||
struct ivl_lpm_ff_s {
|
||||
unsigned swid; // ram only
|
||||
ivl_nexus_t clk;
|
||||
ivl_nexus_t we;
|
||||
ivl_nexus_t aclr;
|
||||
|
|
@ -309,11 +304,6 @@ struct ivl_lpm_s {
|
|||
ivl_nexus_t*pins;
|
||||
ivl_nexus_t pin;
|
||||
} d;
|
||||
union { // ram only
|
||||
ivl_nexus_t*pins;
|
||||
ivl_nexus_t pin;
|
||||
} s;
|
||||
ivl_memory_t mem; // ram only
|
||||
ivl_expr_t aset_value;
|
||||
ivl_expr_t sset_value;
|
||||
} ff;
|
||||
|
|
@ -336,6 +326,12 @@ struct ivl_lpm_s {
|
|||
ivl_nexus_t q, a, b;
|
||||
} arith;
|
||||
|
||||
struct ivl_lpm_array_s {
|
||||
ivl_signal_t sig;
|
||||
unsigned swid;
|
||||
ivl_nexus_t q, a;
|
||||
} array;
|
||||
|
||||
struct ivl_concat_s {
|
||||
unsigned inputs;
|
||||
ivl_nexus_t*pins;
|
||||
|
|
@ -380,8 +376,9 @@ struct ivl_lpm_s {
|
|||
enum ivl_lval_type_t {
|
||||
IVL_LVAL_REG = 0,
|
||||
IVL_LVAL_MUX = 1,
|
||||
IVL_LVAL_MEM = 2,
|
||||
IVL_LVAL_NET = 3 /* Only force can have NET l-values */
|
||||
IVL_LVAL_MEM = 2, /* Deprecated in favor of LVAL_ARR? */
|
||||
IVL_LVAL_NET = 3, /* Only force can have NET l-values */
|
||||
IVL_LVAL_ARR = 4
|
||||
};
|
||||
|
||||
struct ivl_lval_s {
|
||||
|
|
@ -589,7 +586,12 @@ struct ivl_signal_s {
|
|||
perm_string name_;
|
||||
ivl_scope_t scope_;
|
||||
|
||||
ivl_nexus_t pin_;
|
||||
unsigned array_words;
|
||||
int array_base;
|
||||
union {
|
||||
ivl_nexus_t pin;
|
||||
ivl_nexus_t*pins;
|
||||
};
|
||||
|
||||
ivl_delaypath_s*path;
|
||||
unsigned npath;
|
||||
|
|
@ -680,6 +682,12 @@ struct ivl_statement_s {
|
|||
|
||||
/*
|
||||
* $Log: t-dll.h,v $
|
||||
* Revision 1.135 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.134 2006/11/10 05:44:45 steve
|
||||
* Process delay paths in second path over signals.
|
||||
*
|
||||
|
|
|
|||
36
target.cc
36
target.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: target.cc,v 1.79 2006/11/10 05:44:45 steve Exp $"
|
||||
#ident "$Id: target.cc,v 1.80 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -45,13 +45,6 @@ bool target_t::signal_paths(const NetNet*)
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void target_t::memory(const NetMemory*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled memory." << endl;
|
||||
}
|
||||
|
||||
bool target_t::func_def(const NetScope*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
|
|
@ -97,6 +90,13 @@ void target_t::lpm_add_sub(const NetAddSub*)
|
|||
"Unhandled NetAddSub." << endl;
|
||||
}
|
||||
|
||||
bool target_t::lpm_array_dq(const NetArrayDq*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetArrayDq." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
void target_t::lpm_clshift(const NetCLShift*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
|
|
@ -138,13 +138,6 @@ void target_t::lpm_mux(const NetMux*)
|
|||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetMux." << endl;
|
||||
}
|
||||
|
||||
void target_t::lpm_ram_dq(const NetRamDq*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetRamDq." << endl;
|
||||
}
|
||||
|
||||
bool target_t::concat(const NetConcat*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
|
|
@ -380,13 +373,6 @@ void expr_scan_t::expr_concat(const NetEConcat*that)
|
|||
cerr << that->get_line() << ": expr_scan_t (" <<
|
||||
typeid(*this).name() << "): unhandled expr_concat." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_memory(const NetEMemory*)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
"unhandled expr_memory." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_event(const NetEEvent*)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
|
|
@ -443,6 +429,12 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
|
|||
|
||||
/*
|
||||
* $Log: target.cc,v $
|
||||
* Revision 1.80 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.79 2006/11/10 05:44:45 steve
|
||||
* Process delay paths in second path over signals.
|
||||
*
|
||||
|
|
|
|||
14
target.h
14
target.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: target.h,v 1.76 2006/11/10 05:44:45 steve Exp $"
|
||||
#ident "$Id: target.h,v 1.77 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
|
@ -66,15 +66,13 @@ struct target_t {
|
|||
virtual void signal(const NetNet*) =0;
|
||||
virtual bool signal_paths(const NetNet*);
|
||||
|
||||
/* Output a memory (called for each memory object) */
|
||||
virtual void memory(const NetMemory*);
|
||||
|
||||
/* Output a defined task. */
|
||||
virtual void task_def(const NetScope*);
|
||||
virtual bool func_def(const NetScope*);
|
||||
|
||||
/* LPM style components are handled here. */
|
||||
virtual void lpm_add_sub(const NetAddSub*);
|
||||
virtual bool lpm_array_dq(const NetArrayDq*);
|
||||
virtual void lpm_clshift(const NetCLShift*);
|
||||
virtual void lpm_compare(const NetCompare*);
|
||||
virtual void lpm_divide(const NetDivide*);
|
||||
|
|
@ -82,7 +80,6 @@ struct target_t {
|
|||
virtual void lpm_ff(const NetFF*);
|
||||
virtual void lpm_mult(const NetMult*);
|
||||
virtual void lpm_mux(const NetMux*);
|
||||
virtual void lpm_ram_dq(const NetRamDq*);
|
||||
|
||||
virtual bool concat(const NetConcat*);
|
||||
virtual bool part_select(const NetPartSelect*);
|
||||
|
|
@ -139,7 +136,6 @@ struct expr_scan_t {
|
|||
virtual void expr_rparam(const NetECRealParam*);
|
||||
virtual void expr_creal(const NetECReal*);
|
||||
virtual void expr_concat(const NetEConcat*);
|
||||
virtual void expr_memory(const NetEMemory*);
|
||||
virtual void expr_event(const NetEEvent*);
|
||||
virtual void expr_scope(const NetEScope*);
|
||||
virtual void expr_select(const NetESelect*);
|
||||
|
|
@ -172,6 +168,12 @@ extern const struct target *target_table[];
|
|||
|
||||
/*
|
||||
* $Log: target.h,v $
|
||||
* Revision 1.77 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.76 2006/11/10 05:44:45 steve
|
||||
* Process delay paths in second path over signals.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.17 2006/10/30 22:45:37 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.18 2007/01/16 05:44:16 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -52,7 +52,7 @@ dep:
|
|||
$(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
O = stub.o memory.o statement.o
|
||||
O = stub.o expression.o memory.o statement.o
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
TGTLDFLAGS=-L.. -livl
|
||||
|
|
|
|||
|
|
@ -0,0 +1,273 @@
|
|||
/*
|
||||
* Copyright (c) 2007 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: expression.c,v 1.1 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "priv.h"
|
||||
# include <stdlib.h>
|
||||
# include <inttypes.h>
|
||||
# include <assert.h>
|
||||
|
||||
static const char*vt_type_string(ivl_expr_t net)
|
||||
{
|
||||
return data_type_string(ivl_expr_value(net));
|
||||
}
|
||||
|
||||
static void show_array_expression(ivl_expr_t net, unsigned ind)
|
||||
{
|
||||
ivl_signal_t sig = ivl_expr_signal(net);
|
||||
const char*name = ivl_signal_basename(sig);
|
||||
unsigned width = ivl_signal_width(sig);
|
||||
const char*vt = vt_type_string(net);
|
||||
|
||||
fprintf(out, "%*sArray: %s, word_count=%u, width=%u, type=%s\n",
|
||||
ind, "", name, ivl_signal_array_count(sig), width, vt);
|
||||
}
|
||||
|
||||
static void show_binary_expression(ivl_expr_t net, unsigned ind)
|
||||
{
|
||||
unsigned width = ivl_expr_width(net);
|
||||
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
|
||||
const char*vt = vt_type_string(net);
|
||||
|
||||
fprintf(out, "%*s<\"%c\" width=%u, %s, type=%s>\n", ind, "",
|
||||
ivl_expr_opcode(net), width, sign, vt);
|
||||
show_expression(ivl_expr_oper1(net), ind+3);
|
||||
show_expression(ivl_expr_oper2(net), ind+3);
|
||||
|
||||
switch (ivl_expr_opcode(net)) {
|
||||
|
||||
case '*':
|
||||
/* The width of multiply expressions is the sum of the
|
||||
widths of the operands. This is slightly different
|
||||
from the way the Verilog standard does it, but allows
|
||||
us to keep operands smaller. */
|
||||
width = ivl_expr_width(ivl_expr_oper1(net));
|
||||
width += ivl_expr_width(ivl_expr_oper2(net));
|
||||
if (ivl_expr_width(net) != width) {
|
||||
fprintf(out, "%*sERROR: Result width incorrect\n",
|
||||
ind+3, "");
|
||||
stub_errors += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void show_function_call(ivl_expr_t net, unsigned ind)
|
||||
{
|
||||
ivl_scope_t def = ivl_expr_def(net);
|
||||
const char*vt = vt_type_string(net);
|
||||
|
||||
fprintf(out, "%*s<%s function %s>\n", ind, "",
|
||||
vt, ivl_scope_name(def));
|
||||
}
|
||||
|
||||
static void show_memory_expression(ivl_expr_t net, unsigned ind)
|
||||
{
|
||||
unsigned width = ivl_expr_width(net);
|
||||
|
||||
fprintf(out, "%*s<memory width=%u>\n", ind, "",
|
||||
width);
|
||||
}
|
||||
|
||||
static void show_signal_expression(ivl_expr_t net, unsigned ind)
|
||||
{
|
||||
unsigned width = ivl_expr_width(net);
|
||||
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
|
||||
const char*vt = vt_type_string(net);
|
||||
ivl_expr_t word = ivl_expr_oper1(net);
|
||||
|
||||
ivl_signal_t sig = ivl_expr_signal(net);
|
||||
unsigned word_count = ivl_signal_array_count(sig);
|
||||
|
||||
fprintf(out, "%*s<signal=%s, words=%u, width=%u, %s type=%s>\n", ind, "",
|
||||
ivl_expr_name(net), word_count, width, sign, vt);
|
||||
|
||||
/* If the expression refers to a signal array, then there must
|
||||
also be a word select expression, and if the signal is not an
|
||||
array, there must NOT be a word expression. */
|
||||
if (word_count == 1 && word != 0) {
|
||||
fprintf(out, "%*sERROR: Unexpected word expression\n", ind+2, "");
|
||||
stub_errors += 1;
|
||||
}
|
||||
if (word_count > 1 && word == 0) {
|
||||
fprintf(out, "%*sERROR: Missing word expression\n", ind+2, "");
|
||||
stub_errors += 1;
|
||||
}
|
||||
|
||||
if (word != 0) {
|
||||
fprintf(out, "%*sAddress-0 word address:\n", ind+2, "");
|
||||
show_expression(word, ind+2);
|
||||
}
|
||||
}
|
||||
|
||||
static void show_ternary_expression(ivl_expr_t net, unsigned ind)
|
||||
{
|
||||
unsigned width = ivl_expr_width(net);
|
||||
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
|
||||
|
||||
fprintf(out, "%*s<ternary width=%u, %s>\n", ind, "", width, sign);
|
||||
show_expression(ivl_expr_oper1(net), ind+4);
|
||||
show_expression(ivl_expr_oper2(net), ind+4);
|
||||
show_expression(ivl_expr_oper3(net), ind+4);
|
||||
|
||||
if (ivl_expr_width(ivl_expr_oper2(net)) != width) {
|
||||
fprintf(out, "ERROR: Width of TRUE expressions is %u, not %u\n",
|
||||
ivl_expr_width(ivl_expr_oper2(net)), width);
|
||||
stub_errors += 1;
|
||||
}
|
||||
|
||||
if (ivl_expr_width(ivl_expr_oper3(net)) != width) {
|
||||
fprintf(out, "ERROR: Width of FALSE expressions is %u, not %u\n",
|
||||
ivl_expr_width(ivl_expr_oper3(net)), width);
|
||||
stub_errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void show_expression(ivl_expr_t net, unsigned ind)
|
||||
{
|
||||
unsigned idx;
|
||||
const ivl_expr_type_t code = ivl_expr_type(net);
|
||||
ivl_parameter_t par = ivl_expr_parameter(net);
|
||||
unsigned width = ivl_expr_width(net);
|
||||
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
|
||||
const char*vt = vt_type_string(net);
|
||||
|
||||
switch (code) {
|
||||
|
||||
case IVL_EX_ARRAY:
|
||||
show_array_expression(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_EX_BINARY:
|
||||
show_binary_expression(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_EX_CONCAT:
|
||||
fprintf(out, "%*s<concat repeat=%u, width=%u, %s, type=%s>\n",
|
||||
ind, "", ivl_expr_repeat(net), width, sign, vt);
|
||||
for (idx = 0 ; idx < ivl_expr_parms(net) ; idx += 1)
|
||||
show_expression(ivl_expr_parm(net, idx), ind+3);
|
||||
|
||||
break;
|
||||
|
||||
case IVL_EX_MEMORY:
|
||||
show_memory_expression(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_EX_NUMBER: {
|
||||
const char*bits = ivl_expr_bits(net);
|
||||
|
||||
fprintf(out, "%*s<number=%u'b", ind, "", width);
|
||||
for (idx = width ; idx > 0 ; idx -= 1)
|
||||
fprintf(out, "%c", bits[idx-1]);
|
||||
|
||||
fprintf(out, ", %s %s", sign, vt);
|
||||
if (par != 0)
|
||||
fprintf(out, ", parameter=%s",
|
||||
ivl_parameter_basename(par));
|
||||
|
||||
fprintf(out, ">\n");
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_EX_SELECT:
|
||||
/* The SELECT expression can be used to express part
|
||||
select, or if the base is null vector extension. */
|
||||
if (ivl_expr_oper2(net)) {
|
||||
fprintf(out, "%*s<select: width=%u, %s>\n", ind, "",
|
||||
width, sign);
|
||||
show_expression(ivl_expr_oper1(net), ind+3);
|
||||
show_expression(ivl_expr_oper2(net), ind+3);
|
||||
} else {
|
||||
fprintf(out, "%*s<expr pad: width=%u, %s>\n", ind, "",
|
||||
width, sign);
|
||||
show_expression(ivl_expr_oper1(net), ind+3);
|
||||
}
|
||||
break;
|
||||
|
||||
case IVL_EX_STRING:
|
||||
fprintf(out, "%*s<string=\"%s\", width=%u", ind, "",
|
||||
ivl_expr_string(net), ivl_expr_width(net));
|
||||
if (par != 0)
|
||||
fprintf(out, ", parameter=%s",
|
||||
ivl_parameter_basename(par));
|
||||
|
||||
fprintf(out, ">\n");
|
||||
break;
|
||||
|
||||
case IVL_EX_SFUNC:
|
||||
fprintf(out, "%*s<function=\"%s\", width=%u, %s, type=%s>\n",
|
||||
ind, "", ivl_expr_name(net), width, sign, vt);
|
||||
{ unsigned cnt = ivl_expr_parms(net);
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < cnt ; idx += 1)
|
||||
show_expression(ivl_expr_parm(net, idx), ind+3);
|
||||
}
|
||||
break;
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
show_signal_expression(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_EX_TERNARY:
|
||||
show_ternary_expression(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_EX_UNARY:
|
||||
fprintf(out, "%*s<unary \"%c\" width=%u, %s>\n", ind, "",
|
||||
ivl_expr_opcode(net), width, sign);
|
||||
show_expression(ivl_expr_oper1(net), ind+4);
|
||||
break;
|
||||
|
||||
case IVL_EX_UFUNC:
|
||||
show_function_call(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_EX_REALNUM:
|
||||
{
|
||||
int idx;
|
||||
union foo {
|
||||
double rv;
|
||||
unsigned char bv[sizeof(double)];
|
||||
} tmp;
|
||||
tmp.rv = ivl_expr_dvalue(net);
|
||||
fprintf(out, "%*s<realnum=%f (", ind, "", tmp.rv);
|
||||
for (idx = sizeof(double) ; idx > 0 ; idx -= 1)
|
||||
fprintf(out, "%02x", tmp.bv[idx-1]);
|
||||
fprintf(out, ")");
|
||||
if (par != 0)
|
||||
fprintf(out, ", parameter=%s",
|
||||
ivl_parameter_basename(par));
|
||||
|
||||
fprintf(out, ">\n");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(out, "%*s<expr_type=%u>\n", ind, "", code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: priv.h,v 1.3 2005/03/05 05:47:42 steve Exp $"
|
||||
#ident "$Id: priv.h,v 1.4 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <ivl_target.h>
|
||||
|
|
@ -47,3 +47,6 @@ extern void show_memory(ivl_memory_t mem);
|
|||
*/
|
||||
extern void show_statement(ivl_statement_t net, unsigned ind);
|
||||
|
||||
/*
|
||||
*/
|
||||
extern const char*data_type_string(ivl_variable_type_t vtype);
|
||||
|
|
|
|||
|
|
@ -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.10 2006/08/08 05:11:37 steve Exp $"
|
||||
#ident "$Id: statement.c,v 1.11 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -56,12 +56,30 @@ static unsigned show_assign_lval(ivl_lval_t lval, unsigned ind)
|
|||
|
||||
} else {
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
assert(sig);
|
||||
|
||||
fprintf(out, "%*s{name=%s width=%u lvwidth=%u}\n",
|
||||
ind, "",
|
||||
ivl_signal_name(sig),
|
||||
ivl_signal_width(sig),
|
||||
ivl_lval_width(lval));
|
||||
|
||||
if (ivl_lval_idx(lval)) {
|
||||
fprintf(out, "%*sAddress-0 select expression:\n", ind+4, "");
|
||||
show_expression(ivl_lval_idx(lval), ind+6);
|
||||
if (ivl_signal_array_count(sig) <= 1) {
|
||||
fprintf(out, "%*sERROR: Address on signal with "
|
||||
"word count=%u\n", ind+4, "",
|
||||
ivl_signal_array_count(sig));
|
||||
stub_errors += 1;
|
||||
}
|
||||
} else if (ivl_signal_array_count(sig) > 1) {
|
||||
fprintf(out, "%*sERROR: Address missing on signal with "
|
||||
"word count=%u\n", ind+4, "",
|
||||
ivl_signal_array_count(sig));
|
||||
stub_errors += 1;
|
||||
}
|
||||
|
||||
if (ivl_lval_mux(lval)) {
|
||||
fprintf(out, "%*sBit select expression:\n", ind+4, "");
|
||||
show_expression(ivl_lval_mux(lval), ind+8);
|
||||
|
|
|
|||
415
tgt-stub/stub.c
415
tgt-stub/stub.c
|
|
@ -17,9 +17,16 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: stub.c,v 1.142 2006/11/28 05:56:41 steve Exp $"
|
||||
#ident "$Id: stub.c,v 1.143 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is a sample target module. All this does is write to the
|
||||
* output file some information about each object handle when each of
|
||||
* the various object functions is called. This can be used to
|
||||
* understand the behavior of the core as it uses a target module.
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
# include "priv.h"
|
||||
# include <stdlib.h>
|
||||
|
|
@ -127,213 +134,6 @@ const char*data_type_string(ivl_variable_type_t vtype)
|
|||
return vt;
|
||||
}
|
||||
|
||||
const char*vt_type_string(ivl_expr_t net)
|
||||
{
|
||||
return data_type_string(ivl_expr_value(net));
|
||||
}
|
||||
|
||||
void show_binary_expression(ivl_expr_t net, unsigned ind)
|
||||
{
|
||||
unsigned width = ivl_expr_width(net);
|
||||
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
|
||||
const char*vt = vt_type_string(net);
|
||||
|
||||
fprintf(out, "%*s<\"%c\" width=%u, %s, type=%s>\n", ind, "",
|
||||
ivl_expr_opcode(net), width, sign, vt);
|
||||
show_expression(ivl_expr_oper1(net), ind+3);
|
||||
show_expression(ivl_expr_oper2(net), ind+3);
|
||||
|
||||
switch (ivl_expr_opcode(net)) {
|
||||
|
||||
case '*':
|
||||
/* The width of multiply expressions is the sum of the
|
||||
widths of the operands. This is slightly different
|
||||
from the way the Verilog standard does it, but allows
|
||||
us to keep operands smaller. */
|
||||
width = ivl_expr_width(ivl_expr_oper1(net));
|
||||
width += ivl_expr_width(ivl_expr_oper2(net));
|
||||
if (ivl_expr_width(net) != width) {
|
||||
fprintf(out, "%*sERROR: Result width incorrect\n",
|
||||
ind+3, "");
|
||||
stub_errors += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void show_function_call(ivl_expr_t net, unsigned ind)
|
||||
{
|
||||
ivl_scope_t def = ivl_expr_def(net);
|
||||
const char*vt = vt_type_string(net);
|
||||
|
||||
fprintf(out, "%*s<%s function %s>\n", ind, "",
|
||||
vt, ivl_scope_name(def));
|
||||
}
|
||||
|
||||
void show_memory_expression(ivl_expr_t net, unsigned ind)
|
||||
{
|
||||
unsigned width = ivl_expr_width(net);
|
||||
|
||||
fprintf(out, "%*s<memory width=%u>\n", ind, "",
|
||||
width);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a sample target module. All this does is write to the
|
||||
* output file some information about each object handle when each of
|
||||
* the various object functions is called. This can be used to
|
||||
* understand the behavior of the core as it uses a target module.
|
||||
*/
|
||||
|
||||
void show_ternary_expression(ivl_expr_t net, unsigned ind)
|
||||
{
|
||||
unsigned width = ivl_expr_width(net);
|
||||
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
|
||||
|
||||
fprintf(out, "%*s<ternary width=%u, %s>\n", ind, "", width, sign);
|
||||
show_expression(ivl_expr_oper1(net), ind+4);
|
||||
show_expression(ivl_expr_oper2(net), ind+4);
|
||||
show_expression(ivl_expr_oper3(net), ind+4);
|
||||
|
||||
if (ivl_expr_width(ivl_expr_oper2(net)) != width) {
|
||||
fprintf(out, "ERROR: Width of TRUE expressions is %u, not %u\n",
|
||||
ivl_expr_width(ivl_expr_oper2(net)), width);
|
||||
stub_errors += 1;
|
||||
}
|
||||
|
||||
if (ivl_expr_width(ivl_expr_oper3(net)) != width) {
|
||||
fprintf(out, "ERROR: Width of FALSE expressions is %u, not %u\n",
|
||||
ivl_expr_width(ivl_expr_oper3(net)), width);
|
||||
stub_errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void show_expression(ivl_expr_t net, unsigned ind)
|
||||
{
|
||||
unsigned idx;
|
||||
const ivl_expr_type_t code = ivl_expr_type(net);
|
||||
ivl_parameter_t par = ivl_expr_parameter(net);
|
||||
unsigned width = ivl_expr_width(net);
|
||||
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
|
||||
const char*vt = vt_type_string(net);
|
||||
|
||||
switch (code) {
|
||||
|
||||
case IVL_EX_BINARY:
|
||||
show_binary_expression(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_EX_CONCAT:
|
||||
fprintf(out, "%*s<concat repeat=%u, width=%u, %s, type=%s>\n",
|
||||
ind, "", ivl_expr_repeat(net), width, sign, vt);
|
||||
for (idx = 0 ; idx < ivl_expr_parms(net) ; idx += 1)
|
||||
show_expression(ivl_expr_parm(net, idx), ind+3);
|
||||
|
||||
break;
|
||||
|
||||
case IVL_EX_MEMORY:
|
||||
show_memory_expression(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_EX_NUMBER: {
|
||||
const char*bits = ivl_expr_bits(net);
|
||||
|
||||
fprintf(out, "%*s<number=%u'b", ind, "", width);
|
||||
for (idx = width ; idx > 0 ; idx -= 1)
|
||||
fprintf(out, "%c", bits[idx-1]);
|
||||
|
||||
fprintf(out, ", %s %s", sign, vt);
|
||||
if (par != 0)
|
||||
fprintf(out, ", parameter=%s",
|
||||
ivl_parameter_basename(par));
|
||||
|
||||
fprintf(out, ">\n");
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_EX_SELECT:
|
||||
/* The SELECT expression can be used to express part
|
||||
select, or if the base is null vector extension. */
|
||||
if (ivl_expr_oper2(net)) {
|
||||
fprintf(out, "%*s<select: width=%u, %s>\n", ind, "",
|
||||
width, sign);
|
||||
show_expression(ivl_expr_oper1(net), ind+3);
|
||||
show_expression(ivl_expr_oper2(net), ind+3);
|
||||
} else {
|
||||
fprintf(out, "%*s<expr pad: width=%u, %s>\n", ind, "",
|
||||
width, sign);
|
||||
show_expression(ivl_expr_oper1(net), ind+3);
|
||||
}
|
||||
break;
|
||||
|
||||
case IVL_EX_STRING:
|
||||
fprintf(out, "%*s<string=\"%s\", width=%u", ind, "",
|
||||
ivl_expr_string(net), ivl_expr_width(net));
|
||||
if (par != 0)
|
||||
fprintf(out, ", parameter=%s",
|
||||
ivl_parameter_basename(par));
|
||||
|
||||
fprintf(out, ">\n");
|
||||
break;
|
||||
|
||||
case IVL_EX_SFUNC:
|
||||
fprintf(out, "%*s<function=\"%s\", width=%u, %s, type=%s>\n",
|
||||
ind, "", ivl_expr_name(net), width, sign, vt);
|
||||
{ unsigned cnt = ivl_expr_parms(net);
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < cnt ; idx += 1)
|
||||
show_expression(ivl_expr_parm(net, idx), ind+3);
|
||||
}
|
||||
break;
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
fprintf(out, "%*s<signal=%s, width=%u, %s type=%s>\n", ind, "",
|
||||
ivl_expr_name(net), width, sign, vt);
|
||||
break;
|
||||
|
||||
case IVL_EX_TERNARY:
|
||||
show_ternary_expression(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_EX_UNARY:
|
||||
fprintf(out, "%*s<unary \"%c\" width=%u, %s>\n", ind, "",
|
||||
ivl_expr_opcode(net), width, sign);
|
||||
show_expression(ivl_expr_oper1(net), ind+4);
|
||||
break;
|
||||
|
||||
case IVL_EX_UFUNC:
|
||||
show_function_call(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_EX_REALNUM:
|
||||
{
|
||||
int idx;
|
||||
union foo {
|
||||
double rv;
|
||||
unsigned char bv[sizeof(double)];
|
||||
} tmp;
|
||||
tmp.rv = ivl_expr_dvalue(net);
|
||||
fprintf(out, "%*s<realnum=%f (", ind, "", tmp.rv);
|
||||
for (idx = sizeof(double) ; idx > 0 ; idx -= 1)
|
||||
fprintf(out, "%02x", tmp.bv[idx-1]);
|
||||
fprintf(out, ")");
|
||||
if (par != 0)
|
||||
fprintf(out, ", parameter=%s",
|
||||
ivl_parameter_basename(par));
|
||||
|
||||
fprintf(out, ">\n");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(out, "%*s<expr_type=%u>\n", ind, "", code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The compare-like LPM nodes have input widths that match the
|
||||
* ivl_lpm_width() value, and an output width of 1. This function
|
||||
|
|
@ -388,6 +188,35 @@ static void show_lpm_add(ivl_lpm_t net)
|
|||
show_lpm_arithmetic_pins(net);
|
||||
}
|
||||
|
||||
static void show_lpm_array(ivl_lpm_t net)
|
||||
{
|
||||
ivl_nexus_t nex;
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
ivl_signal_t array = ivl_lpm_array(net);
|
||||
|
||||
fprintf(out, " LPM_ARRAY: <width=%u, signal=%s>\n",
|
||||
width, ivl_signal_basename(array));
|
||||
nex = ivl_lpm_q(net, 0);
|
||||
assert(nex);
|
||||
fprintf(out, " Q: %s\n", ivl_nexus_name(nex));
|
||||
nex = ivl_lpm_select(net);
|
||||
assert(nex);
|
||||
fprintf(out, " Address: %s (address width=%u)\n",
|
||||
ivl_nexus_name(nex), ivl_lpm_selects(net));
|
||||
|
||||
if (width_of_nexus(ivl_lpm_q(net,0)) != width) {
|
||||
fprintf(out, " ERROR: Data Q width doesn't match "
|
||||
"nexus width=%u\n", width_of_nexus(ivl_lpm_q(net,0)));
|
||||
stub_errors += 1;
|
||||
}
|
||||
|
||||
if (ivl_signal_width(array) != width) {
|
||||
fprintf(out, " ERROR: Data width doesn't match "
|
||||
"word width=%u\n", ivl_signal_width(array));
|
||||
stub_errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void show_lpm_divide(ivl_lpm_t net)
|
||||
{
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
|
|
@ -735,42 +564,6 @@ static void show_lpm_part_bi(ivl_lpm_t net)
|
|||
}
|
||||
|
||||
|
||||
static void show_lpm_ram(ivl_lpm_t net)
|
||||
{
|
||||
ivl_nexus_t nex;
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
ivl_memory_t mem = ivl_lpm_memory(net);
|
||||
|
||||
fprintf(out, " LPM_RAM: <width=%u>\n", width);
|
||||
nex = ivl_lpm_q(net, 0);
|
||||
assert(nex);
|
||||
fprintf(out, " Q: %s\n", ivl_nexus_name(nex));
|
||||
nex = ivl_lpm_select(net);
|
||||
fprintf(out, " Address: %s (address width=%u)\n",
|
||||
ivl_nexus_name(nex), ivl_lpm_selects(net));
|
||||
|
||||
|
||||
if (width_of_nexus(ivl_lpm_q(net,0)) != width) {
|
||||
fprintf(out, " ERROR: Data width doesn't match "
|
||||
"nexus width=%u\n", width_of_nexus(ivl_lpm_q(net,0)));
|
||||
stub_errors += 1;
|
||||
}
|
||||
|
||||
if (width_of_nexus(ivl_lpm_select(net)) != ivl_lpm_selects(net)) {
|
||||
fprintf(out, " ERROR: Width of address doesn't match "
|
||||
"nexus width=%u\n", width_of_nexus(ivl_lpm_select(net)));
|
||||
stub_errors += 1;
|
||||
}
|
||||
|
||||
/* The width of the port must match the width of the memory
|
||||
word. the compile assures that for us. */
|
||||
if (width != ivl_memory_width(mem)) {
|
||||
fprintf(out, " ERROR: Width doesn't match"
|
||||
" memory word width=%u\n", ivl_memory_width(mem));
|
||||
stub_errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The reduction operators have similar characteristics and are
|
||||
* displayed here.
|
||||
|
|
@ -983,6 +776,10 @@ static void show_lpm(ivl_lpm_t net)
|
|||
show_lpm_add(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_ARRAY:
|
||||
show_lpm_array(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_DIVIDE:
|
||||
show_lpm_divide(net);
|
||||
break;
|
||||
|
|
@ -1012,10 +809,6 @@ static void show_lpm(ivl_lpm_t net)
|
|||
show_lpm_concat(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_RAM:
|
||||
show_lpm_ram(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_RE_AND:
|
||||
case IVL_LPM_RE_NAND:
|
||||
case IVL_LPM_RE_NOR:
|
||||
|
|
@ -1203,6 +996,57 @@ static void signal_nexus_const(ivl_signal_t sig,
|
|||
}
|
||||
}
|
||||
|
||||
static void show_nexus_details(ivl_signal_t net, ivl_nexus_t nex)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
|
||||
ivl_net_const_t con;
|
||||
ivl_net_logic_t log;
|
||||
ivl_lpm_t lpm;
|
||||
ivl_signal_t sig;
|
||||
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
|
||||
|
||||
const char*dr0 = str_tab[ivl_nexus_ptr_drive0(ptr)];
|
||||
const char*dr1 = str_tab[ivl_nexus_ptr_drive1(ptr)];
|
||||
|
||||
if ((sig = ivl_nexus_ptr_sig(ptr))) {
|
||||
fprintf(out, " SIG %s word=%u (%s0, %s1)",
|
||||
ivl_signal_name(sig), ivl_nexus_ptr_pin(ptr), dr0, dr1);
|
||||
|
||||
if (ivl_signal_width(sig) != ivl_signal_width(net)) {
|
||||
fprintf(out, " (ERROR: Width=%u)",
|
||||
ivl_signal_width(sig));
|
||||
stub_errors += 1;
|
||||
}
|
||||
|
||||
if (ivl_signal_data_type(sig) != ivl_signal_data_type(net)) {
|
||||
fprintf(out, " (ERROR: data type mismatch)");
|
||||
stub_errors += 1;
|
||||
}
|
||||
|
||||
fprintf(out, "\n");
|
||||
|
||||
} else if ((log = ivl_nexus_ptr_log(ptr))) {
|
||||
fprintf(out, " LOG %s.%s[%u] (%s0, %s1)\n",
|
||||
ivl_scope_name(ivl_logic_scope(log)),
|
||||
ivl_logic_basename(log),
|
||||
ivl_nexus_ptr_pin(ptr), dr0, dr1);
|
||||
|
||||
} else if ((lpm = ivl_nexus_ptr_lpm(ptr))) {
|
||||
fprintf(out, " LPM %s.%s (%s0, %s1)\n",
|
||||
ivl_scope_name(ivl_lpm_scope(lpm)),
|
||||
ivl_lpm_basename(lpm), dr0, dr1);
|
||||
|
||||
} else if ((con = ivl_nexus_ptr_con(ptr))) {
|
||||
signal_nexus_const(net, ptr, con);
|
||||
|
||||
} else {
|
||||
fprintf(out, " ?[%u] (%s0, %s1)\n",
|
||||
ivl_nexus_ptr_pin(ptr), dr0, dr1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void show_signal(ivl_signal_t net)
|
||||
{
|
||||
|
|
@ -1268,68 +1112,19 @@ static void show_signal(ivl_signal_t net)
|
|||
break;
|
||||
}
|
||||
|
||||
nex = ivl_signal_nex(net);
|
||||
for (idx = 0 ; idx < ivl_signal_array_count(net) ; idx += 1) {
|
||||
|
||||
fprintf(out, " %s %s %s%s[%d:%d] %s <width=%u> nexus=%s\n",
|
||||
type, sign, port, data_type,
|
||||
ivl_signal_msb(net), ivl_signal_lsb(net),
|
||||
ivl_signal_basename(net), ivl_signal_width(net),
|
||||
ivl_nexus_name(nex));
|
||||
nex = ivl_signal_nex(net, idx);
|
||||
|
||||
fprintf(out, " %s %s %s%s[%d:%d] %s[word=%u, adr=%d] <width=%u> nexus=%s\n",
|
||||
type, sign, port, data_type,
|
||||
ivl_signal_msb(net), ivl_signal_lsb(net),
|
||||
ivl_signal_basename(net),
|
||||
idx, ivl_signal_array_base(net)+idx,
|
||||
ivl_signal_width(net),
|
||||
ivl_nexus_name(nex));
|
||||
|
||||
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
|
||||
ivl_net_const_t con;
|
||||
ivl_net_logic_t log;
|
||||
ivl_lpm_t lpm;
|
||||
ivl_signal_t sig;
|
||||
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
|
||||
|
||||
const char*dr0 = str_tab[ivl_nexus_ptr_drive0(ptr)];
|
||||
const char*dr1 = str_tab[ivl_nexus_ptr_drive1(ptr)];
|
||||
|
||||
if ((sig = ivl_nexus_ptr_sig(ptr))) {
|
||||
fprintf(out, " SIG %s (%s0, %s1)",
|
||||
ivl_signal_name(sig), dr0, dr1);
|
||||
|
||||
/* Only pin-0 of signals is used. If this is
|
||||
something other then pin-0, report an error. */
|
||||
if (ivl_nexus_ptr_pin(ptr) != 0) {
|
||||
fprintf(out, " (pin=%u, should be 0)",
|
||||
ivl_nexus_ptr_pin(ptr));
|
||||
stub_errors += 1;
|
||||
}
|
||||
|
||||
if (ivl_signal_width(sig) != ivl_signal_width(net)) {
|
||||
fprintf(out, " (ERROR: Width=%u)",
|
||||
ivl_signal_width(sig));
|
||||
stub_errors += 1;
|
||||
}
|
||||
|
||||
if (ivl_signal_data_type(sig) != ivl_signal_data_type(net)) {
|
||||
fprintf(out, " (ERROR: data type mismatch)");
|
||||
stub_errors += 1;
|
||||
}
|
||||
|
||||
fprintf(out, "\n");
|
||||
|
||||
} else if ((log = ivl_nexus_ptr_log(ptr))) {
|
||||
fprintf(out, " LOG %s.%s[%u] (%s0, %s1)\n",
|
||||
ivl_scope_name(ivl_logic_scope(log)),
|
||||
ivl_logic_basename(log),
|
||||
ivl_nexus_ptr_pin(ptr), dr0, dr1);
|
||||
|
||||
} else if ((lpm = ivl_nexus_ptr_lpm(ptr))) {
|
||||
fprintf(out, " LPM %s.%s (%s0, %s1)\n",
|
||||
ivl_scope_name(ivl_lpm_scope(lpm)),
|
||||
ivl_lpm_basename(lpm), dr0, dr1);
|
||||
|
||||
} else if ((con = ivl_nexus_ptr_con(ptr))) {
|
||||
signal_nexus_const(net, ptr, con);
|
||||
|
||||
} else {
|
||||
fprintf(out, " ?[%u] (%s0, %s1)\n",
|
||||
ivl_nexus_ptr_pin(ptr), dr0, dr1);
|
||||
}
|
||||
show_nexus_details(net, nex);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < ivl_signal_npath(net) ; idx += 1) {
|
||||
|
|
@ -1677,6 +1472,12 @@ int target_design(ivl_design_t des)
|
|||
|
||||
/*
|
||||
* $Log: stub.c,v $
|
||||
* Revision 1.143 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.142 2006/11/28 05:56:41 steve
|
||||
* Dump nand logic.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: draw_mux.c,v 1.13 2005/10/12 17:26:17 steve Exp $"
|
||||
#ident "$Id: draw_mux.c,v 1.14 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
|
|
@ -76,9 +76,9 @@ static void draw_lpm_mux_nest(ivl_lpm_t net, const char*muxz)
|
|||
|
||||
for (idx = 0 ; idx < (ivl_lpm_size(net) >> level); idx += 2) {
|
||||
fprintf(vvp_out, "L_%p/%d/%d .functor %s %u",
|
||||
net, width, level, muxz, idx);
|
||||
fprintf(vvp_out, ", L_%p/%d/%d", net, level-1, idx/2+0);
|
||||
fprintf(vvp_out, ", L_%p/%d/%d", net, level-1, idx/2+1);
|
||||
net, level, idx/2, muxz, width);
|
||||
fprintf(vvp_out, ", L_%p/%d/%d", net, level-1, idx+0);
|
||||
fprintf(vvp_out, ", L_%p/%d/%d", net, level-1, idx+1);
|
||||
fprintf(vvp_out, ", L_%p/%ds", net, level);
|
||||
fprintf(vvp_out, ", C4<>;\n");
|
||||
}
|
||||
|
|
@ -127,6 +127,12 @@ void draw_lpm_mux(ivl_lpm_t net)
|
|||
|
||||
/*
|
||||
* $Log: draw_mux.c,v $
|
||||
* Revision 1.14 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.13 2005/10/12 17:26:17 steve
|
||||
* MUX nodes get inputs from nets, not from net inputs,
|
||||
* Detect and draw alias nodes to reduce net size and
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: draw_ufunc.c,v 1.1 2005/07/13 04:52:31 steve Exp $"
|
||||
#ident "$Id: draw_ufunc.c,v 1.2 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
|
|
@ -32,10 +32,12 @@ static void function_argument_logic(ivl_signal_t port, ivl_expr_t exp)
|
|||
{
|
||||
struct vector_info res;
|
||||
|
||||
/* ports cannot be arrays. */
|
||||
assert(ivl_signal_array_count(port) == 1);
|
||||
|
||||
res = draw_eval_expr_wid(exp, ivl_signal_width(port), 0);
|
||||
assert(res.wid <= ivl_signal_width(port));
|
||||
fprintf(vvp_out, " %%set/v V_%s, %u, %u;\n",
|
||||
vvp_signal_label(port), res.base, res.wid);
|
||||
fprintf(vvp_out, " %%set/v v%p_0, %u, %u;\n", port, res.base, res.wid);
|
||||
|
||||
clr_vector(res);
|
||||
}
|
||||
|
|
@ -44,8 +46,10 @@ static void function_argument_real(ivl_signal_t port, ivl_expr_t exp)
|
|||
{
|
||||
int res = draw_eval_real(exp);
|
||||
|
||||
fprintf(vvp_out, " %%set/wr V_%s, %d;\n",
|
||||
vvp_signal_label(port), res);
|
||||
/* ports cannot be arrays. */
|
||||
assert(ivl_signal_array_count(port) == 1);
|
||||
|
||||
fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", port, res);
|
||||
}
|
||||
|
||||
static void draw_function_argument(ivl_signal_t port, ivl_expr_t exp)
|
||||
|
|
@ -113,8 +117,9 @@ struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
|
|||
if (load_wid > ivl_signal_width(retval))
|
||||
load_wid = ivl_signal_width(retval);
|
||||
|
||||
fprintf(vvp_out, " %%load/v %u, V_%s, %u;\n",
|
||||
res.base, vvp_signal_label(retval), load_wid);
|
||||
assert(ivl_signal_array_count(retval) == 1);
|
||||
fprintf(vvp_out, " %%load/v %u, v%p_0, %u;\n",
|
||||
res.base, retval, load_wid);
|
||||
|
||||
if (load_wid < swid)
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
|
||||
|
|
@ -148,10 +153,12 @@ int draw_ufunc_real(ivl_expr_t exp)
|
|||
fprintf(vvp_out, ", S_%p;\n", def);
|
||||
fprintf(vvp_out, " %%join;\n");
|
||||
|
||||
/* Return value signal cannot be an array. */
|
||||
assert(ivl_signal_array_count(retval) == 1);
|
||||
|
||||
/* Load the result into a word. */
|
||||
res = allocate_word();
|
||||
fprintf(vvp_out, " %%load/wr %d, V_%s;\n",
|
||||
res, vvp_signal_label(retval));
|
||||
fprintf(vvp_out, " %%load/wr %d, v%p_0;\n", res, retval);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: draw_vpi.c,v 1.13 2005/10/11 18:30:50 steve Exp $"
|
||||
#ident "$Id: draw_vpi.c,v 1.14 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
|
|
@ -75,6 +75,7 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
|||
with VPI handles of their own. Therefore, skip
|
||||
them in the process of evaluating expressions. */
|
||||
case IVL_EX_NONE:
|
||||
case IVL_EX_ARRAY:
|
||||
case IVL_EX_NUMBER:
|
||||
case IVL_EX_STRING:
|
||||
case IVL_EX_EVENT:
|
||||
|
|
@ -107,7 +108,8 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
|||
} else if (ivl_expr_signed(expr) !=
|
||||
ivl_signal_signed(ivl_expr_signal(expr))) {
|
||||
break;
|
||||
|
||||
} else if (ivl_signal_array_count(ivl_expr_signal(expr))>1){
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -153,6 +155,10 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
|||
fprintf(vvp_out, ", \" \"");
|
||||
continue;
|
||||
|
||||
case IVL_EX_ARRAY:
|
||||
fprintf(vvp_out, ", v%p", ivl_expr_signal(expr));
|
||||
continue;
|
||||
|
||||
case IVL_EX_NUMBER: {
|
||||
unsigned bit, wid = ivl_expr_width(expr);
|
||||
const char*bits = ivl_expr_bits(expr);
|
||||
|
|
@ -176,13 +182,16 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
|||
ivl_signal_signed(ivl_expr_signal(expr))) {
|
||||
break;
|
||||
|
||||
} else if (ivl_signal_array_count(ivl_expr_signal(expr))>1){
|
||||
break;
|
||||
|
||||
} else {
|
||||
fprintf(vvp_out, ", V_%s",
|
||||
vvp_signal_label(ivl_expr_signal(expr)));
|
||||
ivl_signal_t sig = ivl_expr_signal(expr);
|
||||
assert(ivl_signal_array_count(sig) == 1);
|
||||
fprintf(vvp_out, ", v%p_0", sig);
|
||||
continue;
|
||||
}
|
||||
fprintf(vvp_out, ", V_%s",
|
||||
vvp_signal_label(ivl_expr_signal(expr)));
|
||||
assert(0);
|
||||
continue;
|
||||
|
||||
case IVL_EX_STRING:
|
||||
|
|
@ -291,6 +300,12 @@ int draw_vpi_rfunc_call(ivl_expr_t fnet)
|
|||
|
||||
/*
|
||||
* $Log: draw_vpi.c,v $
|
||||
* Revision 1.14 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.13 2005/10/11 18:30:50 steve
|
||||
* Remove obsolete vvp_memory_label function.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.130 2006/02/02 02:43:59 steve Exp $"
|
||||
#ident "$Id: eval_expr.c,v 1.131 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
|
|
@ -1531,21 +1531,39 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
|
|||
*/
|
||||
static void draw_signal_dest(ivl_expr_t exp, struct vector_info res)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned swid = ivl_expr_width(exp);
|
||||
ivl_signal_t sig = ivl_expr_signal(exp);
|
||||
|
||||
unsigned word = 0;
|
||||
|
||||
if (swid > res.wid)
|
||||
swid = res.wid;
|
||||
|
||||
/* If this is an access to an array, handle that by emiting a
|
||||
load/av instruction. */
|
||||
if (ivl_signal_array_count(sig) > 1) {
|
||||
ivl_expr_t ix = ivl_expr_oper1(exp);
|
||||
if (!number_is_immediate(ix, 8*sizeof(unsigned long))) {
|
||||
draw_eval_expr_into_integer(ix, 3);
|
||||
fprintf(vvp_out, " %%load/av %u, v%p, %u;\n",
|
||||
res.base, sig, swid);
|
||||
return;
|
||||
}
|
||||
|
||||
/* The index is constant, so we can return to direct
|
||||
readout with the specific word selected. */
|
||||
word = get_number_immediate(ix);
|
||||
}
|
||||
|
||||
/* If this is a REG (a variable) then I can do a vector read. */
|
||||
fprintf(vvp_out, " %%load/v %u, V_%s, %u;\n",
|
||||
res.base, vvp_signal_label(sig), swid);
|
||||
fprintf(vvp_out, " %%load/v %u, v%p_%u, %u;\n",
|
||||
res.base, sig, word, swid);
|
||||
|
||||
/* Pad the signal value with zeros. */
|
||||
if (swid < res.wid) {
|
||||
|
||||
if (ivl_expr_signed(exp)) {
|
||||
unsigned idx;
|
||||
for (idx = swid ; idx < res.wid ; idx += 1)
|
||||
fprintf(vvp_out, " %%mov %u, %u, 1;\n",
|
||||
res.base+idx, res.base+swid-1);
|
||||
|
|
@ -1671,6 +1689,24 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
|
|||
struct vector_info res;
|
||||
unsigned idx;
|
||||
|
||||
/* Use this word of the signal. */
|
||||
unsigned use_word = 0;
|
||||
/* If this is an access to an array, handle that by emiting a
|
||||
load/av instruction. */
|
||||
if (ivl_signal_array_count(sig) > 1) {
|
||||
ivl_expr_t ix = ivl_expr_oper1(sube);
|
||||
if (!number_is_immediate(ix, 8*sizeof(unsigned long))) {
|
||||
draw_eval_expr_into_integer(ix, 3);
|
||||
assert(0); /* XXXX Don't know how to load part
|
||||
select! */
|
||||
return res;
|
||||
}
|
||||
|
||||
/* The index is constant, so we can return to direct
|
||||
readout with the specific word selected. */
|
||||
use_word = get_number_immediate(ix);
|
||||
}
|
||||
|
||||
shiv = draw_eval_expr(bit_idx, STUFF_OK_XZ|STUFF_OK_RO);
|
||||
|
||||
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
|
||||
|
|
@ -1683,8 +1719,8 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
|
|||
if (shiv.base == 0 && ivl_expr_width(sube) == wid) {
|
||||
res.base = allocate_vector(wid);
|
||||
res.wid = wid;
|
||||
fprintf(vvp_out, " %%load/v %u, V_%p, %u;\n",
|
||||
res.base, sig, ivl_expr_width(sube));
|
||||
fprintf(vvp_out, " %%load/v %u, v%p_%u, %u;\n",
|
||||
res.base, sig, use_word, ivl_expr_width(sube));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -1698,10 +1734,10 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
|
|||
|
||||
res.base = allocate_vector(ivl_expr_width(sube));
|
||||
res.wid = ivl_expr_width(sube);
|
||||
fprintf(vvp_out, " %%load/v %u, V_%p, %u; Only need %u bits\n",
|
||||
res.base, sig, ivl_expr_width(sube), wid);
|
||||
fprintf(vvp_out, " %%load/v %u, v%p_%u, %u; Only need %u bits\n",
|
||||
res.base, sig, use_word, ivl_expr_width(sube), wid);
|
||||
|
||||
save_signal_lookaside(res.base, sig, res.wid);
|
||||
save_signal_lookaside(res.base, sig, use_word, res.wid);
|
||||
|
||||
{
|
||||
struct vector_info tmp;
|
||||
|
|
@ -1724,8 +1760,8 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
|
|||
ivl_expr_width(sube), wid);
|
||||
break;
|
||||
}
|
||||
fprintf(vvp_out, " %%load/x.p %u, V_%p, 0;\n",
|
||||
res.base+idx, sig);
|
||||
fprintf(vvp_out, " %%load/x.p %u, v%p_%u, 0;\n",
|
||||
res.base+idx, sig, use_word);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
|
@ -2209,6 +2245,12 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
|
|||
|
||||
/*
|
||||
* $Log: eval_expr.c,v $
|
||||
* Revision 1.131 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.130 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_real.c,v 1.16 2006/10/10 23:54:28 steve Exp $"
|
||||
#ident "$Id: eval_real.c,v 1.17 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -245,9 +245,22 @@ static int draw_signal_real_real(ivl_expr_t exp)
|
|||
{
|
||||
ivl_signal_t sig = ivl_expr_signal(exp);
|
||||
int res = allocate_word();
|
||||
unsigned long word = 0;
|
||||
|
||||
fprintf(vvp_out, " %%load/wr %d, V_%s;\n",
|
||||
res, vvp_signal_label(sig));
|
||||
if (ivl_signal_array_count(sig) > 1) {
|
||||
ivl_expr_t ix = ivl_expr_oper1(exp);
|
||||
if (!number_is_immediate(ix, 8*sizeof(word))) {
|
||||
/* XXXX Need to generate a %load/ar instruction. */
|
||||
assert(0);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* The index is constant, so we can return to direct
|
||||
readout with the specific word selected. */
|
||||
word = get_number_immediate(ix);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%load/wr %d, v%p_%lu;\n", res, sig, word);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -326,6 +339,12 @@ int draw_eval_real(ivl_expr_t exp)
|
|||
|
||||
/*
|
||||
* $Log: eval_real.c,v $
|
||||
* Revision 1.17 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.16 2006/10/10 23:54:28 steve
|
||||
* Fix rendering of signed numbers in real expressions.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vector.c,v 1.7 2005/09/17 01:01:00 steve Exp $"
|
||||
#ident "$Id: vector.c,v 1.8 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
|
|
@ -32,6 +32,7 @@
|
|||
static struct allocation_score_s {
|
||||
ivl_expr_t exp;
|
||||
ivl_signal_t sig;
|
||||
unsigned sig_word;
|
||||
unsigned exp_bit : 24;
|
||||
unsigned sig_bit : 24;
|
||||
unsigned alloc : 8;
|
||||
|
|
@ -56,9 +57,10 @@ static inline void set_exp(unsigned addr, ivl_expr_t exp, unsigned ebit)
|
|||
allocation_map[addr].exp_bit = ebit;
|
||||
}
|
||||
|
||||
static inline void set_sig(unsigned addr, ivl_signal_t exp, unsigned ebit)
|
||||
static inline void set_sig(unsigned addr, ivl_signal_t exp, unsigned sig_word, unsigned ebit)
|
||||
{
|
||||
allocation_map[addr].sig = exp;
|
||||
allocation_map[addr].sig_word = sig_word;
|
||||
allocation_map[addr].sig_bit = ebit;
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +141,7 @@ void clear_expression_lookaside(void)
|
|||
|
||||
for (idx = 0 ; idx < lookaside_top ; idx += 1) {
|
||||
set_exp(idx, 0, 0);
|
||||
set_sig(idx, 0, 0);
|
||||
set_sig(idx, 0, 0, 0);
|
||||
}
|
||||
|
||||
lookaside_top = 0;
|
||||
|
|
@ -157,14 +159,14 @@ void save_expression_lookaside(unsigned addr, ivl_expr_t exp, unsigned wid)
|
|||
bits. */
|
||||
for (idx = 0 ; idx < wid ; idx += 1) {
|
||||
set_exp(addr+idx, exp, idx);
|
||||
set_sig(addr+idx, 0, 0);
|
||||
set_sig(addr+idx, 0, 0, 0);
|
||||
}
|
||||
|
||||
if ((addr+wid) > lookaside_top)
|
||||
lookaside_top = addr+wid;
|
||||
}
|
||||
|
||||
void save_signal_lookaside(unsigned addr, ivl_signal_t sig, unsigned wid)
|
||||
void save_signal_lookaside(unsigned addr, ivl_signal_t sig, unsigned sig_word, unsigned wid)
|
||||
{
|
||||
unsigned idx;
|
||||
/* Don't bind any of hte low bits to a signal. */
|
||||
|
|
@ -174,7 +176,7 @@ void save_signal_lookaside(unsigned addr, ivl_signal_t sig, unsigned wid)
|
|||
assert((addr+wid) <= MAX_VEC);
|
||||
|
||||
for (idx = 0 ; idx < wid ; idx += 1)
|
||||
set_sig(addr+idx, sig, idx);
|
||||
set_sig(addr+idx, sig, sig_word, idx);
|
||||
|
||||
if ((addr+wid) > lookaside_top)
|
||||
lookaside_top = addr+wid;
|
||||
|
|
@ -321,6 +323,12 @@ unsigned allocate_vector_exp(ivl_expr_t exp, unsigned wid,
|
|||
|
||||
/*
|
||||
* $Log: vector.c,v $
|
||||
* Revision 1.8 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.7 2005/09/17 01:01:00 steve
|
||||
* More robust use of precalculated expressions, and
|
||||
* Separate lookaside for written variables that can
|
||||
|
|
|
|||
|
|
@ -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.40 2006/02/02 02:43:59 steve Exp $"
|
||||
#ident "$Id: vvp_priv.h,v 1.41 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_config.h"
|
||||
|
|
@ -212,7 +212,7 @@ extern void save_expression_lookaside(unsigned addr,
|
|||
ivl_expr_t exp,
|
||||
unsigned wid);
|
||||
extern void save_signal_lookaside(unsigned addr,
|
||||
ivl_signal_t sig,
|
||||
ivl_signal_t sig, unsigned use_word,
|
||||
unsigned wid);
|
||||
|
||||
extern unsigned allocate_vector_exp(ivl_expr_t exp, unsigned wid,
|
||||
|
|
@ -252,6 +252,12 @@ extern unsigned thread_count;
|
|||
|
||||
/*
|
||||
* $Log: vvp_priv.h,v $
|
||||
* Revision 1.41 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.40 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2005 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2007 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -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.126 2006/10/05 01:37:34 steve Exp $"
|
||||
#ident "$Id: vvp_process.c,v 1.127 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
|
|
@ -78,6 +78,12 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
||||
unsigned part_off = 0;
|
||||
|
||||
/* Although Verilog doesn't support it, we'll handle
|
||||
here the case of an l-value part select of an array
|
||||
word if the address is constant. */
|
||||
ivl_expr_t word_ix = ivl_lval_idx(lval);
|
||||
unsigned long use_word = 0;
|
||||
|
||||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
} else if (number_is_immediate(part_off_ex, 64)) {
|
||||
|
|
@ -85,6 +91,14 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
part_off_ex = 0;
|
||||
}
|
||||
|
||||
/* If the word index is a constand expression, then evaluate
|
||||
it to select the word, and pay no further heed to the
|
||||
expression itself. */
|
||||
if (word_ix && number_is_immediate(word_ix, 8*sizeof(use_word))) {
|
||||
use_word = get_number_immediate(word_ix);
|
||||
word_ix = 0;
|
||||
}
|
||||
|
||||
if (ivl_lval_mux(lval))
|
||||
part_off_ex = ivl_lval_mux(lval);
|
||||
|
||||
|
|
@ -95,12 +109,13 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
a bit-select l-val. Presumably, the x0 index register
|
||||
has been loaded wit the result of the evaluated
|
||||
part select base expression. */
|
||||
assert(!word_ix);
|
||||
|
||||
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",
|
||||
vvp_signal_label(sig), bit, wid);
|
||||
fprintf(vvp_out, " %%set/x0 v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, bit, wid);
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_set);
|
||||
|
||||
} else if (part_off>0 || ivl_lval_width(lval)!=ivl_signal_width(sig)) {
|
||||
|
|
@ -108,15 +123,35 @@ static void set_to_lvariable(ivl_lval_t lval,
|
|||
offset. Load that into index x0 and generate a
|
||||
vector set instruction. */
|
||||
assert(ivl_lval_width(lval) == wid);
|
||||
assert(!word_ix);
|
||||
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", part_off);
|
||||
fprintf(vvp_out, " %%set/x0 V_%s, %u, %u;\n",
|
||||
vvp_signal_label(sig), bit, wid);
|
||||
fprintf(vvp_out, " %%set/x0 v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, bit, wid);
|
||||
|
||||
} else if (ivl_signal_array_count(sig) > 1) {
|
||||
|
||||
/* If the word index is a constant, then we can write
|
||||
directly to the word and save the index calculation. */
|
||||
if (word_ix == 0) {
|
||||
fprintf(vvp_out, " %%set/v v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, bit, wid);
|
||||
|
||||
} else {
|
||||
unsigned skip_set = transient_id++;
|
||||
unsigned index_reg = 3;
|
||||
draw_eval_expr_into_integer(word_ix, index_reg);
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
fprintf(vvp_out, " %%ix/load 1, 0;\n");
|
||||
fprintf(vvp_out, " %%set/av v%p, %u, %u;\n",
|
||||
sig, bit, wid);
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_set);
|
||||
}
|
||||
|
||||
} else {
|
||||
save_signal_lookaside(bit, sig, wid);
|
||||
fprintf(vvp_out, " %%set/v V_%s, %u, %u;\n",
|
||||
vvp_signal_label(sig), bit, wid);
|
||||
save_signal_lookaside(bit, sig, use_word, wid);
|
||||
fprintf(vvp_out, " %%set/v v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, bit, wid);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -149,6 +184,26 @@ static void set_to_memory_word(ivl_lval_t lval, unsigned idx,
|
|||
fprintf(vvp_out, "t_%u ;\n", skip_set);
|
||||
}
|
||||
|
||||
static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||
unsigned bit, unsigned delay, unsigned width)
|
||||
{
|
||||
unsigned skip_assign = transient_id++;
|
||||
|
||||
/* Store expression width into index word 0 */
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
/* Store constant (0) word part select into index 1 */
|
||||
fprintf(vvp_out, " %%ix/load 1, 0;\n");
|
||||
/* Calculate array word index into index register 3 */
|
||||
draw_eval_expr_into_integer(word_ix, 3);
|
||||
/* Skip assignment if word expression is not defined. */
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
||||
|
||||
fprintf(vvp_out, " %%assign/av v%p, %u, %u;\n", lsig, delay, bit);
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||
|
||||
clear_expression_lookaside();
|
||||
}
|
||||
|
||||
static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
||||
unsigned delay, ivl_expr_t dexp,
|
||||
unsigned width)
|
||||
|
|
@ -157,6 +212,20 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
||||
unsigned part_off = 0;
|
||||
|
||||
ivl_expr_t word_ix = ivl_lval_idx(lval);
|
||||
unsigned long use_word = 0;
|
||||
|
||||
if (ivl_signal_array_count(sig) > 1) {
|
||||
assert(word_ix);
|
||||
if (! number_is_immediate(word_ix, 8*sizeof(use_word))) {
|
||||
assert(!dexp);
|
||||
assign_to_array_word(sig, word_ix, bit, delay, width);
|
||||
return;
|
||||
}
|
||||
|
||||
use_word = get_number_immediate(word_ix);
|
||||
}
|
||||
|
||||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
} else if (number_is_immediate(part_off_ex, 64)) {
|
||||
|
|
@ -174,8 +243,8 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
/* 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);
|
||||
fprintf(vvp_out, " %%assign/v0/x1 V_%s, %u, %u;\n",
|
||||
vvp_signal_label(sig), delay, bit);
|
||||
fprintf(vvp_out, " %%assign/v0/x1 v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, delay, bit);
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_assign);
|
||||
|
||||
} else if (part_off>0 || ivl_lval_width(lval)!=ivl_signal_width(sig)) {
|
||||
|
|
@ -188,8 +257,8 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
/* Constant delay... */
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off);
|
||||
fprintf(vvp_out, " %%assign/v0/x1 V_%s, %u, %u;\n",
|
||||
vvp_signal_label(sig), delay, bit);
|
||||
fprintf(vvp_out, " %%assign/v0/x1 v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, delay, bit);
|
||||
|
||||
} else {
|
||||
/* Calculated delay... */
|
||||
|
|
@ -197,20 +266,20 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
|||
draw_eval_expr_into_integer(dexp, delay_index);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off);
|
||||
fprintf(vvp_out, " %%assign/v0/x1/d V_%s, %u, %u;\n",
|
||||
vvp_signal_label(sig), delay_index, bit);
|
||||
fprintf(vvp_out, " %%assign/v0/x1/d v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, delay_index, bit);
|
||||
clr_word(delay_index);
|
||||
}
|
||||
|
||||
} else if (dexp != 0) {
|
||||
draw_eval_expr_into_integer(dexp, 1);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0/d V_%s, 1, %u;\n",
|
||||
vvp_signal_label(sig), bit);
|
||||
fprintf(vvp_out, " %%assign/v0/d v%p_%lu, 1, %u;\n",
|
||||
sig, use_word, bit);
|
||||
} else {
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0 V_%s, %u, %u;\n",
|
||||
vvp_signal_label(sig), delay, bit);
|
||||
fprintf(vvp_out, " %%assign/v0 v%p_%lu, %u, %u;\n",
|
||||
sig, use_word, delay, bit);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -345,8 +414,9 @@ static int show_stmt_assign_sig_real(ivl_statement_t net)
|
|||
var = ivl_lval_sig(lval);
|
||||
assert(var != 0);
|
||||
|
||||
fprintf(vvp_out, " %%set/wr V_%s, %d;\n",
|
||||
vvp_signal_label(var), res);
|
||||
assert(ivl_signal_array_count(var) == 1);
|
||||
|
||||
fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", var, res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -390,13 +460,27 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
|
|||
ivl_signal_t sig;
|
||||
ivl_expr_t rval = ivl_stmt_rval(net);
|
||||
ivl_expr_t del = ivl_stmt_delay_expr(net);
|
||||
|
||||
/* variables for the selection of word from an array. */
|
||||
ivl_expr_t word_ix;
|
||||
unsigned long use_word = 0;
|
||||
/* thread address for a word value. */
|
||||
int word;
|
||||
unsigned long delay;
|
||||
|
||||
/* Must be exactly 1 l-value. */
|
||||
assert(ivl_stmt_lvals(net) == 1);
|
||||
|
||||
lval = ivl_stmt_lval(net, 0);
|
||||
sig = ivl_lval_sig(lval);
|
||||
assert(sig);
|
||||
|
||||
if (ivl_signal_array_count(sig) > 1) {
|
||||
word_ix = ivl_lval_idx(lval);
|
||||
assert(word_ix);
|
||||
assert(number_is_immediate(word_ix, 8*sizeof(use_word)));
|
||||
use_word = get_number_immediate(word_ix);
|
||||
}
|
||||
|
||||
delay = 0;
|
||||
if (del && (ivl_expr_type(del) == IVL_EX_ULONG)) {
|
||||
delay = ivl_expr_uvalue(del);
|
||||
|
|
@ -409,11 +493,8 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
|
|||
/* Evaluate the r-value */
|
||||
word = draw_eval_real(rval);
|
||||
|
||||
lval = ivl_stmt_lval(net, 0);
|
||||
sig = ivl_lval_sig(lval);
|
||||
assert(sig);
|
||||
fprintf(vvp_out, " %%assign/wr V_%s, %lu, %u;\n",
|
||||
vvp_signal_label(sig), delay, word);
|
||||
fprintf(vvp_out, " %%assign/wr v%p_%lu, %lu, %u;\n",
|
||||
sig, use_word, delay, word);
|
||||
|
||||
clr_word(word);
|
||||
|
||||
|
|
@ -750,6 +831,8 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
|
|||
unsigned use_wid = ivl_lval_width(lval);
|
||||
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
||||
unsigned part_off;
|
||||
ivl_expr_t word_idx = ivl_lval_idx(lval);
|
||||
unsigned long use_word = 0;
|
||||
|
||||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
|
|
@ -758,6 +841,11 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
|
|||
part_off = get_number_immediate(part_off_ex);
|
||||
}
|
||||
|
||||
if (word_idx != 0) {
|
||||
assert(number_is_immediate(word_idx, 8*sizeof(unsigned long)));
|
||||
use_word = get_number_immediate(word_idx);
|
||||
}
|
||||
|
||||
/* L-Value must be a signal: reg or wire */
|
||||
assert(lsig != 0);
|
||||
|
||||
|
|
@ -775,8 +863,8 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
|
|||
assert((roff + use_wid) <= rvec.wid);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %s V_%s, %u, %u;\n", command_name,
|
||||
vvp_signal_label(lsig), rvec.base+roff, use_wid);
|
||||
fprintf(vvp_out, " %s v%p_%lu, %u, %u;\n", command_name,
|
||||
lsig, use_word, rvec.base+roff, use_wid);
|
||||
|
||||
if (rvec.base >= 4)
|
||||
roff += use_wid;
|
||||
|
|
@ -790,6 +878,9 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
|
|||
ivl_signal_t lsig;
|
||||
const char*command_name;
|
||||
|
||||
ivl_expr_t lword_idx, rword_idx;
|
||||
unsigned long use_lword = 0, use_rword = 0;
|
||||
|
||||
if (ivl_expr_type(rval) != IVL_EX_SIGNAL)
|
||||
return;
|
||||
|
||||
|
|
@ -811,9 +902,23 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
|
|||
lval = ivl_stmt_lval(net, 0);
|
||||
lsig = ivl_lval_sig(lval);
|
||||
|
||||
/* At least for now, only handle force to fixed words of an array. */
|
||||
if ((lword_idx = ivl_lval_idx(lval)) != 0) {
|
||||
assert(number_is_immediate(lword_idx, 8*sizeof(unsigned long)));
|
||||
use_lword = get_number_immediate(lword_idx);
|
||||
}
|
||||
|
||||
if ((rword_idx = ivl_expr_oper1(rval)) != 0) {
|
||||
assert(number_is_immediate(rword_idx, 8*sizeof(unsigned long)));
|
||||
use_rword = get_number_immediate(rword_idx);
|
||||
}
|
||||
|
||||
assert(ivl_signal_array_count(rsig) == 1);
|
||||
use_rword = 0;
|
||||
|
||||
fprintf(vvp_out, " %s/link", command_name);
|
||||
fprintf(vvp_out, " V_%s", vvp_signal_label(lsig));
|
||||
fprintf(vvp_out, ", V_%s;\n", vvp_signal_label(rsig));
|
||||
fprintf(vvp_out, " v%p_%lu", lsig, use_lword);
|
||||
fprintf(vvp_out, ", v%p_%lu;\n", rsig, use_rword);
|
||||
}
|
||||
|
||||
static int show_stmt_cassign(ivl_statement_t net)
|
||||
|
|
@ -848,11 +953,20 @@ static int show_stmt_deassign(ivl_statement_t net)
|
|||
ivl_lval_t lval = ivl_stmt_lval(net, lidx);
|
||||
ivl_signal_t lsig = ivl_lval_sig(lval);
|
||||
|
||||
ivl_expr_t word_idx = ivl_lval_idx(lval);
|
||||
unsigned long use_word = 0;
|
||||
|
||||
assert(lsig != 0);
|
||||
assert(ivl_lval_mux(lval) == 0);
|
||||
assert(ivl_lval_part_off(lval) == 0);
|
||||
|
||||
fprintf(vvp_out, " %%deassign V_%s;\n", vvp_signal_label(lsig));
|
||||
if (word_idx != 0) {
|
||||
assert(number_is_immediate(word_idx, 8*sizeof(use_word)));
|
||||
use_word = get_number_immediate(word_idx);
|
||||
}
|
||||
|
||||
|
||||
fprintf(vvp_out, " %%deassign v%p_%lu;\n", lsig, use_word);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1086,6 +1200,8 @@ static int show_stmt_release(ivl_statement_t net)
|
|||
ivl_signal_t lsig = ivl_lval_sig(lval);
|
||||
const char*opcode = 0;
|
||||
|
||||
ivl_expr_t word_idx = ivl_lval_idx(lval);
|
||||
unsigned long use_word = 0;
|
||||
assert(lsig != 0);
|
||||
assert(ivl_lval_mux(lval) == 0);
|
||||
assert(ivl_lval_part_off(lval) == 0);
|
||||
|
|
@ -1099,10 +1215,15 @@ static int show_stmt_release(ivl_statement_t net)
|
|||
break;
|
||||
}
|
||||
|
||||
if (word_idx != 0) {
|
||||
assert(number_is_immediate(word_idx, 8*sizeof(use_word)));
|
||||
use_word = get_number_immediate(word_idx);
|
||||
}
|
||||
|
||||
/* Generate the appropriate release statement for this
|
||||
l-value. */
|
||||
fprintf(vvp_out, " %%release/%s V_%s;\n",
|
||||
opcode, vvp_signal_label(lsig));
|
||||
fprintf(vvp_out, " %%release/%s v%p_%lu;\n",
|
||||
opcode, lsig, use_word);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1491,6 +1612,12 @@ int draw_func_definition(ivl_scope_t scope)
|
|||
|
||||
/*
|
||||
* $Log: vvp_process.c,v $
|
||||
* Revision 1.127 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.126 2006/10/05 01:37:34 steve
|
||||
* Remove dead code.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vvp_scope.c,v 1.150 2006/11/23 22:42:48 steve Exp $"
|
||||
#ident "$Id: vvp_scope.c,v 1.151 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
|
|
@ -178,7 +178,7 @@ const char* vvp_signal_label(ivl_signal_t sig)
|
|||
return buf;
|
||||
}
|
||||
|
||||
ivl_signal_t signal_of_nexus(ivl_nexus_t nex)
|
||||
ivl_signal_t signal_of_nexus(ivl_nexus_t nex, unsigned*word)
|
||||
{
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
|
||||
|
|
@ -188,9 +188,8 @@ ivl_signal_t signal_of_nexus(ivl_nexus_t nex)
|
|||
continue;
|
||||
if (ivl_signal_local(sig))
|
||||
continue;
|
||||
|
||||
*word = ivl_nexus_ptr_pin(ptr);
|
||||
return sig;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -575,11 +574,9 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
|||
|
||||
sptr = ivl_nexus_ptr_sig(nptr);
|
||||
if (sptr && (ivl_signal_type(sptr) == IVL_SIT_REG)) {
|
||||
/* Input is a .var. Note that these devices have only
|
||||
exactly one pin (that carries a vector) so nptr_pin
|
||||
must be 0. */
|
||||
assert(nptr_pin == 0);
|
||||
sprintf(result, "V_%s", vvp_signal_label(sptr));
|
||||
/* Input is a .var. This device may be a non-zero pin
|
||||
because it may be an array of reg vectors. */
|
||||
snprintf(result, sizeof result, "v%p_%u", sptr, nptr_pin);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -620,8 +617,8 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
|||
if (lpm) switch (ivl_lpm_type(lpm)) {
|
||||
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_ARRAY:
|
||||
case IVL_LPM_CONCAT:
|
||||
case IVL_LPM_CMP_EEQ:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
|
|
@ -936,12 +933,13 @@ const char*draw_net_input(ivl_nexus_t nex)
|
|||
const char*draw_input_from_net(ivl_nexus_t nex)
|
||||
{
|
||||
static char result[32];
|
||||
unsigned word;
|
||||
|
||||
ivl_signal_t sig = signal_of_nexus(nex);
|
||||
ivl_signal_t sig = signal_of_nexus(nex, &word);
|
||||
if (sig == 0)
|
||||
return draw_net_input(nex);
|
||||
|
||||
snprintf(result, sizeof result, "V_%p", sig);
|
||||
snprintf(result, sizeof result, "v%p_%u", sig, word);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -949,7 +947,8 @@ const char*draw_input_from_net(ivl_nexus_t nex)
|
|||
/*
|
||||
* This function draws a reg/int/variable in the scope. This is a very
|
||||
* simple device to draw as there are no inputs to connect so no need
|
||||
* to scan the nexus.
|
||||
* to scan the nexus. We do have to account for the possibility that
|
||||
* the device is arrayed, though, by making a node for each array element.
|
||||
*/
|
||||
static void draw_reg_in_scope(ivl_signal_t sig)
|
||||
{
|
||||
|
|
@ -967,9 +966,29 @@ static void draw_reg_in_scope(ivl_signal_t sig)
|
|||
break;
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "V_%s .var%s \"%s\", %d, %d;\n",
|
||||
vvp_signal_label(sig), datatype_flag,
|
||||
vvp_mangle_name(ivl_signal_basename(sig)), msb, lsb);
|
||||
/* If the reg objects are collected into an array, then first
|
||||
write out the .array record to declare the array indices. */
|
||||
if (ivl_signal_array_count(sig) > 1) {
|
||||
unsigned word_count = ivl_signal_array_count(sig);
|
||||
unsigned iword;
|
||||
int last = ivl_signal_array_base(sig)+ivl_signal_array_count(sig)-1;
|
||||
int first = ivl_signal_array_base(sig);
|
||||
fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n",
|
||||
sig, vvp_mangle_name(ivl_signal_basename(sig)),
|
||||
last, first);
|
||||
|
||||
/* Scan the words of the array... */
|
||||
for (iword = 0 ; iword < word_count ; iword += 1) {
|
||||
fprintf(vvp_out, "v%p_%u .var%s v%p, %d %d;\n",
|
||||
sig, iword, datatype_flag, sig, msb, lsb);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
fprintf(vvp_out, "v%p_0 .var%s \"%s\", %d %d;\n",
|
||||
sig, datatype_flag,
|
||||
vvp_mangle_name(ivl_signal_basename(sig)), msb, lsb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -981,28 +1000,14 @@ static void draw_net_in_scope(ivl_signal_t sig)
|
|||
{
|
||||
int msb = ivl_signal_msb(sig);
|
||||
int lsb = ivl_signal_lsb(sig);
|
||||
typedef const char*const_charp;
|
||||
const char* arg;
|
||||
const char* driver;
|
||||
|
||||
const char*datatype_flag = ivl_signal_signed(sig)? "/s" : "";
|
||||
|
||||
struct vvp_nexus_data*nex_data;
|
||||
unsigned iword;
|
||||
|
||||
/* Skip the local signal. */
|
||||
if (ivl_signal_local(sig))
|
||||
return;
|
||||
|
||||
/* Connect the pin of the signal to something. */
|
||||
{
|
||||
ivl_nexus_t nex = ivl_signal_nex(sig);
|
||||
driver = draw_net_input(nex);
|
||||
arg = driver;
|
||||
|
||||
nex_data = (struct vvp_nexus_data*)ivl_nexus_get_private(nex);
|
||||
assert(nex_data);
|
||||
}
|
||||
|
||||
switch (ivl_signal_data_type(sig)) {
|
||||
case IVL_VT_REAL:
|
||||
datatype_flag = "/real";
|
||||
|
|
@ -1011,30 +1016,70 @@ static void draw_net_in_scope(ivl_signal_t sig)
|
|||
break;
|
||||
}
|
||||
|
||||
if (nex_data->net == 0) {
|
||||
const char*vec8 = "";
|
||||
if (nex_data->drivers_count > 1)
|
||||
vec8 = "8";
|
||||
if (nex_data->flags & VVP_NEXUS_DATA_STR)
|
||||
vec8 = "8";
|
||||
for (iword = 0 ; iword < ivl_signal_array_count(sig); iword += 1) {
|
||||
|
||||
fprintf(vvp_out, "V_%p .net%s%s \"%s\", %d, %d, %s;"
|
||||
" %u drivers%s\n",
|
||||
sig, vec8, datatype_flag,
|
||||
vvp_mangle_name(ivl_signal_basename(sig)),
|
||||
msb, lsb, arg,
|
||||
nex_data->drivers_count,
|
||||
nex_data->flags&VVP_NEXUS_DATA_STR?", strength-aware":"");
|
||||
nex_data->net = sig;
|
||||
unsigned word_count = ivl_signal_array_count(sig);
|
||||
struct vvp_nexus_data*nex_data;
|
||||
|
||||
} else {
|
||||
/* Detect that this is an alias of nex_data->net. Create
|
||||
a different kind of node that refers to the alias
|
||||
source data instead of holding our own data. */
|
||||
fprintf(vvp_out, "V_%p .alias%s \"%s\", %d, %d, V_%p;\n",
|
||||
sig, datatype_flag,
|
||||
vvp_mangle_name(ivl_signal_basename(sig)),
|
||||
msb, lsb, nex_data->net);
|
||||
/* Connect the pin of the signal to something. */
|
||||
ivl_nexus_t nex = ivl_signal_nex(sig, iword);
|
||||
const char*driver = draw_net_input(nex);
|
||||
|
||||
nex_data = (struct vvp_nexus_data*)ivl_nexus_get_private(nex);
|
||||
assert(nex_data);
|
||||
|
||||
if (nex_data->net == 0) {
|
||||
int strength_aware_flag = 0;
|
||||
const char*vec8 = "";
|
||||
if (nex_data->flags&VVP_NEXUS_DATA_STR)
|
||||
strength_aware_flag = 1;
|
||||
if (nex_data->drivers_count > 1)
|
||||
vec8 = "8";
|
||||
if (strength_aware_flag)
|
||||
vec8 = "8";
|
||||
|
||||
if (iword == 0 && word_count > 1) {
|
||||
int last = ivl_signal_array_base(sig) + word_count-1;
|
||||
int first = ivl_signal_array_base(sig);
|
||||
fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n",
|
||||
sig, vvp_mangle_name(ivl_signal_basename(sig)),
|
||||
last, first);
|
||||
}
|
||||
if (word_count > 1) {
|
||||
/* If this is a word of an array, then use an
|
||||
array reference in place of the net name. */
|
||||
fprintf(vvp_out, "v%p_%u .net%s%s v%p, %d %d, %s;"
|
||||
" %u drivers%s\n",
|
||||
sig, iword, vec8, datatype_flag, sig,
|
||||
msb, lsb, driver,
|
||||
nex_data->drivers_count,
|
||||
strength_aware_flag?", strength-aware":"");
|
||||
} else {
|
||||
/* If this is an isolated word, it uses its
|
||||
own name. */
|
||||
fprintf(vvp_out, "v%p_%u .net%s%s \"%s\", %d %d, %s;"
|
||||
" %u drivers%s\n",
|
||||
sig, iword, vec8, datatype_flag,
|
||||
vvp_mangle_name(ivl_signal_basename(sig)),
|
||||
msb, lsb, driver,
|
||||
nex_data->drivers_count,
|
||||
strength_aware_flag?", strength-aware":"");
|
||||
}
|
||||
nex_data->net = sig;
|
||||
|
||||
} else {
|
||||
|
||||
assert(word_count == 1);
|
||||
assert(ivl_signal_array_count(nex_data->net) == 1);
|
||||
|
||||
/* Detect that this is an alias of nex_data->net. Create
|
||||
a different kind of node that refers to the alias
|
||||
source data instead of holding our own data. */
|
||||
fprintf(vvp_out, "v%p_0 .alias%s \"%s\", %d %d, v%p_0;\n",
|
||||
sig, datatype_flag,
|
||||
vvp_mangle_name(ivl_signal_basename(sig)),
|
||||
msb, lsb, nex_data->net);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1373,13 +1418,16 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
|
|||
fprintf(vvp_out, "L_%p .delay L_%p/d", lptr, lptr);
|
||||
|
||||
sig = ivl_expr_signal(rise_exp);
|
||||
fprintf(vvp_out, ", V_%p", sig);
|
||||
assert(ivl_signal_array_count(sig) == 1);
|
||||
fprintf(vvp_out, ", v%p_0", sig);
|
||||
|
||||
sig = ivl_expr_signal(fall_exp);
|
||||
fprintf(vvp_out, ", V_%p", sig);
|
||||
assert(ivl_signal_array_count(sig) == 1);
|
||||
fprintf(vvp_out, ", v%p_0", sig);
|
||||
|
||||
sig = ivl_expr_signal(decay_exp);
|
||||
fprintf(vvp_out, ", V_%p;\n", sig);
|
||||
assert(ivl_signal_array_count(sig) == 1);
|
||||
fprintf(vvp_out, ", v%p_0;\n", sig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1515,38 +1563,6 @@ static void draw_event_in_scope(ivl_event_t obj)
|
|||
}
|
||||
}
|
||||
|
||||
static void draw_lpm_ram(ivl_lpm_t net)
|
||||
{
|
||||
ivl_memory_t mem = ivl_lpm_memory(net);
|
||||
ivl_nexus_t clk = ivl_lpm_clk(net);
|
||||
ivl_nexus_t pin;
|
||||
|
||||
if (clk) {
|
||||
fprintf(vvp_out, "CLK_%p .event posedge, %s;\n",
|
||||
net, draw_net_input(clk));
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "L_%p .mem/port M_%p, ", net, mem);
|
||||
|
||||
pin = ivl_lpm_select(net);
|
||||
fprintf(vvp_out, "%s", draw_net_input(pin));
|
||||
|
||||
if (clk) {
|
||||
fprintf(vvp_out, ", CLK_%p, ", net);
|
||||
pin = ivl_lpm_enable(net);
|
||||
if (pin)
|
||||
fprintf(vvp_out, "%s", draw_net_input(pin));
|
||||
else
|
||||
fprintf(vvp_out, "C4<1>");
|
||||
|
||||
pin = ivl_lpm_data(net, 0);
|
||||
fprintf(vvp_out, ", %s", draw_net_input(pin));
|
||||
}
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function draws any functors needed to calculate the input to
|
||||
* this nexus, and leaves in the data array strings that can be used
|
||||
|
|
@ -1611,6 +1627,23 @@ static void draw_lpm_add(ivl_lpm_t net)
|
|||
net, type, width, src_table[0], src_table[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* The read port to an array is generated as a single record that takes
|
||||
* the address as an input.
|
||||
*/
|
||||
static void draw_lpm_array(ivl_lpm_t net)
|
||||
{
|
||||
ivl_nexus_t nex;
|
||||
ivl_signal_t mem = ivl_lpm_array(net);
|
||||
|
||||
fprintf(vvp_out, "L_%p .array/port v%p, ", net, mem);
|
||||
|
||||
nex = ivl_lpm_select(net);
|
||||
fprintf(vvp_out, "%s", draw_net_input(nex));
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
static void draw_lpm_cmp(ivl_lpm_t net)
|
||||
{
|
||||
const char*src_table[2];
|
||||
|
|
@ -1951,7 +1984,8 @@ static void draw_lpm_ufunc(ivl_lpm_t net)
|
|||
else
|
||||
fprintf(vvp_out, ", ");
|
||||
|
||||
fprintf(vvp_out, "V_%s", vvp_signal_label(psig));
|
||||
assert(ivl_signal_array_count(psig) == 1);
|
||||
fprintf(vvp_out, "v%p_0", psig);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, ")");
|
||||
|
|
@ -1960,8 +1994,9 @@ static void draw_lpm_ufunc(ivl_lpm_t net)
|
|||
result is collected. */
|
||||
{ ivl_signal_t psig = ivl_scope_port(def, 0);
|
||||
assert(ivl_lpm_width(net) == ivl_signal_width(psig));
|
||||
assert(ivl_signal_array_count(psig) == 1);
|
||||
|
||||
fprintf(vvp_out, " V_%s", vvp_signal_label(psig));
|
||||
fprintf(vvp_out, " v%p_0", psig);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
|
|
@ -2123,10 +2158,6 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
|
|||
{
|
||||
switch (ivl_lpm_type(net)) {
|
||||
|
||||
case IVL_LPM_RAM:
|
||||
draw_lpm_ram(net);
|
||||
return;
|
||||
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_SUB:
|
||||
case IVL_LPM_MULT:
|
||||
|
|
@ -2135,6 +2166,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
|
|||
draw_lpm_add(net);
|
||||
return;
|
||||
|
||||
case IVL_LPM_ARRAY:
|
||||
draw_lpm_array(net);
|
||||
return;
|
||||
|
||||
case IVL_LPM_PART_BI:
|
||||
draw_lpm_part_bi(net);
|
||||
return;
|
||||
|
|
@ -2335,6 +2370,12 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
|
|||
|
||||
/*
|
||||
* $Log: vvp_scope.c,v $
|
||||
* Revision 1.151 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.150 2006/11/23 22:42:48 steve
|
||||
* Do not intertangle modpaths due to references to input nets.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.71 2006/10/30 22:45:38 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.72 2007/01/16 05:44:16 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -81,7 +81,8 @@ vpi_priv.o vpi_scope.o vpi_real.o vpi_signal.o vpi_tasks.o vpi_time.o \
|
|||
vpi_memory.o vpi_vthr_vector.o vpip_bin.o vpip_hex.o vpip_oct.o \
|
||||
vpip_to_dec.o vpip_format.o vvp_vpi.o
|
||||
|
||||
O = main.o parse.o parse_misc.o lexor.o arith.o bufif.o compile.o concat.o \
|
||||
O = main.o parse.o parse_misc.o lexor.o arith.o array.o bufif.o compile.o \
|
||||
concat.o \
|
||||
dff.o extend.o npmos.o part.o reduce.o resolv.o sfunc.o stop.o symbols.o \
|
||||
ufunc.o codes.o \
|
||||
vthread.o schedule.o statistics.o tables.o udp.o vvp_net.o memory.o \
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* $Id: README.txt,v 1.79 2006/11/23 23:02:36 steve Exp $
|
||||
* $Id: README.txt,v 1.80 2007/01/16 05:44:16 steve Exp $
|
||||
*/
|
||||
|
||||
VVP SIMULATION ENGINE
|
||||
|
|
@ -370,6 +370,16 @@ activates the delay.
|
|||
|
||||
.modpath <input> , [ <src> (<delays>) ] ;
|
||||
|
||||
ARRAY INDEX STATEMENTS:
|
||||
|
||||
Variables can be collected into arrays. The words of the array are
|
||||
declared seperately, this statement collects them together:
|
||||
|
||||
<label> .array "name", <last> <first> ;
|
||||
|
||||
the .var or .net statements after this array statement, that have the
|
||||
same "name" are collected, in order, as words.
|
||||
|
||||
MEMORY STATEMENTS:
|
||||
|
||||
Memories are arrays of words, each word a vvp_vector4_t vector of the
|
||||
|
|
|
|||
16
vvp/codes.h
16
vvp/codes.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __codes_H
|
||||
#define __codes_H
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2007 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -19,13 +19,14 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: codes.h,v 1.80 2006/10/05 01:23:53 steve Exp $"
|
||||
#ident "$Id: codes.h,v 1.81 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
# include "pointers.h"
|
||||
# include "vvp_net.h"
|
||||
# include "memory.h"
|
||||
# include "array.h"
|
||||
# include "vthread.h"
|
||||
|
||||
typedef bool (*vvp_code_fun)(vthread_t thr, vvp_code_t code);
|
||||
|
|
@ -40,6 +41,7 @@ extern bool of_ADD_WR(vthread_t thr, vvp_code_t code);
|
|||
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_AV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_D(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);
|
||||
|
|
@ -86,7 +88,7 @@ extern bool of_JMP0(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_JMP0XZ(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_JMP1(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_JOIN(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_MEM(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_AV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_MV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_NX(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code);
|
||||
|
|
@ -110,6 +112,7 @@ extern bool of_OR(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_ORR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_RELEASE_NET(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_RELEASE_REG(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_AV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_MV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_VEC(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_WORDR(vthread_t thr, vvp_code_t code);
|
||||
|
|
@ -146,6 +149,7 @@ struct vvp_code_s {
|
|||
vvp_net_t *net;
|
||||
vvp_code_t cptr;
|
||||
vvp_memory_t mem;
|
||||
vvp_array_t array;
|
||||
struct __vpiHandle*handle;
|
||||
struct __vpiScope*scope;
|
||||
functor_t fun_ptr;
|
||||
|
|
@ -180,6 +184,12 @@ extern vvp_code_t codespace_null(void);
|
|||
|
||||
/*
|
||||
* $Log: codes.h,v $
|
||||
* Revision 1.81 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.80 2006/10/05 01:23:53 steve
|
||||
* Handle non-constant delays on indexed non-blocking assignments.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.226 2006/10/05 01:23:53 steve Exp $"
|
||||
#ident "$Id: compile.cc,v 1.227 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "arith.h"
|
||||
|
|
@ -58,6 +58,8 @@ enum operand_e {
|
|||
OA_NONE,
|
||||
/* The operand is a number, an immediate unsigned integer */
|
||||
OA_NUMBER,
|
||||
/* The operand is a pointer to an array. */
|
||||
OA_ARR_PTR,
|
||||
/* The operand is a thread bit index or short integer */
|
||||
OA_BIT1,
|
||||
OA_BIT2,
|
||||
|
|
@ -87,6 +89,7 @@ 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/av",of_ASSIGN_AV,3,{OA_ARR_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} },
|
||||
|
|
@ -130,7 +133,7 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%jmp/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%jmp/1", of_JMP1, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%join", of_JOIN, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%load/m", of_LOAD_MEM,2, {OA_BIT1, OA_MEM_PTR, OA_NONE} },
|
||||
{ "%load/av",of_LOAD_AV,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
||||
{ "%load/mv",of_LOAD_MV,3, {OA_BIT1, OA_MEM_PTR, OA_BIT2} },
|
||||
{ "%load/nx",of_LOAD_NX,3, {OA_BIT1, OA_VPI_PTR, OA_BIT2} },
|
||||
{ "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
|
||||
|
|
@ -154,6 +157,7 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%or/r", of_ORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%release/net",of_RELEASE_NET,1,{OA_FUNC_PTR,OA_NONE,OA_NONE} },
|
||||
{ "%release/reg",of_RELEASE_REG,1,{OA_FUNC_PTR,OA_NONE,OA_NONE} },
|
||||
{ "%set/av", of_SET_AV, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%set/mv", of_SET_MV, 3, {OA_MEM_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%set/wr", of_SET_WORDR,2,{OA_VPI_PTR, OA_BIT1, OA_NONE} },
|
||||
|
|
@ -570,6 +574,37 @@ static void compile_mem_lookup(struct vvp_code_s *code, char *label)
|
|||
resolv_submit(res);
|
||||
}
|
||||
|
||||
struct array_resolv_list_s: public resolv_list_s {
|
||||
struct vvp_code_s *code;
|
||||
char *label;
|
||||
virtual bool resolve(bool mes);
|
||||
};
|
||||
|
||||
bool array_resolv_list_s::resolve(bool mes)
|
||||
{
|
||||
code->array = array_find(label);
|
||||
if (code->array != 0) {
|
||||
free(label);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mes)
|
||||
fprintf(stderr, "Array unresolved: %s\n", label);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void compile_array_lookup(struct vvp_code_s*code, char*label)
|
||||
{
|
||||
struct array_resolv_list_s *res
|
||||
= new struct array_resolv_list_s;
|
||||
|
||||
res->code = code;
|
||||
res->label = label;
|
||||
|
||||
resolv_submit(res);
|
||||
}
|
||||
|
||||
/*
|
||||
* When parsing is otherwise complete, this function is called to do
|
||||
* the final stuff. Clean up deferred linking here.
|
||||
|
|
@ -1312,6 +1347,15 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
|
|||
case OA_NONE:
|
||||
break;
|
||||
|
||||
case OA_ARR_PTR:
|
||||
if (opa->argv[idx].ltype != L_SYMB) {
|
||||
yyerror("operand format");
|
||||
break;
|
||||
}
|
||||
|
||||
compile_array_lookup(code, opa->argv[idx].symb.text);
|
||||
break;
|
||||
|
||||
case OA_BIT1:
|
||||
if (opa->argv[idx].ltype != L_NUMB) {
|
||||
yyerror("operand format");
|
||||
|
|
@ -1535,6 +1579,12 @@ void compile_param_string(char*label, char*name, char*value)
|
|||
|
||||
/*
|
||||
* $Log: compile.cc,v $
|
||||
* Revision 1.227 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.226 2006/10/05 01:23:53 steve
|
||||
* Handle non-constant delays on indexed non-blocking assignments.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: compile.h,v 1.84 2006/11/22 06:10:05 steve Exp $"
|
||||
#ident "$Id: compile.h,v 1.85 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
|
|
@ -237,6 +237,10 @@ extern char **compile_udp_table(char **table, char *row);
|
|||
* Memory Instances, Ports, and Initialization
|
||||
*/
|
||||
|
||||
extern void compile_array(char*label, char*name, int last, int first);
|
||||
|
||||
extern void compile_array_port(char*label, char*name, char*addr);
|
||||
|
||||
extern void compile_memory(char *label, char *name, int lsb, int msb,
|
||||
unsigned idxs, long *idx);
|
||||
|
||||
|
|
@ -326,7 +330,11 @@ extern void compile_thread(char*start_sym, char*flag);
|
|||
*/
|
||||
extern void compile_variable(char*label, char*name,
|
||||
int msb, int lsb, char signed_flag);
|
||||
extern void compile_var_real(char*label, char*nane,
|
||||
extern void compile_var_real(char*label, char*name,
|
||||
int msb, int lsb);
|
||||
extern void compile_variablew(char*label, char*array_symbol,
|
||||
int msb, int lsb, char signed_flag);
|
||||
extern void compile_varw_real(char*label, char*array_symbol,
|
||||
int msb, int lsb);
|
||||
|
||||
extern void compile_net(char*label, char*name,
|
||||
|
|
@ -337,6 +345,14 @@ extern void compile_net_real(char*label, char*name,
|
|||
int msb, int lsb,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
|
||||
extern void compile_netw(char*label, char*array_symbol,
|
||||
int msb, int lsb, bool signed_flag,
|
||||
bool net8_flag,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_netw_real(char*label, char*array_symbol,
|
||||
int msb, int lsb,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
|
||||
extern void compile_alias(char*label, char*name,
|
||||
int msb, int lsb, bool signed_flag,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
|
|
@ -346,6 +362,12 @@ extern void compile_alias_real(char*label, char*name,
|
|||
|
||||
/*
|
||||
* $Log: compile.h,v $
|
||||
* Revision 1.85 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.84 2006/11/22 06:10:05 steve
|
||||
* Fix spurious event from net8 that is forced.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: lexor.lex,v 1.64 2006/11/22 06:10:05 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.65 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "parse_misc.h"
|
||||
|
|
@ -96,6 +96,8 @@
|
|||
".arith/sub" { return K_ARITH_SUB; }
|
||||
".arith/sub.r" { return K_ARITH_SUB_R; }
|
||||
".arith/sum" { return K_ARITH_SUM; }
|
||||
".array" { return K_ARRAY; }
|
||||
".array/port" { return K_ARRAY_PORT; }
|
||||
".cmp/eeq" { return K_CMP_EEQ; }
|
||||
".cmp/eq" { return K_CMP_EQ; }
|
||||
".cmp/nee" { return K_CMP_NEE; }
|
||||
|
|
@ -212,6 +214,12 @@ int yywrap()
|
|||
|
||||
/*
|
||||
* $Log: lexor.lex,v $
|
||||
* Revision 1.65 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.64 2006/11/22 06:10:05 steve
|
||||
* Fix spurious event from net8 that is forced.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* $Id: opcodes.txt,v 1.72 2006/10/05 01:23:54 steve Exp $
|
||||
* $Id: opcodes.txt,v 1.73 2007/01/16 05:44:16 steve Exp $
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -57,7 +57,21 @@ means the following:
|
|||
1 and 1 --> 1
|
||||
otherwise x
|
||||
|
||||
* %assign/mv <memory-label>, <delay>, <bit>
|
||||
* %assign/av <array-label>, <delay>, <bit>
|
||||
|
||||
The %assign/av instruction assigns a vector value to a word in the
|
||||
labeled array. The <delay> is the delay in simulation time to the
|
||||
assignment (0 for non-blocking assignment) and the <bit> is the base
|
||||
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.
|
||||
|
||||
* %assign/mv <memory-label>, <delay>, <bit> (DEPRECATED)
|
||||
|
||||
the %assign/mv instruction assigns a vector value to a word in the
|
||||
labeled memory. The <delay> is the delay in simulation time to the
|
||||
|
|
@ -360,12 +374,11 @@ If the matching child instruction is still running, a %join suspends
|
|||
the calling thread until the child ends. If the child is already
|
||||
ended, then the %join does not block or yield the thread.
|
||||
|
||||
* %load/m <bit>, <memory-label> (OBSOLETE)
|
||||
* %load/av <bit>, <array-label>, <wid>
|
||||
|
||||
This instruction loads a value from a memory bit into the specified
|
||||
thread register bit. The memory bit is addressed by index register 3.
|
||||
Bit address zero is the LSB of the first memory word. This
|
||||
instruction loads only a single bit.
|
||||
This instruction loads a word from the specified array. The word
|
||||
address is in index register 3. The width should match the width of
|
||||
the array word.
|
||||
|
||||
* %load/mv <bit>, <memory-label>, <wid>
|
||||
|
||||
|
|
@ -535,6 +548,20 @@ register that contains the LSB of the vector, and the <wid> is the
|
|||
size of the vector. The width must exactly match the width of the
|
||||
signal.
|
||||
|
||||
* %set/av <array-label>, <bit>, <wid>
|
||||
|
||||
This sets a thread vector to an array word. The <array-label>
|
||||
addresses an array device, and the <bit>,<wid> describe a vector to be
|
||||
written. Index register 3 contains the address of the word within the
|
||||
array.
|
||||
|
||||
The base of a part select is retrieved from index register 1. The
|
||||
width is implied from the <wid> that is the argument. This is the part
|
||||
*within* the word.
|
||||
|
||||
The address (in canonical form) is precalculated and loaded into index
|
||||
register 3. This is the address of the word within the array.
|
||||
|
||||
* %set/mv <memory-label>, <bit>, <wid>
|
||||
|
||||
This sets a thread vector to a memory word. The <memory-label>
|
||||
|
|
|
|||
82
vvp/parse.y
82
vvp/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.86 2006/11/22 06:10:05 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.87 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "parse_misc.h"
|
||||
|
|
@ -67,7 +67,7 @@ static vvp_fun_modpath*modpath_dst = 0;
|
|||
|
||||
%token K_ALIAS K_ALIAS_S K_ALIAS_R
|
||||
%token K_ARITH_DIV K_ARITH_DIV_R K_ARITH_DIV_S K_ARITH_MOD K_ARITH_MULT
|
||||
%token K_ARITH_SUB K_ARITH_SUB_R K_ARITH_SUM
|
||||
%token K_ARITH_SUB K_ARITH_SUB_R K_ARITH_SUM K_ARRAY K_ARRAY_PORT
|
||||
%token K_CMP_EEQ K_CMP_EQ K_CMP_NEE K_CMP_NE
|
||||
%token K_CMP_GE K_CMP_GE_S K_CMP_GT K_CMP_GT_S
|
||||
%token K_CONCAT K_DEBUG K_DELAY K_DFF
|
||||
|
|
@ -177,8 +177,13 @@ statement
|
|||
|
||||
| mem_init_stmt
|
||||
|
||||
| T_LABEL K_ARRAY T_STRING ',' signed_t_number signed_t_number ';'
|
||||
{ compile_array($1, $3, $5, $6); }
|
||||
|
||||
| T_LABEL K_ARRAY_PORT T_SYMBOL ',' T_SYMBOL ';'
|
||||
{ compile_array_port($1, $3, $5); }
|
||||
|
||||
/* The .ufunc functor is for implementing user defined functions, or
|
||||
/* The .ufunc functor is for implementing user defined functions, or
|
||||
other thread code that is automatically invoked if any of the
|
||||
bits in the symbols list change. */
|
||||
|
||||
|
|
@ -476,52 +481,69 @@ statement
|
|||
creates a functor with the same name that acts as the output of
|
||||
the variable in the netlist. */
|
||||
|
||||
| T_LABEL K_VAR T_STRING ',' signed_t_number ',' signed_t_number ';'
|
||||
{ compile_variable($1, $3, $5, $7, 0 /* unsigned */ ); }
|
||||
| T_LABEL K_VAR T_STRING ',' signed_t_number signed_t_number ';'
|
||||
{ compile_variable($1, $3, $5, $6, 0 /* unsigned */ ); }
|
||||
|
||||
| T_LABEL K_VAR_S T_STRING ',' signed_t_number ',' signed_t_number ';'
|
||||
{ compile_variable($1, $3, $5, $7, 1 /* signed */ ); }
|
||||
| T_LABEL K_VAR_S T_STRING ',' signed_t_number signed_t_number ';'
|
||||
{ compile_variable($1, $3, $5, $6, 1 /* signed */ ); }
|
||||
|
||||
| T_LABEL K_VAR_I T_STRING ',' T_NUMBER ',' T_NUMBER ';'
|
||||
{ compile_variable($1, $3, $5, $7, 2 /* integer */); }
|
||||
| T_LABEL K_VAR_I T_STRING ',' T_NUMBER T_NUMBER ';'
|
||||
{ compile_variable($1, $3, $5, $6, 2 /* integer */); }
|
||||
|
||||
| T_LABEL K_VAR_R T_STRING ',' signed_t_number ',' signed_t_number ';'
|
||||
{ compile_var_real($1, $3, $5, $7); }
|
||||
| T_LABEL K_VAR_R T_STRING ',' signed_t_number signed_t_number ';'
|
||||
{ compile_var_real($1, $3, $5, $6); }
|
||||
|
||||
/* Arrayed versions of variable directives. */
|
||||
|
||||
| T_LABEL K_VAR T_SYMBOL ',' signed_t_number signed_t_number ';'
|
||||
{ compile_variablew($1, $3, $5, $6, 0 /* unsigned */ ); }
|
||||
|
||||
| T_LABEL K_VAR_S T_SYMBOL ',' signed_t_number signed_t_number ';'
|
||||
{ compile_variablew($1, $3, $5, $6, 1 /* signed */ ); }
|
||||
|
||||
| T_LABEL K_VAR_I T_SYMBOL ',' T_NUMBER T_NUMBER ';'
|
||||
{ compile_variablew($1, $3, $5, $6, 2 /* integer */); }
|
||||
|
||||
/* Net statements are similar to .var statements, except that they
|
||||
declare nets, and they have an input list. */
|
||||
|
||||
| T_LABEL K_NET T_STRING ',' signed_t_number ',' signed_t_number
|
||||
| T_LABEL K_NET T_STRING ',' signed_t_number signed_t_number
|
||||
',' symbols_net ';'
|
||||
{ compile_net($1, $3, $5, $7, false, false, $9.cnt, $9.vect); }
|
||||
{ compile_net($1, $3, $5, $6, false, false, $8.cnt, $8.vect); }
|
||||
|
||||
| T_LABEL K_NET_S T_STRING ',' signed_t_number ',' signed_t_number
|
||||
| T_LABEL K_NET_S T_STRING ',' signed_t_number signed_t_number
|
||||
',' symbols_net ';'
|
||||
{ compile_net($1, $3, $5, $7, true, false, $9.cnt, $9.vect); }
|
||||
{ compile_net($1, $3, $5, $6, true, false, $8.cnt, $8.vect); }
|
||||
|
||||
| T_LABEL K_NET8 T_STRING ',' signed_t_number ',' signed_t_number
|
||||
| T_LABEL K_NET8 T_STRING ',' signed_t_number signed_t_number
|
||||
',' symbols_net ';'
|
||||
{ compile_net($1, $3, $5, $7, false, true, $9.cnt, $9.vect); }
|
||||
{ compile_net($1, $3, $5, $6, false, true, $8.cnt, $8.vect); }
|
||||
|
||||
| T_LABEL K_NET8_S T_STRING ',' signed_t_number ',' signed_t_number
|
||||
| T_LABEL K_NET8_S T_STRING ',' signed_t_number signed_t_number
|
||||
',' symbols_net ';'
|
||||
{ compile_net($1, $3, $5, $7, true, true, $9.cnt, $9.vect); }
|
||||
{ compile_net($1, $3, $5, $6, true, true, $8.cnt, $8.vect); }
|
||||
|
||||
| T_LABEL K_NET_R T_STRING ',' signed_t_number ',' signed_t_number
|
||||
| T_LABEL K_NET_R T_STRING ',' signed_t_number signed_t_number
|
||||
',' symbols_net ';'
|
||||
{ compile_net_real($1, $3, $5, $7, $9.cnt, $9.vect); }
|
||||
{ compile_net_real($1, $3, $5, $6, $8.cnt, $8.vect); }
|
||||
|
||||
| T_LABEL K_ALIAS T_STRING ',' signed_t_number ',' signed_t_number
|
||||
| T_LABEL K_ALIAS T_STRING ',' signed_t_number signed_t_number
|
||||
',' symbols_net ';'
|
||||
{ compile_alias($1, $3, $5, $7, false, $9.cnt, $9.vect); }
|
||||
{ compile_alias($1, $3, $5, $6, false, $8.cnt, $8.vect); }
|
||||
|
||||
| T_LABEL K_ALIAS_S T_STRING ',' signed_t_number ',' signed_t_number
|
||||
| T_LABEL K_ALIAS_S T_STRING ',' signed_t_number signed_t_number
|
||||
',' symbols_net ';'
|
||||
{ compile_alias($1, $3, $5, $7, true, $9.cnt, $9.vect); }
|
||||
{ compile_alias($1, $3, $5, $6, true, $8.cnt, $8.vect); }
|
||||
|
||||
| T_LABEL K_ALIAS_R T_STRING ',' signed_t_number ',' signed_t_number
|
||||
| T_LABEL K_ALIAS_R T_STRING ',' signed_t_number signed_t_number
|
||||
',' symbols_net ';'
|
||||
{ compile_alias_real($1, $3, $5, $7, $9.cnt, $9.vect); }
|
||||
{ compile_alias_real($1, $3, $5, $6, $8.cnt, $8.vect); }
|
||||
|
||||
/* Arrayed versions of net directives. */
|
||||
|
||||
| T_LABEL K_NET T_SYMBOL ',' signed_t_number signed_t_number
|
||||
',' symbols_net ';'
|
||||
{ compile_netw($1, $3, $5, $6, false, false, $8.cnt, $8.vect); }
|
||||
|
||||
/* Parameter statements come in a few simple forms. The most basic
|
||||
is the string parameter. */
|
||||
|
|
@ -781,6 +803,12 @@ int compile_design(const char*path)
|
|||
|
||||
/*
|
||||
* $Log: parse.y,v $
|
||||
* Revision 1.87 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.86 2006/11/22 06:10:05 steve
|
||||
* Fix spurious event from net8 that is forced.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.44 2006/09/29 16:55:04 steve Exp $"
|
||||
#ident "$Id: schedule.cc,v 1.45 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "schedule.h"
|
||||
|
|
@ -147,6 +147,20 @@ void assign_memory_word_s::run_run(void)
|
|||
memory_set_word(mem, adr, off, val);
|
||||
}
|
||||
|
||||
struct assign_array_word_s : public event_s {
|
||||
vvp_array_t mem;
|
||||
unsigned adr;
|
||||
vvp_vector4_t val;
|
||||
unsigned off;
|
||||
void run_run(void);
|
||||
};
|
||||
|
||||
void assign_array_word_s::run_run(void)
|
||||
{
|
||||
count_assign_events += 1;
|
||||
array_set_word(mem, adr, off, val);
|
||||
}
|
||||
|
||||
struct generic_event_s : public event_s {
|
||||
vvp_gen_event_t obj;
|
||||
unsigned char val;
|
||||
|
|
@ -467,6 +481,20 @@ void schedule_assign_memory_word(vvp_memory_t mem,
|
|||
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
||||
}
|
||||
|
||||
void schedule_assign_array_word(vvp_array_t mem,
|
||||
unsigned word_addr,
|
||||
unsigned off,
|
||||
vvp_vector4_t val,
|
||||
vvp_time64_t delay)
|
||||
{
|
||||
struct assign_array_word_s*cur = new struct assign_array_word_s;
|
||||
cur->mem = mem;
|
||||
cur->adr = word_addr;
|
||||
cur->off = off;
|
||||
cur->val = val;
|
||||
schedule_event_(cur, delay, SEQ_NBASSIGN);
|
||||
}
|
||||
|
||||
void schedule_set_vector(vvp_net_ptr_t ptr, vvp_vector4_t bit)
|
||||
{
|
||||
struct assign_vector4_event_s*cur = new struct assign_vector4_event_s;
|
||||
|
|
@ -617,6 +645,12 @@ void schedule_simulate(void)
|
|||
|
||||
/*
|
||||
* $Log: schedule.cc,v $
|
||||
* Revision 1.45 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.44 2006/09/29 16:55:04 steve
|
||||
* Allow rosync events to create new rosync events.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,13 +19,14 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: schedule.h,v 1.28 2006/09/29 01:24:34 steve Exp $"
|
||||
#ident "$Id: schedule.h,v 1.29 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vthread.h"
|
||||
# include "pointers.h"
|
||||
# include "vvp_net.h"
|
||||
# include "memory.h"
|
||||
# include "array.h"
|
||||
|
||||
/*
|
||||
* This causes a thread to be scheduled for execution. The schedule
|
||||
|
|
@ -54,6 +55,11 @@ extern void schedule_assign_vector(vvp_net_ptr_t ptr,
|
|||
const vvp_vector4_t&val,
|
||||
vvp_time64_t delay);
|
||||
|
||||
extern void schedule_assign_array_word(vvp_array_t mem,
|
||||
unsigned word_address,
|
||||
unsigned off,
|
||||
vvp_vector4_t val,
|
||||
vvp_time64_t delay);
|
||||
extern void schedule_assign_memory_word(vvp_memory_t mem,
|
||||
unsigned word_address,
|
||||
unsigned off,
|
||||
|
|
@ -142,6 +148,12 @@ extern unsigned long count_event_pool;
|
|||
|
||||
/*
|
||||
* $Log: schedule.h,v $
|
||||
* Revision 1.29 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.28 2006/09/29 01:24:34 steve
|
||||
* rwsync callback fixes from Ben Staveley (with modifications.)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_callback.cc,v 1.44 2006/09/29 01:24:34 steve Exp $"
|
||||
#ident "$Id: vpi_callback.cc,v 1.45 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -436,11 +436,14 @@ void callback_execute(struct __vpiCallback*cur)
|
|||
vvp_vpi_callback::vvp_vpi_callback()
|
||||
{
|
||||
vpi_callbacks_ = 0;
|
||||
array_ = 0;
|
||||
array_word_ = 0;
|
||||
}
|
||||
|
||||
vvp_vpi_callback::~vvp_vpi_callback()
|
||||
{
|
||||
assert(vpi_callbacks_ == 0);
|
||||
assert(array_ == 0);
|
||||
}
|
||||
|
||||
void vvp_vpi_callback::add_vpi_callback(__vpiCallback*cb)
|
||||
|
|
@ -449,6 +452,13 @@ void vvp_vpi_callback::add_vpi_callback(__vpiCallback*cb)
|
|||
vpi_callbacks_ = cb;
|
||||
}
|
||||
|
||||
void vvp_vpi_callback::attach_as_word(vvp_array_t arr, unsigned long addr)
|
||||
{
|
||||
assert(array_ == 0);
|
||||
array_ = arr;
|
||||
array_word_ = addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* A vvp_fun_signal uses this method to run its callbacks whenever it
|
||||
* has a value change. If the cb_rtn is non-nil, then call the
|
||||
|
|
@ -460,6 +470,8 @@ void vvp_vpi_callback::run_vpi_callbacks()
|
|||
struct __vpiCallback *next = vpi_callbacks_;
|
||||
struct __vpiCallback *prev = 0;
|
||||
|
||||
if (array_) array_word_change(array_, array_word_);
|
||||
|
||||
while (next) {
|
||||
struct __vpiCallback*cur = next;
|
||||
next = cur->next;
|
||||
|
|
@ -576,6 +588,12 @@ void vvp_fun_signal_real::get_value(struct t_vpi_value*vp)
|
|||
|
||||
/*
|
||||
* $Log: vpi_callback.cc,v $
|
||||
* Revision 1.45 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.44 2006/09/29 01:24:34 steve
|
||||
* rwsync callback fixes from Ben Staveley (with modifications.)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_priv.h,v 1.71 2006/06/18 04:15:50 steve Exp $"
|
||||
#ident "$Id: vpi_priv.h,v 1.72 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_user.h"
|
||||
|
|
@ -170,7 +170,7 @@ extern void vpip_make_root_iterator(struct __vpiHandle**&table,
|
|||
struct __vpiSignal {
|
||||
struct __vpiHandle base;
|
||||
struct __vpiScope* scope;
|
||||
/* The name of this reg/net object */
|
||||
/* The name of this reg/net, or nil if this is an array word. */
|
||||
const char*name;
|
||||
/* The indices that define the width and access offset. */
|
||||
int msb, lsb;
|
||||
|
|
@ -187,6 +187,12 @@ extern vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
|
|||
extern vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
||||
bool signed_flag, vvp_net_t*node);
|
||||
|
||||
/*
|
||||
* This function safely converts a vpiHandle back to a
|
||||
* __vpiSignal. Return a nil if the type is not appropriate.
|
||||
*/
|
||||
extern __vpiSignal* vpip_signal_from_handle(vpiHandle obj);
|
||||
|
||||
|
||||
/*
|
||||
* These methods support the vpi creation of events. The name string
|
||||
|
|
@ -444,6 +450,12 @@ extern char *need_result_buf(unsigned cnt, vpi_rbuf_t type);
|
|||
|
||||
/*
|
||||
* $Log: vpi_priv.h,v $
|
||||
* Revision 1.72 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.71 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_signal.cc,v 1.75 2006/12/09 19:06:53 steve Exp $"
|
||||
#ident "$Id: vpi_signal.cc,v 1.76 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -75,15 +75,22 @@ char *need_result_buf(unsigned cnt, vpi_rbuf_t type)
|
|||
return result_buf[type];
|
||||
}
|
||||
|
||||
struct __vpiSignal* vpip_signal_from_handle(vpiHandle ref)
|
||||
{
|
||||
if ((ref->vpi_type->type_code != vpiNet)
|
||||
&& (ref->vpi_type->type_code != vpiReg))
|
||||
return 0;
|
||||
|
||||
return (struct __vpiSignal*)ref;
|
||||
}
|
||||
|
||||
/*
|
||||
* implement vpi_get for vpiReg objects.
|
||||
*/
|
||||
static int signal_get(int code, vpiHandle ref)
|
||||
{
|
||||
assert((ref->vpi_type->type_code==vpiNet)
|
||||
|| (ref->vpi_type->type_code==vpiReg));
|
||||
|
||||
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
|
||||
struct __vpiSignal*rfp = vpip_signal_from_handle(ref);
|
||||
assert(rfp);
|
||||
|
||||
switch (code) {
|
||||
|
||||
|
|
@ -581,31 +588,19 @@ static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp)
|
|||
}
|
||||
break;
|
||||
#endif
|
||||
#if 0
|
||||
case vpiVectorVal:
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
unsigned long aval = vp->value.vector[idx/32].aval;
|
||||
unsigned long bval = vp->value.vector[idx/32].bval;
|
||||
aval >>= idx%32;
|
||||
bval >>= idx%32;
|
||||
int bit = (aval&1) | ((bval<<1)&2);
|
||||
switch (bit) {
|
||||
case 0: /* zero */
|
||||
functor_poke(rfp,idx, 0, St0, 0);
|
||||
break;
|
||||
case 1: /* one */
|
||||
functor_poke(rfp,idx, 1, St1, 0);
|
||||
break;
|
||||
case 2: /* z */
|
||||
functor_poke(rfp,idx, 3, HiZ, 0);
|
||||
break;
|
||||
case 3: /* x */
|
||||
functor_poke(rfp,idx, 2, StX, 0);
|
||||
break;
|
||||
}
|
||||
int bitmask = (aval&1) | ((bval<<1)&2);
|
||||
static const vvp_bit4_t bit_table[4] = {
|
||||
BIT4_0, BIT4_1, BIT4_X, BIT4_Z };
|
||||
vvp_bit4_t bit = bit_table[bitmask];
|
||||
val.set_bit(idx, bit);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case vpiBinStrVal:
|
||||
vpip_bin_str_to_vec4(val, vp->value.str, false);
|
||||
break;
|
||||
|
|
@ -707,7 +702,7 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
|||
{
|
||||
struct __vpiSignal*obj = allocate_vpiSignal();
|
||||
obj->base.vpi_type = &vpip_net_rt;
|
||||
obj->name = vpip_name_string(name);
|
||||
obj->name = name? vpip_name_string(name) : 0;
|
||||
obj->msb = msb;
|
||||
obj->lsb = lsb;
|
||||
obj->signed_flag = signed_flag? 1 : 0;
|
||||
|
|
@ -724,6 +719,12 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
|||
|
||||
/*
|
||||
* $Log: vpi_signal.cc,v $
|
||||
* Revision 1.76 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.75 2006/12/09 19:06:53 steve
|
||||
* Handle vpiRealVal reads of signals, and real anyedge events.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.157 2006/10/05 01:23:54 steve Exp $"
|
||||
#ident "$Id: vthread.cc,v 1.158 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -536,6 +536,28 @@ bool of_ADDI(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* %assign/av <array>, <delay>, <bit>
|
||||
* This generates an assignment event to an array. Index register 0
|
||||
* contains the width of the vector (and the word) and index register
|
||||
* 3 contains the canonical address of the word in memory.
|
||||
*/
|
||||
bool of_ASSIGN_AV(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);
|
||||
|
||||
unsigned delay = cp->bit_idx[0];
|
||||
unsigned bit = cp->bit_idx[1];
|
||||
|
||||
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
|
||||
|
||||
schedule_assign_array_word(cp->array, adr, off, value, delay);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is %assign/v0 <label>, <delay>, <bit>
|
||||
* Index register 0 contains a vector width.
|
||||
|
|
@ -1886,15 +1908,34 @@ bool of_JOIN(vthread_t thr, vvp_code_t cp)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool of_LOAD_MEM(vthread_t thr, vvp_code_t cp)
|
||||
/*
|
||||
* %load/av <bit>, <array-label>, <wid> ;
|
||||
*
|
||||
* <bit> is the thread bit address for the result
|
||||
* <array-label> is the array to access, and
|
||||
* <wid> is the width of the word to read.
|
||||
*
|
||||
* The address of the word in the array is in index register 3.
|
||||
*/
|
||||
bool of_LOAD_AV(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
#if 0
|
||||
assert(cp->bit_idx[0] >= 4);
|
||||
unsigned char val = memory_get(cp->mem, thr->words[3].w_int);
|
||||
thr_put_bit(thr, cp->bit_idx[0], val);
|
||||
#else
|
||||
fprintf(stderr, "XXXX %%load/m is obsolete\n");
|
||||
#endif
|
||||
unsigned bit = cp->bit_idx[0];
|
||||
unsigned wid = cp->bit_idx[1];
|
||||
unsigned adr = thr->words[3].w_int;
|
||||
|
||||
vvp_vector4_t word = array_get_word(cp->array, adr);
|
||||
|
||||
if (word.size() != wid) {
|
||||
fprintf(stderr, "internal error: array width=%u, word.size()=%u, wid=%u\n",
|
||||
0, word.size(), wid);
|
||||
}
|
||||
assert(word.size() == wid);
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1, bit += 1) {
|
||||
vvp_bit4_t val = word.value(idx);
|
||||
thr_put_bit(thr, bit, val);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2863,6 +2904,25 @@ bool of_RELEASE_REG(vthread_t thr, vvp_code_t cp)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* This implements the "%set/av <label>, <bit>, <wid>" instruction. In
|
||||
* this case, the <label> is an array label, and the <bit> and <wid>
|
||||
* are the thread vector of a value to be written in.
|
||||
*/
|
||||
bool of_SET_AV(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);
|
||||
|
||||
array_set_word(cp->array, adr, off, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This implements the "%set/mv <label>, <bit>, <wid>" instruction. In
|
||||
* this case, the <label> is a memory label, and the <bit> and <wid>
|
||||
|
|
@ -3312,6 +3372,12 @@ bool of_JOIN_UFUNC(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
/*
|
||||
* $Log: vthread.cc,v $
|
||||
* Revision 1.158 2007/01/16 05:44:16 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.157 2006/10/05 01:23:54 steve
|
||||
* Handle non-constant delays on indexed non-blocking assignments.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: vvp_net.h,v 1.53 2006/12/09 19:06:53 steve Exp $"
|
||||
#ident "$Id: vvp_net.h,v 1.54 2007/01/16 05:44:17 steve Exp $"
|
||||
|
||||
# include "config.h"
|
||||
# include <stddef.h>
|
||||
|
|
@ -765,6 +765,10 @@ class vvp_fun_extend_signed : public vvp_net_fun_t {
|
|||
* propagate starting at the next input change.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Things derived from vvp_vpi_callback may also be array'ed, so it
|
||||
* includes some members that arrays use.
|
||||
*/
|
||||
class vvp_vpi_callback {
|
||||
|
||||
public:
|
||||
|
|
@ -776,8 +780,12 @@ class vvp_vpi_callback {
|
|||
|
||||
virtual void get_value(struct t_vpi_value*value) =0;
|
||||
|
||||
void attach_as_word(class __vpiArray* arr, unsigned long addr);
|
||||
|
||||
private:
|
||||
struct __vpiCallback*vpi_callbacks_;
|
||||
class __vpiArray* array_;
|
||||
unsigned long array_word_;
|
||||
};
|
||||
|
||||
class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_vpi_callback {
|
||||
|
|
@ -1027,6 +1035,12 @@ inline void vvp_send_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&val,
|
|||
|
||||
/*
|
||||
* $Log: vvp_net.h,v $
|
||||
* Revision 1.54 2007/01/16 05:44:17 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.53 2006/12/09 19:06:53 steve
|
||||
* Handle vpiRealVal reads of signals, and real anyedge events.
|
||||
*
|
||||
|
|
|
|||
81
vvp/words.cc
81
vvp/words.cc
|
|
@ -17,11 +17,12 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: words.cc,v 1.7 2005/11/27 16:47:14 steve Exp $"
|
||||
#ident "$Id: words.cc,v 1.8 2007/01/16 05:44:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "compile.h"
|
||||
# include "vpi_priv.h"
|
||||
# include "array.h"
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
|
|
@ -51,13 +52,17 @@ void compile_var_real(char*label, char*name, int msb, int lsb)
|
|||
* A variable is a special functor, so we allocate that functor and
|
||||
* write the label into the symbol table.
|
||||
*/
|
||||
void compile_variable(char*label, char*name, int msb, int lsb,
|
||||
char signed_flag)
|
||||
static void __compile_var(char*label, char*name, char*array_label,
|
||||
int msb, int lsb, char signed_flag)
|
||||
{
|
||||
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
|
||||
|
||||
vvp_fun_signal*vsig = new vvp_fun_signal(wid);
|
||||
vvp_net_t*node = new vvp_net_t;
|
||||
|
||||
vvp_array_t array = array_label? array_find(array_label) : 0;
|
||||
assert(array_label? array!=0 : true);
|
||||
|
||||
node->fun = vsig;
|
||||
define_functor_symbol(label, node);
|
||||
|
||||
|
|
@ -66,10 +71,33 @@ void compile_variable(char*label, char*name, int msb, int lsb,
|
|||
vpip_make_int(name, msb, lsb, node) :
|
||||
vpip_make_reg(name, msb, lsb, signed_flag!=0, node);
|
||||
compile_vpi_symbol(label, obj);
|
||||
vpip_attach_to_current_scope(obj);
|
||||
|
||||
// If the signal has a name, then it goes into the current
|
||||
// scope as a signal.
|
||||
if (name) {
|
||||
assert(!array);
|
||||
vpip_attach_to_current_scope(obj);
|
||||
}
|
||||
// If this is an array word, then it does not have a name, and
|
||||
// it is attached to the addressed array.
|
||||
if (array) {
|
||||
assert(!name);
|
||||
array_attach_word(array, obj);
|
||||
}
|
||||
free(label);
|
||||
free(name);
|
||||
if (name) free(name);
|
||||
if (array_label) free(array_label);
|
||||
}
|
||||
|
||||
void compile_variable(char*label, char*name,
|
||||
int msb, int lsb, char signed_flag)
|
||||
{
|
||||
__compile_var(label, name, 0, msb, lsb, signed_flag);
|
||||
}
|
||||
|
||||
void compile_variablew(char*label, char*array_label,
|
||||
int msb, int lsb, char signed_flag)
|
||||
{
|
||||
__compile_var(label, 0, array_label, msb, lsb, signed_flag);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -83,14 +111,18 @@ void compile_variable(char*label, char*name, int msb, int lsb,
|
|||
* Create a VPI handle to represent it, and fill that handle in with
|
||||
* references into the net.
|
||||
*/
|
||||
void compile_net(char*label, char*name, int msb, int lsb,
|
||||
bool signed_flag, bool net8_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
static void __compile_net(char*label, char*name, char*array_label,
|
||||
int msb, int lsb,
|
||||
bool signed_flag, bool net8_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
|
||||
|
||||
vvp_net_t*node = new vvp_net_t;
|
||||
|
||||
vvp_array_t array = array_label? array_find(array_label) : 0;
|
||||
assert(array_label? array!=0 : true);
|
||||
|
||||
vvp_fun_signal_base*vsig = net8_flag
|
||||
? dynamic_cast<vvp_fun_signal_base*>(new vvp_fun_signal8(wid))
|
||||
: dynamic_cast<vvp_fun_signal_base*>(new vvp_fun_signal(wid));
|
||||
|
|
@ -108,12 +140,35 @@ void compile_net(char*label, char*name, int msb, int lsb,
|
|||
vpiHandle obj = vpip_make_net(name, msb, lsb, signed_flag, node);
|
||||
compile_vpi_symbol(label, obj);
|
||||
vpip_attach_to_current_scope(obj);
|
||||
if (array)
|
||||
array_attach_word(array, obj);
|
||||
|
||||
free(label);
|
||||
free(name);
|
||||
if (name) free(name);
|
||||
if (array_label) free(array_label);
|
||||
free(argv);
|
||||
}
|
||||
|
||||
void compile_net(char*label, char*name,
|
||||
int msb, int lsb,
|
||||
bool signed_flag, bool net8_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
__compile_net(label, name, 0,
|
||||
msb, lsb, signed_flag, net8_flag,
|
||||
argc, argv);
|
||||
}
|
||||
|
||||
void compile_netw(char*label, char*array_label,
|
||||
int msb, int lsb,
|
||||
bool signed_flag, bool net8_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
__compile_net(label, 0, array_label,
|
||||
msb, lsb, signed_flag, net8_flag,
|
||||
argc, argv);
|
||||
}
|
||||
|
||||
void compile_net_real(char*label, char*name, int msb, int lsb,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
|
|
@ -186,6 +241,12 @@ void compile_alias_real(char*label, char*name, int msb, int lsb,
|
|||
|
||||
/*
|
||||
* $Log: words.cc,v $
|
||||
* Revision 1.8 2007/01/16 05:44:17 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.7 2005/11/27 16:47:14 steve
|
||||
* Fix type safety warning from gcc.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue