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

View File

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

View File

@ -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(list<perm_string>roots)
/*
* $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.
*

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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
* 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()) {

307
synth2.cc
View File

@ -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 <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,
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<NetEvProbe*>&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<NetEvProbe*>&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<NetEvProbe*>&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<NetEvProbe*>&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,
svector<NetEvProbe*>events (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<NetEvProbe*>());
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.
*/

View File

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

View File

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

View File

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

View File

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