Fix handling of exploded memories with partial or missing resets.
This commit is contained in:
parent
058dac4290
commit
f02b2c9d7a
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
22
ivl_target.h
22
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.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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
35
netlist.cc
35
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.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.
|
||||
*
|
||||
|
|
|
|||
29
netlist.h
29
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.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
109
synth2.cc
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
11
t-dll-api.cc
11
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.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.
|
||||
*
|
||||
|
|
|
|||
18
t-dll.cc
18
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.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.
|
||||
*
|
||||
|
|
|
|||
8
t-dll.h
8
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.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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue