Handle asynchronous demux/bit replacements.
This commit is contained in:
parent
faf7f30283
commit
312d09dc1d
|
|
@ -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.3 2006/03/12 07:34:16 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.149.2.4 2006/03/26 23:09:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -224,6 +224,14 @@ void NetDecode::dump_node(ostream&o, unsigned ind) const
|
|||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetDemux::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_DEMUX (NetDemux): " << name()
|
||||
<< " word width=" << width() << ", address width=" << awidth() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetDivide::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NET_DIVIDE (NetDivide): " << name() << endl;
|
||||
|
|
@ -1109,6 +1117,9 @@ void Design::dump(ostream&o) const
|
|||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.149.2.4 2006/03/26 23:09:21 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.149.2.3 2006/03/12 07:34:16 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
|
|
|
|||
10
emit.cc
10
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.77.2.1 2006/02/19 00:11:31 steve Exp $"
|
||||
#ident "$Id: emit.cc,v 1.77.2.2 2006/03/26 23:09:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -91,6 +91,11 @@ bool NetDecode::emit_node(struct target_t*tgt) const
|
|||
return tgt->lpm_decode(this);
|
||||
}
|
||||
|
||||
bool NetDemux::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->lpm_demux(this);
|
||||
}
|
||||
|
||||
bool NetDivide::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_divide(this);
|
||||
|
|
@ -516,6 +521,9 @@ bool emit(const Design*des, const char*type)
|
|||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.77.2.2 2006/03/26 23:09:21 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.77.2.1 2006/02/19 00:11:31 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
|
|
|
|||
28
ivl_target.h
28
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.3 2006/03/12 07:34:16 steve Exp $"
|
||||
#ident "$Id: ivl_target.h,v 1.126.2.4 2006/03/26 23:09:22 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -227,6 +227,7 @@ typedef enum ivl_lpm_type_e {
|
|||
IVL_LPM_CMP_GT = 2,
|
||||
IVL_LPM_CMP_NE = 11,
|
||||
IVL_LPM_DECODE = 15,
|
||||
IVL_LPM_DEMUX = 16,
|
||||
IVL_LPM_DIVIDE = 12,
|
||||
IVL_LPM_FF = 3,
|
||||
IVL_LPM_MOD = 13,
|
||||
|
|
@ -705,6 +706,17 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
|||
* "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.
|
||||
*
|
||||
* - IVL_LPM_DEMUX
|
||||
* This device is a form of bit replacement. The device has a data
|
||||
* 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
|
||||
* inputs to the device. Normally, the device passes the data inputs
|
||||
* through to the Q output.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */
|
||||
|
|
@ -732,20 +744,21 @@ extern ivl_lpm_t ivl_lpm_decode(ivl_lpm_t net);
|
|||
extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF IVL_LPM_RAM */
|
||||
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB */
|
||||
/* IVL_LPM_ADD IVL_LPM_DEMUX IVL_LPM_FF IVL_LPM_MULT */
|
||||
/* IVL_LPM_RAM IVL_LPM_SUB */
|
||||
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */
|
||||
/* IVL_LPM_ADD IVL_LPM_DEMUX IVL_LPM_MULT IVL_LPM_SUB */
|
||||
/* IVL_LPM_MUX IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
|
||||
extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx);
|
||||
/* IVL_LPM_UFUNC */
|
||||
extern unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx);
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB
|
||||
/* IVL_LPM_ADD IVL_LPM_DEMUX IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB
|
||||
IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_MUX IVL_LPM_DECODE IVL_LPM_RAM */
|
||||
/* IVL_LPM_MUX IVL_LPM_DECODE IVL_LPM_DEMUX IVL_LPM_RAM */
|
||||
extern unsigned ivl_lpm_selects(ivl_lpm_t net);
|
||||
/* IVL_LPM_MUX IVL_LPM_DECODE IVL_LPM_RAM */
|
||||
/* 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 */
|
||||
extern unsigned ivl_lpm_size(ivl_lpm_t net);
|
||||
|
|
@ -1288,6 +1301,9 @@ _END_DECL
|
|||
|
||||
/*
|
||||
* $Log: ivl_target.h,v $
|
||||
* Revision 1.126.2.4 2006/03/26 23:09:22 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.126.2.3 2006/03/12 07:34:16 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
|
|
|
|||
88
netlist.cc
88
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.4 2006/03/16 05:40:18 steve Exp $"
|
||||
#ident "$Id: netlist.cc,v 1.226.2.5 2006/03/26 23:09:22 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -721,6 +721,89 @@ unsigned NetDecode::awidth() const
|
|||
return pin_count();
|
||||
}
|
||||
|
||||
NetDemux::NetDemux(NetScope*s, perm_string name,
|
||||
unsigned word_width, unsigned address_width)
|
||||
: NetNode(s, name, word_width*2+address_width+1)
|
||||
{
|
||||
width_ = word_width;
|
||||
awidth_ = address_width;
|
||||
|
||||
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
|
||||
pin_Q(idx).set_dir(Link::OUTPUT);
|
||||
pin_Q(idx).set_name(perm_string::literal("Q"), idx);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
|
||||
pin_Data(idx).set_dir(Link::INPUT);
|
||||
pin_Data(idx).set_name(perm_string::literal("Data"), idx);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < awidth_ ; idx += 1) {
|
||||
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);
|
||||
}
|
||||
|
||||
NetDemux::~NetDemux()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned NetDemux::width() const
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
|
||||
unsigned NetDemux::awidth() const
|
||||
{
|
||||
return awidth_;
|
||||
}
|
||||
|
||||
Link& NetDemux::pin_Q(unsigned idx)
|
||||
{
|
||||
assert(idx < width_);
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
const Link& NetDemux::pin_Q(unsigned idx) const
|
||||
{
|
||||
assert(idx < width_);
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
Link& NetDemux::pin_Data(unsigned idx)
|
||||
{
|
||||
assert(idx < width_);
|
||||
return pin(width_+idx);
|
||||
}
|
||||
|
||||
const Link& NetDemux::pin_Data(unsigned idx) const
|
||||
{
|
||||
assert(idx < width_);
|
||||
return pin(width_+idx);
|
||||
}
|
||||
|
||||
Link& NetDemux::pin_Address(unsigned idx)
|
||||
{
|
||||
assert(idx < awidth_);
|
||||
return pin(width_+width_+idx);
|
||||
}
|
||||
|
||||
const Link& NetDemux::pin_Address(unsigned idx) const
|
||||
{
|
||||
assert(idx < awidth_);
|
||||
return pin(width_+width_+idx);
|
||||
}
|
||||
|
||||
Link& NetDemux::pin_WriteData()
|
||||
{
|
||||
return pin(width_+width_+awidth_);
|
||||
}
|
||||
|
||||
const Link& NetDemux::pin_WriteData() const
|
||||
{
|
||||
return pin(width_+width_+awidth_);
|
||||
}
|
||||
|
||||
NetDecode* NetFF::get_demux()
|
||||
{
|
||||
return demux_;
|
||||
|
|
@ -2388,6 +2471,9 @@ const NetProc*NetTaskDef::proc() const
|
|||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* Revision 1.226.2.5 2006/03/26 23:09:22 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.226.2.4 2006/03/16 05:40:18 steve
|
||||
* Fix crash when memory exploding doesnot work
|
||||
*
|
||||
|
|
|
|||
71
netlist.h
71
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.13 2006/03/18 18:43:21 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.321.2.14 2006/03/26 23:09:23 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -635,6 +635,46 @@ class NetDecode : public NetNode {
|
|||
void make_pins_(unsigned awid);
|
||||
};
|
||||
|
||||
/*
|
||||
* The NetDemux is similar to the NetDecode, except that it is
|
||||
* combinational. The inputs are an address, Data, and WriteData.
|
||||
* The Q output is the same as the Data input, except for the bit that
|
||||
* is addressed by the address input, which gets WriteData instead.
|
||||
*/
|
||||
class NetDemux : public NetNode {
|
||||
|
||||
public:
|
||||
NetDemux(NetScope*s, perm_string name,
|
||||
unsigned word_width, unsigned address_width);
|
||||
~NetDemux();
|
||||
|
||||
// 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;
|
||||
|
||||
Link& pin_Address(unsigned idx);
|
||||
Link& pin_Data(unsigned idx);
|
||||
Link& pin_Q(unsigned idx);
|
||||
Link& pin_WriteData();
|
||||
|
||||
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;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
unsigned width_, awidth_;
|
||||
|
||||
private:
|
||||
void make_pins_(unsigned wid, unsigned awid);
|
||||
};
|
||||
|
||||
/*
|
||||
* This class represents a theoretical (though not necessarily
|
||||
* practical) integer divider gate. This is not to represent any real
|
||||
|
|
@ -1425,9 +1465,13 @@ class NetProc : public virtual LineInfo {
|
|||
// sync_flag is used to tell the async synthesizer that the
|
||||
// output nex_map is ultimately connected to a DFF Q
|
||||
// output. This can affect how cycles are handled.
|
||||
virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
|
||||
bool synth_async_noaccum(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out);
|
||||
|
||||
virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
NetNet*accum_in);
|
||||
|
||||
|
|
@ -1571,8 +1615,7 @@ class NetAssignBase : public NetProc {
|
|||
unsigned lwidth() const;
|
||||
|
||||
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
NetNet*nex_map, NetNet*nex_out);
|
||||
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
NetNet*accum_in);
|
||||
bool synth_sync(Design*des, NetScope*scope,
|
||||
|
|
@ -1645,7 +1688,8 @@ class NetBlock : public NetProc {
|
|||
|
||||
// synthesize as asynchronous logic, and return true.
|
||||
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
NetNet*nex_map, NetNet*nex_out);
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in);
|
||||
|
||||
bool synth_sync(Design*des, NetScope*scope,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
|
|
@ -1701,8 +1745,7 @@ class NetCase : public NetProc {
|
|||
virtual void nex_output(NexusSet&out);
|
||||
|
||||
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
NetNet*nex_map, NetNet*nex_out);
|
||||
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in);
|
||||
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
|
|
@ -1710,6 +1753,7 @@ class NetCase : public NetProc {
|
|||
|
||||
private:
|
||||
bool synth_async_1hot_(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in,
|
||||
NetNet*esig, unsigned hot_items);
|
||||
private:
|
||||
|
|
@ -1789,8 +1833,7 @@ class NetCondit : public NetProc {
|
|||
|
||||
bool is_asynchronous();
|
||||
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
NetNet*nex_map, NetNet*nex_out);
|
||||
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum);
|
||||
|
||||
bool synth_sync(Design*des, NetScope*scope,
|
||||
|
|
@ -2017,7 +2060,9 @@ class NetEvWait : public NetProc {
|
|||
virtual void nex_output(NexusSet&out);
|
||||
|
||||
virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
NetNet*nex_map, NetNet*nex_out);
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
NetNet*accum_in);
|
||||
|
||||
virtual bool synth_sync(Design*des, NetScope*scope,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
|
|
@ -2416,7 +2461,8 @@ class NetWhile : public NetProc {
|
|||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
NetNet*nex_map, NetNet*nex_out);
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in);
|
||||
|
||||
private:
|
||||
NetExpr* cond_;
|
||||
|
|
@ -3466,6 +3512,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.321.2.14 2006/03/26 23:09:23 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.321.2.13 2006/03/18 18:43:21 steve
|
||||
* Better error messages when synthesis fails.
|
||||
*
|
||||
|
|
|
|||
146
synth2.cc
146
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.25 2006/03/18 18:43:22 steve Exp $"
|
||||
#ident "$Id: synth2.cc,v 1.39.2.26 2006/03/26 23:09:24 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -41,17 +41,27 @@ static int debug_synth2=0;
|
|||
#define DEBUG_SYNTH2_EXIT(class,val)
|
||||
#endif
|
||||
|
||||
bool NetProc::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
NetNet*nex_map, NetNet*nex_out)
|
||||
bool NetProc::synth_async_noaccum(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out)
|
||||
{
|
||||
return false;
|
||||
/* Make an unconnected stub for the accum_in net. */
|
||||
const perm_string tmp = perm_string::literal("tmp");
|
||||
NetNet*stub = new NetNet(scope, tmp, NetNet::WIRE, nex_out->pin_count());
|
||||
|
||||
bool flag = synth_async(des, scope, sync_flag, nex_ff,
|
||||
nex_map, nex_out, stub);
|
||||
|
||||
delete stub;
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool NetProc::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
NetNet*accum_in)
|
||||
{
|
||||
return synth_async(des, scope, sync_flag, nex_map, nex_out);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetProc::synth_sync(Design*des, NetScope*scope,
|
||||
|
|
@ -59,8 +69,7 @@ bool NetProc::synth_sync(Design*des, NetScope*scope,
|
|||
NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events)
|
||||
{
|
||||
/* Synthesize the input to the DFF. */
|
||||
return synth_async(des, scope, true, nex_map, nex_out);
|
||||
return synth_async_noaccum(des, scope, true, nex_ff, nex_map, nex_out);
|
||||
}
|
||||
|
||||
static unsigned find_nexus_in_set(const NetNet*nset, const Nexus*nex)
|
||||
|
|
@ -85,16 +94,7 @@ static unsigned find_nexus_in_set(const NetNet*nset, const Nexus*nex)
|
|||
*/
|
||||
|
||||
bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
NetNet*nex_map, NetNet*nex_out)
|
||||
{
|
||||
const perm_string tmp = perm_string::literal("tmp");
|
||||
NetNet*stub = new NetNet(scope, tmp, NetNet::WIRE, nex_out->pin_count());
|
||||
bool flag = synth_async(des, scope, sync_flag, nex_map, nex_out, stub);
|
||||
delete stub;
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
NetNet*accum_in)
|
||||
{
|
||||
|
|
@ -160,6 +160,45 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Handle the special case that this is a decoded
|
||||
enable. generate a demux for the device, with the
|
||||
WriteData connected to the r-value and the Data
|
||||
vector connected to the feedback. */
|
||||
if (cur->bmux() != 0) {
|
||||
assert(sync_flag);
|
||||
|
||||
NetNet*adr = cur->bmux()->synthesize(des);
|
||||
|
||||
NetDemux*dq = new NetDemux(scope, scope->local_symbol(),
|
||||
lsig->pin_count(),
|
||||
adr->pin_count());
|
||||
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));
|
||||
|
||||
assert(cur->lwidth() == 1);
|
||||
|
||||
for (unsigned idx = 0; idx < lsig->pin_count(); idx += 1) {
|
||||
unsigned off = cur->get_loff()+idx;
|
||||
unsigned ptr = find_nexus_in_set(nex_map, lsig->pin(off).nexus());
|
||||
assert(ptr <= nex_map->pin_count());
|
||||
connect(nex_out->pin(ptr), dq->pin_Q(idx));
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
roff += cur->lwidth();
|
||||
cur->turn_sig_to_wire_on_release();
|
||||
continue;
|
||||
}
|
||||
|
||||
/* By this point ant bmux() has been dealt with. Panic
|
||||
if that is not so. */
|
||||
assert(! cur->bmux());
|
||||
|
||||
/* Bind the outputs that we do make to the nex_out. Use the
|
||||
|
|
@ -192,7 +231,8 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
|||
* substatements.
|
||||
*/
|
||||
bool NetBlock::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
NetNet*nex_map, NetNet*nex_out)
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in)
|
||||
{
|
||||
DEBUG_SYNTH2_ENTRY("NetBlock")
|
||||
if (last_ == 0) {
|
||||
|
|
@ -241,7 +281,7 @@ bool NetBlock::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
|||
connect(new_accum->pin(idx), accum_out->pin(ptr));
|
||||
}
|
||||
|
||||
bool ok_flag = cur->synth_async(des, scope, sync_flag,
|
||||
bool ok_flag = cur->synth_async(des, scope, sync_flag, nex_ff,
|
||||
tmp_map, tmp_out, new_accum);
|
||||
flag = flag && ok_flag;
|
||||
|
||||
|
|
@ -307,16 +347,7 @@ bool NetBlock::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
|||
}
|
||||
|
||||
bool NetCase::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
NetNet*nex_map, NetNet*nex_out)
|
||||
{
|
||||
const perm_string tmp = perm_string::literal("tmp");
|
||||
NetNet*stub = new NetNet(scope, tmp, NetNet::WIRE, nex_out->pin_count());
|
||||
bool flag = synth_async(des, scope, sync_flag, nex_map, nex_out, stub);
|
||||
delete stub;
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool NetCase::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum)
|
||||
{
|
||||
unsigned cur;
|
||||
|
|
@ -371,7 +402,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
|||
/* Handle the special case that this can be done it a smaller
|
||||
1-hot MUX. */
|
||||
if (nondefault_items < sel_pins)
|
||||
return synth_async_1hot_(des, scope, sync_flag,
|
||||
return synth_async_1hot_(des, scope, sync_flag, nex_ff,
|
||||
nex_map, nex_out, accum,
|
||||
esig, nondefault_items);
|
||||
|
||||
|
|
@ -502,6 +533,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
|||
connect all the output bits it knows how to the
|
||||
sig net. */
|
||||
statement_map[item]->synth_async(des, scope, sync_flag,
|
||||
nex_ff,
|
||||
nex_map, sig, accum);
|
||||
|
||||
for (unsigned idx = 0 ; idx < mux->width() ; idx += 1) {
|
||||
|
|
@ -529,6 +561,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
|||
}
|
||||
|
||||
bool NetCase::synth_async_1hot_(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum,
|
||||
NetNet*esig, unsigned hot_items)
|
||||
{
|
||||
|
|
@ -583,7 +616,7 @@ bool NetCase::synth_async_1hot_(Design*des, NetScope*scope, bool sync_flag,
|
|||
NetNet*item_sig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, nex_map->pin_count());
|
||||
assert(items_[item].statement);
|
||||
items_[item].statement->synth_async(des, scope, sync_flag,
|
||||
items_[item].statement->synth_async(des, scope, sync_flag, nex_ff,
|
||||
nex_map, item_sig, accum);
|
||||
for (unsigned idx = 0 ; idx < item_sig->pin_count() ; idx += 1)
|
||||
connect(mux->pin_Data(idx, 1<<use_item), item_sig->pin(idx));
|
||||
|
|
@ -600,7 +633,7 @@ bool NetCase::synth_async_1hot_(Design*des, NetScope*scope, bool sync_flag,
|
|||
if (default_statement) {
|
||||
default_sig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, nex_map->pin_count());
|
||||
default_statement->synth_async(des, scope, sync_flag,
|
||||
default_statement->synth_async(des, scope, sync_flag, nex_ff,
|
||||
nex_map, default_sig, accum);
|
||||
|
||||
}
|
||||
|
|
@ -643,27 +676,13 @@ bool NetCase::synth_async_1hot_(Design*des, NetScope*scope, bool sync_flag,
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the synth_async method is called without an accumulated input
|
||||
* (in other words not from within a block) then stub the input signal
|
||||
* with an unconnected net.
|
||||
*/
|
||||
bool NetCondit::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
NetNet*nex_map, NetNet*nex_out)
|
||||
{
|
||||
const perm_string tmp = perm_string::literal("tmp");
|
||||
NetNet*stub = new NetNet(scope, tmp, NetNet::WIRE, nex_out->pin_count());
|
||||
bool flag = synth_async(des, scope, sync_flag, nex_map, nex_out, stub);
|
||||
delete stub;
|
||||
return flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle synthesis for an asynchronous condition statement. If we get
|
||||
* here, we know that the CE of a DFF has already been filled, so the
|
||||
* condition expression goes to the select of an asynchronous mux.
|
||||
*/
|
||||
bool NetCondit::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
NetNet*accum)
|
||||
{
|
||||
|
|
@ -726,7 +745,7 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
|||
}
|
||||
|
||||
} else {
|
||||
bool flag = if_->synth_async(des, scope, sync_flag,
|
||||
bool flag = if_->synth_async(des, scope, sync_flag, nex_ff,
|
||||
nex_map, asig, accum);
|
||||
if (!flag) {
|
||||
delete asig;
|
||||
|
|
@ -750,7 +769,7 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
|||
connect(bsig->pin(idx), nex_map->pin(idx));
|
||||
}
|
||||
} else {
|
||||
bool flag = else_->synth_async(des, scope, sync_flag,
|
||||
bool flag = else_->synth_async(des, scope, sync_flag, nex_ff,
|
||||
nex_map, bsig, accum);
|
||||
if (!flag) {
|
||||
delete asig;
|
||||
|
|
@ -818,10 +837,11 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
|||
}
|
||||
|
||||
bool NetEvWait::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
NetNet*nex_map, NetNet*nex_out)
|
||||
sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in)
|
||||
{
|
||||
bool flag = statement_->synth_async(des, scope, sync_flag,
|
||||
nex_map, nex_out);
|
||||
bool flag = statement_->synth_async(des, scope, sync_flag, nex_ff,
|
||||
nex_map, nex_out, accum_in);
|
||||
return flag;
|
||||
}
|
||||
|
||||
|
|
@ -836,8 +856,8 @@ bool NetProcTop::synth_async(Design*des)
|
|||
for (unsigned idx = 0 ; idx < nex_out->pin_count() ; idx += 1)
|
||||
connect(nex_set[idx], nex_out->pin(idx));
|
||||
|
||||
bool flag = statement_->synth_async(des, scope(), false,
|
||||
nex_out, nex_out);
|
||||
bool flag = statement_->synth_async_noaccum(des, scope(), false, 0,
|
||||
nex_out, nex_out);
|
||||
|
||||
delete nex_out;
|
||||
return flag;
|
||||
|
|
@ -915,7 +935,8 @@ bool NetAssignBase::synth_sync(Design*des, NetScope*scope,
|
|||
assignments. */
|
||||
if (demux == 0) {
|
||||
/* Synthesize the input to the DFF. */
|
||||
return synth_async(des, scope, true, nex_map, nex_out);
|
||||
return synth_async_noaccum(des, scope, true, nex_ff,
|
||||
nex_map, nex_out);
|
||||
}
|
||||
|
||||
assert(demux->bmux() != 0);
|
||||
|
|
@ -1256,7 +1277,8 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope,
|
|||
asig->local_flag(true);
|
||||
|
||||
assert(if_ != 0);
|
||||
bool flag = if_->synth_async(des, scope, true, nex_map, asig);
|
||||
bool flag = if_->synth_async_noaccum(des, scope, true, nex_ff,
|
||||
nex_map, asig);
|
||||
|
||||
assert(asig->pin_count() == ff->width());
|
||||
|
||||
|
|
@ -1347,7 +1369,8 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope,
|
|||
NetNet*asig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, nex_map->pin_count());
|
||||
asig->local_flag(true);
|
||||
bool flag = if_->synth_async(des, scope, true, nex_map, asig);
|
||||
bool flag = if_->synth_async_noaccum(des, scope, true, nex_ff,
|
||||
nex_map, asig);
|
||||
|
||||
if (!flag) {
|
||||
/* This path leads nowhere */
|
||||
|
|
@ -1399,7 +1422,8 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope,
|
|||
/* If this is an if/then/else, then it is likely a
|
||||
combinational if, and I should synthesize it that way. */
|
||||
if (if_ && else_) {
|
||||
bool flag = synth_async(des, scope, true, nex_map, nex_out);
|
||||
bool flag =synth_async_noaccum(des, scope, true, nex_ff,
|
||||
nex_map, nex_out);
|
||||
return flag;
|
||||
}
|
||||
|
||||
|
|
@ -1531,7 +1555,8 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
bool NetWhile::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
NetNet*nex_map, NetNet*nex_out)
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in)
|
||||
{
|
||||
cerr << get_line()
|
||||
<< ": error: Cannot synthesize for or while loops."
|
||||
|
|
@ -1671,6 +1696,9 @@ void synth2(Design*des)
|
|||
|
||||
/*
|
||||
* $Log: synth2.cc,v $
|
||||
* Revision 1.39.2.26 2006/03/26 23:09:24 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.39.2.25 2006/03/18 18:43:22 steve
|
||||
* Better error messages when synthesis fails.
|
||||
*
|
||||
|
|
|
|||
26
t-dll-api.cc
26
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.3 2006/03/12 07:34:19 steve Exp $"
|
||||
#ident "$Id: t-dll-api.cc,v 1.108.2.4 2006/03/26 23:09:24 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -765,6 +765,10 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
|||
assert(idx < net->u_.arith.width);
|
||||
return net->u_.arith.a[idx];
|
||||
|
||||
case IVL_LPM_DEMUX:
|
||||
assert(idx < net->u_.demux.width);
|
||||
return net->u_.demux.d[idx];
|
||||
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
assert(idx < net->u_.shift.width);
|
||||
|
|
@ -801,6 +805,10 @@ extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx)
|
|||
assert(idx < net->u_.arith.width);
|
||||
return net->u_.arith.b[idx];
|
||||
|
||||
case IVL_LPM_DEMUX:
|
||||
assert(idx < 1);
|
||||
return net->u_.demux.bit_in;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -939,6 +947,10 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
|
|||
else
|
||||
return net->u_.mux.q.pins[idx];
|
||||
|
||||
case IVL_LPM_DEMUX:
|
||||
assert(idx < net->u_.demux.width);
|
||||
return net->u_.demux.q[idx];
|
||||
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
assert(idx < net->u_.shift.width);
|
||||
|
|
@ -978,6 +990,10 @@ extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx)
|
|||
else
|
||||
return net->u_.mux.s.pins[idx];
|
||||
|
||||
case IVL_LPM_DEMUX:
|
||||
assert(idx < net->u_.demux.awid);
|
||||
return net->u_.demux.a[idx];
|
||||
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
assert(idx < net->u_.shift.select);
|
||||
|
|
@ -997,6 +1013,8 @@ extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net)
|
|||
case IVL_LPM_DECODE:
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.swid;
|
||||
case IVL_LPM_DEMUX:
|
||||
return net->u_.demux.awid;
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
return net->u_.shift.select;
|
||||
|
|
@ -1013,6 +1031,7 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
|||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
case IVL_LPM_MUX:
|
||||
case IVL_LPM_DEMUX:
|
||||
return 0;
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
|
|
@ -1066,6 +1085,8 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
|
|||
case IVL_LPM_DECODE:
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.width;
|
||||
case IVL_LPM_DEMUX:
|
||||
return net->u_.demux.width;
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
case IVL_LPM_CMP_GE:
|
||||
|
|
@ -1981,6 +2002,9 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
|
|||
|
||||
/*
|
||||
* $Log: t-dll-api.cc,v $
|
||||
* Revision 1.108.2.4 2006/03/26 23:09:24 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.108.2.3 2006/03/12 07:34:19 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
|
|
|
|||
65
t-dll.cc
65
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.5 2006/03/12 07:34:19 steve Exp $"
|
||||
#ident "$Id: t-dll.cc,v 1.131.2.6 2006/03/26 23:09:24 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -1547,6 +1547,66 @@ ivl_lpm_t dll_target::lpm_decode_ff_(const NetDecode*net)
|
|||
return obj;
|
||||
}
|
||||
|
||||
bool dll_target::lpm_demux(const NetDemux*net)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned width = net->width();
|
||||
unsigned awid = net->awidth();
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_DEMUX;
|
||||
obj->name = net->name();
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.demux.width = width;
|
||||
obj->u_.demux.awid = awid;
|
||||
|
||||
ivl_nexus_t*tmp = new ivl_nexus_t [2*net->width() + net->awidth()];
|
||||
obj->u_.demux.q = tmp;
|
||||
obj->u_.demux.d = tmp + width;
|
||||
obj->u_.demux.a = tmp + 2*width;
|
||||
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
const Nexus*nex = net->pin_Q(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.demux.q[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.demux.q[idx], obj, idx,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
const Nexus*nex = net->pin_Data(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.demux.d[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.demux.d[idx], obj, idx,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < awid ; idx += 1) {
|
||||
const Nexus*nex = net->pin_Address(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.demux.a[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.demux.a[idx], obj, idx,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
|
||||
{
|
||||
const Nexus*nex = net->pin_WriteData().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,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
|
||||
obj->nattr = net->attr_cnt();
|
||||
obj->attr = fill_in_attributes(net);
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
void dll_target::lpm_ff(const NetFF*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
|
|
@ -2271,6 +2331,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
|
|||
|
||||
/*
|
||||
* $Log: t-dll.cc,v $
|
||||
* Revision 1.131.2.6 2006/03/26 23:09:24 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.131.2.5 2006/03/12 07:34:19 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
|
|
|
|||
13
t-dll.h
13
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.3 2006/03/12 07:34:19 steve Exp $"
|
||||
#ident "$Id: t-dll.h,v 1.115.2.4 2006/03/26 23:09:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
|
|
@ -77,6 +77,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
void lpm_clshift(const NetCLShift*);
|
||||
void lpm_compare(const NetCompare*);
|
||||
bool lpm_decode(const NetDecode*);
|
||||
bool lpm_demux(const NetDemux*);
|
||||
void lpm_divide(const NetDivide*);
|
||||
void lpm_ff(const NetFF*);
|
||||
void lpm_modulo(const NetModulo*);
|
||||
|
|
@ -342,6 +343,13 @@ struct ivl_lpm_s {
|
|||
} s;
|
||||
} mux;
|
||||
|
||||
struct ivl_lpm_demux_s {
|
||||
unsigned width;
|
||||
unsigned awid;
|
||||
ivl_nexus_t bit_in;
|
||||
ivl_nexus_t *q,*d,*a;
|
||||
} demux;
|
||||
|
||||
struct ivl_lpm_shift_s {
|
||||
unsigned width;
|
||||
unsigned select;
|
||||
|
|
@ -694,6 +702,9 @@ struct ivl_variable_s {
|
|||
|
||||
/*
|
||||
* $Log: t-dll.h,v $
|
||||
* Revision 1.115.2.4 2006/03/26 23:09:25 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.115.2.3 2006/03/12 07:34:19 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
|
|
|
|||
12
target.cc
12
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.69.2.1 2006/02/19 00:11:34 steve Exp $"
|
||||
#ident "$Id: target.cc,v 1.69.2.2 2006/03/26 23:09:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -108,6 +108,13 @@ bool target_t::lpm_decode(const NetDecode*)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool target_t::lpm_demux(const NetDemux*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetDemux." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
void target_t::lpm_divide(const NetDivide*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
|
|
@ -427,6 +434,9 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
|
|||
|
||||
/*
|
||||
* $Log: target.cc,v $
|
||||
* Revision 1.69.2.2 2006/03/26 23:09:25 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.69.2.1 2006/02/19 00:11:34 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
|
|
|
|||
6
target.h
6
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.65.2.1 2006/02/19 00:11:34 steve Exp $"
|
||||
#ident "$Id: target.h,v 1.65.2.2 2006/03/26 23:09:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
|
@ -80,6 +80,7 @@ struct target_t {
|
|||
virtual void lpm_clshift(const NetCLShift*);
|
||||
virtual void lpm_compare(const NetCompare*);
|
||||
virtual bool lpm_decode(const NetDecode*);
|
||||
virtual bool lpm_demux(const NetDemux*);
|
||||
virtual void lpm_divide(const NetDivide*);
|
||||
virtual void lpm_modulo(const NetModulo*);
|
||||
virtual void lpm_ff(const NetFF*);
|
||||
|
|
@ -171,6 +172,9 @@ extern const struct target *target_table[];
|
|||
|
||||
/*
|
||||
* $Log: target.h,v $
|
||||
* Revision 1.65.2.2 2006/03/26 23:09:25 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.65.2.1 2006/02/19 00:11:34 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.7 2006/03/12 07:34:20 steve Exp $"
|
||||
#ident "$Id: stub.c,v 1.90.2.8 2006/03/26 23:09:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -233,6 +233,36 @@ static void show_lpm_ram(ivl_lpm_t net)
|
|||
}
|
||||
}
|
||||
|
||||
static void show_lpm_demux(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
unsigned awid = ivl_lpm_selects(net);
|
||||
|
||||
fprintf(out, " LPM_DEMUX %s (word-width=%u, addr-width=%u)\n",
|
||||
ivl_lpm_basename(net), width, awid);
|
||||
|
||||
for (idx = 0 ; idx < width ; idx += 1)
|
||||
fprintf(out, " Q %u: %s\n", idx,
|
||||
ivl_nexus_name(ivl_lpm_q(net, idx)));
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
ivl_nexus_t nex = ivl_lpm_data(net, idx);
|
||||
fprintf(out, " Data %u: %s\n", idx,
|
||||
nex? ivl_nexus_name(nex) : "");
|
||||
}
|
||||
for (idx = 0 ; idx < awid ; idx += 1) {
|
||||
ivl_nexus_t nex = ivl_lpm_select(net, idx);
|
||||
fprintf(out, " Address %u: %s\n", idx,
|
||||
nex? ivl_nexus_name(nex) : "");
|
||||
}
|
||||
|
||||
{
|
||||
ivl_nexus_t nex = ivl_lpm_datab(net, 0);
|
||||
fprintf(out, " WriteIn: %s\n",
|
||||
nex? ivl_nexus_name(nex) : "");
|
||||
}
|
||||
}
|
||||
|
||||
static void show_lpm(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
|
|
@ -341,6 +371,10 @@ static void show_lpm(ivl_lpm_t net)
|
|||
break;
|
||||
}
|
||||
|
||||
case IVL_LPM_DEMUX:
|
||||
show_lpm_demux(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_RAM:
|
||||
show_lpm_ram(net);
|
||||
break;
|
||||
|
|
@ -1073,6 +1107,9 @@ int target_design(ivl_design_t des)
|
|||
|
||||
/*
|
||||
* $Log: stub.c,v $
|
||||
* Revision 1.90.2.8 2006/03/26 23:09:25 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.90.2.7 2006/03/12 07:34:20 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: vvp_scope.c,v 1.103.2.4 2006/03/12 07:34:20 steve Exp $"
|
||||
#ident "$Id: vvp_scope.c,v 1.103.2.5 2006/03/26 23:09:26 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
|
|
@ -402,6 +402,7 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
|||
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_MUX:
|
||||
case IVL_LPM_DEMUX:
|
||||
for (idx = 0 ; idx < ivl_lpm_width(lpm) ; idx += 1)
|
||||
if (ivl_lpm_q(lpm, idx) == nex) {
|
||||
sprintf(result, "L_%s.%s/%u",
|
||||
|
|
@ -1296,6 +1297,49 @@ static void draw_lpm_decode(ivl_lpm_t net)
|
|||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw a demux as an address decoder and .decode bit slices.
|
||||
*/
|
||||
static void draw_lpm_demux(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
|
||||
/* Draw a .decode/adr node to do address decoding. */
|
||||
draw_lpm_decode(net);
|
||||
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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>");
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw == and != gates. This is done as XNOR functors to compare each
|
||||
* pair of bits. The result is combined with a wide and, or a NAND if
|
||||
|
|
@ -1698,6 +1742,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
|
|||
draw_lpm_decode(net);
|
||||
return;
|
||||
|
||||
case IVL_LPM_DEMUX:
|
||||
draw_lpm_demux(net);
|
||||
return;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "XXXX LPM not supported: %s.%s\n",
|
||||
ivl_scope_name(ivl_lpm_scope(net)), ivl_lpm_basename(net));
|
||||
|
|
@ -1821,6 +1869,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
|
|||
|
||||
/*
|
||||
* $Log: vvp_scope.c,v $
|
||||
* Revision 1.103.2.5 2006/03/26 23:09:26 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.103.2.4 2006/03/12 07:34:20 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue