Fix the memsynth1 case.

This commit is contained in:
steve 2006-03-12 07:34:16 +00:00
parent 79cb8c883a
commit b8bc531f05
17 changed files with 501 additions and 72 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.2 2006/02/19 00:11:31 steve Exp $"
#ident "$Id: design_dump.cc,v 1.149.2.3 2006/03/12 07:34:16 steve Exp $"
#endif
# include "config.h"
@ -219,7 +219,7 @@ void NetCompare::dump_node(ostream&o, unsigned ind) const
void NetDecode::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_DECODE (NetDecode): " << name()
<< " ff=" << ff_->name() << endl;
<< " ff=" << ff_->name() << ", word width=" << width() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@ -369,7 +369,11 @@ void NetRamDq::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_RAM_DQ (";
if (mem_) o << "mem=" << mem_->name();
if (mem_)
if (NetNet*tmp = mem_->reg_from_explode())
o << "exploded mem=" << tmp->name();
else
o << "mem=" << mem_->name();
o << "): " << name() << endl;
@ -1105,6 +1109,9 @@ void Design::dump(ostream&o) const
/*
* $Log: design_dump.cc,v $
* Revision 1.149.2.3 2006/03/12 07:34:16 steve
* Fix the memsynth1 case.
*
* Revision 1.149.2.2 2006/02/19 00:11:31 steve
* Handle synthesis of FF vectors with l-value decoder.
*

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.2 2006/02/25 05:03:28 steve Exp $"
#ident "$Id: ivl_target.h,v 1.126.2.3 2006/03/12 07:34:16 steve Exp $"
#endif
#ifdef __cplusplus
@ -675,9 +675,16 @@ extern const char* ivl_udp_name(ivl_udp_t net);
* - IVL_LPM_FF
* The IVL_LPM_FF and IVL_LPM_DECODE devices are closely related. If
* the ivl_lpm_decode function returns a non-nil value, then the
* decoder represents an extra ENABLE-like input, where exactly one(1)
* bit of the width of the FF is enabled. The decoder inputs are and
* address that selects the FF to be enabled.
* decoder represents an extra ENABLE-like input, where exactly <N>
* bits of the width of the FF is enabled. The ivl_lpm_width of the
* decoder defines <N>.
*
* The decoder inputs are the address that selects the FF to be
* enabled, and the ivl_lpm_selects for the decoder gives the width of
* the address. The address of the LSB of the memory, then, is the
* word width times the input address. For a simple l-value bit
* select, the word width <N> will be 1, and the address goes directly
* to the bit. Otherwise, <N>*address gets to the first bit of the word.
*
* The core compiler generates these attributes in certain cases:
*
@ -685,6 +692,19 @@ extern const char* ivl_udp_name(ivl_udp_t net);
* If present, the string value can be "INVERT". That indicates
* that the clock is negedge sensitive instead of the default
* posedge sensitive.
*
* - IVL_LPM_RAM
* The IVL_LPM_RAM may also appear as a READ port for a FF array. In
* this case, the IVL_LPM_RAM device has an ivl_lpm_width that is the
* width of the word, and an ivl_lpm_size that is the number of words
* in the array. In effect, the IVL_LPM_RAM reorganizes a vector into
* an array of words. If this is happening, then the ivl_lpm_memory
* will return 0.
*
* The ivl_lpm_q function gets the output nexa of the read port. The
* "q" port has as many bits as the width. The ivl_lpm_data2 function
* gets the nexa of the input, with the sdx the word address and the
* idx the bit within the word.
*/
extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */
@ -727,7 +747,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_RAM */
extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_MUX */
/* 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);
@ -1268,6 +1288,9 @@ _END_DECL
/*
* $Log: ivl_target.h,v $
* Revision 1.126.2.3 2006/03/12 07:34:16 steve
* Fix the memsynth1 case.
*
* Revision 1.126.2.2 2006/02/25 05:03:28 steve
* Add support for negedge FFs by using attributes.
*

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 2004/08/28 15:08:31 steve Exp $"
#ident "$Id: net_assign.cc,v 1.18.2.1 2006/03/12 07:34:17 steve Exp $"
#endif
# include "config.h"
@ -71,6 +71,14 @@ NetAssign_::~NetAssign_()
sig_->type(NetNet::WIRE);
}
if (mem_) {
NetNet*exp = mem_->reg_from_explode();
if (exp) {
exp->decr_lref();
if (turn_sig_to_wire_on_release_ && exp->peek_lref() == 0)
exp->type(NetNet::WIRE);
}
}
assert( more == 0 );
if (bmux_) delete bmux_;
}
@ -111,7 +119,10 @@ perm_string NetAssign_::name() const
NetNet* NetAssign_::sig() const
{
return sig_;
if (mem_)
return 0;
else
return sig_;
}
NetMemory* NetAssign_::mem() const
@ -261,6 +272,9 @@ NetAssignNB::~NetAssignNB()
/*
* $Log: net_assign.cc,v $
* Revision 1.18.2.1 2006/03/12 07:34:17 steve
* Fix the memsynth1 case.
*
* Revision 1.18 2004/08/28 15:08:31 steve
* Do not change reg to wire in NetAssign_ unless synthesizing.
*

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.1 2006/01/18 01:23:23 steve Exp $"
#ident "$Id: net_nex_output.cc,v 1.11.2.2 2006/03/12 07:34:17 steve Exp $"
#endif
# include "config.h"
@ -47,18 +47,42 @@ void NetAssignBase::nex_output(NexusSet&out)
{
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
if (NetNet*lsig = cur->sig()) {
#if 0
if (cur->bmux()) {
cerr << get_line() << ": internal error: "
<< "L-Value mux not supported by nex_output: ";
cur->dump_lval(cerr);
cerr << endl;
}
#endif
/* Handle l-value signals. We don't need to worry
here about whether there is a bmux, because the
synthesizer will detect that mux and create a
decoder between the expression and the signal. */
for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) {
unsigned off = cur->get_loff() + idx;
out.add(lsig->pin(off).nexus());
}
} else if (NetMemory*lmem = cur->mem()) {
/* Memories here are treated as a bunch of reg
devices. Use the explode_to_reg method to get
access to the FF version of the memory and use
that in our l-value management. */
NetNet*tmp = lmem->explode_to_reg();
if (NetEConst*ae = dynamic_cast<NetEConst*>(cur->bmux())) {
/* The address is constant, so simply
connect to the right pins and we are
done. */
long adr= ae->value().as_long();
adr = lmem->index_to_address(adr) * lmem->width();
for (unsigned idx = 0; idx < cur->lwidth(); idx += 1)
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());
}
} else {
/* Quoting from netlist.h comments for class NetMemory:
* "This is not a node because memory objects can only be
@ -130,6 +154,9 @@ void NetWhile::nex_output(NexusSet&out)
/*
* $Log: net_nex_output.cc,v $
* Revision 1.11.2.2 2006/03/12 07:34:17 steve
* Fix the memsynth1 case.
*
* Revision 1.11.2.1 2006/01/18 01:23:23 steve
* Rework l-value handling to allow for more l-value type flexibility.
*

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.2 2006/02/19 00:11:32 steve Exp $"
#ident "$Id: netlist.cc,v 1.226.2.3 2006/03/12 07:34:17 steve Exp $"
#endif
# include "config.h"
@ -686,6 +686,11 @@ const verinum& NetFF::sset_value() const
return sset_value_;
}
unsigned NetDecode::width() const
{
return width_;
}
unsigned NetDecode::awidth() const
{
return pin_count();
@ -1076,9 +1081,13 @@ const Link& NetCompare::pin_DataB(unsigned idx) const
return pin(8+width_+idx);
}
NetDecode::NetDecode(NetScope*s, perm_string name, NetFF*mem, unsigned awid)
NetDecode::NetDecode(NetScope*s, perm_string name, NetFF*mem,
unsigned awid, unsigned word_width)
: NetNode(s, name, awid)
{
width_ = word_width;
assert( mem->width() % width_ == 0 );
ff_ = mem;
ff_->demux_ = this;
make_pins_(awid);
@ -2057,6 +2066,7 @@ 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;
explode_ = 0;
scope_->add_memory(this);
}
@ -2087,7 +2097,24 @@ unsigned NetMemory::index_to_address(long idx) const
return idx - idxl_;
}
NetNet* NetMemory::explode_to_reg()
{
if (explode_)
return explode_;
explode_ = new NetNet(scope_, name_, NetNet::REG, count()*width_);
return explode_;
}
NetNet* NetMemory::reg_from_explode()
{
return explode_;
}
const NetNet* NetMemory::reg_from_explode() const
{
return explode_;
}
NetEMemory* NetEMemory::dup_expr() const
{
@ -2335,6 +2362,9 @@ const NetProc*NetTaskDef::proc() const
/*
* $Log: netlist.cc,v $
* Revision 1.226.2.3 2006/03/12 07:34:17 steve
* Fix the memsynth1 case.
*
* Revision 1.226.2.2 2006/02/19 00:11:32 steve
* Handle synthesis of FF vectors with l-value decoder.
*

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.10 2006/02/19 00:11:32 steve Exp $"
#ident "$Id: netlist.h,v 1.321.2.11 2006/03/12 07:34:17 steve Exp $"
#endif
/*
@ -599,9 +599,15 @@ class NetCompare : public NetNode {
class NetDecode : public NetNode {
public:
NetDecode(NetScope*s, perm_string name, NetFF*mem, unsigned awid);
NetDecode(NetScope*s, perm_string name, NetFF*mem,
unsigned awid, unsigned word_width);
~NetDecode();
// This is the width of the word. The width of the NetFF mem
// is an even multiple of this.
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;
const NetFF*ff() const;
@ -615,6 +621,7 @@ class NetDecode : public NetNode {
virtual bool emit_node(struct target_t*) const;
private:
unsigned width_;
NetFF* ff_;
private:
@ -784,6 +791,7 @@ class NetMemory {
// NetScope*scope();
const NetScope*scope() const { return scope_; };
NetScope*scope() { return scope_; };
// This is the number of memory positions.
unsigned count() const;
@ -793,6 +801,13 @@ class NetMemory {
// that are not zero based.
unsigned index_to_address(long idx) const;
// This method returns a NetNet::REG that has the same number
// of bits as the memory as a whole. This is used to represent
// memories that are synthesized to individual bits.
NetNet* explode_to_reg();
NetNet* reg_from_explode();
const NetNet* reg_from_explode() const;
void dump(ostream&o, unsigned lm) const;
private:
@ -808,6 +823,8 @@ class NetMemory {
NetMemory*snext_, *sprev_;
NetScope*scope_;
NetNet*explode_;
private: // not implemented
NetMemory(const NetMemory&);
NetMemory& operator= (const NetMemory&);
@ -3439,6 +3456,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.321.2.11 2006/03/12 07:34:17 steve
* Fix the memsynth1 case.
*
* Revision 1.321.2.10 2006/02/19 00:11:32 steve
* Handle synthesis of FF vectors with l-value decoder.
*

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.22 2006/02/25 05:03:29 steve Exp $"
#ident "$Id: synth2.cc,v 1.39.2.23 2006/03/12 07:34:18 steve Exp $"
#endif
# include "config.h"
@ -105,6 +105,44 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag,
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
NetMemory*lmem = cur->mem();
if (lmem && !sync_flag) {
cerr << get_line() << ": error: Cannot synthesize memory "
<< "assignment is asynchronous logic." << endl;
des->errors += 1;
return false;
}
/* Is this an assignment to a memory? If so, then
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.
Note that this is only workable if we are in the
asynchronous path of a synchronous thread. The
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));
}
}
continue;
}
NetNet*lsig = cur->sig();
if (!lsig) {
cerr << get_line() << ": error: NetAssignBase::synth_async "
@ -851,6 +889,8 @@ bool NetAssignBase::synth_sync(Design*des, NetScope*scope,
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
if (cur->bmux())
demux = cur;
if (cur->mem())
demux = cur;
count_lval += 1;
}
@ -872,7 +912,8 @@ bool NetAssignBase::synth_sync(Design*des, NetScope*scope,
NetNet*adr = demux->bmux()->synthesize(des);
NetDecode*dq = new NetDecode(scope, scope->local_symbol(),
nex_ff[0].ff, adr->pin_count());
nex_ff[0].ff, adr->pin_count(),
lval_->lwidth());
des->add_node(dq);
dq->set_line(*this);
@ -880,11 +921,16 @@ bool NetAssignBase::synth_sync(Design*des, NetScope*scope,
connect(dq->pin_Address(idx), adr->pin(idx));
NetNet*rsig = rval_->synthesize(des);
assert(rsig->pin_count() == 1);
assert(rsig->pin_count() == lval_->lwidth());
for (unsigned idx = 0 ; idx < nex_ff[0].ff->width() ; idx += 1)
connect(nex_ff[0].ff->pin_Data(idx), rsig->pin(0));
connect(nex_ff[0].ff->pin_Data(idx), rsig->pin(idx%lval_->lwidth()));
if (lval_->mem()) {
NetNet*exp = lval_->mem()->reg_from_explode();
assert(exp);
exp->incr_lref();
}
lval_->turn_sig_to_wire_on_release();
return true;
}
@ -1269,7 +1315,10 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope,
Also, we will not allow both Sset and Sclr to be used on a
single LPM_FF (due to unclear priority issues) so don't try
if either are already connected. */
if either are already connected.
XXXX This should be disabled if there is a memory involved
in any sub-statements? */
assert(if_ != 0);
NexusSet*a_set = if_->nex_input();
@ -1639,6 +1688,9 @@ void synth2(Design*des)
/*
* $Log: synth2.cc,v $
* Revision 1.39.2.23 2006/03/12 07:34:18 steve
* Fix the memsynth1 case.
*
* Revision 1.39.2.22 2006/02/25 05:03:29 steve
* Add support for negedge FFs by using attributes.
*

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.2 2006/02/25 05:03:29 steve Exp $"
#ident "$Id: t-dll-api.cc,v 1.108.2.3 2006/03/12 07:34:19 steve Exp $"
#endif
# include "config.h"
@ -826,6 +826,22 @@ extern "C" ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx)
return net->u_.ufunc.pins[base+idx];
}
case IVL_LPM_RAM:
if (net->u_.ff.a.mem == 0) {
// This is an exploded RAM, so we use sdx and idx
// to address a nexa into the exploded ram.
if (sdx >= net->u_.ff.scnt)
return 0;
if (idx >= net->u_.ff.width)
return 0;
unsigned adr = sdx * net->u_.ff.width + idx;
return net->u_.ff.d.pins[adr];
} else {
// Normal RAM port does not have data2 nexa
return 0;
}
default:
assert(0);
return 0;
@ -1025,6 +1041,8 @@ extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
switch (net->type) {
case IVL_LPM_MUX:
return net->u_.mux.size;
case IVL_LPM_RAM:
return net->u_.ff.scnt;
case IVL_LPM_UFUNC:
return net->u_.ufunc.ports - 1;
default:
@ -1045,6 +1063,7 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
case IVL_LPM_FF:
case IVL_LPM_RAM:
return net->u_.ff.width;
case IVL_LPM_DECODE:
case IVL_LPM_MUX:
return net->u_.mux.width;
case IVL_LPM_ADD:
@ -1062,8 +1081,6 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
return net->u_.shift.width;
case IVL_LPM_UFUNC:
return net->u_.ufunc.port_wid[0];
case IVL_LPM_DECODE:
return 1;
default:
assert(0);
return 0;
@ -1964,6 +1981,9 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
/*
* $Log: t-dll-api.cc,v $
* Revision 1.108.2.3 2006/03/12 07:34:19 steve
* Fix the memsynth1 case.
*
* Revision 1.108.2.2 2006/02/25 05:03:29 steve
* Add support for negedge FFs by using attributes.
*

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-expr.cc,v 1.39 2004/06/17 16:06:19 steve Exp $"
#ident "$Id: t-dll-expr.cc,v 1.39.2.1 2006/03/12 07:34:19 steve Exp $"
#endif
# include "config.h"
@ -222,12 +222,58 @@ void dll_target::expr_memory(const NetEMemory*net)
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_;
const NetMemory*mem = net->memory();
if (const NetNet*reg = mem->reg_from_explode()) {
cur->type_ = IVL_EX_SELECT;
cur->value_ = IVL_VT_VECTOR;
cur->width_ = net->expr_width();
cur->signed_ = net->has_sign()? 1 : 0;
// Create an expression form of the exploded
// memory. This is what the select will apply to.
ivl_expr_t sig = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
sig->type_ = IVL_EX_SIGNAL;
sig->value_ = IVL_VT_VECTOR;
sig->width_ = reg->pin_count();
sig->signed_ = 0;
sig->u_.signal_.sig = find_signal(des_, reg);
sig->u_.signal_.lsi = 0;
sig->u_.signal_.msi = reg->pin_count()-1;
cur->u_.binary_.lef_ = sig;
// Create an expression of the address calculation.
cur->u_.binary_.rig_ = expr_;
if (cur->width_ > 1) {
ivl_expr_t mul = (ivl_expr_t)calloc(2, sizeof(struct ivl_expr_s));
ivl_expr_t fac = mul+1;
fac->type_ = IVL_EX_ULONG;
fac->value_ = IVL_VT_VECTOR;
fac->width_ = 8*sizeof(cur->width_);
fac->signed_= 0;
fac->u_.ulong_.value = cur->width_;
mul->type_ = IVL_EX_BINARY;
mul->value_ = IVL_VT_VECTOR;
mul->width_ = fac->width_;
mul->signed_= 0;
mul->u_.binary_.op_ = '*';
mul->u_.binary_.lef_ = cur->u_.binary_.rig_;
mul->u_.binary_.rig_ = fac;
cur->u_.binary_.rig_ = mul;
}
} else {
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;
}
@ -604,6 +650,9 @@ void dll_target::expr_variable(const NetEVariable*net)
/*
* $Log: t-dll-expr.cc,v $
* Revision 1.39.2.1 2006/03/12 07:34:19 steve
* Fix the memsynth1 case.
*
* Revision 1.39 2004/06/17 16:06:19 steve
* Help system function signedness survive elaboration.
*

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.4 2006/02/25 05:03:29 steve Exp $"
#ident "$Id: t-dll.cc,v 1.131.2.5 2006/03/12 07:34:19 steve Exp $"
#endif
# include "config.h"
@ -1522,7 +1522,7 @@ ivl_lpm_t dll_target::lpm_decode_ff_(const NetDecode*net)
obj->u_.mux.swid = net->awidth();
obj->u_.mux.size = 0;
obj->u_.mux.width = 0;
obj->u_.mux.width = net->width();
obj->u_.mux.d = 0;
if (obj->u_.mux.swid > 1) {
@ -1671,18 +1671,23 @@ void dll_target::lpm_ff(const NetFF*net)
void dll_target::lpm_ram_dq(const NetRamDq*net)
{
ivl_memory_t mem = find_memory(des_, net->mem());
assert(mem);
const NetNet*ereg = net->mem()->reg_from_explode();
ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_RAM;
obj->name = net->name();
obj->attr = 0;
obj->nattr = 0;
obj->u_.ff.a.mem = find_memory(des_, net->mem());
assert(obj->u_.ff.a.mem);
obj->u_.ff.a.mem = ereg? 0 : mem;
obj->scope = find_scope(des_, net->mem()->scope());
assert(obj->scope);
obj->u_.ff.width = net->width();
obj->u_.ff.swid = net->awidth();
obj->u_.ff.scnt = net->mem()->count();
scope_add_lpm(obj->scope, obj);
@ -1692,6 +1697,7 @@ void dll_target::lpm_ram_dq(const NetRamDq*net)
// the clock input.
bool has_write_port = net->pin_InClock().is_linked();
assert( ereg? !has_write_port : 1 );
// Connect the write clock and write enable
@ -1783,6 +1789,21 @@ void dll_target::lpm_ram_dq(const NetRamDq*net)
IVL_DR_STRONG, IVL_DR_STRONG);
}
}
if (ereg) {
unsigned count = obj->u_.ff.width * obj->u_.ff.scnt;
assert(ereg->pin_count() == count);
obj->u_.ff.d.pins = new ivl_nexus_t [count];
for (unsigned idx = 0 ; idx < count ; idx += 1) {
nex = ereg->pin(idx).nexus();
assert(nex->t_cookie());
obj->u_.ff.d.pins[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.ff.d.pins[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ);
}
}
}
void dll_target::lpm_mult(const NetMult*net)
@ -2250,6 +2271,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/*
* $Log: t-dll.cc,v $
* Revision 1.131.2.5 2006/03/12 07:34:19 steve
* Fix the memsynth1 case.
*
* Revision 1.131.2.4 2006/02/25 05:03:29 steve
* Add support for negedge FFs by using attributes.
*

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.2 2006/02/25 05:03:30 steve Exp $"
#ident "$Id: t-dll.h,v 1.115.2.3 2006/03/12 07:34:19 steve Exp $"
#endif
# include "target.h"
@ -300,6 +300,7 @@ struct ivl_lpm_s {
struct ivl_lpm_ff_s {
unsigned width;
unsigned swid; // ram only
unsigned scnt;
ivl_nexus_t clk;
ivl_nexus_t we;
ivl_nexus_t aclr;
@ -693,6 +694,9 @@ struct ivl_variable_s {
/*
* $Log: t-dll.h,v $
* Revision 1.115.2.3 2006/03/12 07:34:19 steve
* Fix the memsynth1 case.
*
* Revision 1.115.2.2 2006/02/25 05:03:30 steve
* Add support for negedge FFs by using attributes.
*

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.6 2006/02/25 05:03:30 steve Exp $"
#ident "$Id: stub.c,v 1.90.2.7 2006/03/12 07:34:20 steve Exp $"
#endif
# include "config.h"
@ -112,6 +112,12 @@ static void show_expression(ivl_expr_t net, unsigned ind)
break;
}
case IVL_EX_ULONG: {
fprintf(out, "%*s<ulong=%u'd%lu, %s>\n",
ind, "", width, ivl_expr_uvalue(net), sign);
break;
}
case IVL_EX_SELECT:
/* The SELECT expression can be used to express part
select, or if the base is null vector extension. */
@ -198,6 +204,35 @@ static void show_expression(ivl_expr_t net, unsigned ind)
}
}
static void show_lpm_ram(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
unsigned count = ivl_lpm_size(net);
unsigned idx, sdx;
fprintf(out, " LPM_RAM_DQ %s (word-width=%u, count=%u)\n",
ivl_lpm_basename(net), ivl_lpm_width(net), count);
for (idx = 0 ; idx < ivl_lpm_selects(net) ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_select(net, idx);
fprintf(out, " Address %u: %s\n", idx,
nex? ivl_nexus_name(nex) : "");
}
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_q(net, idx);
fprintf(out, " Q %u: %s\n", idx, nex? ivl_nexus_name(nex) : "");
}
for (sdx = 0 ; sdx < count ; sdx += 1) {
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_data2(net, sdx, idx);
fprintf(out, " Word%u %u: %s\n",
sdx, idx, nex? ivl_nexus_name(nex) : "");
}
}
}
static void show_lpm(ivl_lpm_t net)
{
unsigned idx;
@ -296,7 +331,8 @@ static void show_lpm(ivl_lpm_t net)
}
case IVL_LPM_DECODE: {
fprintf(out, " LPM_DECODE %s\n", ivl_lpm_basename(net));
fprintf(out, " LPM_DECODE %s (word-width=%u)\n",
ivl_lpm_basename(net), ivl_lpm_width(net));
for (idx = 0 ; idx < ivl_lpm_selects(net) ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_select(net, idx);
fprintf(out, " Address %u: %s\n", idx,
@ -305,6 +341,10 @@ static void show_lpm(ivl_lpm_t net)
break;
}
case IVL_LPM_RAM:
show_lpm_ram(net);
break;
case IVL_LPM_SHIFTL: {
fprintf(out, " LPM_SHIFTL %s: <width=%u, selects=%u %s>\n",
ivl_lpm_basename(net), width, ivl_lpm_selects(net),
@ -1033,6 +1073,9 @@ int target_design(ivl_design_t des)
/*
* $Log: stub.c,v $
* Revision 1.90.2.7 2006/03/12 07:34:20 steve
* Fix the memsynth1 case.
*
* Revision 1.90.2.6 2006/02/25 05:03:30 steve
* Add support for negedge FFs by using attributes.
*

View File

@ -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.110 2004/10/04 01:10:57 steve Exp $"
#ident "$Id: eval_expr.c,v 1.110.2.1 2006/03/12 07:34:20 steve Exp $"
#endif
# include "vvp_priv.h"
@ -1841,6 +1841,40 @@ static struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
return res;
}
static struct vector_info draw_ulong_expr(ivl_expr_t exp, unsigned wid)
{
unsigned long idx;
struct vector_info res;
unsigned long uval = ivl_expr_uvalue(exp);
if (uval == 0) {
res.wid = wid;
res.base = 0;
return res;
}
res.base = allocate_vector(wid);
res.wid = wid;
idx = 0;
while (idx < wid) {
unsigned long cnt;
int bit = 1 & (uval >> idx);
for (cnt = 1 ; idx+cnt < wid ; cnt += 1) {
int tmp = 1 & (uval >> (idx+cnt));
if (tmp != bit)
break;
}
fprintf(vvp_out, " %%mov %u, %d, %lu;\n",
res.base+idx, bit, cnt);
idx += cnt;
}
return res;
}
static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
{
struct vector_info res;
@ -2120,6 +2154,10 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
res = draw_ufunc_expr(exp, wid);
break;
case IVL_EX_ULONG:
res = draw_ulong_expr(exp, wid);
break;
case IVL_EX_UNARY:
res = draw_unary_expr(exp, wid);
break;
@ -2139,6 +2177,9 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
/*
* $Log: eval_expr.c,v $
* Revision 1.110.2.1 2006/03/12 07:34:20 steve
* Fix the memsynth1 case.
*
* Revision 1.110 2004/10/04 01:10:57 steve
* Clean up spurious trailing white space.
*

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.3 2006/02/25 05:03:30 steve Exp $"
#ident "$Id: vvp_scope.c,v 1.103.2.4 2006/03/12 07:34:20 steve Exp $"
#endif
# include "vvp_priv.h"
@ -411,7 +411,29 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
}
break;
/* The output for a RAM depends on whether it is
exploded or not. If it is, treat is like a MUX. If it
is not, treat it like an arithmetic LPM. */
case IVL_LPM_RAM:
if (ivl_lpm_memory(lpm)) {
for (idx = 0 ; idx < ivl_lpm_width(lpm) ; idx += 1) {
if (ivl_lpm_q(lpm, idx) == nex) {
sprintf(result, "L_%p[%u]", lpm, idx);
return result;
}
}
} else {
for (idx = 0 ; idx < ivl_lpm_width(lpm) ; idx += 1) {
if (ivl_lpm_q(lpm, idx) == nex) {
sprintf(result, "L_%s.%s/%u",
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(lpm))),
vvp_mangle_id(ivl_lpm_basename(lpm)), idx);
return result;
}
}
}
break;
case IVL_LPM_ADD:
case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR:
@ -1105,7 +1127,13 @@ static void draw_event_in_scope(ivl_event_t obj)
}
}
inline static void draw_lpm_ram(ivl_lpm_t net)
static void draw_lpm_ram_exploded(ivl_lpm_t net)
{
fprintf(vvp_out, "; exploded ram port!\n");
draw_lpm_mux(net);
}
static void draw_lpm_ram(ivl_lpm_t net)
{
unsigned idx;
unsigned width = ivl_lpm_width(net);
@ -1114,6 +1142,11 @@ inline static void draw_lpm_ram(ivl_lpm_t net)
ivl_nexus_t clk = ivl_lpm_clk(net);
ivl_nexus_t pin;
if (mem == 0) {
draw_lpm_ram_exploded(net);
return;
}
if (clk) {
fprintf(vvp_out, "CLK_%p .event posedge, ", net);
draw_input_from_net(clk);
@ -1317,6 +1350,7 @@ static void draw_lpm_ff(ivl_lpm_t net)
unsigned width, idx;
ivl_attribute_t clock_pol = find_lpm_attr(net, "ivl:clock_polarity");
ivl_lpm_t decode = ivl_lpm_decode(net);
width = ivl_lpm_width(net);
@ -1408,23 +1442,34 @@ static void draw_lpm_ff(ivl_lpm_t net)
}
/* If there is a decoder for this FF, then create a
decoder enable node. */
if (ivl_lpm_decode(net)) {
decoder enable node. The .decode/en arguments are the
label for the .decode/adr, a .decoder/en slice
number (the address it responds to), the label for a
decoder enable, and the label for a mass-write enable. */
if (decode) {
ivl_lpm_t dec = ivl_lpm_decode(net);
fprintf(vvp_out, "L_%s.%s/dec/%u .decode/en L_%s.%s, %u",
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)), idx,
vvp_mangle_id(ivl_lpm_basename(net)),
idx,
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(dec))),
vvp_mangle_id(ivl_lpm_basename(dec)), idx);
vvp_mangle_id(ivl_lpm_basename(dec)),
idx / ivl_lpm_width(decode));
tmp = ivl_lpm_enable(net);
if (tmp && (ivl_lpm_sync_clr(net)||ivl_lpm_sync_set(net))) {
fprintf(vvp_out, ", L_%s.%s/en",
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)));
} else if (tmp) {
if (tmp) {
fprintf(vvp_out, ", ");
draw_input_from_net(tmp);
} else {
fprintf(vvp_out, ", C<1> ");
}
fprintf(vvp_out, ", ");
if (ivl_lpm_sync_clr(net)) {
draw_input_from_net(ivl_lpm_sync_clr(net));
} else if (ivl_lpm_sync_set(net)) {
draw_input_from_net(ivl_lpm_sync_set(net));
} else {
fprintf(vvp_out, "C<0>");
}
fprintf(vvp_out, ";\n");
}
@ -1776,6 +1821,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/*
* $Log: vvp_scope.c,v $
* Revision 1.103.2.4 2006/03/12 07:34:20 steve
* Fix the memsynth1 case.
*
* Revision 1.103.2.3 2006/02/25 05:03:30 steve
* Add support for negedge FFs by using attributes.
*

View File

@ -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.56.2.1 2006/02/19 00:11:35 steve Exp $"
#ident "$Id: compile.h,v 1.56.2.2 2006/03/12 07:34:21 steve Exp $"
#endif
# include <stdio.h>
@ -118,7 +118,8 @@ extern void compile_cmp_gt(char*label, long width, bool signed_flag,
extern void compile_decode_adr(char*label,
unsigned argc, struct symb_s*argv);
extern void compile_decode_en(char*label, char*decoder, int slice,
struct symb_s enable);
struct symb_s enable,
struct symb_s mass_enable);
extern void compile_shiftl(char*label, long width,
unsigned argc, struct symb_s*argv);
extern void compile_shiftr(char*label, long width,
@ -272,6 +273,9 @@ extern void compile_net(char*label, char*name,
/*
* $Log: compile.h,v $
* Revision 1.56.2.2 2006/03/12 07:34:21 steve
* Fix the memsynth1 case.
*
* Revision 1.56.2.1 2006/02/19 00:11:35 steve
* Handle synthesis of FF vectors with l-value decoder.
*

View File

@ -16,7 +16,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: decoder.cc,v 1.1.2.1 2006/02/19 00:11:36 steve Exp $"
#ident "$Id: decoder.cc,v 1.1.2.2 2006/03/12 07:34:21 steve Exp $"
# include "compile.h"
# include "functor.h"
@ -86,6 +86,8 @@ struct vvp_decode_en_s : public functor_s {
bool decode_en;
// This is the enable that arrives from the extra input.
bool extra_en;
// This is the mass-enable that enables independent of address
bool mass_en;
};
vvp_decode_adr_s::vvp_decode_adr_s(vvp_ipoint_t me, unsigned w)
@ -119,6 +121,7 @@ vvp_decode_en_s::vvp_decode_en_s(vvp_decode_adr_s*dec, unsigned s)
enable_next = 0;
decode_en = false;
extra_en = true;
mass_en = false;
decoder = dec;
enable_next = decoder->enable_list;
@ -132,13 +135,25 @@ void vvp_decode_en_s::set(vvp_ipoint_t i, bool push,
ifu->put(i, val);
int abval = functor_get_input(i);
if (abval == 1) {
extra_en = true;
} else {
extra_en = false;
unsigned port = ipoint_port(i);
switch (port) {
case 0: // regular enable
if (abval == 1) {
extra_en = true;
} else {
extra_en = false;
}
break;
case 1: // mass enable
if (abval == 1) {
mass_en = true;
} else {
mass_en = false;
}
break;
}
if (extra_en && decode_en)
if (extra_en && decode_en || mass_en)
put_oval(1, true);
else
put_oval(0, true);
@ -183,7 +198,8 @@ void compile_decode_adr(char*label, unsigned argc, struct symb_s*argv)
}
void compile_decode_en(char*label, char*decoder, int slice,
struct symb_s enable)
struct symb_s enable,
struct symb_s mass_enable)
{
vvp_decode_adr_s*adr = decoder_find(decoder);
vvp_decode_en_s*a = new struct vvp_decode_en_s(adr, slice);
@ -191,9 +207,10 @@ void compile_decode_en(char*label, char*decoder, int slice,
vvp_ipoint_t ix = functor_allocate(1);
functor_define(ix, a);
if (enable.text) {
inputs_connect(ix, 1, &enable);
}
symb_s argv[2];
argv[0] = enable;
argv[1] = mass_enable;
inputs_connect(ix, 2, argv);
define_functor_symbol(label, ix);
free(label);
@ -201,6 +218,9 @@ void compile_decode_en(char*label, char*decoder, int slice,
/*
* $Log: decoder.cc,v $
* Revision 1.1.2.2 2006/03/12 07:34:21 steve
* Fix the memsynth1 case.
*
* Revision 1.1.2.1 2006/02/19 00:11:36 steve
* Handle synthesis of FF vectors with l-value decoder.
*

View File

@ -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.60.2.1 2006/02/19 00:11:36 steve Exp $"
#ident "$Id: parse.y,v 1.60.2.2 2006/03/12 07:34:21 steve Exp $"
#endif
# include "parse_misc.h"
@ -270,8 +270,8 @@ statement
compile_decode_adr($1, obj.cnt, obj.vect);
}
| T_LABEL K_DECODE_EN T_SYMBOL ',' T_NUMBER ',' symbol ';'
{ compile_decode_en($1, $3, $5, $7);
| T_LABEL K_DECODE_EN T_SYMBOL ',' T_NUMBER ',' symbol ',' symbol ';'
{ compile_decode_en($1, $3, $5, $7, $9);
}
/* Event statements take a label, a type (the first T_SYMBOL) and a
@ -646,6 +646,9 @@ int compile_design(const char*path)
/*
* $Log: parse.y,v $
* Revision 1.60.2.2 2006/03/12 07:34:21 steve
* Fix the memsynth1 case.
*
* Revision 1.60.2.1 2006/02/19 00:11:36 steve
* Handle synthesis of FF vectors with l-value decoder.
*