Update DFF support to new data flow.

This commit is contained in:
steve 2005-04-24 23:44:01 +00:00
parent f884652c19
commit 365cfedd55
17 changed files with 458 additions and 464 deletions

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: compiler.h,v 1.26 2004/10/04 01:10:52 steve Exp $" #ident "$Id: compiler.h,v 1.27 2005/04/24 23:44:01 steve Exp $"
#endif #endif
# include <list> # include <list>
@ -84,6 +84,7 @@ extern bool verbose_flag;
extern bool debug_scopes; extern bool debug_scopes;
extern bool debug_eval_tree; extern bool debug_eval_tree;
extern bool debug_elaborate; extern bool debug_elaborate;
extern bool debug_synth2;
/* Path to a directory useful for finding subcomponents. */ /* Path to a directory useful for finding subcomponents. */
extern const char*basedir; extern const char*basedir;
@ -136,6 +137,9 @@ extern int load_sys_func_table(const char*path);
/* /*
* $Log: compiler.h,v $ * $Log: compiler.h,v $
* Revision 1.27 2005/04/24 23:44:01 steve
* Update DFF support to new data flow.
*
* Revision 1.26 2004/10/04 01:10:52 steve * Revision 1.26 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: cprop.cc,v 1.51 2005/02/12 22:52:45 steve Exp $" #ident "$Id: cprop.cc,v 1.52 2005/04/24 23:44:01 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -201,54 +201,15 @@ void cprop_functor::lpm_ff(Design*des, NetFF*obj)
// Look for and count unlinked FF outputs. Note that if the // Look for and count unlinked FF outputs. Note that if the
// Data and Q pins are connected together, they can be removed // Data and Q pins are connected together, they can be removed
// from the circuit, since it doesn't do anything. // from the circuit, since it doesn't do anything.
unsigned unlinked_count = 0;
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) { if (connected(obj->pin_Data(), obj->pin_Q())
if (connected(obj->pin_Data(idx), obj->pin_Q(idx))
&& (! obj->pin_Sclr().is_linked()) && (! obj->pin_Sclr().is_linked())
&& (! obj->pin_Sset().is_linked()) && (! obj->pin_Sset().is_linked())
&& (! obj->pin_Aclr().is_linked()) && (! obj->pin_Aclr().is_linked())
&& (! obj->pin_Aset().is_linked())) { && (! obj->pin_Aset().is_linked())) {
obj->pin_Data(idx).unlink(); obj->pin_Data().unlink();
obj->pin_Q(idx).unlink(); obj->pin_Q().unlink();
}
if (! obj->pin_Q(idx).is_linked())
unlinked_count += 1;
}
// If the entire FF is unlinked, remove the whole thing.
if (unlinked_count == obj->width()) {
delete obj; delete obj;
count += 1;
return;
}
// If some of the FFs are unconnected, make a new FF array
// that does not include the useless FF devices.
if (unlinked_count > 0) {
NetFF*tmp = new NetFF(obj->scope(), obj->name(),
obj->width()-unlinked_count);
connect(tmp->pin_Clock(), obj->pin_Clock());
connect(tmp->pin_Enable(), obj->pin_Enable());
connect(tmp->pin_Aload(), obj->pin_Aload());
connect(tmp->pin_Aset(), obj->pin_Aset());
connect(tmp->pin_Aclr(), obj->pin_Aclr());
connect(tmp->pin_Sload(), obj->pin_Sload());
connect(tmp->pin_Sset(), obj->pin_Sset());
connect(tmp->pin_Sclr(), obj->pin_Sclr());
unsigned tidx = 0;
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1)
if (obj->pin_Q(idx).is_linked()) {
connect(tmp->pin_Data(tidx), obj->pin_Data(idx));
connect(tmp->pin_Q(tidx), obj->pin_Q(idx));
tidx += 1;
}
assert(tidx == obj->width() - unlinked_count);
delete obj;
des->add_node(tmp);
count += 1;
return;
} }
} }
@ -980,6 +941,9 @@ void cprop(Design*des)
/* /*
* $Log: cprop.cc,v $ * $Log: cprop.cc,v $
* Revision 1.52 2005/04/24 23:44:01 steve
* Update DFF support to new data flow.
*
* Revision 1.51 2005/02/12 22:52:45 steve * Revision 1.51 2005/02/12 22:52:45 steve
* Fix copyright notice. * Fix copyright notice.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: elaborate.cc,v 1.320 2005/03/05 05:38:33 steve Exp $" #ident "$Id: elaborate.cc,v 1.321 2005/04/24 23:44:01 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -1372,7 +1372,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
} else { } else {
unsigned wid = count_lval_width(lv); unsigned wid = count_lval_width(lv);
rv->set_width(wid); bool flag = rv->set_width(wid);
rv = pad_to_width(rv, wid); rv = pad_to_width(rv, wid);
assert(rv->expr_width() >= wid); assert(rv->expr_width() >= wid);
} }
@ -2942,6 +2942,9 @@ Design* elaborate(list<perm_string>roots)
/* /*
* $Log: elaborate.cc,v $ * $Log: elaborate.cc,v $
* Revision 1.321 2005/04/24 23:44:01 steve
* Update DFF support to new data flow.
*
* Revision 1.320 2005/03/05 05:38:33 steve * Revision 1.320 2005/03/05 05:38:33 steve
* Get rval width right for arguments into task calls. * Get rval width right for arguments into task calls.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: expr_synth.cc,v 1.65 2005/03/12 06:43:35 steve Exp $" #ident "$Id: expr_synth.cc,v 1.66 2005/04/24 23:44:02 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -788,14 +788,15 @@ NetNet* NetETernary::synthesize(Design *des)
osig->local_flag(true); osig->local_flag(true);
/* Make sure both value operands are the right width. */ /* Make sure both value operands are the right width. */
tsig = pad_to_width(des, tsig, width); tsig = crop_to_width(des, pad_to_width(des, tsig, width), width);
fsig = pad_to_width(des, fsig, width); fsig = crop_to_width(des, pad_to_width(des, fsig, width), width);
assert(width <= tsig->vector_width()); assert(width == tsig->vector_width());
assert(width <= fsig->vector_width()); assert(width == fsig->vector_width());
perm_string oname = csig->scope()->local_symbol(); perm_string oname = csig->scope()->local_symbol();
NetMux *mux = new NetMux(csig->scope(), oname, width, 2, width); NetMux *mux = new NetMux(csig->scope(), oname, width,
2, csig->vector_width());
connect(tsig->pin(0), mux->pin_Data(1)); connect(tsig->pin(0), mux->pin_Data(1));
connect(fsig->pin(0), mux->pin_Data(0)); connect(fsig->pin(0), mux->pin_Data(0));
connect(osig->pin(0), mux->pin_Result()); connect(osig->pin(0), mux->pin_Result());
@ -842,6 +843,9 @@ NetNet* NetESignal::synthesize(Design*des)
/* /*
* $Log: expr_synth.cc,v $ * $Log: expr_synth.cc,v $
* Revision 1.66 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.65 2005/03/12 06:43:35 steve * Revision 1.65 2005/03/12 06:43:35 steve
* Update support for LPM_MOD. * Update support for LPM_MOD.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_target.h,v 1.151 2005/04/13 06:35:11 steve Exp $" #ident "$Id: ivl_target.h,v 1.152 2005/04/24 23:44:02 steve Exp $"
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
@ -891,6 +891,11 @@ extern const char* ivl_udp_name(ivl_udp_t net);
* are. All the data inputs have the same width, the width of the * are. All the data inputs have the same width, the width of the
* ivl_lpm_q output. * ivl_lpm_q output.
* *
* - D-FlipFlop (IVL_LPM_FF)
* This data is an edge sensitive register. The ivl_lpm_q output and
* single ivl_lpm_data input are the same with, ivl_lpm_width. This
* device carries a vector like other LPM devices.
*
* - Memory port (IVL_LPM_RAM) * - Memory port (IVL_LPM_RAM)
* These are structural ports into a memory device. They represent * These are structural ports into a memory device. They represent
* address/data ports of a memory device that the context can hook to * address/data ports of a memory device that the context can hook to
@ -1642,6 +1647,9 @@ _END_DECL
/* /*
* $Log: ivl_target.h,v $ * $Log: ivl_target.h,v $
* Revision 1.152 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.151 2005/04/13 06:35:11 steve * Revision 1.151 2005/04/13 06:35:11 steve
* Make logic aware of strength. * Make logic aware of strength.
* *

View File

@ -19,7 +19,7 @@ const char COPYRIGHT[] =
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: main.cc,v 1.88 2005/01/22 01:06:55 steve Exp $" #ident "$Id: main.cc,v 1.89 2005/04/24 23:44:02 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -112,6 +112,7 @@ bool error_implicit = false;
bool debug_scopes = false; bool debug_scopes = false;
bool debug_eval_tree = false; bool debug_eval_tree = false;
bool debug_elaborate = false; bool debug_elaborate = false;
bool debug_synth2 = false;
/* /*
* Verbose messages enabled. * Verbose messages enabled.
*/ */
@ -318,6 +319,9 @@ static void read_iconfig_file(const char*ipath)
} else if (strcmp(cp,"elaborate") == 0) { } else if (strcmp(cp,"elaborate") == 0) {
debug_elaborate = true; debug_elaborate = true;
cerr << "debug: Enable elaborate debug" << endl; cerr << "debug: Enable elaborate debug" << endl;
} else if (strcmp(cp,"synth2") == 0) {
debug_synth2 = true;
cerr << "debug: Enable synth2 debug" << endl;
} else { } else {
} }
@ -754,6 +758,9 @@ int main(int argc, char*argv[])
/* /*
* $Log: main.cc,v $ * $Log: main.cc,v $
* Revision 1.89 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.88 2005/01/22 01:06:55 steve * Revision 1.88 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node. * Change case compare from logic to an LPM node.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: net_link.cc,v 1.15 2005/01/09 20:16:01 steve Exp $" #ident "$Id: net_link.cc,v 1.16 2005/04/24 23:44:02 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -313,6 +313,30 @@ void* Nexus::t_cookie(void*val)const
return tmp; return tmp;
} }
unsigned Nexus::vector_width() const
{
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
const NetNet*sig = dynamic_cast<const NetNet*>(cur->get_obj());
if (sig == 0)
continue;
return sig->vector_width();
}
return 0;
}
NetNet* Nexus::pick_any_net()
{
for (Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
NetNet*sig = dynamic_cast<const NetNet*>(cur->get_obj());
if (sig != 0)
return sig;
}
return 0;
}
const char* Nexus::name() const const char* Nexus::name() const
{ {
if (name_) if (name_)
@ -499,6 +523,9 @@ bool NexusSet::intersect(const NexusSet&that) const
/* /*
* $Log: net_link.cc,v $ * $Log: net_link.cc,v $
* Revision 1.16 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.15 2005/01/09 20:16:01 steve * Revision 1.15 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports. * Use PartSelect/PV and VP to handle part selects through ports.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.cc,v 1.241 2005/04/08 04:51:16 steve Exp $" #ident "$Id: netlist.cc,v 1.242 2005/04/24 23:44:02 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -226,6 +226,15 @@ NetNode::~NetNode()
design_->del_node(this); design_->del_node(this);
} }
NetBus::NetBus(NetScope*s, unsigned pin_count)
: NetObj(s, perm_string::literal(""), pin_count)
{
}
NetBus::~NetBus()
{
}
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins) NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
: NetObj(s, n, 1), sig_next_(0), sig_prev_(0), : NetObj(s, n, 1), sig_next_(0), sig_prev_(0),
type_(t), port_type_(NOT_A_PORT), signed_(false), msb_(npins-1), lsb_(0), type_(t), port_type_(NOT_A_PORT), signed_(false), msb_(npins-1), lsb_(0),
@ -588,43 +597,34 @@ unsigned NetReplicate::repeat() const
* like so: * like so:
* 0 -- Clock * 0 -- Clock
* 1 -- Enable * 1 -- Enable
* 2 -- Aload * 2 -- Aset
* 3 -- Aset * 3 -- Aclr
* 4 -- Aclr * 4 -- Sset
* 5 -- Sload * 5 -- Sclr
* 6 -- Sset * 6 -- Data
* 7 -- Sclr * 7 -- Q
*
* 8 -- Data[0]
* 9 -- Q[0]
* ... * ...
*/ */
NetFF::NetFF(NetScope*s, perm_string n, unsigned wid) NetFF::NetFF(NetScope*s, perm_string n, unsigned width)
: NetNode(s, n, 8 + 2*wid) : NetNode(s, n, 8), width_(width)
{ {
pin_Clock().set_dir(Link::INPUT); pin_Clock().set_dir(Link::INPUT);
pin_Clock().set_name(perm_string::literal("Clock"), 0); pin_Clock().set_name(perm_string::literal("Clock"), 0);
pin_Enable().set_dir(Link::INPUT); pin_Enable().set_dir(Link::INPUT);
pin_Enable().set_name(perm_string::literal("Enable"), 0); pin_Enable().set_name(perm_string::literal("Enable"), 0);
pin_Aload().set_dir(Link::INPUT);
pin_Aload().set_name(perm_string::literal("Aload"), 0);
pin_Aset().set_dir(Link::INPUT); pin_Aset().set_dir(Link::INPUT);
pin_Aset().set_name(perm_string::literal("Aset"), 0); pin_Aset().set_name(perm_string::literal("Aset"), 0);
pin_Aclr().set_dir(Link::INPUT); pin_Aclr().set_dir(Link::INPUT);
pin_Aclr().set_name(perm_string::literal("Aclr"), 0); pin_Aclr().set_name(perm_string::literal("Aclr"), 0);
pin_Sload().set_dir(Link::INPUT);
pin_Sload().set_name(perm_string::literal("Sload"), 0);
pin_Sset().set_dir(Link::INPUT); pin_Sset().set_dir(Link::INPUT);
pin_Sset().set_name(perm_string::literal("Sset"), 0); pin_Sset().set_name(perm_string::literal("Sset"), 0);
pin_Sclr().set_dir(Link::INPUT); pin_Sclr().set_dir(Link::INPUT);
pin_Sclr().set_name(perm_string::literal("Sclr"), 0); pin_Sclr().set_name(perm_string::literal("Sclr"), 0);
for (unsigned idx = 0 ; idx < wid ; idx += 1) { pin_Data().set_dir(Link::INPUT);
pin_Data(idx).set_dir(Link::INPUT); pin_Data().set_name(perm_string::literal("Data"), 0);
pin_Data(idx).set_name(perm_string::literal("Data"), idx); pin_Q().set_dir(Link::OUTPUT);
pin_Q(idx).set_dir(Link::OUTPUT); pin_Q().set_name(perm_string::literal("Q"), 0);
pin_Q(idx).set_name(perm_string::literal("Q"), idx);
}
} }
NetFF::~NetFF() NetFF::~NetFF()
@ -633,7 +633,7 @@ NetFF::~NetFF()
unsigned NetFF::width() const unsigned NetFF::width() const
{ {
return (pin_count() - 8) / 2; return width_;
} }
Link& NetFF::pin_Clock() Link& NetFF::pin_Clock()
@ -656,82 +656,64 @@ const Link& NetFF::pin_Enable() const
return pin(1); return pin(1);
} }
Link& NetFF::pin_Aload() Link& NetFF::pin_Aset()
{ {
return pin(2); return pin(2);
} }
Link& NetFF::pin_Aset()
{
return pin(3);
}
const Link& NetFF::pin_Aset() const const Link& NetFF::pin_Aset() const
{ {
return pin(3); return pin(2);
} }
Link& NetFF::pin_Aclr() Link& NetFF::pin_Aclr()
{ {
return pin(4); return pin(3);
} }
const Link& NetFF::pin_Aclr() const const Link& NetFF::pin_Aclr() const
{ {
return pin(4); return pin(3);
}
Link& NetFF::pin_Sload()
{
return pin(5);
} }
Link& NetFF::pin_Sset() Link& NetFF::pin_Sset()
{ {
return pin(6); return pin(4);
} }
const Link& NetFF::pin_Sset() const const Link& NetFF::pin_Sset() const
{ {
return pin(6); return pin(4);
} }
Link& NetFF::pin_Sclr() Link& NetFF::pin_Sclr()
{ {
return pin(7); return pin(5);
} }
const Link& NetFF::pin_Sclr() const const Link& NetFF::pin_Sclr() const
{
return pin(5);
}
Link& NetFF::pin_Data()
{
return pin(6);
}
const Link& NetFF::pin_Data() const
{
return pin(6);
}
Link& NetFF::pin_Q()
{ {
return pin(7); return pin(7);
} }
Link& NetFF::pin_Data(unsigned w) const Link& NetFF::pin_Q() const
{ {
unsigned pn = 8 + 2*w; return pin(7);
assert(pn < pin_count());
return pin(pn);
}
const Link& NetFF::pin_Data(unsigned w) const
{
unsigned pn = 8 + 2*w;
assert(pn < pin_count());
return pin(pn);
}
Link& NetFF::pin_Q(unsigned w)
{
unsigned pn = 9 + w*2;
assert(pn < pin_count());
return pin(pn);
}
const Link& NetFF::pin_Q(unsigned w) const
{
unsigned pn = 9 + w*2;
assert(pn < pin_count());
return pin(pn);
} }
void NetFF::aset_value(const verinum&val) void NetFF::aset_value(const verinum&val)
@ -2174,6 +2156,9 @@ const NetProc*NetTaskDef::proc() const
/* /*
* $Log: netlist.cc,v $ * $Log: netlist.cc,v $
* Revision 1.242 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.241 2005/04/08 04:51:16 steve * Revision 1.241 2005/04/08 04:51:16 steve
* All memory addresses are signed. * All memory addresses are signed.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.h,v 1.340 2005/04/08 04:51:16 steve Exp $" #ident "$Id: netlist.h,v 1.341 2005/04/24 23:44:02 steve Exp $"
#endif #endif
/* /*
@ -48,6 +48,7 @@ class ostream;
class Design; class Design;
class Link; class Link;
class Nexus; class Nexus;
class NetNet;
class NetNode; class NetNode;
class NetProc; class NetProc;
class NetProcTop; class NetProcTop;
@ -253,6 +254,12 @@ class Nexus {
Link*first_nlink(); Link*first_nlink();
const Link* first_nlink()const; const Link* first_nlink()const;
/* Get the width of the Nexus, or 0 if there are no vectors
(in the form of NetNet objects) linked. */
unsigned vector_width() const;
NetNet* pick_any_net();
/* This method returns true if all the possible drivers of /* This method returns true if all the possible drivers of
this nexus are constant. It will also return true if there this nexus are constant. It will also return true if there
are no drivers at all. */ are no drivers at all. */
@ -316,6 +323,22 @@ class NexusSet {
NexusSet& operator= (const NexusSet&); NexusSet& operator= (const NexusSet&);
}; };
/*
* A NetBus is a transparent device that is merely a bunch of pins
* used to tie some pins to. It is a convenient way to collect a
* bundle of pins and pass that bundle around.
*/
class NetBus : public NetObj {
public:
NetBus(NetScope*scope, unsigned pin_count);
~NetBus();
private: // not implemented
NetBus(const NetBus&);
NetBus& operator= (const NetBus&);
};
/* /*
* A NetNode is a device of some sort, where each pin has a different * A NetNode is a device of some sort, where each pin has a different
* meaning. (i.e., pin(0) is the output to an and gate.) NetNode * meaning. (i.e., pin(0) is the output to an and gate.) NetNode
@ -699,22 +722,19 @@ class NetModulo : public NetNode {
class NetFF : public NetNode { class NetFF : public NetNode {
public: public:
NetFF(NetScope*s, perm_string n, unsigned width); NetFF(NetScope*s, perm_string n, unsigned vector_width);
~NetFF(); ~NetFF();
unsigned width() const; unsigned width() const;
Link& pin_Clock(); Link& pin_Clock();
Link& pin_Enable(); Link& pin_Enable();
Link& pin_Aload();
Link& pin_Aset(); Link& pin_Aset();
Link& pin_Aclr(); Link& pin_Aclr();
Link& pin_Sload();
Link& pin_Sset(); Link& pin_Sset();
Link& pin_Sclr(); Link& pin_Sclr();
Link& pin_Data();
Link& pin_Data(unsigned); Link& pin_Q();
Link& pin_Q(unsigned);
const Link& pin_Clock() const; const Link& pin_Clock() const;
const Link& pin_Enable() const; const Link& pin_Enable() const;
@ -722,8 +742,8 @@ class NetFF : public NetNode {
const Link& pin_Aclr() const; const Link& pin_Aclr() const;
const Link& pin_Sset() const; const Link& pin_Sset() const;
const Link& pin_Sclr() const; const Link& pin_Sclr() const;
const Link& pin_Data(unsigned) const; const Link& pin_Data() const;
const Link& pin_Q(unsigned) const; const Link& pin_Q() const;
void aset_value(const verinum&val); void aset_value(const verinum&val);
const verinum& aset_value() const; const verinum& aset_value() const;
@ -736,6 +756,7 @@ class NetFF : public NetNode {
virtual void functor_node(Design*des, functor_t*fun); virtual void functor_node(Design*des, functor_t*fun);
private: private:
unsigned width_;
verinum aset_value_; verinum aset_value_;
verinum sset_value_; verinum sset_value_;
}; };
@ -1479,10 +1500,10 @@ class NetProc : public virtual LineInfo {
// synthesize as asynchronous logic, and return true. // synthesize as asynchronous logic, and return true.
virtual bool synth_async(Design*des, NetScope*scope, virtual bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out); const NetBus&nex_map, NetBus&nex_out);
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff, virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out, const NetBus&nex_map, NetBus&nex_out,
const svector<NetEvProbe*>&events); const svector<NetEvProbe*>&events);
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
@ -1614,7 +1635,7 @@ class NetAssignBase : public NetProc {
unsigned lwidth() const; unsigned lwidth() const;
bool synth_async(Design*des, NetScope*scope, bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out); const NetBus&nex_map, NetBus&nex_out);
// This dumps all the lval structures. // This dumps all the lval structures.
void dump_lval(ostream&) const; void dump_lval(ostream&) const;
@ -1681,10 +1702,10 @@ class NetBlock : public NetProc {
// synthesize as asynchronous logic, and return true. // synthesize as asynchronous logic, and return true.
bool synth_async(Design*des, NetScope*scope, bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out); const NetBus&nex_map, NetBus&nex_out);
bool synth_sync(Design*des, NetScope*scope, NetFF*ff, bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out, const NetBus&nex_map, NetBus&nex_out,
const svector<NetEvProbe*>&events); const svector<NetEvProbe*>&events);
// This version of emit_recurse scans all the statements of // This version of emit_recurse scans all the statements of
@ -1736,7 +1757,7 @@ class NetCase : public NetProc {
virtual void nex_output(NexusSet&out); virtual void nex_output(NexusSet&out);
bool synth_async(Design*des, NetScope*scope, bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out); const NetBus&nex_map, NetBus&nex_out);
virtual bool emit_proc(struct target_t*) const; virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
@ -1804,10 +1825,10 @@ class NetCondit : public NetProc {
bool is_asynchronous(); bool is_asynchronous();
bool synth_async(Design*des, NetScope*scope, bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out); const NetBus&nex_map, NetBus&nex_out);
bool synth_sync(Design*des, NetScope*scope, NetFF*ff, bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out, const NetBus&nex_map, NetBus&nex_out,
const svector<NetEvProbe*>&events); const svector<NetEvProbe*>&events);
virtual bool emit_proc(struct target_t*) const; virtual bool emit_proc(struct target_t*) const;
@ -2024,10 +2045,10 @@ class NetEvWait : public NetProc {
virtual void nex_output(NexusSet&out); virtual void nex_output(NexusSet&out);
virtual bool synth_async(Design*des, NetScope*scope, virtual bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out); const NetBus&nex_map, NetBus&nex_out);
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff, virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out, const NetBus&nex_map, NetBus&nex_out,
const svector<NetEvProbe*>&events); const svector<NetEvProbe*>&events);
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
@ -3416,6 +3437,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/* /*
* $Log: netlist.h,v $ * $Log: netlist.h,v $
* Revision 1.341 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.340 2005/04/08 04:51:16 steve * Revision 1.340 2005/04/08 04:51:16 steve
* All memory addresses are signed. * All memory addresses are signed.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: netmisc.h,v 1.20 2005/01/24 05:28:31 steve Exp $" #ident "$Id: netmisc.h,v 1.21 2005/04/24 23:44:02 steve Exp $"
#endif #endif
# include "netlist.h" # include "netlist.h"
@ -50,6 +50,13 @@ extern NetScope* symbol_search(Design*des, NetScope*start, hname_t path,
extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid); extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid);
extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w); extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w);
/*
* This function transforms an expression by cropping the high bits
* off with a part select. The result has the width w passed in. This
* function does not pad, use pad_to_width if padding is desired.
*/
extern NetNet*crop_to_width(Design*des, NetNet*n, unsigned w);
/* /*
* This function takes as input a NetNet signal and adds a constant * This function takes as input a NetNet signal and adds a constant
* value to it. If the val is 0, then simply return sig. Otherwise, * value to it. If the val is 0, then simply return sig. Otherwise,
@ -92,6 +99,9 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe);
/* /*
* $Log: netmisc.h,v $ * $Log: netmisc.h,v $
* Revision 1.21 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.20 2005/01/24 05:28:31 steve * Revision 1.20 2005/01/24 05:28:31 steve
* Remove the NetEBitSel and combine all bit/part select * Remove the NetEBitSel and combine all bit/part select
* behavior into the NetESelect node and IVL_EX_SELECT * behavior into the NetESelect node and IVL_EX_SELECT

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: pad_to_width.cc,v 1.16 2005/01/12 03:17:37 steve Exp $" #ident "$Id: pad_to_width.cc,v 1.17 2005/04/24 23:44:02 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -110,8 +110,31 @@ NetNet*pad_to_width(Design*des, NetNet*net, unsigned wid)
return tmp; return tmp;
} }
NetNet*crop_to_width(Design*des, NetNet*net, unsigned wid)
{
NetScope*scope = net->scope();
if (net->vector_width() <= wid)
return net;
NetPartSelect*ps = new NetPartSelect(net, 0, wid, NetPartSelect::VP);
des->add_node(ps);
ps->set_line(*net);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, wid);
tmp->local_flag(true);
tmp->set_line(*tmp);
connect(ps->pin(0), tmp->pin(0));
return tmp;
}
/* /*
* $Log: pad_to_width.cc,v $ * $Log: pad_to_width.cc,v $
* Revision 1.17 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.16 2005/01/12 03:17:37 steve * Revision 1.16 2005/01/12 03:17:37 steve
* Properly pad vector widths in pgassign. * Properly pad vector widths in pgassign.
* *

View File

@ -1,7 +1,7 @@
%{ %{
/* /*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com) * Copyright (c) 2000-2005 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: syn-rules.y,v 1.32 2005/04/06 05:29:08 steve Exp $" #ident "$Id: syn-rules.y,v 1.33 2005/04/24 23:44:02 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -118,11 +118,8 @@ static void hookup_DFF_CE(NetFF*ff, NetESignal*d, NetEvProbe*pclk,
// where lval is really a "reg [7:0]". In other words, part // where lval is really a "reg [7:0]". In other words, part
// selects in the l-value are handled by loff and the lwidth(). // selects in the l-value are handled by loff and the lwidth().
int loff = a->get_loff(); connect(ff->pin_Data(), d->bit(0));
for (unsigned idx = 0 ; idx < ff->width() ; idx += 1) { connect(ff->pin_Q(), a->sig()->pin(0));
connect(ff->pin_Data(idx), d->bit(idx+rval_pinoffset));
connect(ff->pin_Q(idx), a->sig()->pin(idx+loff));
}
connect(ff->pin_Clock(), pclk->pin(0)); connect(ff->pin_Clock(), pclk->pin(0));
if (ce) connect(ff->pin_Enable(), ce->pin(0)); if (ce) connect(ff->pin_Enable(), ce->pin(0));
@ -207,7 +204,7 @@ static void make_DFF_CE(Design*des, NetProcTop*top, NetEvWait*wclk,
if (a->sig()) { if (a->sig()) {
// cerr << "new NetFF named " << a->name() << endl; // cerr << "new NetFF named " << a->name() << endl;
NetFF*ff = new NetFF(top->scope(), a->name(), NetFF*ff = new NetFF(top->scope(), a->name(),
a->lwidth()); a->sig()->vector_width());
hookup_DFF_CE(ff, d, pclk, ce, a, rval_pinoffset); hookup_DFF_CE(ff, d, pclk, ce, a, rval_pinoffset);
des->add_node(ff); des->add_node(ff);
} else if (a->mem()) { } else if (a->mem()) {

307
synth2.cc
View File

@ -17,42 +17,28 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: synth2.cc,v 1.41 2005/02/12 06:25:40 steve Exp $" #ident "$Id: synth2.cc,v 1.42 2005/04/24 23:44:02 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
# include "functor.h" # include "functor.h"
# include "netlist.h" # include "netlist.h"
# include "netmisc.h"
# include "compiler.h" # include "compiler.h"
# include <assert.h> # include <assert.h>
static int debug_synth2=0;
#ifdef __FUNCTION__
#define DEBUG_SYNTH2_ENTRY(class) if (debug_synth2) { cerr << "Enter " << class << "::" \
<< __FUNCTION__ << endl; dump(cerr, 4); }
#define DEBUG_SYNTH2_EXIT(class,val) if (debug_synth2) { cerr << "Exit " << class << "::" \
<< __FUNCTION__ << ", result " << val << endl; }
#else
#define DEBUG_SYNTH2_ENTRY(class)
#define DEBUG_SYNTH2_EXIT(class,val)
#endif
bool NetProc::synth_async(Design*des, NetScope*scope, bool NetProc::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out) const NetBus&nex_map, NetBus&nex_out)
{ {
return false; return false;
} }
bool NetProc::synth_sync(Design*des, NetScope*scope, NetFF*ff, bool NetProc::synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out, const NetBus&nex_map, NetBus&nex_out,
const svector<NetEvProbe*>&events) const svector<NetEvProbe*>&events)
{ {
DEBUG_SYNTH2_ENTRY("NetProc")
if (events.count() > 0) { if (events.count() > 0) {
cerr << get_line() << ": error: Events are unaccounted" cerr << get_line() << ": error: Events are unaccounted"
<< " for in process synthesis." << endl; << " for in process synthesis." << endl;
@ -63,11 +49,11 @@ bool NetProc::synth_sync(Design*des, NetScope*scope, NetFF*ff,
return synth_async(des, scope, nex_map, nex_out); return synth_async(des, scope, nex_map, nex_out);
} }
static unsigned find_nexus_in_set(const NetNet*nset, const Nexus*nex) static unsigned find_nexus_in_set(const NetBus&nset, const Nexus*nex)
{ {
unsigned idx = 0; unsigned idx = 0;
for (idx = 0 ; idx < nset->pin_count() ; idx += 1) for (idx = 0 ; idx < nset.pin_count() ; idx += 1)
if (nset->pin(idx).nexus() == nex) if (nset.pin(idx).nexus() == nex)
return idx; return idx;
return idx; return idx;
@ -84,36 +70,36 @@ static unsigned find_nexus_in_set(const NetNet*nset, const Nexus*nex)
* r-value. * r-value.
*/ */
bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool NetAssignBase::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out) const NetBus&nex_map, NetBus&nex_out)
{ {
DEBUG_SYNTH2_ENTRY("NetAssignBase")
NetNet*rsig = rval_->synthesize(des); NetNet*rsig = rval_->synthesize(des);
assert(rsig); assert(rsig);
NetNet*lsig = lval_->sig(); NetNet*lsig = lval_->sig();
if (!lsig) { if (!lsig) {
cerr << get_line() << ": error: NetAssignBase::synth_async on unsupported lval "; cerr << get_line() << ": error: "
<< "NetAssignBase::synth_async on unsupported lval ";
dump_lval(cerr); dump_lval(cerr);
cerr << endl; cerr << endl;
DEBUG_SYNTH2_EXIT("NetAssignBase",false)
return false; return false;
} }
assert(lval_->more == 0); assert(lval_->more == 0);
if (lval_->lwidth() != nex_map->pin_count()) { #if 0
cerr << get_line() << ": error: NetAssignBase::synth_async pin count mismatch, " /* The l-value and r-value map must have the same width. */
<< lval_->lwidth() << " != " << nex_map->pin_count() << endl; if (lval_->lwidth() != nex_map->vector_width()) {
DEBUG_SYNTH2_EXIT("NetAssignBase",false) cerr << get_line() << ": error: Assignment synthesis: "
<< "vector width mismatch, "
<< lval_->lwidth() << " bits != "
<< nex_map->vector_width() << " bits." << endl;
return false; return false;
} }
assert(nex_map->pin_count() <= rsig->pin_count()); #else
/* For now, assume there is exactly one output. */
assert(nex_out.pin_count() == 1);
#endif
for (unsigned idx = 0 ; idx < lval_->lwidth() ; idx += 1) { connect(nex_out.pin(0), rsig->pin(0));
unsigned off = lval_->get_loff()+idx;
unsigned ptr = find_nexus_in_set(nex_map, lsig->pin(off).nexus());
connect(nex_out->pin(ptr), rsig->pin(idx));
}
/* This lval_ represents a reg that is a WIRE in the /* This lval_ represents a reg that is a WIRE in the
synthesized results. This function signals the destructor synthesized results. This function signals the destructor
@ -122,7 +108,6 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
synthesis can continue to work with it as a WIRE. */ synthesis can continue to work with it as a WIRE. */
lval_->turn_sig_to_wire_on_release(); lval_->turn_sig_to_wire_on_release();
DEBUG_SYNTH2_EXIT("NetAssignBase",true)
return true; return true;
} }
@ -133,14 +118,13 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
* substatements. * substatements.
*/ */
bool NetBlock::synth_async(Design*des, NetScope*scope, bool NetBlock::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out) const NetBus&nex_map, NetBus&nex_out)
{ {
DEBUG_SYNTH2_ENTRY("NetBlock")
if (last_ == 0) { if (last_ == 0) {
DEBUG_SYNTH2_EXIT("NetBlock",true)
return true; return true;
} }
#if 0
const perm_string tmp1 = perm_string::literal("tmp1"); const perm_string tmp1 = perm_string::literal("tmp1");
const perm_string tmp2 = perm_string::literal("tmp2"); const perm_string tmp2 = perm_string::literal("tmp2");
@ -182,12 +166,16 @@ bool NetBlock::synth_async(Design*des, NetScope*scope,
DEBUG_SYNTH2_EXIT("NetBlock",flag) DEBUG_SYNTH2_EXIT("NetBlock",flag)
return flag; return flag;
#else
cerr << get_line() << ": sorry: "
"forgot how to implement NetBlock::synth_async" << endl;
return false;
#endif
} }
bool NetCase::synth_async(Design*des, NetScope*scope, bool NetCase::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out) const NetBus&nex_map, NetBus&nex_out)
{ {
DEBUG_SYNTH2_ENTRY("NetCase")
#if 0 #if 0
unsigned cur; unsigned cur;
@ -321,9 +309,9 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
} }
bool NetCondit::synth_async(Design*des, NetScope*scope, bool NetCondit::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out) const NetBus&nex_map, NetBus&nex_out)
{ {
DEBUG_SYNTH2_ENTRY("NetCondit") #if 0
NetNet*ssig = expr_->synthesize(des); NetNet*ssig = expr_->synthesize(des);
assert(ssig); assert(ssig);
@ -377,23 +365,40 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
DEBUG_SYNTH2_EXIT("NetCondit",true) DEBUG_SYNTH2_EXIT("NetCondit",true)
return true; return true;
#else
cerr << get_line() << ": sorry: "
<< "Forgot to implement NetCondit::synth_async" << endl;
return false;
#endif
} }
bool NetEvWait::synth_async(Design*des, NetScope*scope, bool NetEvWait::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out) const NetBus&nex_map, NetBus&nex_out)
{ {
DEBUG_SYNTH2_ENTRY("NetEvWait")
bool flag = statement_->synth_async(des, scope, nex_map, nex_out); bool flag = statement_->synth_async(des, scope, nex_map, nex_out);
DEBUG_SYNTH2_EXIT("NetEvWait",flag)
return flag; return flag;
} }
/*
* This method is called when the process is shown to be
* asynchronous. Figure out the nexus set of outputs from this
* process, and pass that to the synth_async method for the statement
* of the process. The statement will connect its output to the
* nex_out set, using the nex_map as a guide. Starting from the top,
* the nex_map is the same as the nex_map.
*/
bool NetProcTop::synth_async(Design*des) bool NetProcTop::synth_async(Design*des)
{ {
DEBUG_SYNTH2_ENTRY("NetProcTop")
NexusSet nex_set; NexusSet nex_set;
statement_->nex_output(nex_set); statement_->nex_output(nex_set);
if (debug_synth2) {
cerr << get_line() << ": debug: Process has "
<< nex_set.count() << " outputs." << endl;
}
#if 0
const perm_string tmp1 = perm_string::literal("tmp"); const perm_string tmp1 = perm_string::literal("tmp");
NetNet*nex_out = new NetNet(scope(), tmp1, NetNet::WIRE, NetNet*nex_out = new NetNet(scope(), tmp1, NetNet::WIRE,
nex_set.count()); nex_set.count());
@ -403,8 +408,12 @@ bool NetProcTop::synth_async(Design*des)
bool flag = statement_->synth_async(des, scope(), nex_out, nex_out); bool flag = statement_->synth_async(des, scope(), nex_out, nex_out);
delete nex_out; delete nex_out;
DEBUG_SYNTH2_EXIT("NetProcTop",flag)
return flag; return flag;
#else
cerr << get_line() << ": sorry: "
<< "forgot to implement NetProcTop::synth_async" << endl;
return false;
#endif
} }
/* /*
@ -422,15 +431,14 @@ bool NetProcTop::synth_async(Design*des)
* the statements may each infer different reset and enable signals. * the statements may each infer different reset and enable signals.
*/ */
bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff, bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out, const NetBus&nex_map, NetBus&nex_out,
const svector<NetEvProbe*>&events_in) const svector<NetEvProbe*>&events_in)
{ {
DEBUG_SYNTH2_ENTRY("NetBlock")
if (last_ == 0) { if (last_ == 0) {
DEBUG_SYNTH2_EXIT("NetBlock",true)
return true; return true;
} }
#if 0
bool flag = true; bool flag = true;
const perm_string tmp1 = perm_string::literal("tmp1"); const perm_string tmp1 = perm_string::literal("tmp1");
@ -572,8 +580,14 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
taken up by the smaller NetFF devices. */ taken up by the smaller NetFF devices. */
delete ff; delete ff;
DEBUG_SYNTH2_EXIT("NetBlock",flag)
return flag; return flag;
#else
cerr << get_line() << ": sorry: "
<< "Forgot to implement NetBlock::synth_sync"
<< endl;
return false;
#endif
} }
/* /*
@ -583,10 +597,10 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
* expression is connected to an event, or not. * expression is connected to an event, or not.
*/ */
bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff, bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out, const NetBus&nex_map, NetBus&nex_out,
const svector<NetEvProbe*>&events_in) const svector<NetEvProbe*>&events_in)
{ {
DEBUG_SYNTH2_ENTRY("NetCondit") #if 0
/* First try to turn the condition expression into an /* First try to turn the condition expression into an
asynchronous set/reset. If the condition expression has asynchronous set/reset. If the condition expression has
inputs that are included in the sensitivity list, then it inputs that are included in the sensitivity list, then it
@ -788,15 +802,19 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
bool flag = if_->synth_sync(des, scope, ff, nex_map, nex_out, events_in); bool flag = if_->synth_sync(des, scope, ff, nex_map, nex_out, events_in);
DEBUG_SYNTH2_EXIT("NetCondit",flag)
return flag; return flag;
#else
cerr << get_line() << ": sorry: "
<< "Forgot to implement NetCondit::synth_sync" << endl;
return false;
#endif
} }
bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff, bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out, const NetBus&nex_map, NetBus&nex_out,
const svector<NetEvProbe*>&events_in) const svector<NetEvProbe*>&events_in)
{ {
DEBUG_SYNTH2_ENTRY("NetEvWait")
if (events_in.count() > 0) { if (events_in.count() > 0) {
cerr << get_line() << ": error: Events are unaccounted" cerr << get_line() << ": error: Events are unaccounted"
<< " for in process synthesis." << endl; << " for in process synthesis." << endl;
@ -814,7 +832,7 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
svector<NetEvProbe*>events (ev->nprobe() - 1); svector<NetEvProbe*>events (ev->nprobe() - 1);
/* Get the input set from the substatement. This will be used /* Get the input set from the substatement. This will be used
to figure out which of the probes in the clock. */ to figure out which of the probes is the clock. */
NexusSet*statement_input = statement_ -> nex_input(); NexusSet*statement_input = statement_ -> nex_input();
/* Search for a clock input. The clock input is the edge event /* Search for a clock input. The clock input is the edge event
@ -848,62 +866,109 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
<< " are valid clock inputs." << endl; << " are valid clock inputs." << endl;
cerr << get_line() << ": : Perhaps the clock" cerr << get_line() << ": : Perhaps the clock"
<< " is read by a statement or expression?" << endl; << " is read by a statement or expression?" << endl;
DEBUG_SYNTH2_EXIT("NetEvWait",false)
return false; return false;
} }
connect(ff->pin_Clock(), pclk->pin(0)); connect(ff->pin_Clock(), pclk->pin(0));
if (pclk->edge() == NetEvProbe::NEGEDGE) if (pclk->edge() == NetEvProbe::NEGEDGE) {
ff->attribute(perm_string::literal("Clock:LPM_Polarity"), verinum("INVERT")); perm_string polarity = perm_string::literal("Clock:LPM_Polarity");
ff->attribute(polarity, verinum("INVERT"));
if (debug_synth2) {
cerr << get_line() << ": debug: "
<< "Detected a NEGEDGE clock for the synthesized ff."
<< endl;
}
}
/* Synthesize the input to the DFF. */ /* Synthesize the input to the DFF. */
bool flag = statement_->synth_sync(des, scope, ff, bool flag = statement_->synth_sync(des, scope, ff,
nex_map, nex_out, events); nex_map, nex_out, events);
DEBUG_SYNTH2_EXIT("NetEvWait",flag)
return flag; return flag;
} }
/*
* This method is called for a process that is determined to be
* synchronous. Create a NetFF device to hold the output from the
* statement, and synthesize that statement in place.
*/
bool NetProcTop::synth_sync(Design*des) bool NetProcTop::synth_sync(Design*des)
{ {
DEBUG_SYNTH2_ENTRY("NetProcTop") if (debug_synth2) {
cerr << get_line() << ": debug: "
<< "Process is apparently synchronous. Making NetFFs."
<< endl;
}
NexusSet nex_set; NexusSet nex_set;
statement_->nex_output(nex_set); statement_->nex_output(nex_set);
/* Make a model FF that will connect to the first item in the
set, and will also take the initial connection of clocks
and resets. */
NetFF*ff = new NetFF(scope(), scope()->local_symbol(), NetFF*ff = new NetFF(scope(), scope()->local_symbol(),
nex_set.count()); nex_set[0]->vector_width());
des->add_node(ff); des->add_node(ff);
ff->attribute(perm_string::literal("LPM_FFType"), verinum("DFF")); ff->attribute(perm_string::literal("LPM_FFType"), verinum("DFF"));
/* The D inputs to the DFF device will receive the output from NetBus nex_d (scope(), nex_set.count());
the statements of the process. */ NetBus nex_q (scope(), nex_set.count());
NetNet*nex_d = new NetNet(scope(), scope()->local_symbol(),
NetNet::WIRE, nex_set.count()); /* The Q of the NetFF devices is connected to the output that
nex_d->local_flag(true); we are. The nex_q is a bundle of the outputs. We will also
pass the nex_q as a map to the statement's synth_sync
method to map it to the correct nex_d pin. */
for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) { for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) {
connect(nex_d->pin(idx), ff->pin_Data(idx)); connect(nex_set[idx], nex_q.pin(idx));
} }
/* The Q outputs of the DFF will connect to the actual outputs // Connect the input later.
of the process. Thus, the DFF will be between the outputs
of the process and the outputs of the substatement. */
const perm_string tmpq = perm_string::literal("tmpq");
NetNet*nex_q = new NetNet(scope(), tmpq, NetNet::WIRE,
nex_set.count());
for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) {
connect(nex_set[idx], nex_q->pin(idx));
connect(nex_q->pin(idx), ff->pin_Q(idx));
}
/* Synthesize the input to the DFF. */ /* Synthesize the input to the DFF. */
bool flag = statement_->synth_sync(des, scope(), ff, bool flag = statement_->synth_sync(des, scope(), ff,
nex_q, nex_d, nex_q, nex_d,
svector<NetEvProbe*>()); svector<NetEvProbe*>());
if (! flag) {
delete ff;
return false;
}
delete nex_q;
DEBUG_SYNTH2_EXIT("NetProcTop",flag) NetNet*tmp = nex_d.pin(0).nexus()->pick_any_net();
return flag; assert(tmp);
tmp = crop_to_width(des, tmp, ff->width());
connect(tmp->pin(0), ff->pin_Data());
connect(nex_q.pin(0), ff->pin_Q());
for (unsigned idx = 1 ; idx < nex_set.count() ; idx += 1) {
NetFF*ff2 = new NetFF(scope(), scope()->local_symbol(),
nex_set[idx]->vector_width());
des->add_node(ff2);
tmp = nex_d.pin(idx).nexus()->pick_any_net();
assert(tmp);
tmp = crop_to_width(des, tmp, ff2->width());
connect(nex_q.pin(idx), ff2->pin_Q());
connect(tmp->pin(0), ff2->pin_Data());
connect(ff->pin_Clock(), ff2->pin_Clock());
if (ff->pin_Enable().is_linked())
connect(ff->pin_Enable(), ff2->pin_Enable());
if (ff->pin_Aset().is_linked())
connect(ff->pin_Aset(), ff2->pin_Aset());
if (ff->pin_Aclr().is_linked())
connect(ff->pin_Aclr(), ff2->pin_Aclr());
if (ff->pin_Sset().is_linked())
connect(ff->pin_Sset(), ff2->pin_Sset());
if (ff->pin_Sclr().is_linked())
connect(ff->pin_Sclr(), ff2->pin_Sclr());
}
return true;
} }
class synth2_f : public functor_t { class synth2_f : public functor_t {
@ -978,84 +1043,14 @@ void synth2_f::process(class Design*des, class NetProcTop*top)
void synth2(Design*des) void synth2(Design*des)
{ {
debug_synth2 = atoi(des->get_flag("ivl-synth2-debug"));
synth2_f synth_obj; synth2_f synth_obj;
des->functor(&synth_obj); des->functor(&synth_obj);
} }
/* /*
* $Log: synth2.cc,v $ * $Log: synth2.cc,v $
* Revision 1.41 2005/02/12 06:25:40 steve * Revision 1.42 2005/04/24 23:44:02 steve
* Restructure NetMux devices to pass vectors. * Update DFF support to new data flow.
* Generate NetMux devices from ternary expressions,
* Reduce NetMux devices to bufif when appropriate.
* *
* Revision 1.40 2004/12/11 02:31:27 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* 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 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-api.cc,v 1.124 2005/04/13 06:35:11 steve Exp $" #ident "$Id: t-dll-api.cc,v 1.125 2005/04/24 23:44:02 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -819,11 +819,8 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
return net->u_.ff.d.pin; return net->u_.ff.d.pin;
case IVL_LPM_FF: case IVL_LPM_FF:
assert(idx < net->u_.ff.width); assert(idx == 0);
if (net->u_.ff.width == 1)
return net->u_.ff.d.pin; return net->u_.ff.d.pin;
else
return net->u_.ff.d.pins[idx];
case IVL_LPM_CONCAT: case IVL_LPM_CONCAT:
assert(idx < net->u_.concat.inputs); assert(idx < net->u_.concat.inputs);
@ -969,11 +966,8 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
return net->u_.ff.q.pin; return net->u_.ff.q.pin;
case IVL_LPM_FF: case IVL_LPM_FF:
assert(idx < net->u_.ff.width); assert(idx == 0);
if (net->u_.ff.width == 1)
return net->u_.ff.q.pin; return net->u_.ff.q.pin;
else
return net->u_.ff.q.pins[idx];
case IVL_LPM_MUX: case IVL_LPM_MUX:
assert(idx == 0); assert(idx == 0);
@ -2038,6 +2032,9 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
/* /*
* $Log: t-dll-api.cc,v $ * $Log: t-dll-api.cc,v $
* Revision 1.125 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.124 2005/04/13 06:35:11 steve * Revision 1.124 2005/04/13 06:35:11 steve
* Make logic aware of strength. * Make logic aware of strength.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.cc,v 1.147 2005/04/06 05:29:08 steve Exp $" #ident "$Id: t-dll.cc,v 1.148 2005/04/24 23:44:02 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -1500,36 +1500,17 @@ void dll_target::lpm_ff(const NetFF*net)
obj->u_.ff.sset_value = 0; obj->u_.ff.sset_value = 0;
} }
if (obj->u_.ff.width == 1) { nex = net->pin_Q().nexus();
nex = net->pin_Q(0).nexus();
assert(nex->t_cookie()); assert(nex->t_cookie());
obj->u_.ff.q.pin = (ivl_nexus_t) nex->t_cookie(); obj->u_.ff.q.pin = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.ff.q.pin, obj, 0, nexus_lpm_add(obj->u_.ff.q.pin, obj, 0,
IVL_DR_STRONG, IVL_DR_STRONG); IVL_DR_STRONG, IVL_DR_STRONG);
nex = net->pin_Data(0).nexus(); nex = net->pin_Data().nexus();
assert(nex->t_cookie()); assert(nex->t_cookie());
obj->u_.ff.d.pin = (ivl_nexus_t) nex->t_cookie(); obj->u_.ff.d.pin = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.ff.d.pin, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ); nexus_lpm_add(obj->u_.ff.d.pin, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
} else {
obj->u_.ff.q.pins = new ivl_nexus_t [obj->u_.ff.width * 2];
obj->u_.ff.d.pins = obj->u_.ff.q.pins + obj->u_.ff.width;
for (unsigned idx = 0 ; idx < obj->u_.ff.width ; idx += 1) {
nex = net->pin_Q(idx).nexus();
assert(nex->t_cookie());
obj->u_.ff.q.pins[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.ff.q.pins[idx], obj, 0,
IVL_DR_STRONG, IVL_DR_STRONG);
nex = net->pin_Data(idx).nexus();
assert(nex->t_cookie());
obj->u_.ff.d.pins[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.ff.d.pins[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ);
}
}
} }
void dll_target::lpm_ram_dq(const NetRamDq*net) void dll_target::lpm_ram_dq(const NetRamDq*net)
@ -2090,6 +2071,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/* /*
* $Log: t-dll.cc,v $ * $Log: t-dll.cc,v $
* Revision 1.148 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.147 2005/04/06 05:29:08 steve * Revision 1.147 2005/04/06 05:29:08 steve
* Rework NetRamDq and IVL_LPM_RAM nodes. * Rework NetRamDq and IVL_LPM_RAM nodes.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: stub.c,v 1.122 2005/04/13 06:35:11 steve Exp $" #ident "$Id: stub.c,v 1.123 2005/04/24 23:44:02 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -410,6 +410,50 @@ static void show_lpm_concat(ivl_lpm_t net)
} }
} }
static void show_lpm_ff(ivl_lpm_t net)
{
ivl_nexus_t nex;
unsigned width = ivl_lpm_width(net);
fprintf(out, " LPM_FF %s: <width=%u>\n",
ivl_lpm_basename(net), width);
nex = ivl_lpm_clk(net);
fprintf(out, " clk: %s\n", ivl_nexus_name(nex));
if (width_of_nexus(nex) != 1) {
fprintf(out, " clk: ERROR: Nexus width is %u\n",
width_of_nexus(nex));
stub_errors += 1;
}
if (ivl_lpm_enable(net)) {
nex = ivl_lpm_enable(net);
fprintf(out, " CE: %s\n", ivl_nexus_name(nex));
if (width_of_nexus(nex) != 1) {
fprintf(out, " CE: ERROR: Nexus width is %u\n",
width_of_nexus(nex));
stub_errors += 1;
}
}
nex = ivl_lpm_data(net,0);
fprintf(out, " D: %s\n", ivl_nexus_name(nex));
if (width_of_nexus(nex) != width) {
fprintf(out, " D: ERROR: Nexus width is %u\n",
width_of_nexus(nex));
stub_errors += 1;
}
nex = ivl_lpm_q(net,0);
fprintf(out, " Q: %s\n", ivl_nexus_name(nex));
if (width_of_nexus(nex) != width) {
fprintf(out, " Q: ERROR: Nexus width is %u\n",
width_of_nexus(nex));
stub_errors += 1;
}
}
static void show_lpm_mod(ivl_lpm_t net) static void show_lpm_mod(ivl_lpm_t net)
{ {
unsigned width = ivl_lpm_width(net); unsigned width = ivl_lpm_width(net);
@ -478,7 +522,7 @@ static void show_lpm_mux(ivl_lpm_t net)
ivl_nexus_name(nex), ivl_nexus_name(nex),
ivl_lpm_selects(net)); ivl_lpm_selects(net));
if (ivl_lpm_selects(net) != width_of_nexus(nex)) { if (ivl_lpm_selects(net) != width_of_nexus(nex)) {
fprintf(out, " S: ERROR: Nexus width is %uj\n", fprintf(out, " S: ERROR: Nexus width is %u\n",
width_of_nexus(nex)); width_of_nexus(nex));
stub_errors += 1; stub_errors += 1;
} }
@ -708,8 +752,6 @@ static void show_lpm_ufunc(ivl_lpm_t net)
static void show_lpm(ivl_lpm_t net) static void show_lpm(ivl_lpm_t net)
{ {
unsigned idx;
unsigned width = ivl_lpm_width(net);
switch (ivl_lpm_type(net)) { switch (ivl_lpm_type(net)) {
@ -726,6 +768,10 @@ static void show_lpm(ivl_lpm_t net)
show_lpm_cmp_eeq(net); show_lpm_cmp_eeq(net);
break; break;
case IVL_LPM_FF:
show_lpm_ff(net);
break;
case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GE:
show_lpm_cmp_ge(net); show_lpm_cmp_ge(net);
break; break;
@ -762,41 +808,6 @@ static void show_lpm(ivl_lpm_t net)
show_lpm_sub(net); show_lpm_sub(net);
break; break;
case IVL_LPM_FF: {
fprintf(out, " LPM_FF %s: <width=%u>\n",
ivl_lpm_basename(net), width);
if (ivl_lpm_enable(net))
fprintf(out, " clk: %s CE: %s\n",
ivl_nexus_name(ivl_lpm_clk(net)),
ivl_nexus_name(ivl_lpm_enable(net)));
else
fprintf(out, " clk: %s\n",
ivl_nexus_name(ivl_lpm_clk(net)));
if (ivl_lpm_async_clr(net))
fprintf(out, " Aclr: %s\n",
ivl_nexus_name(ivl_lpm_async_clr(net)));
if (ivl_lpm_async_set(net)) {
fprintf(out, " Aset: %s\n",
ivl_nexus_name(ivl_lpm_async_set(net)));
if (ivl_lpm_aset_value(net))
show_expression(ivl_lpm_aset_value(net), 10);
}
for (idx = 0 ; idx < width ; idx += 1)
fprintf(out, " Data %u: %s\n", idx,
ivl_nexus_name(ivl_lpm_data(net, idx)));
for (idx = 0 ; idx < width ; idx += 1)
fprintf(out, " Q %u: %s\n", idx,
ivl_nexus_name(ivl_lpm_q(net, idx)));
break;
}
case IVL_LPM_MOD: case IVL_LPM_MOD:
show_lpm_mod(net); show_lpm_mod(net);
break; break;
@ -1342,6 +1353,9 @@ int target_design(ivl_design_t des)
/* /*
* $Log: stub.c,v $ * $Log: stub.c,v $
* Revision 1.123 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.122 2005/04/13 06:35:11 steve * Revision 1.122 2005/04/13 06:35:11 steve
* Make logic aware of strength. * Make logic aware of strength.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_scope.c,v 1.125 2005/04/06 05:29:09 steve Exp $" #ident "$Id: vvp_scope.c,v 1.126 2005/04/24 23:44:02 steve Exp $"
#endif #endif
# include "vvp_priv.h" # include "vvp_priv.h"
@ -431,7 +431,6 @@ static void draw_C8_to_string(char*result, size_t nresult,
static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
{ {
static char result[2048]; static char result[2048];
unsigned idx;
unsigned nptr_pin = ivl_nexus_ptr_pin(nptr); unsigned nptr_pin = ivl_nexus_ptr_pin(nptr);
ivl_net_const_t cptr; ivl_net_const_t cptr;
ivl_net_logic_t lptr; ivl_net_logic_t lptr;
@ -551,15 +550,6 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
if (lpm) switch (ivl_lpm_type(lpm)) { if (lpm) switch (ivl_lpm_type(lpm)) {
case IVL_LPM_FF: case IVL_LPM_FF:
for (idx = 0 ; idx < ivl_lpm_width(lpm) ; idx += 1)
if (ivl_lpm_q(lpm, idx) == nex) {
sprintf(result, "L_%s.%s/%u",
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(lpm))),
vvp_mangle_id(ivl_lpm_basename(lpm)), idx);
return result;
}
break;
case IVL_LPM_RAM: case IVL_LPM_RAM:
case IVL_LPM_ADD: case IVL_LPM_ADD:
case IVL_LPM_CONCAT: case IVL_LPM_CONCAT:
@ -1591,87 +1581,42 @@ static void draw_lpm_ff(ivl_lpm_t net)
ivl_expr_t aset_expr = 0; ivl_expr_t aset_expr = 0;
const char*aset_bits = 0; const char*aset_bits = 0;
unsigned width, idx; ivl_nexus_t nex;
unsigned width;
width = ivl_lpm_width(net); width = ivl_lpm_width(net);
/* Q C CE D RS --> Q+ */
fprintf(vvp_out, "L_%s.%s/def .udp/sequ \"DFF\", 5, 2,"
" \"?" "r" "1" "0" "00" "0\","
" \"?" "r" "1" "1" "00" "1\","
" \"?" "r" "1" "x" "00" "x\","
" \"0" "r" "x" "0" "00" "0\","
" \"1" "r" "x" "1" "00" "1\","
" \"?" "*" "0" "?" "00" "-\","
" \"?" "_" "?" "?" "00" "-\","
" \"?" "?" "?" "?" "01" "1\","
" \"?" "?" "?" "?" "1?" "0\","
" \"?" "?" "1" "?" "00" "-\","
" \"?" "?" "?" "?" "00" "-\""
";\n",
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)));
aset_expr = ivl_lpm_aset_value(net); aset_expr = ivl_lpm_aset_value(net);
if (aset_expr) { if (aset_expr) {
assert(ivl_expr_width(aset_expr) == width); assert(ivl_expr_width(aset_expr) == width);
aset_bits = ivl_expr_bits(aset_expr); aset_bits = ivl_expr_bits(aset_expr);
} }
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t tmp;
fprintf(vvp_out, "L_%s.%s/%u .udp ", fprintf(vvp_out, "L_%p .dff ", net);
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
vvp_mangle_id(ivl_lpm_basename(net)), idx);
fprintf(vvp_out, "L_%s.%s/def, ", nex = ivl_lpm_data(net,0);
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))), assert(nex);
vvp_mangle_id(ivl_lpm_basename(net))); draw_input_from_net(nex);
tmp = ivl_lpm_clk(net); nex = ivl_lpm_clk(net);
draw_input_from_net(tmp); assert(nex);
tmp = ivl_lpm_enable(net);
fprintf(vvp_out, ", "); fprintf(vvp_out, ", ");
if (tmp) draw_input_from_net(nex);
draw_input_from_net(tmp);
else
fprintf(vvp_out, "C<1>");
tmp = ivl_lpm_data(net, idx); nex = ivl_lpm_enable(net);
assert(tmp); if (nex) {
fprintf(vvp_out, ", "); fprintf(vvp_out, ", ");
draw_input_from_net(tmp); draw_input_from_net(nex);
/* Connect reset input. This may be the Aclr input, or
an Aset to zero. */
fprintf(vvp_out, ", ");
tmp = ivl_lpm_async_clr(net);
if (tmp) {
draw_input_from_net(tmp);
} else { } else {
tmp = ivl_lpm_async_set(net); fprintf(vvp_out, ", C4<1>");
if (aset_bits && (aset_bits[idx] == '0'))
draw_input_from_net(tmp);
else
fprintf(vvp_out, "C<0>");
} }
/* Connect set input */ /* Stub asynchronous input for now. */
fprintf(vvp_out, ", "); fprintf(vvp_out, ", C4<z>");
tmp = ivl_lpm_async_set(net);
if (aset_bits && (aset_bits[idx] != '1'))
tmp = 0;
if (tmp)
draw_input_from_net(tmp);
else
fprintf(vvp_out, "C<0>");
fprintf(vvp_out, ";\n"); fprintf(vvp_out, ";\n");
} }
}
static void draw_lpm_shiftl(ivl_lpm_t net) static void draw_lpm_shiftl(ivl_lpm_t net)
{ {
@ -1987,6 +1932,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/* /*
* $Log: vvp_scope.c,v $ * $Log: vvp_scope.c,v $
* Revision 1.126 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.125 2005/04/06 05:29:09 steve * Revision 1.125 2005/04/06 05:29:09 steve
* Rework NetRamDq and IVL_LPM_RAM nodes. * Rework NetRamDq and IVL_LPM_RAM nodes.
* *