diff --git a/compiler.h b/compiler.h index 8374d1949..3865b2e2e 100644 --- a/compiler.h +++ b/compiler.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #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 # include @@ -84,6 +84,7 @@ extern bool verbose_flag; extern bool debug_scopes; extern bool debug_eval_tree; extern bool debug_elaborate; +extern bool debug_synth2; /* Path to a directory useful for finding subcomponents. */ extern const char*basedir; @@ -136,6 +137,9 @@ extern int load_sys_func_table(const char*path); /* * $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 * Clean up spurious trailing white space. * diff --git a/cprop.cc b/cprop.cc index 63d4676ca..1a12cedd9 100644 --- a/cprop.cc +++ b/cprop.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #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 # 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 // Data and Q pins are connected together, they can be removed // 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(idx), obj->pin_Q(idx)) - && (! obj->pin_Sclr().is_linked()) - && (! obj->pin_Sset().is_linked()) - && (! obj->pin_Aclr().is_linked()) - && (! obj->pin_Aset().is_linked())) { - obj->pin_Data(idx).unlink(); - obj->pin_Q(idx).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()) { + if (connected(obj->pin_Data(), obj->pin_Q()) + && (! obj->pin_Sclr().is_linked()) + && (! obj->pin_Sset().is_linked()) + && (! obj->pin_Aclr().is_linked()) + && (! obj->pin_Aset().is_linked())) { + obj->pin_Data().unlink(); + obj->pin_Q().unlink(); 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 $ + * 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 * Fix copyright notice. * diff --git a/elaborate.cc b/elaborate.cc index d9b7b4a1b..5fed329b4 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #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 # include "config.h" @@ -1372,7 +1372,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const } else { unsigned wid = count_lval_width(lv); - rv->set_width(wid); + bool flag = rv->set_width(wid); rv = pad_to_width(rv, wid); assert(rv->expr_width() >= wid); } @@ -2942,6 +2942,9 @@ Design* elaborate(listroots) /* * $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 * Get rval width right for arguments into task calls. * diff --git a/expr_synth.cc b/expr_synth.cc index 204e06e3f..e7ce35ae5 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #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 # include "config.h" @@ -788,14 +788,15 @@ NetNet* NetETernary::synthesize(Design *des) osig->local_flag(true); /* Make sure both value operands are the right width. */ - tsig = pad_to_width(des, tsig, width); - fsig = pad_to_width(des, fsig, width); + tsig = crop_to_width(des, pad_to_width(des, tsig, width), width); + fsig = crop_to_width(des, pad_to_width(des, fsig, width), width); - assert(width <= tsig->vector_width()); - assert(width <= fsig->vector_width()); + assert(width == tsig->vector_width()); + assert(width == fsig->vector_width()); 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(fsig->pin(0), mux->pin_Data(0)); connect(osig->pin(0), mux->pin_Result()); @@ -842,6 +843,9 @@ NetNet* NetESignal::synthesize(Design*des) /* * $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 * Update support for LPM_MOD. * diff --git a/ivl_target.h b/ivl_target.h index 42808a373..7232bcc25 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: ivl_target.h,v 1.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 #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 * 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) * These are structural ports into a memory device. They represent * address/data ports of a memory device that the context can hook to @@ -1642,6 +1647,9 @@ _END_DECL /* * $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 * Make logic aware of strength. * diff --git a/main.cc b/main.cc index 73ae96d4e..111839724 100644 --- a/main.cc +++ b/main.cc @@ -19,7 +19,7 @@ const char COPYRIGHT[] = * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #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 # include "config.h" @@ -112,6 +112,7 @@ bool error_implicit = false; bool debug_scopes = false; bool debug_eval_tree = false; bool debug_elaborate = false; +bool debug_synth2 = false; /* * Verbose messages enabled. */ @@ -318,6 +319,9 @@ static void read_iconfig_file(const char*ipath) } else if (strcmp(cp,"elaborate") == 0) { debug_elaborate = true; cerr << "debug: Enable elaborate debug" << endl; + } else if (strcmp(cp,"synth2") == 0) { + debug_synth2 = true; + cerr << "debug: Enable synth2 debug" << endl; } else { } @@ -754,6 +758,9 @@ int main(int argc, char*argv[]) /* * $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 * Change case compare from logic to an LPM node. * diff --git a/net_link.cc b/net_link.cc index a4fc08681..23104d79b 100644 --- a/net_link.cc +++ b/net_link.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #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 # include "config.h" @@ -313,6 +313,30 @@ void* Nexus::t_cookie(void*val)const return tmp; } +unsigned Nexus::vector_width() const +{ + for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) { + const NetNet*sig = dynamic_cast(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(cur->get_obj()); + if (sig != 0) + return sig; + } + + return 0; +} + const char* Nexus::name() const { if (name_) @@ -499,6 +523,9 @@ bool NexusSet::intersect(const NexusSet&that) const /* * $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 * Use PartSelect/PV and VP to handle part selects through ports. * diff --git a/netlist.cc b/netlist.cc index ffe121152..a3bf1ac47 100644 --- a/netlist.cc +++ b/netlist.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: netlist.cc,v 1.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 # include "config.h" @@ -226,6 +226,15 @@ NetNode::~NetNode() 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) : NetObj(s, n, 1), sig_next_(0), sig_prev_(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: * 0 -- Clock * 1 -- Enable - * 2 -- Aload - * 3 -- Aset - * 4 -- Aclr - * 5 -- Sload - * 6 -- Sset - * 7 -- Sclr - * - * 8 -- Data[0] - * 9 -- Q[0] + * 2 -- Aset + * 3 -- Aclr + * 4 -- Sset + * 5 -- Sclr + * 6 -- Data + * 7 -- Q * ... */ -NetFF::NetFF(NetScope*s, perm_string n, unsigned wid) -: NetNode(s, n, 8 + 2*wid) +NetFF::NetFF(NetScope*s, perm_string n, unsigned width) +: NetNode(s, n, 8), width_(width) { pin_Clock().set_dir(Link::INPUT); pin_Clock().set_name(perm_string::literal("Clock"), 0); pin_Enable().set_dir(Link::INPUT); 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_name(perm_string::literal("Aset"), 0); pin_Aclr().set_dir(Link::INPUT); 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_name(perm_string::literal("Sset"), 0); pin_Sclr().set_dir(Link::INPUT); pin_Sclr().set_name(perm_string::literal("Sclr"), 0); - for (unsigned idx = 0 ; idx < wid ; idx += 1) { - pin_Data(idx).set_dir(Link::INPUT); - pin_Data(idx).set_name(perm_string::literal("Data"), idx); - pin_Q(idx).set_dir(Link::OUTPUT); - pin_Q(idx).set_name(perm_string::literal("Q"), idx); - } + pin_Data().set_dir(Link::INPUT); + pin_Data().set_name(perm_string::literal("Data"), 0); + pin_Q().set_dir(Link::OUTPUT); + pin_Q().set_name(perm_string::literal("Q"), 0); } NetFF::~NetFF() @@ -633,7 +633,7 @@ NetFF::~NetFF() unsigned NetFF::width() const { - return (pin_count() - 8) / 2; + return width_; } Link& NetFF::pin_Clock() @@ -656,82 +656,64 @@ const Link& NetFF::pin_Enable() const return pin(1); } -Link& NetFF::pin_Aload() +Link& NetFF::pin_Aset() { return pin(2); } -Link& NetFF::pin_Aset() -{ - return pin(3); -} - const Link& NetFF::pin_Aset() const { - return pin(3); + return pin(2); } Link& NetFF::pin_Aclr() { - return pin(4); + return pin(3); } const Link& NetFF::pin_Aclr() const { - return pin(4); -} - -Link& NetFF::pin_Sload() -{ - return pin(5); + return pin(3); } Link& NetFF::pin_Sset() { - return pin(6); + return pin(4); } const Link& NetFF::pin_Sset() const { - return pin(6); + return pin(4); } Link& NetFF::pin_Sclr() { - return pin(7); + return pin(5); } 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); } -Link& NetFF::pin_Data(unsigned w) +const Link& NetFF::pin_Q() const { - unsigned pn = 8 + 2*w; - 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); + return pin(7); } void NetFF::aset_value(const verinum&val) @@ -2174,6 +2156,9 @@ const NetProc*NetTaskDef::proc() const /* * $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 * All memory addresses are signed. * diff --git a/netlist.h b/netlist.h index a4f2d6de0..c916400cd 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: netlist.h,v 1.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 /* @@ -48,6 +48,7 @@ class ostream; class Design; class Link; class Nexus; +class NetNet; class NetNode; class NetProc; class NetProcTop; @@ -253,6 +254,12 @@ class Nexus { Link*first_nlink(); 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 nexus are constant. It will also return true if there are no drivers at all. */ @@ -316,6 +323,22 @@ class 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 * 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 { public: - NetFF(NetScope*s, perm_string n, unsigned width); + NetFF(NetScope*s, perm_string n, unsigned vector_width); ~NetFF(); unsigned width() const; Link& pin_Clock(); Link& pin_Enable(); - Link& pin_Aload(); Link& pin_Aset(); Link& pin_Aclr(); - Link& pin_Sload(); Link& pin_Sset(); Link& pin_Sclr(); - - Link& pin_Data(unsigned); - Link& pin_Q(unsigned); + Link& pin_Data(); + Link& pin_Q(); const Link& pin_Clock() const; const Link& pin_Enable() const; @@ -722,8 +742,8 @@ class NetFF : public NetNode { const Link& pin_Aclr() const; const Link& pin_Sset() const; const Link& pin_Sclr() const; - const Link& pin_Data(unsigned) const; - const Link& pin_Q(unsigned) const; + const Link& pin_Data() const; + const Link& pin_Q() const; void aset_value(const verinum&val); const verinum& aset_value() const; @@ -736,6 +756,7 @@ class NetFF : public NetNode { virtual void functor_node(Design*des, functor_t*fun); private: + unsigned width_; verinum aset_value_; verinum sset_value_; }; @@ -1479,10 +1500,10 @@ class NetProc : public virtual LineInfo { // synthesize as asynchronous logic, and return true. 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, - const NetNet*nex_map, NetNet*nex_out, + const NetBus&nex_map, NetBus&nex_out, const svector&events); virtual void dump(ostream&, unsigned ind) const; @@ -1614,7 +1635,7 @@ class NetAssignBase : public NetProc { unsigned lwidth() const; 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. void dump_lval(ostream&) const; @@ -1681,10 +1702,10 @@ class NetBlock : public NetProc { // synthesize as asynchronous logic, and return true. 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, - const NetNet*nex_map, NetNet*nex_out, + const NetBus&nex_map, NetBus&nex_out, const svector&events); // This version of emit_recurse scans all the statements of @@ -1736,7 +1757,7 @@ class NetCase : public NetProc { virtual void nex_output(NexusSet&out); 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 void dump(ostream&, unsigned ind) const; @@ -1804,10 +1825,10 @@ class NetCondit : public NetProc { bool is_asynchronous(); 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, - const NetNet*nex_map, NetNet*nex_out, + const NetBus&nex_map, NetBus&nex_out, const svector&events); virtual bool emit_proc(struct target_t*) const; @@ -2024,10 +2045,10 @@ class NetEvWait : public NetProc { virtual void nex_output(NexusSet&out); 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, - const NetNet*nex_map, NetNet*nex_out, + const NetBus&nex_map, NetBus&nex_out, const svector&events); virtual void dump(ostream&, unsigned ind) const; @@ -3416,6 +3437,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $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 * All memory addresses are signed. * diff --git a/netmisc.h b/netmisc.h index f8a05b484..6c96ddc62 100644 --- a/netmisc.h +++ b/netmisc.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #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 # 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 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 * 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 $ + * 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 * Remove the NetEBitSel and combine all bit/part select * behavior into the NetESelect node and IVL_EX_SELECT diff --git a/pad_to_width.cc b/pad_to_width.cc index bcecf6620..2bc2cbf9e 100644 --- a/pad_to_width.cc +++ b/pad_to_width.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #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 # include "config.h" @@ -110,8 +110,31 @@ NetNet*pad_to_width(Design*des, NetNet*net, unsigned wid) 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 $ + * 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 * Properly pad vector widths in pgassign. * diff --git a/syn-rules.y b/syn-rules.y index bb8cd8299..2a36fff87 100644 --- a/syn-rules.y +++ b/syn-rules.y @@ -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 * 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 */ #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 # 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 // selects in the l-value are handled by loff and the lwidth(). - int loff = a->get_loff(); - for (unsigned idx = 0 ; idx < ff->width() ; idx += 1) { - connect(ff->pin_Data(idx), d->bit(idx+rval_pinoffset)); - connect(ff->pin_Q(idx), a->sig()->pin(idx+loff)); - } + connect(ff->pin_Data(), d->bit(0)); + connect(ff->pin_Q(), a->sig()->pin(0)); connect(ff->pin_Clock(), pclk->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()) { // cerr << "new NetFF named " << a->name() << endl; NetFF*ff = new NetFF(top->scope(), a->name(), - a->lwidth()); + a->sig()->vector_width()); hookup_DFF_CE(ff, d, pclk, ce, a, rval_pinoffset); des->add_node(ff); } else if (a->mem()) { diff --git a/synth2.cc b/synth2.cc index a275e94f1..45263b268 100644 --- a/synth2.cc +++ b/synth2.cc @@ -17,42 +17,28 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #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 # include "config.h" # include "functor.h" # include "netlist.h" +# include "netmisc.h" # include "compiler.h" # include -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, - const NetNet*nex_map, NetNet*nex_out) + const NetBus&nex_map, NetBus&nex_out) { return false; } 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&events) { - DEBUG_SYNTH2_ENTRY("NetProc") - if (events.count() > 0) { cerr << get_line() << ": error: Events are unaccounted" << " 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); } -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; - for (idx = 0 ; idx < nset->pin_count() ; idx += 1) - if (nset->pin(idx).nexus() == nex) + for (idx = 0 ; idx < nset.pin_count() ; idx += 1) + if (nset.pin(idx).nexus() == nex) return idx; return idx; @@ -84,36 +70,36 @@ static unsigned find_nexus_in_set(const NetNet*nset, const Nexus*nex) * r-value. */ 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); assert(rsig); NetNet*lsig = lval_->sig(); 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); cerr << endl; - DEBUG_SYNTH2_EXIT("NetAssignBase",false) return false; } assert(lval_->more == 0); - if (lval_->lwidth() != nex_map->pin_count()) { - cerr << get_line() << ": error: NetAssignBase::synth_async pin count mismatch, " - << lval_->lwidth() << " != " << nex_map->pin_count() << endl; - DEBUG_SYNTH2_EXIT("NetAssignBase",false) +#if 0 + /* The l-value and r-value map must have the same width. */ + if (lval_->lwidth() != nex_map->vector_width()) { + cerr << get_line() << ": error: Assignment synthesis: " + << "vector width mismatch, " + << lval_->lwidth() << " bits != " + << nex_map->vector_width() << " bits." << endl; 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) { - 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)); - } + connect(nex_out.pin(0), rsig->pin(0)); /* This lval_ represents a reg that is a WIRE in the 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. */ lval_->turn_sig_to_wire_on_release(); - DEBUG_SYNTH2_EXIT("NetAssignBase",true) return true; } @@ -133,14 +118,13 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, * substatements. */ 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) { - DEBUG_SYNTH2_EXIT("NetBlock",true) return true; } +#if 0 const perm_string tmp1 = perm_string::literal("tmp1"); 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) 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, - const NetNet*nex_map, NetNet*nex_out) + const NetBus&nex_map, NetBus&nex_out) { - DEBUG_SYNTH2_ENTRY("NetCase") #if 0 unsigned cur; @@ -321,9 +309,9 @@ bool NetCase::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); assert(ssig); @@ -377,23 +365,40 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, DEBUG_SYNTH2_EXIT("NetCondit",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, - 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); - DEBUG_SYNTH2_EXIT("NetEvWait",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) { - DEBUG_SYNTH2_ENTRY("NetProcTop") NexusSet 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"); NetNet*nex_out = new NetNet(scope(), tmp1, NetNet::WIRE, nex_set.count()); @@ -403,8 +408,12 @@ bool NetProcTop::synth_async(Design*des) bool flag = statement_->synth_async(des, scope(), nex_out, nex_out); delete nex_out; - DEBUG_SYNTH2_EXIT("NetProcTop",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. */ 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&events_in) { - DEBUG_SYNTH2_ENTRY("NetBlock") if (last_ == 0) { - DEBUG_SYNTH2_EXIT("NetBlock",true) return true; } +#if 0 bool flag = true; 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. */ delete ff; - DEBUG_SYNTH2_EXIT("NetBlock",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. */ 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&events_in) { - DEBUG_SYNTH2_ENTRY("NetCondit") +#if 0 /* First try to turn the condition expression into an asynchronous set/reset. If the condition expression has 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); - DEBUG_SYNTH2_EXIT("NetCondit",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, - const NetNet*nex_map, NetNet*nex_out, + const NetBus&nex_map, NetBus&nex_out, const svector&events_in) { - DEBUG_SYNTH2_ENTRY("NetEvWait") if (events_in.count() > 0) { cerr << get_line() << ": error: Events are unaccounted" << " for in process synthesis." << endl; @@ -814,7 +832,7 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff, svectorevents (ev->nprobe() - 1); /* 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(); /* 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; cerr << get_line() << ": : Perhaps the clock" << " is read by a statement or expression?" << endl; - DEBUG_SYNTH2_EXIT("NetEvWait",false) return false; } connect(ff->pin_Clock(), pclk->pin(0)); - if (pclk->edge() == NetEvProbe::NEGEDGE) - ff->attribute(perm_string::literal("Clock:LPM_Polarity"), verinum("INVERT")); + if (pclk->edge() == NetEvProbe::NEGEDGE) { + 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. */ bool flag = statement_->synth_sync(des, scope, ff, nex_map, nex_out, events); - DEBUG_SYNTH2_EXIT("NetEvWait",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) { - DEBUG_SYNTH2_ENTRY("NetProcTop") + if (debug_synth2) { + cerr << get_line() << ": debug: " + << "Process is apparently synchronous. Making NetFFs." + << endl; + } + NexusSet 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(), - nex_set.count()); + nex_set[0]->vector_width()); des->add_node(ff); ff->attribute(perm_string::literal("LPM_FFType"), verinum("DFF")); - /* The D inputs to the DFF device will receive the output from - the statements of the process. */ - NetNet*nex_d = new NetNet(scope(), scope()->local_symbol(), - NetNet::WIRE, nex_set.count()); - nex_d->local_flag(true); + NetBus nex_d (scope(), nex_set.count()); + NetBus nex_q (scope(), nex_set.count()); + + /* The Q of the NetFF devices is connected to the output that + 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) { - 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 - 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)); - } + // Connect the input later. /* Synthesize the input to the DFF. */ bool flag = statement_->synth_sync(des, scope(), ff, nex_q, nex_d, svector()); + if (! flag) { + delete ff; + return false; + } - delete nex_q; - DEBUG_SYNTH2_EXIT("NetProcTop",flag) - return flag; + NetNet*tmp = nex_d.pin(0).nexus()->pick_any_net(); + 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 { @@ -978,84 +1043,14 @@ void synth2_f::process(class Design*des, class NetProcTop*top) void synth2(Design*des) { - debug_synth2 = atoi(des->get_flag("ivl-synth2-debug")); synth2_f synth_obj; des->functor(&synth_obj); } /* * $Log: synth2.cc,v $ - * Revision 1.41 2005/02/12 06:25:40 steve - * Restructure NetMux devices to pass vectors. - * Generate NetMux devices from ternary expressions, - * Reduce NetMux devices to bufif when appropriate. + * Revision 1.42 2005/04/24 23:44:02 steve + * Update DFF support to new data flow. * - * 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. */ diff --git a/t-dll-api.cc b/t-dll-api.cc index 48f63d2e3..c36fefe5c 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: t-dll-api.cc,v 1.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 # 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; case IVL_LPM_FF: - assert(idx < net->u_.ff.width); - if (net->u_.ff.width == 1) - return net->u_.ff.d.pin; - else - return net->u_.ff.d.pins[idx]; + assert(idx == 0); + return net->u_.ff.d.pin; case IVL_LPM_CONCAT: 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; case IVL_LPM_FF: - assert(idx < net->u_.ff.width); - if (net->u_.ff.width == 1) - return net->u_.ff.q.pin; - else - return net->u_.ff.q.pins[idx]; + assert(idx == 0); + return net->u_.ff.q.pin; case IVL_LPM_MUX: 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 $ + * 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 * Make logic aware of strength. * diff --git a/t-dll.cc b/t-dll.cc index a08948393..96ca7b1b4 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: t-dll.cc,v 1.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 # include "config.h" @@ -1500,36 +1500,17 @@ void dll_target::lpm_ff(const NetFF*net) obj->u_.ff.sset_value = 0; } - if (obj->u_.ff.width == 1) { - nex = net->pin_Q(0).nexus(); - assert(nex->t_cookie()); - obj->u_.ff.q.pin = (ivl_nexus_t) nex->t_cookie(); - nexus_lpm_add(obj->u_.ff.q.pin, obj, 0, - IVL_DR_STRONG, IVL_DR_STRONG); + nex = net->pin_Q().nexus(); + assert(nex->t_cookie()); + obj->u_.ff.q.pin = (ivl_nexus_t) nex->t_cookie(); + nexus_lpm_add(obj->u_.ff.q.pin, obj, 0, + IVL_DR_STRONG, IVL_DR_STRONG); - nex = net->pin_Data(0).nexus(); - assert(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); + nex = net->pin_Data().nexus(); + assert(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); - } 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) @@ -2090,6 +2071,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj }; /* * $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 * Rework NetRamDq and IVL_LPM_RAM nodes. * diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index 696ce466d..8b4e311db 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -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.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 # 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: \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) { unsigned width = ivl_lpm_width(net); @@ -478,7 +522,7 @@ static void show_lpm_mux(ivl_lpm_t net) ivl_nexus_name(nex), ivl_lpm_selects(net)); 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)); stub_errors += 1; } @@ -708,8 +752,6 @@ static void show_lpm_ufunc(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)) { @@ -726,6 +768,10 @@ static void show_lpm(ivl_lpm_t net) show_lpm_cmp_eeq(net); break; + case IVL_LPM_FF: + show_lpm_ff(net); + break; + case IVL_LPM_CMP_GE: show_lpm_cmp_ge(net); break; @@ -762,41 +808,6 @@ static void show_lpm(ivl_lpm_t net) show_lpm_sub(net); break; - case IVL_LPM_FF: { - - fprintf(out, " LPM_FF %s: \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: show_lpm_mod(net); break; @@ -1342,6 +1353,9 @@ int target_design(ivl_design_t des) /* * $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 * Make logic aware of strength. * diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index ee13c7875..74317d92d 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -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.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 # 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 char result[2048]; - unsigned idx; unsigned nptr_pin = ivl_nexus_ptr_pin(nptr); ivl_net_const_t cptr; 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)) { 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_ADD: case IVL_LPM_CONCAT: @@ -1591,86 +1581,41 @@ static void draw_lpm_ff(ivl_lpm_t net) ivl_expr_t aset_expr = 0; const char*aset_bits = 0; - unsigned width, idx; + ivl_nexus_t nex; + unsigned width; 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); if (aset_expr) { assert(ivl_expr_width(aset_expr) == width); 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 ", - vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))), - vvp_mangle_id(ivl_lpm_basename(net)), idx); + fprintf(vvp_out, "L_%p .dff ", net); - fprintf(vvp_out, "L_%s.%s/def, ", - vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))), - vvp_mangle_id(ivl_lpm_basename(net))); + nex = ivl_lpm_data(net,0); + assert(nex); + draw_input_from_net(nex); - tmp = ivl_lpm_clk(net); - draw_input_from_net(tmp); + nex = ivl_lpm_clk(net); + assert(nex); + fprintf(vvp_out, ", "); + draw_input_from_net(nex); - tmp = ivl_lpm_enable(net); + nex = ivl_lpm_enable(net); + if (nex) { fprintf(vvp_out, ", "); - if (tmp) - draw_input_from_net(tmp); - else - fprintf(vvp_out, "C<1>"); - - tmp = ivl_lpm_data(net, idx); - assert(tmp); - fprintf(vvp_out, ", "); - draw_input_from_net(tmp); - - /* 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 { - tmp = ivl_lpm_async_set(net); - if (aset_bits && (aset_bits[idx] == '0')) - draw_input_from_net(tmp); - else - fprintf(vvp_out, "C<0>"); - } - - /* Connect set input */ - fprintf(vvp_out, ", "); - 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"); + draw_input_from_net(nex); + } else { + fprintf(vvp_out, ", C4<1>"); } + + /* Stub asynchronous input for now. */ + fprintf(vvp_out, ", C4"); + + fprintf(vvp_out, ";\n"); } 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 $ + * 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 * Rework NetRamDq and IVL_LPM_RAM nodes. *