Handle synthesis of FF vectors with l-value decoder.

This commit is contained in:
steve 2006-02-19 00:11:31 +00:00
parent 3ea1214160
commit 7527c466ed
21 changed files with 697 additions and 175 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: design_dump.cc,v 1.149.2.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
View File

@ -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.
*

View File

@ -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

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_target.h,v 1.126 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.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.cc,v 1.226.2.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.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.h,v 1.321.2.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
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: synth2.cc,v 1.39.2.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.
*/

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-api.cc,v 1.108 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.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.cc,v 1.131.2.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
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.h,v 1.115 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.
*

View File

@ -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

View File

@ -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

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: stub.c,v 1.90.2.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.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_scope.c,v 1.103.2.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.
*

View File

@ -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.

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: compile.h,v 1.56 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.
*

208
vvp/decoder.cc Normal file
View File

@ -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.
*
*/

View File

@ -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.
*

View File

@ -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.
*

View File

@ -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.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: parse.y,v 1.60 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.
*