Handle synthesis of FF vectors with l-value decoder.
This commit is contained in:
parent
3ea1214160
commit
7527c466ed
|
|
@ -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.1 2006/01/18 01:23:23 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.149.2.2 2006/02/19 00:11:31 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -216,6 +216,14 @@ void NetCompare::dump_node(ostream&o, unsigned ind) const
|
|||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetDecode::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_DECODE (NetDecode): " << name()
|
||||
<< " ff=" << ff_->name() << 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;
|
||||
|
|
@ -272,7 +280,11 @@ void NetFF::dump_node(ostream&o, unsigned ind) const
|
|||
{
|
||||
o << setw(ind) << "" << "LPM_FF: " << name()
|
||||
<< " scope=" << (scope()? scope()->name() : "")
|
||||
<< " aset_value=" << aset_value_ << endl;
|
||||
<< " aset_value=" << aset_value_;
|
||||
|
||||
if (demux_) o << " demux=" << demux_->name();
|
||||
|
||||
o << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
|
|
@ -358,7 +370,6 @@ void NetRamDq::dump_node(ostream&o, unsigned ind) const
|
|||
o << setw(ind) << "" << "LPM_RAM_DQ (";
|
||||
|
||||
if (mem_) o << "mem=" << mem_->name();
|
||||
if (sig_) o << "sig=" << sig_->name();
|
||||
|
||||
o << "): " << name() << endl;
|
||||
|
||||
|
|
@ -1094,6 +1105,9 @@ void Design::dump(ostream&o) const
|
|||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.149.2.2 2006/02/19 00:11:31 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.149.2.1 2006/01/18 01:23:23 steve
|
||||
* Rework l-value handling to allow for more l-value type flexibility.
|
||||
*
|
||||
|
|
|
|||
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 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: emit.cc,v 1.77.2.1 2006/02/19 00:11:31 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -86,6 +86,11 @@ bool NetConst::emit_node(struct target_t*tgt) const
|
|||
return tgt->net_const(this);
|
||||
}
|
||||
|
||||
bool NetDecode::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->lpm_decode(this);
|
||||
}
|
||||
|
||||
bool NetDivide::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_divide(this);
|
||||
|
|
@ -511,6 +516,9 @@ bool emit(const Design*des, const char*type)
|
|||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.77.2.1 2006/02/19 00:11:31 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.77 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
1
ivl.def
1
ivl.def
|
|
@ -68,6 +68,7 @@ ivl_lpm_data
|
|||
ivl_lpm_datab
|
||||
ivl_lpm_data2
|
||||
ivl_lpm_data2_width
|
||||
ivl_lpm_decode
|
||||
ivl_lpm_define
|
||||
ivl_lpm_enable
|
||||
ivl_lpm_memory
|
||||
|
|
|
|||
29
ivl_target.h
29
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 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: ivl_target.h,v 1.126.2.1 2006/02/19 00:11:31 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -226,6 +226,7 @@ typedef enum ivl_lpm_type_e {
|
|||
IVL_LPM_CMP_GE = 1,
|
||||
IVL_LPM_CMP_GT = 2,
|
||||
IVL_LPM_CMP_NE = 11,
|
||||
IVL_LPM_DECODE = 15,
|
||||
IVL_LPM_DIVIDE = 12,
|
||||
IVL_LPM_FF = 3,
|
||||
IVL_LPM_MOD = 13,
|
||||
|
|
@ -642,13 +643,18 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
|||
* Return the input data nexus for device types that have a second
|
||||
* input vector. For example, arithmetic devices are like this.
|
||||
*
|
||||
* ivl_lpm_decode
|
||||
* Return the DECODER associated with this LPM_FF device. The
|
||||
* decoder for a FF takes an input address and generates an enable
|
||||
* input for no more then 1 bit (can be none) of the FF device.
|
||||
*
|
||||
* ivl_lpm_q
|
||||
* Return the output data nexus for device types that have a single
|
||||
* output vector. This is most devices, it turns out.
|
||||
*
|
||||
* ivl_lpm_selects
|
||||
* This is the size of the select input for a LPM_MUX device, or the
|
||||
* address bus width of an LPM_RAM.
|
||||
* This is the size of the select input for a LPM_MUX or LPM_DECODE
|
||||
* device, or the address bus width of an LPM_RAM.
|
||||
*
|
||||
* ivl_lpm_signed
|
||||
* Arithmetic LPM devices may be signed or unsigned if there is a
|
||||
|
|
@ -658,6 +664,14 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
|||
* In addition to a width, some devices have a size. The size is
|
||||
* often the number of inputs per out, i.e., the number of inputs
|
||||
* per bit for a MUX.
|
||||
*
|
||||
* SEMANTIC NOTES:
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */
|
||||
|
|
@ -676,6 +690,8 @@ extern ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net);
|
|||
extern ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF IVL_LPM_RAM */
|
||||
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF */
|
||||
extern ivl_lpm_t ivl_lpm_decode(ivl_lpm_t net);
|
||||
/* IVL_LPM_UFUNC */
|
||||
extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF IVL_LPM_RAM */
|
||||
|
|
@ -691,9 +707,9 @@ 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_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_MUX IVL_LPM_RAM */
|
||||
/* IVL_LPM_MUX IVL_LPM_DECODE IVL_LPM_RAM */
|
||||
extern unsigned ivl_lpm_selects(ivl_lpm_t net);
|
||||
/* IVL_LPM_MUX IVL_LPM_RAM */
|
||||
/* 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 */
|
||||
extern unsigned ivl_lpm_size(ivl_lpm_t net);
|
||||
|
|
@ -1236,6 +1252,9 @@ _END_DECL
|
|||
|
||||
/*
|
||||
* $Log: ivl_target.h,v $
|
||||
* Revision 1.126.2.1 2006/02/19 00:11:31 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.126 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
77
netlist.cc
77
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.1 2006/01/18 01:23:23 steve Exp $"
|
||||
#ident "$Id: netlist.cc,v 1.226.2.2 2006/02/19 00:11:32 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -234,7 +234,6 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
|||
assert(s);
|
||||
|
||||
release_list_ = 0;
|
||||
ram_ = 0;
|
||||
|
||||
verinum::V init_value = verinum::Vz;
|
||||
Link::DIR dir = Link::PASSIVE;
|
||||
|
|
@ -276,7 +275,6 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, long ms, long ls)
|
|||
assert(s);
|
||||
|
||||
release_list_ = 0;
|
||||
ram_ = 0;
|
||||
|
||||
verinum::V init_value = verinum::Vz;
|
||||
Link::DIR dir = Link::PASSIVE;
|
||||
|
|
@ -535,6 +533,8 @@ const NetScope* NetProcTop::scope() const
|
|||
NetFF::NetFF(NetScope*s, perm_string n, unsigned wid)
|
||||
: NetNode(s, n, 8 + 2*wid)
|
||||
{
|
||||
demux_ = 0;
|
||||
|
||||
pin_Clock().set_dir(Link::INPUT);
|
||||
pin_Clock().set_name(perm_string::literal("Clock"), 0);
|
||||
pin_Enable().set_dir(Link::INPUT);
|
||||
|
|
@ -686,6 +686,20 @@ const verinum& NetFF::sset_value() const
|
|||
return sset_value_;
|
||||
}
|
||||
|
||||
unsigned NetDecode::awidth() const
|
||||
{
|
||||
return pin_count();
|
||||
}
|
||||
|
||||
NetDecode* NetFF::get_demux()
|
||||
{
|
||||
return demux_;
|
||||
}
|
||||
|
||||
const NetDecode* NetFF::get_demux() const
|
||||
{
|
||||
return demux_;
|
||||
}
|
||||
|
||||
/*
|
||||
* The NetAddSub class represents an LPM_ADD_SUB device. The pinout is
|
||||
|
|
@ -1062,6 +1076,36 @@ const Link& NetCompare::pin_DataB(unsigned idx) const
|
|||
return pin(8+width_+idx);
|
||||
}
|
||||
|
||||
NetDecode::NetDecode(NetScope*s, perm_string name, NetFF*mem, unsigned awid)
|
||||
: NetNode(s, name, awid)
|
||||
{
|
||||
ff_ = mem;
|
||||
ff_->demux_ = this;
|
||||
make_pins_(awid);
|
||||
}
|
||||
|
||||
NetDecode::~NetDecode()
|
||||
{
|
||||
}
|
||||
|
||||
void NetDecode::make_pins_(unsigned awid)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < awid ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("Address"), idx);
|
||||
}
|
||||
}
|
||||
|
||||
Link& NetDecode::pin_Address(unsigned idx)
|
||||
{
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
const Link& NetDecode::pin_Address(unsigned idx) const
|
||||
{
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
NetDivide::NetDivide(NetScope*sc, perm_string n, unsigned wr,
|
||||
unsigned wa, unsigned wb)
|
||||
: NetNode(sc, n, wr+wa+wb),
|
||||
|
|
@ -1412,23 +1456,13 @@ void NetRamDq::make_pins_(unsigned wid)
|
|||
|
||||
NetRamDq::NetRamDq(NetScope*s, perm_string n, NetMemory*mem, unsigned awid)
|
||||
: NetNode(s, n, 3+2*mem->width()+awid),
|
||||
mem_(mem), sig_(0), awidth_(awid)
|
||||
mem_(mem), awidth_(awid)
|
||||
{
|
||||
make_pins_(mem->width());
|
||||
next_ = mem_->ram_list_;
|
||||
mem_->ram_list_ = this;
|
||||
}
|
||||
|
||||
NetRamDq::NetRamDq(NetScope*s, perm_string n, NetNet*sig, unsigned awid)
|
||||
: NetNode(s, n, 3+2*1+awid),
|
||||
mem_(0), sig_(sig), awidth_(awid)
|
||||
{
|
||||
make_pins_(1);
|
||||
|
||||
assert(sig->ram_ == 0);
|
||||
sig->ram_ = this;
|
||||
}
|
||||
|
||||
NetRamDq::~NetRamDq()
|
||||
{
|
||||
if (mem_) {
|
||||
|
|
@ -1445,17 +1479,11 @@ NetRamDq::~NetRamDq()
|
|||
cur->next_ = next_;
|
||||
}
|
||||
}
|
||||
|
||||
if (sig_) {
|
||||
assert(sig_->ram_ == this);
|
||||
sig_->ram_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned NetRamDq::width() const
|
||||
{
|
||||
if (mem_) return mem_->width();
|
||||
if (sig_) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1467,7 +1495,6 @@ unsigned NetRamDq::awidth() const
|
|||
unsigned NetRamDq::size() const
|
||||
{
|
||||
if (mem_) return mem_->count();
|
||||
if (sig_) return sig_->pin_count();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1476,11 +1503,6 @@ const NetMemory* NetRamDq::mem() const
|
|||
return mem_;
|
||||
}
|
||||
|
||||
const NetNet* NetRamDq::sig() const
|
||||
{
|
||||
return sig_;
|
||||
}
|
||||
|
||||
unsigned NetRamDq::count_partners() const
|
||||
{
|
||||
unsigned count = 0;
|
||||
|
|
@ -2313,6 +2335,9 @@ const NetProc*NetTaskDef::proc() const
|
|||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* Revision 1.226.2.2 2006/02/19 00:11:32 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.226.2.1 2006/01/18 01:23:23 steve
|
||||
* Rework l-value handling to allow for more l-value type flexibility.
|
||||
*
|
||||
|
|
|
|||
54
netlist.h
54
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.9 2006/01/21 21:42:31 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.321.2.10 2006/02/19 00:11:32 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -447,9 +447,6 @@ class NetNet : public NetObj {
|
|||
friend class NetRelease;
|
||||
NetRelease*release_list_;
|
||||
|
||||
friend class NetRamDq;
|
||||
class NetRamDq*ram_;
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
PortType port_type_;
|
||||
|
|
@ -594,6 +591,36 @@ class NetCompare : public NetNode {
|
|||
bool signed_flag_;
|
||||
};
|
||||
|
||||
/*
|
||||
* A decoder takes an address input and activates (high) the single
|
||||
* Q bit that is addressed. This can be used, for example, to
|
||||
* generate an enable for a FF from an array of FFs.
|
||||
*/
|
||||
class NetDecode : public NetNode {
|
||||
|
||||
public:
|
||||
NetDecode(NetScope*s, perm_string name, NetFF*mem, unsigned awid);
|
||||
~NetDecode();
|
||||
|
||||
unsigned awidth() const;
|
||||
|
||||
const NetFF*ff() const;
|
||||
|
||||
Link& pin_Address(unsigned idx);
|
||||
|
||||
const Link& pin_Address(unsigned idx) const;
|
||||
const Link& pin_Q(unsigned idx) const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
NetFF* ff_;
|
||||
|
||||
private:
|
||||
void make_pins_(unsigned awid);
|
||||
};
|
||||
|
||||
/*
|
||||
* This class represents a theoretical (though not necessarily
|
||||
* practical) integer divider gate. This is not to represent any real
|
||||
|
|
@ -716,10 +743,19 @@ class NetFF : public NetNode {
|
|||
void sset_value(const verinum&val);
|
||||
const verinum& sset_value() const;
|
||||
|
||||
NetDecode* get_demux();
|
||||
const NetDecode* get_demux() const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
virtual void functor_node(Design*des, functor_t*fun);
|
||||
|
||||
private:
|
||||
// If there is a demux associated with this gate, the demux_
|
||||
// member will point to the decoder.
|
||||
friend class NetDecode;
|
||||
NetDecode*demux_;
|
||||
|
||||
private:
|
||||
verinum aset_value_;
|
||||
verinum sset_value_;
|
||||
|
|
@ -886,14 +922,12 @@ class NetRamDq : public NetNode {
|
|||
|
||||
public:
|
||||
NetRamDq(NetScope*s, perm_string name, NetMemory*mem, unsigned awid);
|
||||
NetRamDq(NetScope*s, perm_string name, NetNet*mem, unsigned awid);
|
||||
~NetRamDq();
|
||||
|
||||
unsigned width() const;
|
||||
unsigned awidth() const;
|
||||
unsigned size() const;
|
||||
const NetMemory*mem() const;
|
||||
const NetNet*sig() const;
|
||||
|
||||
Link& pin_InClock();
|
||||
Link& pin_OutClock();
|
||||
|
|
@ -925,7 +959,6 @@ class NetRamDq : public NetNode {
|
|||
|
||||
private:
|
||||
NetMemory*mem_;
|
||||
NetNet* sig_;
|
||||
NetRamDq*next_;
|
||||
unsigned awidth_;
|
||||
|
||||
|
|
@ -1518,6 +1551,10 @@ class NetAssignBase : public NetProc {
|
|||
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
NetNet*accum_in);
|
||||
bool synth_sync(Design*des, NetScope*scope,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events);
|
||||
|
||||
// This dumps all the lval structures.
|
||||
void dump_lval(ostream&) const;
|
||||
|
|
@ -3402,6 +3439,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.321.2.10 2006/02/19 00:11:32 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.321.2.9 2006/01/21 21:42:31 steve
|
||||
* When mux has wide select but sparse choices, use 1hot translation.
|
||||
*
|
||||
|
|
|
|||
194
synth2.cc
194
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.20 2006/01/27 01:58:53 steve Exp $"
|
||||
#ident "$Id: synth2.cc,v 1.39.2.21 2006/02/19 00:11:33 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -59,13 +59,6 @@ bool NetProc::synth_sync(Design*des, NetScope*scope,
|
|||
NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events)
|
||||
{
|
||||
#if 0
|
||||
if (events.count() > 0) {
|
||||
cerr << get_line() << ": error: Events are unaccounted"
|
||||
<< " for in process synthesis. (proc)" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
#endif
|
||||
/* Synthesize the input to the DFF. */
|
||||
return synth_async(des, scope, true, nex_map, nex_out);
|
||||
}
|
||||
|
|
@ -128,31 +121,7 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Detect and handle the special case that this is a
|
||||
memory-like access to a vector. */
|
||||
if (cur->bmux()) {
|
||||
NetNet*adr = cur->bmux()->synthesize(des);
|
||||
NetRamDq*dq = new NetRamDq(scope, scope->local_symbol(),
|
||||
lsig, 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));
|
||||
#if 0
|
||||
/* Connect the Q bit to all the bits of the
|
||||
output. This is a signal to a later stage that
|
||||
the DFF should be replaced with a RAM to
|
||||
support this port. */
|
||||
for (unsigned idx = 0; idx < lsig->pin_count(); idx += 1){
|
||||
unsigned ptr = find_nexus_in_set(nex_map, lsig->pin(idx).nexus());
|
||||
connect(dq->pin_Q(0), nex_out->pin(ptr));
|
||||
}
|
||||
#endif
|
||||
connect(dq->pin_Data(0), rsig->pin(roff));
|
||||
roff += cur->lwidth();
|
||||
continue;
|
||||
}
|
||||
assert(! cur->bmux());
|
||||
|
||||
/* Bind the outputs that we do make to the nex_out. Use the
|
||||
nex_map to map the l-value bit position to the nex_out bit
|
||||
|
|
@ -871,6 +840,55 @@ static bool merge_ff_slices(NetFF*ff1, unsigned idx1,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NetAssignBase::synth_sync(Design*des, NetScope*scope,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events)
|
||||
{
|
||||
unsigned count_lval = 0;
|
||||
NetAssign_*demux = 0;
|
||||
|
||||
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
|
||||
if (cur->bmux())
|
||||
demux = cur;
|
||||
|
||||
count_lval += 1;
|
||||
}
|
||||
|
||||
if (demux != 0 && count_lval != 1) {
|
||||
cerr << get_line() << ": error: Cannot synthesize assignmnents"
|
||||
<< "that mix memory and vector assignments." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* There is no memory address, so resort to async
|
||||
assignments. */
|
||||
if (demux == 0) {
|
||||
/* Synthesize the input to the DFF. */
|
||||
return synth_async(des, scope, true, nex_map, nex_out);
|
||||
}
|
||||
|
||||
assert(demux->bmux() != 0);
|
||||
|
||||
NetNet*adr = demux->bmux()->synthesize(des);
|
||||
NetDecode*dq = new NetDecode(scope, scope->local_symbol(),
|
||||
nex_ff[0].ff, 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));
|
||||
|
||||
NetNet*rsig = rval_->synthesize(des);
|
||||
assert(rsig->pin_count() == 1);
|
||||
|
||||
for (unsigned idx = 0 ; idx < nex_ff[0].ff->width() ; idx += 1)
|
||||
connect(nex_ff[0].ff->pin_Data(idx), rsig->pin(0));
|
||||
|
||||
lval_->turn_sig_to_wire_on_release();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is called when a block is encountered near the surface
|
||||
* of a synchronous always statement. For example, this code will be
|
||||
|
|
@ -1459,10 +1477,11 @@ bool NetProcTop::synth_sync(Design*des)
|
|||
nex_set.count());
|
||||
des->add_node(ff);
|
||||
ff->attribute(perm_string::literal("LPM_FFType"), verinum("DFF"));
|
||||
unsigned process_pin_count = ff->width();
|
||||
|
||||
struct sync_accounting_cell*nex_ff
|
||||
= new struct sync_accounting_cell[ff->pin_count()];
|
||||
for (unsigned idx = 0 ; idx < ff->pin_count() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < process_pin_count ; idx += 1) {
|
||||
nex_ff[idx].ff = ff;
|
||||
nex_ff[idx].pin = idx;
|
||||
nex_ff[idx].proc = statement_;
|
||||
|
|
@ -1494,6 +1513,47 @@ bool NetProcTop::synth_sync(Design*des)
|
|||
nex_q, nex_d,
|
||||
svector<NetEvProbe*>());
|
||||
|
||||
#if 0
|
||||
/* Now look for FFs that have been attached to a
|
||||
decoder. These need to be handled specially. */
|
||||
for (unsigned idx = 0; idx < process_pin_count ; idx += 1) {
|
||||
NetFF*ff = nex_ff[idx].ff;
|
||||
unsigned pin = nex_ff[idx].pin;
|
||||
if (ff == 0)
|
||||
continue;
|
||||
|
||||
NetDecode*demux = ff->get_demux();
|
||||
|
||||
nex_ff[idx].ff = 0;
|
||||
|
||||
if (demux == 0)
|
||||
continue;
|
||||
|
||||
cerr << "XXXX Demux bit " << idx << "["<<pin<<"]"
|
||||
<< " of " << ff
|
||||
<< " with demux=" << demux << endl;
|
||||
ff->pin_Data(pin).unlink();
|
||||
|
||||
for (unsigned idx2 = idx+1 ; idx2 < process_pin_count; idx2+=1) {
|
||||
NetFF*ff2 = nex_ff[idx2].ff;
|
||||
unsigned pin2 = nex_ff[idx2].pin;
|
||||
|
||||
if (ff2->get_demux() != demux)
|
||||
continue;
|
||||
|
||||
nex_ff[idx2].ff = 0;
|
||||
assert(ff2 == ff);
|
||||
|
||||
cerr << "XXXX Demux bit " << idx2
|
||||
<< "["<<pin2<<"]"
|
||||
<< " also attached to demux=" << demux << endl;
|
||||
|
||||
ff2->pin_Data(pin2).unlink();
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
delete nex_q;
|
||||
delete[]nex_ff;
|
||||
|
||||
|
|
@ -1579,6 +1639,9 @@ void synth2(Design*des)
|
|||
|
||||
/*
|
||||
* $Log: synth2.cc,v $
|
||||
* Revision 1.39.2.21 2006/02/19 00:11:33 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.39.2.20 2006/01/27 01:58:53 steve
|
||||
* Document how the default statement handling works.
|
||||
*
|
||||
|
|
@ -1638,68 +1701,5 @@ void synth2(Design*des)
|
|||
*
|
||||
* Revision 1.39.2.1 2005/08/21 22:49:54 steve
|
||||
* Handle statements in blocks overriding previous statement outputs.
|
||||
*
|
||||
* Revision 1.39 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.38 2004/08/28 15:08:32 steve
|
||||
* Do not change reg to wire in NetAssign_ unless synthesizing.
|
||||
*
|
||||
* Revision 1.37 2004/03/15 18:40:12 steve
|
||||
* Only include DEBUG_SYNTH2 if __FUNCTION__ defined.
|
||||
*
|
||||
* Revision 1.36 2004/02/20 18:53:35 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
* Revision 1.35 2004/02/18 17:11:58 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.34 2003/12/20 00:59:31 steve
|
||||
* Synthesis debug messages.
|
||||
*
|
||||
* Revision 1.33 2003/12/17 16:52:39 steve
|
||||
* Debug dumps for synth2.
|
||||
*
|
||||
* Revision 1.32 2003/10/27 02:18:04 steve
|
||||
* Handle special case of FF with enable and constant data.
|
||||
*
|
||||
* Revision 1.31 2003/08/28 04:11:19 steve
|
||||
* Spelling patch.
|
||||
*
|
||||
* Revision 1.30 2003/08/15 02:23:53 steve
|
||||
* Add synthesis support for synchronous reset.
|
||||
*
|
||||
* Revision 1.29 2003/08/14 02:41:05 steve
|
||||
* Fix dangling pointer in NexusSet handling blocks.
|
||||
*
|
||||
* Revision 1.28 2003/08/10 17:04:23 steve
|
||||
* Detect asynchronous FF inputs that are expressions.
|
||||
*
|
||||
* Revision 1.27 2003/06/23 00:14:44 steve
|
||||
* ivl_synthesis_cell cuts off synthesis within a module.
|
||||
*
|
||||
* Revision 1.26 2003/06/21 01:21:43 steve
|
||||
* Harmless fixup of warnings.
|
||||
*
|
||||
* Revision 1.25 2003/04/03 04:30:00 steve
|
||||
* Prevent overrun comparing verinums to zero.
|
||||
*
|
||||
* Revision 1.24 2003/03/25 04:04:29 steve
|
||||
* Handle defaults in synthesized case statements.
|
||||
*
|
||||
* Revision 1.23 2003/03/06 00:28:42 steve
|
||||
* All NetObj objects have lex_string base names.
|
||||
*
|
||||
* Revision 1.22 2003/02/26 01:29:24 steve
|
||||
* LPM objects store only their base names.
|
||||
*
|
||||
* Revision 1.21 2003/01/27 05:09:17 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.20 2002/11/09 23:29:29 steve
|
||||
* Handle nested-if chip enables.
|
||||
*
|
||||
* Revision 1.19 2002/11/09 20:22:57 steve
|
||||
* Detect synthesis conflicts blocks statements share outputs.
|
||||
*/
|
||||
|
||||
|
|
|
|||
25
t-dll-api.cc
25
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 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: t-dll-api.cc,v 1.108.2.1 2006/02/19 00:11:33 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -833,6 +833,18 @@ extern "C" unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx)
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_lpm_t ivl_lpm_decode(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_FF:
|
||||
return net->u_.ff.a.decode;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns the hierarchical name for the LPM device. The
|
||||
* name needs to be built up from the scope name and the lpm base
|
||||
|
|
@ -929,6 +941,7 @@ extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx)
|
|||
else
|
||||
return net->u_.ff.s.pins[idx];
|
||||
|
||||
case IVL_LPM_DECODE:
|
||||
case IVL_LPM_MUX:
|
||||
assert(idx < net->u_.mux.swid);
|
||||
if (net->u_.mux.swid == 1)
|
||||
|
|
@ -952,6 +965,7 @@ extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net)
|
|||
switch (net->type) {
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.swid;
|
||||
case IVL_LPM_DECODE:
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.swid;
|
||||
case IVL_LPM_SHIFTL:
|
||||
|
|
@ -984,7 +998,7 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
|||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
return net->u_.shift.signed_flag;
|
||||
return 0;
|
||||
case IVL_LPM_DECODE:
|
||||
case IVL_LPM_UFUNC:
|
||||
return 0;
|
||||
default:
|
||||
|
|
@ -1035,6 +1049,8 @@ 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;
|
||||
|
|
@ -1046,7 +1062,7 @@ extern "C" ivl_memory_t ivl_lpm_memory(ivl_lpm_t net)
|
|||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.mem;
|
||||
return net->u_.ff.a.mem;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -1935,6 +1951,9 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
|
|||
|
||||
/*
|
||||
* $Log: t-dll-api.cc,v $
|
||||
* Revision 1.108.2.1 2006/02/19 00:11:33 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.108 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
52
t-dll.cc
52
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.2 2006/01/21 21:42:33 steve Exp $"
|
||||
#ident "$Id: t-dll.cc,v 1.131.2.3 2006/02/19 00:11:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -1491,12 +1491,55 @@ void dll_target::lpm_modulo(const NetModulo*net)
|
|||
scope_add_lpm(obj->scope, obj);
|
||||
}
|
||||
|
||||
bool dll_target::lpm_decode(const NetDecode*net)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
ivl_lpm_t dll_target::lpm_decode_ff_(const NetDecode*net)
|
||||
{
|
||||
if (net == 0)
|
||||
return 0;
|
||||
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_DECODE;
|
||||
obj->name = net->name();
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
|
||||
obj->u_.mux.swid = net->awidth();
|
||||
obj->u_.mux.size = 0;
|
||||
obj->u_.mux.width = 0;
|
||||
obj->u_.mux.d = 0;
|
||||
|
||||
if (obj->u_.mux.swid > 1) {
|
||||
obj->u_.mux.s.pins = new ivl_nexus_t[obj->u_.mux.swid];
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->u_.mux.swid ; idx += 1) {
|
||||
const Nexus*nex = net->pin_Address(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.mux.s.pins[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.mux.s.pins[idx], obj, idx,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
} else {
|
||||
assert(obj->u_.mux.swid == 1);
|
||||
const Nexus*nex = net->pin_Address(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.mux.s.pin = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.mux.s.pin, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
void dll_target::lpm_ff(const NetFF*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_FF;
|
||||
obj->name = net->name();
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
obj->u_.ff.a.decode = lpm_decode_ff_(net->get_demux());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.ff.width = net->width();
|
||||
|
|
@ -1612,8 +1655,8 @@ void dll_target::lpm_ram_dq(const NetRamDq*net)
|
|||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_RAM;
|
||||
obj->name = net->name();
|
||||
obj->u_.ff.mem = find_memory(des_, net->mem());
|
||||
assert(obj->u_.ff.mem);
|
||||
obj->u_.ff.a.mem = find_memory(des_, net->mem());
|
||||
assert(obj->u_.ff.a.mem);
|
||||
obj->scope = find_scope(des_, net->mem()->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
|
|
@ -2182,6 +2225,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
|
|||
|
||||
/*
|
||||
* $Log: t-dll.cc,v $
|
||||
* Revision 1.131.2.3 2006/02/19 00:11:34 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.131.2.2 2006/01/21 21:42:33 steve
|
||||
* When mux has wide select but sparse choices, use 1hot translation.
|
||||
*
|
||||
|
|
|
|||
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 2004/10/04 01:10:56 steve Exp $"
|
||||
#ident "$Id: t-dll.h,v 1.115.2.1 2006/02/19 00:11:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
|
|
@ -76,6 +76,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
void lpm_add_sub(const NetAddSub*);
|
||||
void lpm_clshift(const NetCLShift*);
|
||||
void lpm_compare(const NetCompare*);
|
||||
bool lpm_decode(const NetDecode*);
|
||||
void lpm_divide(const NetDivide*);
|
||||
void lpm_ff(const NetFF*);
|
||||
void lpm_modulo(const NetModulo*);
|
||||
|
|
@ -162,6 +163,8 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
|
||||
void add_root(ivl_design_s &des_, const NetScope *s);
|
||||
|
||||
ivl_lpm_t lpm_decode_ff_(const NetDecode*);
|
||||
|
||||
void sub_off_from_expr_(long);
|
||||
void mul_expr_by_const_(long);
|
||||
|
||||
|
|
@ -312,7 +315,10 @@ struct ivl_lpm_s {
|
|||
ivl_nexus_t*pins;
|
||||
ivl_nexus_t pin;
|
||||
} s;
|
||||
ivl_memory_t mem; // ram only
|
||||
union {
|
||||
ivl_memory_t mem; // ram only
|
||||
ivl_lpm_t decode; // FF only
|
||||
} a;
|
||||
ivl_expr_t aset_value;
|
||||
ivl_expr_t sset_value;
|
||||
} ff;
|
||||
|
|
@ -684,6 +690,9 @@ struct ivl_variable_s {
|
|||
|
||||
/*
|
||||
* $Log: t-dll.h,v $
|
||||
* Revision 1.115.2.1 2006/02/19 00:11:34 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.115 2004/10/04 01:10:56 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
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 2004/05/31 23:34:39 steve Exp $"
|
||||
#ident "$Id: target.cc,v 1.69.2.1 2006/02/19 00:11:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -101,6 +101,13 @@ void target_t::lpm_compare(const NetCompare*)
|
|||
"Unhandled NetCompare." << endl;
|
||||
}
|
||||
|
||||
bool target_t::lpm_decode(const NetDecode*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetDecode." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
void target_t::lpm_divide(const NetDivide*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
|
|
@ -420,6 +427,9 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
|
|||
|
||||
/*
|
||||
* $Log: target.cc,v $
|
||||
* Revision 1.69.2.1 2006/02/19 00:11:34 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.69 2004/05/31 23:34:39 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
|
|
|
|||
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 2004/05/31 23:34:39 steve Exp $"
|
||||
#ident "$Id: target.h,v 1.65.2.1 2006/02/19 00:11:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
|
@ -79,6 +79,7 @@ struct target_t {
|
|||
virtual void lpm_add_sub(const NetAddSub*);
|
||||
virtual void lpm_clshift(const NetCLShift*);
|
||||
virtual void lpm_compare(const NetCompare*);
|
||||
virtual bool lpm_decode(const NetDecode*);
|
||||
virtual void lpm_divide(const NetDivide*);
|
||||
virtual void lpm_modulo(const NetModulo*);
|
||||
virtual void lpm_ff(const NetFF*);
|
||||
|
|
@ -170,6 +171,9 @@ extern const struct target *target_table[];
|
|||
|
||||
/*
|
||||
* $Log: target.h,v $
|
||||
* Revision 1.65.2.1 2006/02/19 00:11:34 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.65 2004/05/31 23:34:39 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
|
|
|
|||
|
|
@ -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.4 2006/01/21 21:42:33 steve Exp $"
|
||||
#ident "$Id: stub.c,v 1.90.2.5 2006/02/19 00:11:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -278,6 +278,16 @@ static void show_lpm(ivl_lpm_t net)
|
|||
break;
|
||||
}
|
||||
|
||||
case IVL_LPM_DECODE: {
|
||||
fprintf(out, " LPM_DECODE %s\n", ivl_lpm_basename(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,
|
||||
nex? ivl_nexus_name(nex) : "");
|
||||
}
|
||||
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),
|
||||
|
|
@ -330,6 +340,12 @@ static void show_lpm(ivl_lpm_t net)
|
|||
fprintf(out, " LPM_FF %s: <width=%u>\n",
|
||||
ivl_lpm_basename(net), width);
|
||||
|
||||
if (ivl_lpm_decode(net)) {
|
||||
ivl_lpm_t dec = ivl_lpm_decode(net);
|
||||
fprintf(out, " decoder: %s\n",
|
||||
ivl_lpm_basename(dec));
|
||||
}
|
||||
|
||||
if (ivl_lpm_enable(net))
|
||||
fprintf(out, " clk: %s CE: %s\n",
|
||||
ivl_nexus_name(ivl_lpm_clk(net)),
|
||||
|
|
@ -1007,6 +1023,9 @@ int target_design(ivl_design_t des)
|
|||
|
||||
/*
|
||||
* $Log: stub.c,v $
|
||||
* Revision 1.90.2.5 2006/02/19 00:11:34 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.90.2.4 2006/01/21 21:42:33 steve
|
||||
* When mux has wide select but sparse choices, use 1hot translation.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.1 2006/01/18 06:15:45 steve Exp $"
|
||||
#ident "$Id: vvp_scope.c,v 1.103.2.2 2006/02/19 00:11:35 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
|
|
@ -383,6 +383,11 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
|||
lpm = ivl_nexus_ptr_lpm(nptr);
|
||||
if (lpm) switch (ivl_lpm_type(lpm)) {
|
||||
|
||||
case IVL_LPM_DECODE:
|
||||
/* The decoder has no outputs.
|
||||
(It is bound to other devices.) */
|
||||
break;
|
||||
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_MUX:
|
||||
for (idx = 0 ; idx < ivl_lpm_width(lpm) ; idx += 1)
|
||||
|
|
@ -1224,6 +1229,28 @@ static void draw_lpm_cmp(ivl_lpm_t net)
|
|||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
static void draw_lpm_decode(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
fprintf(vvp_out, "L_%s.%s .decode/adr ",
|
||||
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
|
||||
vvp_mangle_id(ivl_lpm_basename(net)));
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_selects(net) ; idx += 1) {
|
||||
ivl_nexus_t a = ivl_lpm_select(net, idx);
|
||||
if (idx > 0)
|
||||
fprintf(vvp_out, ", ");
|
||||
if (a) {
|
||||
draw_input_from_net(a);
|
||||
} else {
|
||||
fprintf(vvp_out, "C<0>");
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
|
@ -1349,6 +1376,28 @@ static void draw_lpm_ff(ivl_lpm_t net)
|
|||
fprintf(vvp_out, ", C<1>;\n");
|
||||
}
|
||||
|
||||
/* If there is a decoder for this FF, then create a
|
||||
decoder enable node. */
|
||||
if (ivl_lpm_decode(net)) {
|
||||
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_scope_name(ivl_lpm_scope(dec))),
|
||||
vvp_mangle_id(ivl_lpm_basename(dec)), idx);
|
||||
|
||||
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) {
|
||||
fprintf(vvp_out, ", ");
|
||||
draw_input_from_net(tmp);
|
||||
}
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "L_%s.%s/%u .udp ",
|
||||
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
|
||||
vvp_mangle_id(ivl_lpm_basename(net)), idx);
|
||||
|
|
@ -1363,17 +1412,28 @@ static void draw_lpm_ff(ivl_lpm_t net)
|
|||
/* Draw the enable input. */
|
||||
tmp = ivl_lpm_enable(net);
|
||||
fprintf(vvp_out, ", ");
|
||||
if (tmp && (ivl_lpm_sync_clr(net) || ivl_lpm_sync_set(net))) {
|
||||
if (ivl_lpm_decode(net)) {
|
||||
/* If there is a decoder, get the enable from a
|
||||
decoder node. */
|
||||
fprintf(vvp_out, "L_%s.%s/dec/%u",
|
||||
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
|
||||
vvp_mangle_id(ivl_lpm_basename(net)), idx);
|
||||
} else if (tmp && (ivl_lpm_sync_clr(net) || ivl_lpm_sync_set(net))) {
|
||||
/* If there is no decoder but an otherwise complex
|
||||
enable, get the enable from the calculated
|
||||
logic. */
|
||||
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) {
|
||||
/* Draw a simple enable if that's what we got. */
|
||||
draw_input_from_net(tmp);
|
||||
} else {
|
||||
/* Otherwise, permanently enable the DFF. */
|
||||
fprintf(vvp_out, "C<1>");
|
||||
}
|
||||
|
||||
/* Drat the data input. MUX it with the sync input
|
||||
/* Draw the data input. MUX it with the sync input
|
||||
if there is one. */
|
||||
if (ivl_lpm_sync_clr(net) || ivl_lpm_sync_set(net)) {
|
||||
fprintf(vvp_out, ", L_%s.%s/din/%u",
|
||||
|
|
@ -1558,6 +1618,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
|
|||
draw_lpm_ufunc(net);
|
||||
return;
|
||||
|
||||
case IVL_LPM_DECODE:
|
||||
draw_lpm_decode(net);
|
||||
return;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "XXXX LPM not supported: %s.%s\n",
|
||||
ivl_scope_name(ivl_lpm_scope(net)), ivl_lpm_basename(net));
|
||||
|
|
@ -1681,6 +1745,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
|
|||
|
||||
/*
|
||||
* $Log: vvp_scope.c,v $
|
||||
* Revision 1.103.2.2 2006/02/19 00:11:35 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.103.2.1 2006/01/18 06:15:45 steve
|
||||
* Support DFF with synchronous inputs.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.61.2.1 2005/02/23 18:40:24 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.61.2.2 2006/02/19 00:11:35 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -85,7 +85,7 @@ vpip_to_dec.o vpip_format.o vvp_vpi.o
|
|||
O = main.o parse.o parse_misc.o lexor.o arith.o bufif.o compile.o \
|
||||
functor.o fvectors.o npmos.o resolv.o stop.o symbols.o ufunc.o codes.o \
|
||||
vthread.o schedule.o statistics.o tables.o udp.o memory.o force.o event.o \
|
||||
logic.o delay.o words.o $V
|
||||
logic.o delay.o words.o decoder.o $V
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
# Under Windows (mingw) I need to make the ivl.exe in two steps.
|
||||
|
|
|
|||
|
|
@ -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 2004/10/04 01:10:59 steve Exp $"
|
||||
#ident "$Id: compile.h,v 1.56.2.1 2006/02/19 00:11:35 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
|
|
@ -115,6 +115,10 @@ extern void compile_cmp_ge(char*label, long width, bool signed_flag,
|
|||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_cmp_gt(char*label, long width, bool signed_flag,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
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);
|
||||
extern void compile_shiftl(char*label, long width,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_shiftr(char*label, long width,
|
||||
|
|
@ -268,6 +272,9 @@ extern void compile_net(char*label, char*name,
|
|||
|
||||
/*
|
||||
* $Log: compile.h,v $
|
||||
* Revision 1.56.2.1 2006/02/19 00:11:35 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.56 2004/10/04 01:10:59 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* Copyright (c) 2006 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: decoder.cc,v 1.1.2.1 2006/02/19 00:11:36 steve Exp $"
|
||||
|
||||
# include "compile.h"
|
||||
# include "functor.h"
|
||||
# include "symbols.h"
|
||||
# include <stdlib.h>
|
||||
# include <malloc.h>
|
||||
# include <limits.h>
|
||||
# include <assert.h>
|
||||
|
||||
struct vvp_decode_adr_s;
|
||||
struct vvp_decode_en_s;
|
||||
|
||||
static symbol_table_t decoder_table = 0;
|
||||
|
||||
static struct vvp_decode_adr_s* decoder_find(char *label)
|
||||
{
|
||||
if (decoder_table == 0)
|
||||
return 0;
|
||||
|
||||
symbol_value_t v = sym_get_value(decoder_table, label);
|
||||
return (vvp_decode_adr_s*)v.ptr;
|
||||
}
|
||||
|
||||
static void decoder_save(char*label, struct vvp_decode_adr_s*obj)
|
||||
{
|
||||
if (! decoder_table)
|
||||
decoder_table = new_symbol_table();
|
||||
|
||||
assert(! decoder_find(label));
|
||||
|
||||
symbol_value_t v;
|
||||
v.ptr = obj;
|
||||
sym_set_value(decoder_table, label, v);
|
||||
}
|
||||
|
||||
/*
|
||||
* This structure represents a decoder address object. We receive the
|
||||
* value changes of address bits, and accumulate the current address value.
|
||||
*/
|
||||
struct vvp_decode_adr_s : public functor_s {
|
||||
|
||||
vvp_decode_adr_s(vvp_ipoint_t i, unsigned w);
|
||||
|
||||
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
|
||||
|
||||
// functor index for this node, for finding all the input
|
||||
// functors related to me.
|
||||
vvp_ipoint_t ix;
|
||||
const unsigned width;
|
||||
// Keep a list of decode_en objects that reference me.
|
||||
struct vvp_decode_en_s* enable_list;
|
||||
};
|
||||
|
||||
struct vvp_decode_en_s : public functor_s {
|
||||
|
||||
vvp_decode_en_s(vvp_decode_adr_s*dec, unsigned s);
|
||||
|
||||
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
|
||||
|
||||
void propagate_decoder_address(unsigned adr);
|
||||
|
||||
struct vvp_decode_adr_s*decoder;
|
||||
struct vvp_decode_en_s* enable_next;
|
||||
|
||||
const unsigned self;
|
||||
// This is the enable calculated from the decoder
|
||||
bool decode_en;
|
||||
// This is the enable that arrives from the extra input.
|
||||
bool extra_en;
|
||||
};
|
||||
|
||||
vvp_decode_adr_s::vvp_decode_adr_s(vvp_ipoint_t me, unsigned w)
|
||||
: ix(me), width(w), enable_list(0)
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_decode_adr_s::set(vvp_ipoint_t i, bool push,
|
||||
unsigned val, unsigned str)
|
||||
{
|
||||
functor_t ifu = functor_index(i);
|
||||
ifu->put(i, val);
|
||||
unsigned cur_adr = 0;
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1) {
|
||||
int abval = functor_get_input(ix + idx);
|
||||
unsigned mask = 1 << idx;
|
||||
if (abval > 1)
|
||||
cur_adr |= UINT_MAX;
|
||||
else if (abval == 1)
|
||||
cur_adr |= mask;
|
||||
|
||||
}
|
||||
|
||||
for (vvp_decode_en_s*cur = enable_list ; cur ; cur = cur->enable_next)
|
||||
cur->propagate_decoder_address(cur_adr);
|
||||
}
|
||||
|
||||
vvp_decode_en_s::vvp_decode_en_s(vvp_decode_adr_s*dec, unsigned s)
|
||||
: self(s)
|
||||
{
|
||||
enable_next = 0;
|
||||
decode_en = false;
|
||||
extra_en = true;
|
||||
|
||||
decoder = dec;
|
||||
enable_next = decoder->enable_list;
|
||||
decoder->enable_list = this;
|
||||
}
|
||||
|
||||
void vvp_decode_en_s::set(vvp_ipoint_t i, bool push,
|
||||
unsigned val, unsigned str)
|
||||
{
|
||||
functor_t ifu = functor_index(i);
|
||||
ifu->put(i, val);
|
||||
|
||||
int abval = functor_get_input(i);
|
||||
if (abval == 1) {
|
||||
extra_en = true;
|
||||
} else {
|
||||
extra_en = false;
|
||||
}
|
||||
|
||||
if (extra_en && decode_en)
|
||||
put_oval(1, true);
|
||||
else
|
||||
put_oval(0, true);
|
||||
}
|
||||
|
||||
void vvp_decode_en_s::propagate_decoder_address(unsigned adr)
|
||||
{
|
||||
if (adr == self) {
|
||||
decode_en = true;
|
||||
} else {
|
||||
decode_en = false;
|
||||
}
|
||||
|
||||
if (extra_en && decode_en)
|
||||
put_oval(1, true);
|
||||
else
|
||||
put_oval(0, true);
|
||||
}
|
||||
|
||||
void compile_decode_adr(char*label, unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
unsigned nfun = (argc + 3)/4;
|
||||
vvp_ipoint_t ix = functor_allocate(nfun);
|
||||
|
||||
vvp_decode_adr_s*a = new struct vvp_decode_adr_s(ix, argc);
|
||||
|
||||
functor_define(ix, a);
|
||||
|
||||
if (nfun > 0) {
|
||||
extra_ports_functor_s *fu = new extra_ports_functor_s[nfun-1];
|
||||
for (unsigned idx = 1 ; idx < nfun ; idx += 1) {
|
||||
fu[idx-1].base_ = ix;
|
||||
functor_define(ipoint_index(ix, idx), fu+idx-1);
|
||||
}
|
||||
}
|
||||
|
||||
inputs_connect(ix, argc, argv);
|
||||
free(argv);
|
||||
|
||||
decoder_save(label, a);
|
||||
free(label);
|
||||
}
|
||||
|
||||
void compile_decode_en(char*label, char*decoder, int slice,
|
||||
struct symb_s enable)
|
||||
{
|
||||
vvp_decode_adr_s*adr = decoder_find(decoder);
|
||||
vvp_decode_en_s*a = new struct vvp_decode_en_s(adr, slice);
|
||||
|
||||
vvp_ipoint_t ix = functor_allocate(1);
|
||||
functor_define(ix, a);
|
||||
|
||||
if (enable.text) {
|
||||
inputs_connect(ix, 1, &enable);
|
||||
}
|
||||
|
||||
define_functor_symbol(label, ix);
|
||||
free(label);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: decoder.cc,v $
|
||||
* Revision 1.1.2.1 2006/02/19 00:11:36 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -19,11 +19,12 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: functor.h,v 1.52 2004/10/04 01:10:59 steve Exp $"
|
||||
#ident "$Id: functor.h,v 1.52.2.1 2006/02/19 00:11:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "pointers.h"
|
||||
# include "delay.h"
|
||||
# include <assert.h>
|
||||
|
||||
/*
|
||||
* The vvp_ipoint_t is an integral type that is 32bits. The low 2 bits
|
||||
|
|
@ -340,9 +341,27 @@ extern vvp_ipoint_t *vvp_fvector_member(vvp_fvector_t v, unsigned i);
|
|||
extern vvp_fvector_t vvp_fvector_new(unsigned size);
|
||||
extern vvp_fvector_t vvp_fvector_continuous_new(unsigned size, vvp_ipoint_t p);
|
||||
|
||||
inline static
|
||||
unsigned char functor_get_inputs(vvp_ipoint_t ip)
|
||||
{
|
||||
functor_t fp = functor_index(ip);
|
||||
assert(fp);
|
||||
return fp->ival;
|
||||
}
|
||||
|
||||
inline static
|
||||
unsigned char functor_get_input(vvp_ipoint_t ip)
|
||||
{
|
||||
unsigned char bits = functor_get_inputs(ip);
|
||||
return (bits >> (2*ipoint_port(ip))) & 3;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: functor.h,v $
|
||||
* Revision 1.52.2.1 2006/02/19 00:11:36 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.52 2004/10/04 01:10:59 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: lexor.lex,v 1.43 2004/06/30 02:15:57 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.43.2.1 2006/02/19 00:11:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "parse_misc.h"
|
||||
|
|
@ -95,6 +95,8 @@
|
|||
".cmp/ge.s" { return K_CMP_GE_S; }
|
||||
".cmp/gt" { return K_CMP_GT; }
|
||||
".cmp/gt.s" { return K_CMP_GT_S; }
|
||||
".decode/adr" { return K_DECODE_ADR; }
|
||||
".decode/en" { return K_DECODE_EN; }
|
||||
".event" { return K_EVENT; }
|
||||
".event/or" { return K_EVENT_OR; }
|
||||
".functor" { return K_FUNCTOR; }
|
||||
|
|
@ -182,6 +184,9 @@ int yywrap()
|
|||
|
||||
/*
|
||||
* $Log: lexor.lex,v $
|
||||
* Revision 1.43.2.1 2006/02/19 00:11:36 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.43 2004/06/30 02:15:57 steve
|
||||
* Add signed LPM divide.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: memory.cc,v 1.22 2004/10/04 01:10:59 steve Exp $"
|
||||
#ident "$Id: memory.cc,v 1.22.2.1 2006/02/19 00:11:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include "memory.h"
|
||||
|
|
@ -292,21 +292,6 @@ unsigned char get_bit(vvp_memory_bits_t bits, int bit)
|
|||
return (get_nibble(bits, bit) >> (2*(bit&3))) & 3;
|
||||
}
|
||||
|
||||
inline static
|
||||
unsigned char functor_get_inputs(vvp_ipoint_t ip)
|
||||
{
|
||||
functor_t fp = functor_index(ip);
|
||||
assert(fp);
|
||||
return fp->ival;
|
||||
}
|
||||
|
||||
inline static
|
||||
unsigned char functor_get_input(vvp_ipoint_t ip)
|
||||
{
|
||||
unsigned char bits = functor_get_inputs(ip);
|
||||
return (bits >> (2*ipoint_port(ip))) & 3;
|
||||
}
|
||||
|
||||
static
|
||||
bool update_addr_bit(vvp_memory_port_t addr, vvp_ipoint_t ip)
|
||||
{
|
||||
|
|
@ -509,6 +494,9 @@ void schedule_memory(vvp_memory_t mem, unsigned idx,
|
|||
|
||||
/*
|
||||
* $Log: memory.cc,v $
|
||||
* Revision 1.22.2.1 2006/02/19 00:11:36 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.22 2004/10/04 01:10:59 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
16
vvp/parse.y
16
vvp/parse.y
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: parse.y,v 1.60 2004/10/04 01:10:59 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.60.2.1 2006/02/19 00:11:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "parse_misc.h"
|
||||
|
|
@ -60,6 +60,7 @@ extern FILE*yyin;
|
|||
%token K_ARITH_DIV K_ARITH_DIV_S K_ARITH_MOD K_ARITH_MULT
|
||||
%token K_ARITH_SUB K_ARITH_SUM
|
||||
%token K_CMP_EQ K_CMP_NE K_CMP_GE K_CMP_GE_S K_CMP_GT K_CMP_GT_S
|
||||
%token K_DECODE_ADR K_DECODE_EN
|
||||
%token K_EVENT K_EVENT_OR K_FUNCTOR K_NET K_NET_S K_PARAM
|
||||
%token K_RESOLV K_SCOPE K_SHIFTL K_SHIFTR K_THREAD K_TIMESCALE K_UFUNC
|
||||
%token K_UDP K_UDP_C K_UDP_S
|
||||
|
|
@ -262,6 +263,16 @@ statement
|
|||
compile_shiftr($1, $3, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
/* Decoder nodes. */
|
||||
|
||||
| T_LABEL K_DECODE_ADR symbols ';'
|
||||
{ struct symbv_s obj = $3;
|
||||
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);
|
||||
}
|
||||
|
||||
/* Event statements take a label, a type (the first T_SYMBOL) and a
|
||||
list of inputs. If the type is instead a string, then we have a
|
||||
|
|
@ -635,6 +646,9 @@ int compile_design(const char*path)
|
|||
|
||||
/*
|
||||
* $Log: parse.y,v $
|
||||
* Revision 1.60.2.1 2006/02/19 00:11:36 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.60 2004/10/04 01:10:59 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue