Fix handling of exploded memories with partial or missing resets.

This commit is contained in:
steve 2006-04-16 19:26:37 +00:00
parent 058dac4290
commit f02b2c9d7a
12 changed files with 273 additions and 99 deletions

View File

@ -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.149.2.4 2006/03/26 23:09:21 steve Exp $"
#ident "$Id: design_dump.cc,v 1.149.2.5 2006/04/16 19:26:37 steve Exp $"
#endif
# include "config.h"
@ -227,7 +227,8 @@ void NetDecode::dump_node(ostream&o, unsigned ind) const
void NetDemux::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_DEMUX (NetDemux): " << name()
<< " word width=" << width() << ", address width=" << awidth() << endl;
<< " bus width=" << width() << ", address width=" << awidth()
<< ", word count=" << size() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@ -288,7 +289,8 @@ void NetFF::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_FF: " << name()
<< " scope=" << (scope()? scope()->name() : "")
<< " aset_value=" << aset_value_;
<< " aset_value=" << aset_value_
<< " sset_value=" << sset_value_;
if (demux_) o << " demux=" << demux_->name();
@ -1117,6 +1119,9 @@ void Design::dump(ostream&o) const
/*
* $Log: design_dump.cc,v $
* Revision 1.149.2.5 2006/04/16 19:26:37 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.149.2.4 2006/03/26 23:09:21 steve
* Handle asynchronous demux/bit replacements.
*

View File

@ -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.126.2.4 2006/03/26 23:09:22 steve Exp $"
#ident "$Id: ivl_target.h,v 1.126.2.5 2006/04/16 19:26:37 steve Exp $"
#endif
#ifdef __cplusplus
@ -708,12 +708,23 @@ extern const char* ivl_udp_name(ivl_udp_t net);
* idx the bit within the word.
*
* - IVL_LPM_DEMUX
* This device is a form of bit replacement. The device has a data
* This device is a form of bit replacement. The device has a data bus
* width (ivl_lpm_width) and an address width. The Data outputs are
* ivl_lpm_q and have the data width. The ivl_lpm_data functions are
* ivl_lpm_q and have the data bus width. The ivl_lpm_data functions are
* inputs to the device. Normally, the device passes the data inputs
* through to the Q output.
*
* The IVL_LPM_DEMUX also has a size (ivl_lpm_size) which is the
* number of addressable units in the device. If the device is bit-
* addressable, then the size is the same as the width. I.e. if
* ivl_lpm_width == ivl_lpm_size, then the address selects a single
* bit. If ivl_lpm_width/ivl_lpm_size == 8, then the address selects
* words of 8 bits and there are ivl_lpm_size of them. The
* ivl_lpm_width will always be an exact multiple of
* ivl_lpm_size. This is slightly different from the meaning of width
* in memory ports, but reflects that the DEMUX manipulates fixed
* width ranges within a single vector.
*
* The ivl_lpm_select inputs address a bit of the device. The
* addressed bit is substituted by the replacement bit. This
* replacement bit comes from the ivl_lpm_datab(net,0) nexus.
@ -760,7 +771,7 @@ extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
extern unsigned ivl_lpm_selects(ivl_lpm_t net);
/* IVL_LPM_MUX IVL_LPM_DECODE IVL_LPM_DEMUX IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_MUX, IVL_LPM_RAM */
/* IVL_LPM_DEMUX, IVL_LPM_MUX, IVL_LPM_RAM */
extern unsigned ivl_lpm_size(ivl_lpm_t net);
/* IVL_LPM_RAM */
extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
@ -1301,6 +1312,9 @@ _END_DECL
/*
* $Log: ivl_target.h,v $
* Revision 1.126.2.5 2006/04/16 19:26:37 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.126.2.4 2006/03/26 23:09:22 steve
* Handle asynchronous demux/bit replacements.
*

View File

@ -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.18.2.1 2006/03/12 07:34:17 steve Exp $"
#ident "$Id: net_assign.cc,v 1.18.2.2 2006/04/16 19:26:38 steve Exp $"
#endif
# include "config.h"
@ -61,6 +61,7 @@ NetAssign_::NetAssign_(NetVariable*s)
loff_ = 0;
lwid_ = 0;
more = 0;
mem_lref_ = 0;
}
NetAssign_::~NetAssign_()
@ -73,7 +74,7 @@ NetAssign_::~NetAssign_()
if (mem_) {
NetNet*exp = mem_->reg_from_explode();
if (exp) {
if (exp && mem_lref_) {
exp->decr_lref();
if (turn_sig_to_wire_on_release_ && exp->peek_lref() == 0)
exp->type(NetNet::WIRE);
@ -135,6 +136,16 @@ NetVariable* NetAssign_::var() const
return var_;
}
void NetAssign_::incr_mem_lref()
{
if (! mem_lref_) {
assert(mem_);
NetNet*exp = mem_->reg_from_explode();
assert(exp);
exp->incr_lref();
mem_lref_ = true;
}
}
void NetAssign_::set_part(unsigned lo, unsigned lw)
{
@ -272,6 +283,9 @@ NetAssignNB::~NetAssignNB()
/*
* $Log: net_assign.cc,v $
* Revision 1.18.2.2 2006/04/16 19:26:38 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.18.2.1 2006/03/12 07:34:17 steve
* Fix the memsynth1 case.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_nex_output.cc,v 1.11.2.2 2006/03/12 07:34:17 steve Exp $"
#ident "$Id: net_nex_output.cc,v 1.11.2.3 2006/04/16 19:26:38 steve Exp $"
#endif
# include "config.h"
@ -76,11 +76,11 @@ void NetAssignBase::nex_output(NexusSet&out)
out.add(tmp->pin(adr+idx).nexus());
} else {
/* Fake an address of 0. The context will
actually shove a decoder in place here. */
long adr= 0;
for (unsigned idx = 0; idx < cur->lwidth(); idx += 1)
out.add(tmp->pin(adr+idx).nexus());
/* Put all the bits of the memory into the
set. The synthesis will generate a
decoder to handle this. */
for (unsigned idx = 0; idx < tmp->pin_count(); idx+=1)
out.add(tmp->pin(idx).nexus());
}
} else {
@ -154,6 +154,9 @@ void NetWhile::nex_output(NexusSet&out)
/*
* $Log: net_nex_output.cc,v $
* Revision 1.11.2.3 2006/04/16 19:26:38 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.11.2.2 2006/03/12 07:34:17 steve
* Fix the memsynth1 case.
*

View File

@ -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.226.2.5 2006/03/26 23:09:22 steve Exp $"
#ident "$Id: netlist.cc,v 1.226.2.6 2006/04/16 19:26:38 steve Exp $"
#endif
# include "config.h"
@ -722,11 +722,12 @@ unsigned NetDecode::awidth() const
}
NetDemux::NetDemux(NetScope*s, perm_string name,
unsigned word_width, unsigned address_width)
: NetNode(s, name, word_width*2+address_width+1)
unsigned bus_width, unsigned address_width, unsigned size)
: NetNode(s, name, bus_width*2+address_width+bus_width/size)
{
width_ = word_width;
width_ = bus_width;
awidth_ = address_width;
size_ = size;
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
pin_Q(idx).set_dir(Link::OUTPUT);
@ -740,8 +741,10 @@ NetDemux::NetDemux(NetScope*s, perm_string name,
pin_Address(idx).set_dir(Link::INPUT);
pin_Address(idx).set_name(perm_string::literal("Address"), idx);
}
pin_WriteData().set_dir(Link::INPUT);
pin_WriteData().set_name(perm_string::literal("Writedata"), 0);
for (unsigned idx = 0 ; idx < width_/size_ ; idx += 1) {
pin_WriteData(idx).set_dir(Link::INPUT);
pin_WriteData(idx).set_name(perm_string::literal("Writedata"), idx);
}
}
NetDemux::~NetDemux()
@ -758,6 +761,11 @@ unsigned NetDemux::awidth() const
return awidth_;
}
unsigned NetDemux::size() const
{
return size_;
}
Link& NetDemux::pin_Q(unsigned idx)
{
assert(idx < width_);
@ -794,14 +802,16 @@ const Link& NetDemux::pin_Address(unsigned idx) const
return pin(width_+width_+idx);
}
Link& NetDemux::pin_WriteData()
Link& NetDemux::pin_WriteData(unsigned idx)
{
return pin(width_+width_+awidth_);
assert(idx < width_/size_);
return pin(width_+width_+awidth_+idx);
}
const Link& NetDemux::pin_WriteData() const
const Link& NetDemux::pin_WriteData(unsigned idx) const
{
return pin(width_+width_+awidth_);
assert(idx < width_/size_);
return pin(width_+width_+awidth_+idx);
}
NetDecode* NetFF::get_demux()
@ -2211,7 +2221,7 @@ NetNet* NetMemory::explode_to_reg()
return explode_;
explode_ = new NetNet(scope_, name_, NetNet::REG, count()*width_);
explode_->mref(this);
//explode_->incr_lref();
return explode_;
}
@ -2471,6 +2481,9 @@ const NetProc*NetTaskDef::proc() const
/*
* $Log: netlist.cc,v $
* Revision 1.226.2.6 2006/04/16 19:26:38 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.226.2.5 2006/03/26 23:09:22 steve
* Handle asynchronous demux/bit replacements.
*

View File

@ -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.321.2.15 2006/04/10 03:43:39 steve Exp $"
#ident "$Id: netlist.h,v 1.321.2.16 2006/04/16 19:26:38 steve Exp $"
#endif
/*
@ -645,31 +645,35 @@ class NetDemux : public NetNode {
public:
NetDemux(NetScope*s, perm_string name,
unsigned word_width, unsigned address_width);
unsigned bus_width, unsigned address_width,
unsigned size);
~NetDemux();
// This is the width of the word. The width of the NetFF mem
// is an even multiple of this.
// This is the width of the bus that passes through the
// device. The address addresses into this width.
unsigned width() const;
// This is the width of the address. The address value for the
// base of a word is the address * width().
unsigned awidth() const;
// This is the number of words in the width that can be
// addressed. This implies (by division) the width of a word.
unsigned size() const;
Link& pin_Address(unsigned idx);
Link& pin_Data(unsigned idx);
Link& pin_Q(unsigned idx);
Link& pin_WriteData();
Link& pin_WriteData(unsigned idx);
const Link& pin_Address(unsigned idx) const;
const Link& pin_Data(unsigned idx) const;
const Link& pin_Q(unsigned idx) const;
const Link& pin_WriteData() const;
const Link& pin_WriteData(unsigned idx) const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
private:
unsigned width_, awidth_;
unsigned width_, awidth_, size_;
private:
void make_pins_(unsigned wid, unsigned awid);
@ -1564,6 +1568,8 @@ class NetAssign_ {
// into a wire.
void turn_sig_to_wire_on_release();
void incr_mem_lref();
// It is possible that l-values can have *inputs*, as well as
// being outputs. For example foo[idx] = ... is the l-value
// (NetAssign_ object) with a foo l-value and the input
@ -1584,6 +1590,7 @@ class NetAssign_ {
bool turn_sig_to_wire_on_release_;
unsigned loff_;
unsigned lwid_;
bool mem_lref_;
};
class NetAssignBase : public NetProc {
@ -1627,6 +1634,11 @@ class NetAssignBase : public NetProc {
void dump_lval(ostream&) const;
virtual void dump(ostream&, unsigned ind) const;
private:
bool synth_async_mem_sync_(Design*des, NetScope*scope,
NetAssign_*cur, NetNet*rsig, unsigned&roff,
NetNet*nex_map, NetNet*nex_out);
private:
NetAssign_*lval_;
NetExpr *rval_;
@ -3512,6 +3524,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.321.2.16 2006/04/16 19:26:38 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.321.2.15 2006/04/10 03:43:39 steve
* Exploded memories accessed by constant indices.
*

109
synth2.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: synth2.cc,v 1.39.2.28 2006/04/10 03:43:40 steve Exp $"
#ident "$Id: synth2.cc,v 1.39.2.29 2006/04/16 19:26:39 steve Exp $"
#endif
# include "config.h"
@ -126,19 +126,8 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag,
sync_flag must be true in this case. */
if (lmem) {
assert(sync_flag);
NetNet*msig = lmem->explode_to_reg();
msig->incr_lref();
if (NetEConst*ae = dynamic_cast<NetEConst*>(cur->bmux())) {
long adr= ae->value().as_long();
adr = lmem->index_to_address(adr) * lmem->width();
for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) {
unsigned off = adr+idx;
unsigned ptr = find_nexus_in_set(nex_map, msig->pin(off).nexus());
assert(ptr <= nex_map->pin_count());
connect(nex_out->pin(ptr), rsig->pin(roff+idx));
}
}
synth_async_mem_sync_(des, scope, cur, rsig, roff,
nex_map, nex_out);
continue;
}
@ -171,7 +160,8 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag,
NetDemux*dq = new NetDemux(scope, scope->local_symbol(),
lsig->pin_count(),
adr->pin_count());
adr->pin_count(),
lsig->pin_count());
des->add_node(dq);
dq->set_line(*this);
@ -190,7 +180,7 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag,
for (unsigned idx = 0 ; idx < lsig->pin_count(); idx += 1)
connect(dq->pin_Data(idx), nex_map->pin(roff+idx));
connect(dq->pin_WriteData(), rsig->pin(roff));
connect(dq->pin_WriteData(0), rsig->pin(roff));
roff += cur->lwidth();
cur->turn_sig_to_wire_on_release();
@ -224,6 +214,73 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag,
return true;
}
/*
* Handle the special case of assignment to memory. Explode the memory
* to an array of reg bits. The context that is calling this will
* attach a decoder between the ff and the r-val. In fact, the memory
* at this point has already been scanned and exploded, so the
* explode_to_reg method below will return a pre-existing vector.
*/
bool NetAssignBase::synth_async_mem_sync_(Design*des, NetScope*scope,
NetAssign_*cur,
NetNet*rsig, unsigned&roff,
NetNet*nex_map, NetNet*nex_out)
{
NetMemory*lmem = cur->mem();
assert(lmem);
NetNet*msig = lmem->explode_to_reg();
cur->incr_mem_lref();
/* Handle the special case that the mux expression is
constant. In this case, just hook up the pertinent bits. */
if (NetEConst*ae = dynamic_cast<NetEConst*>(cur->bmux())) {
long adr= ae->value().as_long();
adr = lmem->index_to_address(adr) * lmem->width();
for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) {
unsigned off = adr+idx;
unsigned ptr = find_nexus_in_set(nex_map, msig->pin(off).nexus());
assert(ptr <= nex_map->pin_count());
connect(nex_out->pin(ptr), rsig->pin(roff+idx));
}
cur->turn_sig_to_wire_on_release();
return true;
}
assert(cur->bmux() != 0);
NetNet*adr = cur->bmux()->synthesize(des);
NetDemux*dq = new NetDemux(scope, scope->local_symbol(),
msig->pin_count(),
adr->pin_count(),
msig->pin_count() / cur->lwidth());
des->add_node(dq);
dq->set_line(*this);
for (unsigned idx = 0; idx < adr->pin_count() ; idx += 1)
connect(dq->pin_Address(idx), adr->pin(idx));
for (unsigned idx = 0; idx < msig->pin_count(); idx += 1) {
unsigned off = idx;
unsigned ptr = find_nexus_in_set(nex_map, msig->pin(off).nexus());
assert(ptr <= nex_map->pin_count());
connect(nex_out->pin(ptr), dq->pin_Q(idx));
}
for (unsigned idx = 0 ; idx < msig->pin_count(); idx += 1)
connect(dq->pin_Data(idx), nex_map->pin(roff+idx));
for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1)
connect(dq->pin_WriteData(idx), rsig->pin(roff+idx));
roff += cur->lwidth();
cur->turn_sig_to_wire_on_release();
return true;
}
/*
* Sequential blocks are translated to asynchronous logic by
* translating each statement of the block, in order, into gates. The
@ -951,7 +1008,7 @@ bool NetAssignBase::synth_sync(Design*des, NetScope*scope,
if (demux->mem() && dynamic_cast<NetEConst*>(demux->bmux())) {
NetMemory*lmem = demux->mem();
NetNet*msig = lmem->explode_to_reg();
msig->incr_lref();
demux->incr_mem_lref();
NetEConst*ae = dynamic_cast<NetEConst*>(demux->bmux());
long adr = ae->value().as_long();
@ -985,7 +1042,7 @@ bool NetAssignBase::synth_sync(Design*des, NetScope*scope,
if (lval_->mem()) {
NetNet*exp = lval_->mem()->reg_from_explode();
assert(exp);
exp->incr_lref();
lval_->incr_mem_lref();
}
lval_->turn_sig_to_wire_on_release();
return true;
@ -1441,17 +1498,22 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope,
break;
}
if (! tmp.is_defined())
cerr << get_line() << ": internal error: "
<< "Strange clr r-value=" << tmp << endl;
assert(tmp.is_defined());
if (tmp.is_zero()) {
connect(ff->pin_Sclr(), rst->pin(0));
if (debug_synth)
cerr << get_line() << ": debug: "
<< "Create a synchronous clr (set=0) for "
<< ff->width() << " bit ff." << endl;
} else {
connect(ff->pin_Sset(), rst->pin(0));
ff->sset_value(tmp);
if (debug_synth)
cerr << get_line() << ": debug: "
<< "Create a synchronous set for "
<< ff->width() << " bit ff." << endl;
}
delete a_set;
@ -1748,6 +1810,9 @@ void synth2(Design*des)
/*
* $Log: synth2.cc,v $
* Revision 1.39.2.29 2006/04/16 19:26:39 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.39.2.28 2006/04/10 03:43:40 steve
* Exploded memories accessed by constant indices.
*

View File

@ -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.108.2.4 2006/03/26 23:09:24 steve Exp $"
#ident "$Id: t-dll-api.cc,v 1.108.2.5 2006/04/16 19:26:40 steve Exp $"
#endif
# include "config.h"
@ -806,8 +806,8 @@ extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx)
return net->u_.arith.b[idx];
case IVL_LPM_DEMUX:
assert(idx < 1);
return net->u_.demux.bit_in;
assert(idx < net->u_.demux.width/net->u_.demux.size);
return net->u_.demux.bit_in[idx];
default:
assert(0);
@ -1058,6 +1058,8 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
{
switch (net->type) {
case IVL_LPM_DEMUX:
return net->u_.demux.size;
case IVL_LPM_MUX:
return net->u_.mux.size;
case IVL_LPM_RAM:
@ -2002,6 +2004,9 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
/*
* $Log: t-dll-api.cc,v $
* Revision 1.108.2.5 2006/04/16 19:26:40 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.108.2.4 2006/03/26 23:09:24 steve
* Handle asynchronous demux/bit replacements.
*

View File

@ -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.131.2.6 2006/03/26 23:09:24 steve Exp $"
#ident "$Id: t-dll.cc,v 1.131.2.7 2006/04/16 19:26:40 steve Exp $"
#endif
# include "config.h"
@ -1552,6 +1552,7 @@ bool dll_target::lpm_demux(const NetDemux*net)
unsigned idx;
unsigned width = net->width();
unsigned awid = net->awidth();
unsigned size = net->size();
ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_DEMUX;
obj->name = net->name();
@ -1562,11 +1563,13 @@ bool dll_target::lpm_demux(const NetDemux*net)
obj->u_.demux.width = width;
obj->u_.demux.awid = awid;
obj->u_.demux.size = net->size();
ivl_nexus_t*tmp = new ivl_nexus_t [2*net->width() + net->awidth()];
ivl_nexus_t*tmp = new ivl_nexus_t [2*width + awid + width/size];
obj->u_.demux.q = tmp;
obj->u_.demux.d = tmp + width;
obj->u_.demux.a = tmp + 2*width;
obj->u_.demux.bit_in = tmp + 2*width + awid;
for (idx = 0 ; idx < width ; idx += 1) {
const Nexus*nex = net->pin_Q(idx).nexus();
@ -1592,11 +1595,11 @@ bool dll_target::lpm_demux(const NetDemux*net)
IVL_DR_HiZ, IVL_DR_HiZ);
}
{
const Nexus*nex = net->pin_WriteData().nexus();
for (idx = 0 ; idx < width/size ; idx += 1) {
const Nexus*nex = net->pin_WriteData(idx).nexus();
assert(nex->t_cookie());
obj->u_.demux.bit_in = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.demux.bit_in, obj, 0,
obj->u_.demux.bit_in[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.demux.bit_in[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ);
}
@ -2331,6 +2334,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/*
* $Log: t-dll.cc,v $
* Revision 1.131.2.7 2006/04/16 19:26:40 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.131.2.6 2006/03/26 23:09:24 steve
* Handle asynchronous demux/bit replacements.
*

View File

@ -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.115.2.4 2006/03/26 23:09:25 steve Exp $"
#ident "$Id: t-dll.h,v 1.115.2.5 2006/04/16 19:26:40 steve Exp $"
#endif
# include "target.h"
@ -346,7 +346,8 @@ struct ivl_lpm_s {
struct ivl_lpm_demux_s {
unsigned width;
unsigned awid;
ivl_nexus_t bit_in;
unsigned size;
ivl_nexus_t*bit_in;
ivl_nexus_t *q,*d,*a;
} demux;
@ -702,6 +703,9 @@ struct ivl_variable_s {
/*
* $Log: t-dll.h,v $
* Revision 1.115.2.5 2006/04/16 19:26:40 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.115.2.4 2006/03/26 23:09:25 steve
* Handle asynchronous demux/bit replacements.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: stub.c,v 1.90.2.8 2006/03/26 23:09:25 steve Exp $"
#ident "$Id: stub.c,v 1.90.2.9 2006/04/16 19:26:41 steve Exp $"
#endif
# include "config.h"
@ -238,9 +238,14 @@ static void show_lpm_demux(ivl_lpm_t net)
unsigned idx;
unsigned width = ivl_lpm_width(net);
unsigned awid = ivl_lpm_selects(net);
unsigned size = ivl_lpm_size(net);
fprintf(out, " LPM_DEMUX %s (word-width=%u, addr-width=%u)\n",
ivl_lpm_basename(net), width, awid);
fprintf(out, " LPM_DEMUX %s (bus-width=%u, addr-width=%u, size=%u)\n",
ivl_lpm_basename(net), width, awid, size);
if (width%size != 0) {
fprintf(out, " ERROR: width %% size == %u\n", width%size);
}
for (idx = 0 ; idx < width ; idx += 1)
fprintf(out, " Q %u: %s\n", idx,
@ -256,9 +261,9 @@ static void show_lpm_demux(ivl_lpm_t net)
nex? ivl_nexus_name(nex) : "");
}
{
ivl_nexus_t nex = ivl_lpm_datab(net, 0);
fprintf(out, " WriteIn: %s\n",
for (idx = 0 ; idx < width/size ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_datab(net, idx);
fprintf(out, " WriteIn %u: %s\n", idx,
nex? ivl_nexus_name(nex) : "");
}
}
@ -463,6 +468,8 @@ static void show_lpm(ivl_lpm_t net)
if (ivl_lpm_sync_set(net)) {
fprintf(out, " Sset: %s\n",
ivl_nexus_name(ivl_lpm_sync_set(net)));
if (ivl_lpm_sset_value(net))
show_expression(ivl_lpm_sset_value(net), 10);
}
for (idx = 0 ; idx < width ; idx += 1)
@ -1107,6 +1114,9 @@ int target_design(ivl_design_t des)
/*
* $Log: stub.c,v $
* Revision 1.90.2.9 2006/04/16 19:26:41 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.90.2.8 2006/03/26 23:09:25 steve
* Handle asynchronous demux/bit replacements.
*

View File

@ -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.103.2.5 2006/03/26 23:09:26 steve Exp $"
#ident "$Id: vvp_scope.c,v 1.103.2.6 2006/04/16 19:26:41 steve Exp $"
#endif
# include "vvp_priv.h"
@ -1302,41 +1302,47 @@ static void draw_lpm_decode(ivl_lpm_t net)
*/
static void draw_lpm_demux(ivl_lpm_t net)
{
unsigned idx;
unsigned idx, wbit;
unsigned width = ivl_lpm_width(net);
unsigned size = ivl_lpm_size(net);
unsigned word = width / size;
assert(width%size == 0);
/* Draw a .decode/adr node to do address decoding. */
draw_lpm_decode(net);
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t nex;
for (wbit = 0 ; wbit < word ; wbit += 1) {
for (idx = wbit ; idx < width ; idx += word) {
ivl_nexus_t nex;
/* This is a demux bit slice idx */
fprintf(vvp_out, "L_%s.%s/%u .demux ",
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)), idx);
/* This is a demux bit slice idx */
fprintf(vvp_out, "L_%s.%s/%u .demux ",
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)), idx);
/* Reference the address decoder... */
fprintf(vvp_out, "L_%s.%s, %u, ",
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)), idx);
/* Reference the address decoder... */
fprintf(vvp_out, "L_%s.%s, %u, ",
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)), idx/word);
/* not-selected bit value. */
nex = ivl_lpm_data(net, idx);
if (nex)
draw_input_from_net(nex);
else
fprintf(vvp_out, "C<z>");
/* not-selected bit value. */
nex = ivl_lpm_data(net, idx);
if (nex)
draw_input_from_net(nex);
else
fprintf(vvp_out, "C<z>");
/* selected bit value. */
fprintf(vvp_out, ", ");
nex = ivl_lpm_datab(net, 0);
if (nex)
draw_input_from_net(nex);
else
fprintf(vvp_out, "C<z>");
/* selected bit value. */
fprintf(vvp_out, ", ");
nex = ivl_lpm_datab(net, wbit);
if (nex)
draw_input_from_net(nex);
else
fprintf(vvp_out, "C<z>");
fprintf(vvp_out, ";\n");
fprintf(vvp_out, ";\n");
}
}
}
@ -1390,7 +1396,9 @@ static void draw_lpm_eq(ivl_lpm_t net)
static void draw_lpm_ff(ivl_lpm_t net)
{
ivl_expr_t aset_expr = 0;
ivl_expr_t sset_expr = 0;
const char*aset_bits = 0;
const char*sset_bits = 0;
unsigned width, idx;
ivl_attribute_t clock_pol = find_lpm_attr(net, "ivl:clock_polarity");
@ -1439,6 +1447,12 @@ static void draw_lpm_ff(ivl_lpm_t net)
aset_bits = ivl_expr_bits(aset_expr);
}
sset_expr = ivl_lpm_sset_value(net);
if (sset_expr) {
assert(ivl_expr_width(sset_expr) == width);
sset_bits = ivl_expr_bits(sset_expr);
}
/* If there is a synchronous clear or set, then draw a
compound enable that includes the Sclr or Sset input. We
will use this for the enable of the basic DFF. */
@ -1480,7 +1494,10 @@ static void draw_lpm_ff(ivl_lpm_t net)
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)), idx);
draw_input_from_net(ivl_lpm_data(net,idx));
fprintf(vvp_out, ", C<1>, ");
if (sset_bits[idx] == '1')
fprintf(vvp_out, ", C<1>, ");
else
fprintf(vvp_out, ", C<0>, ");
draw_input_from_net(ivl_lpm_sync_set(net));
fprintf(vvp_out, ", C<1>;\n");
}
@ -1869,6 +1886,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/*
* $Log: vvp_scope.c,v $
* Revision 1.103.2.6 2006/04/16 19:26:41 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.103.2.5 2006/03/26 23:09:26 steve
* Handle asynchronous demux/bit replacements.
*