Rework l-value handling to allow for more l-value type flexibility.
This commit is contained in:
parent
fc227aa3e1
commit
52b8ed9077
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CVS_IDENT
|
#ifdef HAVE_CVS_IDENT
|
||||||
#ident "$Id: design_dump.cc,v 1.149 2004/10/04 01:10:52 steve Exp $"
|
#ident "$Id: design_dump.cc,v 1.149.2.1 2006/01/18 01:23:23 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
|
@ -355,8 +355,13 @@ void NetModulo::dump_node(ostream&o, unsigned ind) const
|
||||||
|
|
||||||
void NetRamDq::dump_node(ostream&o, unsigned ind) const
|
void NetRamDq::dump_node(ostream&o, unsigned ind) const
|
||||||
{
|
{
|
||||||
o << setw(ind) << "" << "LPM_RAM_DQ (" << mem_->name() << "): "
|
o << setw(ind) << "" << "LPM_RAM_DQ (";
|
||||||
<< name() << endl;
|
|
||||||
|
if (mem_) o << "mem=" << mem_->name();
|
||||||
|
if (sig_) o << "sig=" << sig_->name();
|
||||||
|
|
||||||
|
o << "): " << name() << endl;
|
||||||
|
|
||||||
dump_node_pins(o, ind+4);
|
dump_node_pins(o, ind+4);
|
||||||
dump_obj_attr(o, ind+4);
|
dump_obj_attr(o, ind+4);
|
||||||
}
|
}
|
||||||
|
|
@ -1089,6 +1094,9 @@ void Design::dump(ostream&o) const
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: design_dump.cc,v $
|
* $Log: design_dump.cc,v $
|
||||||
|
* Revision 1.149.2.1 2006/01/18 01:23:23 steve
|
||||||
|
* Rework l-value handling to allow for more l-value type flexibility.
|
||||||
|
*
|
||||||
* Revision 1.149 2004/10/04 01:10:52 steve
|
* Revision 1.149 2004/10/04 01:10:52 steve
|
||||||
* Clean up spurious trailing white space.
|
* Clean up spurious trailing white space.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CVS_IDENT
|
#ifdef HAVE_CVS_IDENT
|
||||||
#ident "$Id: net_nex_output.cc,v 1.11 2004/09/16 03:17:33 steve Exp $"
|
#ident "$Id: net_nex_output.cc,v 1.11.2.1 2006/01/18 01:23:23 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
|
@ -47,6 +47,14 @@ void NetAssignBase::nex_output(NexusSet&out)
|
||||||
{
|
{
|
||||||
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
|
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
|
||||||
if (NetNet*lsig = cur->sig()) {
|
if (NetNet*lsig = cur->sig()) {
|
||||||
|
#if 0
|
||||||
|
if (cur->bmux()) {
|
||||||
|
cerr << get_line() << ": internal error: "
|
||||||
|
<< "L-Value mux not supported by nex_output: ";
|
||||||
|
cur->dump_lval(cerr);
|
||||||
|
cerr << endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) {
|
||||||
unsigned off = cur->get_loff() + idx;
|
unsigned off = cur->get_loff() + idx;
|
||||||
out.add(lsig->pin(off).nexus());
|
out.add(lsig->pin(off).nexus());
|
||||||
|
|
@ -122,6 +130,9 @@ void NetWhile::nex_output(NexusSet&out)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: net_nex_output.cc,v $
|
* $Log: net_nex_output.cc,v $
|
||||||
|
* Revision 1.11.2.1 2006/01/18 01:23:23 steve
|
||||||
|
* Rework l-value handling to allow for more l-value type flexibility.
|
||||||
|
*
|
||||||
* Revision 1.11 2004/09/16 03:17:33 steve
|
* Revision 1.11 2004/09/16 03:17:33 steve
|
||||||
* net_output handles l-value concatenations.
|
* net_output handles l-value concatenations.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
57
netlist.cc
57
netlist.cc
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CVS_IDENT
|
#ifdef HAVE_CVS_IDENT
|
||||||
#ident "$Id: netlist.cc,v 1.226 2004/10/04 01:10:54 steve Exp $"
|
#ident "$Id: netlist.cc,v 1.226.2.1 2006/01/18 01:23:23 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
|
@ -234,6 +234,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
||||||
assert(s);
|
assert(s);
|
||||||
|
|
||||||
release_list_ = 0;
|
release_list_ = 0;
|
||||||
|
ram_ = 0;
|
||||||
|
|
||||||
verinum::V init_value = verinum::Vz;
|
verinum::V init_value = verinum::Vz;
|
||||||
Link::DIR dir = Link::PASSIVE;
|
Link::DIR dir = Link::PASSIVE;
|
||||||
|
|
@ -275,6 +276,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, long ms, long ls)
|
||||||
assert(s);
|
assert(s);
|
||||||
|
|
||||||
release_list_ = 0;
|
release_list_ = 0;
|
||||||
|
ram_ = 0;
|
||||||
|
|
||||||
verinum::V init_value = verinum::Vz;
|
verinum::V init_value = verinum::Vz;
|
||||||
Link::DIR dir = Link::PASSIVE;
|
Link::DIR dir = Link::PASSIVE;
|
||||||
|
|
@ -1385,10 +1387,7 @@ const Link& NetMux::pin_Data(unsigned w, unsigned s) const
|
||||||
return pin(2+width_+swidth_+s*width_+w);
|
return pin(2+width_+swidth_+s*width_+w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetRamDq::make_pins_(unsigned wid)
|
||||||
NetRamDq::NetRamDq(NetScope*s, perm_string n, NetMemory*mem, unsigned awid)
|
|
||||||
: NetNode(s, n, 3+2*mem->width()+awid),
|
|
||||||
mem_(mem), awidth_(awid)
|
|
||||||
{
|
{
|
||||||
pin(0).set_dir(Link::INPUT); pin(0).set_name(perm_string::literal("InClock"), 0);
|
pin(0).set_dir(Link::INPUT); pin(0).set_name(perm_string::literal("InClock"), 0);
|
||||||
pin(1).set_dir(Link::INPUT); pin(1).set_name(perm_string::literal("OutClock"), 0);
|
pin(1).set_dir(Link::INPUT); pin(1).set_name(perm_string::literal("OutClock"), 0);
|
||||||
|
|
@ -1399,22 +1398,40 @@ NetRamDq::NetRamDq(NetScope*s, perm_string n, NetMemory*mem, unsigned awid)
|
||||||
pin(3+idx).set_name(perm_string::literal("Address"), idx);
|
pin(3+idx).set_name(perm_string::literal("Address"), idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < width() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||||
pin(3+awidth_+idx).set_dir(Link::INPUT);
|
pin(3+awidth_+idx).set_dir(Link::INPUT);
|
||||||
pin(3+awidth_+idx).set_name(perm_string::literal("Data"), idx);
|
pin(3+awidth_+idx).set_name(perm_string::literal("Data"), idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < width() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||||
pin(3+awidth_+width()+idx).set_dir(Link::OUTPUT);
|
pin(3+awidth_+wid+idx).set_dir(Link::OUTPUT);
|
||||||
pin(3+awidth_+width()+idx).set_name(perm_string::literal("Q"), idx);
|
pin(3+awidth_+wid+idx).set_name(perm_string::literal("Q"), idx);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NetRamDq::NetRamDq(NetScope*s, perm_string n, NetMemory*mem, unsigned awid)
|
||||||
|
: NetNode(s, n, 3+2*mem->width()+awid),
|
||||||
|
mem_(mem), sig_(0), awidth_(awid)
|
||||||
|
{
|
||||||
|
make_pins_(mem->width());
|
||||||
next_ = mem_->ram_list_;
|
next_ = mem_->ram_list_;
|
||||||
mem_->ram_list_ = this;
|
mem_->ram_list_ = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetRamDq::NetRamDq(NetScope*s, perm_string n, NetNet*sig, unsigned awid)
|
||||||
|
: NetNode(s, n, 3+2*1+awid),
|
||||||
|
mem_(0), sig_(sig), awidth_(awid)
|
||||||
|
{
|
||||||
|
make_pins_(1);
|
||||||
|
|
||||||
|
assert(sig->ram_ == 0);
|
||||||
|
sig->ram_ = this;
|
||||||
|
}
|
||||||
|
|
||||||
NetRamDq::~NetRamDq()
|
NetRamDq::~NetRamDq()
|
||||||
{
|
{
|
||||||
|
if (mem_) {
|
||||||
if (mem_->ram_list_ == this) {
|
if (mem_->ram_list_ == this) {
|
||||||
mem_->ram_list_ = next_;
|
mem_->ram_list_ = next_;
|
||||||
|
|
||||||
|
|
@ -1427,11 +1444,19 @@ NetRamDq::~NetRamDq()
|
||||||
assert(cur->next_ == this);
|
assert(cur->next_ == this);
|
||||||
cur->next_ = next_;
|
cur->next_ = next_;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sig_) {
|
||||||
|
assert(sig_->ram_ == this);
|
||||||
|
sig_->ram_ = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned NetRamDq::width() const
|
unsigned NetRamDq::width() const
|
||||||
{
|
{
|
||||||
return mem_->width();
|
if (mem_) return mem_->width();
|
||||||
|
if (sig_) return 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned NetRamDq::awidth() const
|
unsigned NetRamDq::awidth() const
|
||||||
|
|
@ -1441,7 +1466,9 @@ unsigned NetRamDq::awidth() const
|
||||||
|
|
||||||
unsigned NetRamDq::size() const
|
unsigned NetRamDq::size() const
|
||||||
{
|
{
|
||||||
return mem_->count();
|
if (mem_) return mem_->count();
|
||||||
|
if (sig_) return sig_->pin_count();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NetMemory* NetRamDq::mem() const
|
const NetMemory* NetRamDq::mem() const
|
||||||
|
|
@ -1449,6 +1476,11 @@ const NetMemory* NetRamDq::mem() const
|
||||||
return mem_;
|
return mem_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NetNet* NetRamDq::sig() const
|
||||||
|
{
|
||||||
|
return sig_;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned NetRamDq::count_partners() const
|
unsigned NetRamDq::count_partners() const
|
||||||
{
|
{
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
|
|
@ -2281,6 +2313,9 @@ const NetProc*NetTaskDef::proc() const
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: netlist.cc,v $
|
* $Log: netlist.cc,v $
|
||||||
|
* Revision 1.226.2.1 2006/01/18 01:23:23 steve
|
||||||
|
* Rework l-value handling to allow for more l-value type flexibility.
|
||||||
|
*
|
||||||
* Revision 1.226 2004/10/04 01:10:54 steve
|
* Revision 1.226 2004/10/04 01:10:54 steve
|
||||||
* Clean up spurious trailing white space.
|
* Clean up spurious trailing white space.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
32
netlist.h
32
netlist.h
|
|
@ -19,7 +19,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CVS_IDENT
|
#ifdef HAVE_CVS_IDENT
|
||||||
#ident "$Id: netlist.h,v 1.321.2.7 2005/12/31 04:28:14 steve Exp $"
|
#ident "$Id: netlist.h,v 1.321.2.8 2006/01/18 01:23:24 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -58,6 +58,7 @@ class NetEvProbe;
|
||||||
class NetExpr;
|
class NetExpr;
|
||||||
class NetESignal;
|
class NetESignal;
|
||||||
class NetEVariable;
|
class NetEVariable;
|
||||||
|
class NetFF;
|
||||||
class NetFuncDef;
|
class NetFuncDef;
|
||||||
|
|
||||||
class NetRamDq;
|
class NetRamDq;
|
||||||
|
|
@ -67,6 +68,12 @@ class NetEvWait;
|
||||||
struct target;
|
struct target;
|
||||||
struct functor_t;
|
struct functor_t;
|
||||||
|
|
||||||
|
struct sync_accounting_cell {
|
||||||
|
NetProc*proc;
|
||||||
|
NetFF*ff;
|
||||||
|
unsigned pin;
|
||||||
|
};
|
||||||
|
|
||||||
/* =========
|
/* =========
|
||||||
* A NetObj is anything that has any kind of behavior in the
|
* A NetObj is anything that has any kind of behavior in the
|
||||||
* netlist. Nodes can be gates, registers, etc. and are linked
|
* netlist. Nodes can be gates, registers, etc. and are linked
|
||||||
|
|
@ -440,6 +447,9 @@ class NetNet : public NetObj {
|
||||||
friend class NetRelease;
|
friend class NetRelease;
|
||||||
NetRelease*release_list_;
|
NetRelease*release_list_;
|
||||||
|
|
||||||
|
friend class NetRamDq;
|
||||||
|
class NetRamDq*ram_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type type_;
|
Type type_;
|
||||||
PortType port_type_;
|
PortType port_type_;
|
||||||
|
|
@ -876,12 +886,14 @@ class NetRamDq : public NetNode {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NetRamDq(NetScope*s, perm_string name, NetMemory*mem, unsigned awid);
|
NetRamDq(NetScope*s, perm_string name, NetMemory*mem, unsigned awid);
|
||||||
|
NetRamDq(NetScope*s, perm_string name, NetNet*mem, unsigned awid);
|
||||||
~NetRamDq();
|
~NetRamDq();
|
||||||
|
|
||||||
unsigned width() const;
|
unsigned width() const;
|
||||||
unsigned awidth() const;
|
unsigned awidth() const;
|
||||||
unsigned size() const;
|
unsigned size() const;
|
||||||
const NetMemory*mem() const;
|
const NetMemory*mem() const;
|
||||||
|
const NetNet*sig() const;
|
||||||
|
|
||||||
Link& pin_InClock();
|
Link& pin_InClock();
|
||||||
Link& pin_OutClock();
|
Link& pin_OutClock();
|
||||||
|
|
@ -913,9 +925,12 @@ class NetRamDq : public NetNode {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetMemory*mem_;
|
NetMemory*mem_;
|
||||||
|
NetNet* sig_;
|
||||||
NetRamDq*next_;
|
NetRamDq*next_;
|
||||||
unsigned awidth_;
|
unsigned awidth_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void make_pins_(unsigned wid);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1365,7 +1380,8 @@ class NetProc : public virtual LineInfo {
|
||||||
// was created to receive the Data inputs. The method *may*
|
// was created to receive the Data inputs. The method *may*
|
||||||
// delete that DFF in favor of multiple smaller devices, but
|
// delete that DFF in favor of multiple smaller devices, but
|
||||||
// in that case it will set the ff argument to nil.
|
// in that case it will set the ff argument to nil.
|
||||||
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
virtual bool synth_sync(Design*des, NetScope*scope,
|
||||||
|
struct sync_accounting_cell*nex_ff,
|
||||||
NetNet*nex_map, NetNet*nex_out,
|
NetNet*nex_map, NetNet*nex_out,
|
||||||
const svector<NetEvProbe*>&events);
|
const svector<NetEvProbe*>&events);
|
||||||
|
|
||||||
|
|
@ -1570,7 +1586,8 @@ class NetBlock : public NetProc {
|
||||||
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||||
NetNet*nex_map, NetNet*nex_out);
|
NetNet*nex_map, NetNet*nex_out);
|
||||||
|
|
||||||
bool synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
bool synth_sync(Design*des, NetScope*scope,
|
||||||
|
struct sync_accounting_cell*nex_ff,
|
||||||
NetNet*nex_map, NetNet*nex_out,
|
NetNet*nex_map, NetNet*nex_out,
|
||||||
const svector<NetEvProbe*>&events);
|
const svector<NetEvProbe*>&events);
|
||||||
|
|
||||||
|
|
@ -1711,7 +1728,8 @@ class NetCondit : public NetProc {
|
||||||
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum);
|
NetNet*nex_map, NetNet*nex_out, NetNet*accum);
|
||||||
|
|
||||||
bool synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
bool synth_sync(Design*des, NetScope*scope,
|
||||||
|
struct sync_accounting_cell*nex_ff,
|
||||||
NetNet*nex_map, NetNet*nex_out,
|
NetNet*nex_map, NetNet*nex_out,
|
||||||
const svector<NetEvProbe*>&events);
|
const svector<NetEvProbe*>&events);
|
||||||
|
|
||||||
|
|
@ -1936,7 +1954,8 @@ class NetEvWait : public NetProc {
|
||||||
virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||||
NetNet*nex_map, NetNet*nex_out);
|
NetNet*nex_map, NetNet*nex_out);
|
||||||
|
|
||||||
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
virtual bool synth_sync(Design*des, NetScope*scope,
|
||||||
|
struct sync_accounting_cell*nex_ff,
|
||||||
NetNet*nex_map, NetNet*nex_out,
|
NetNet*nex_map, NetNet*nex_out,
|
||||||
const svector<NetEvProbe*>&events);
|
const svector<NetEvProbe*>&events);
|
||||||
|
|
||||||
|
|
@ -3379,6 +3398,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: netlist.h,v $
|
* $Log: netlist.h,v $
|
||||||
|
* Revision 1.321.2.8 2006/01/18 01:23:24 steve
|
||||||
|
* Rework l-value handling to allow for more l-value type flexibility.
|
||||||
|
*
|
||||||
* Revision 1.321.2.7 2005/12/31 04:28:14 steve
|
* Revision 1.321.2.7 2005/12/31 04:28:14 steve
|
||||||
* Fix crashes caused bu synthesis of sqrt32.v.
|
* Fix crashes caused bu synthesis of sqrt32.v.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
275
synth2.cc
275
synth2.cc
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CVS_IDENT
|
#ifdef HAVE_CVS_IDENT
|
||||||
#ident "$Id: synth2.cc,v 1.39.2.15 2006/01/01 02:25:07 steve Exp $"
|
#ident "$Id: synth2.cc,v 1.39.2.16 2006/01/18 01:23:25 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
|
@ -54,7 +54,8 @@ bool NetProc::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||||
return synth_async(des, scope, sync_flag, nex_map, nex_out);
|
return synth_async(des, scope, sync_flag, nex_map, nex_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetProc::synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
bool NetProc::synth_sync(Design*des, NetScope*scope,
|
||||||
|
struct sync_accounting_cell*nex_ff,
|
||||||
NetNet*nex_map, NetNet*nex_out,
|
NetNet*nex_map, NetNet*nex_out,
|
||||||
const svector<NetEvProbe*>&events)
|
const svector<NetEvProbe*>&events)
|
||||||
{
|
{
|
||||||
|
|
@ -120,6 +121,39 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cur->bmux() && !sync_flag) {
|
||||||
|
cerr << get_line() << ": error: Assign to bit select "
|
||||||
|
<< "Not possible in asynchronous logic." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Detect and handle the special case that this is a
|
||||||
|
memory-like access to a vector. */
|
||||||
|
if (cur->bmux()) {
|
||||||
|
NetNet*adr = cur->bmux()->synthesize(des);
|
||||||
|
NetRamDq*dq = new NetRamDq(scope, scope->local_symbol(),
|
||||||
|
lsig, adr->pin_count());
|
||||||
|
des->add_node(dq);
|
||||||
|
dq->set_line(*this);
|
||||||
|
|
||||||
|
for (unsigned idx = 0 ; idx < adr->pin_count() ; idx += 1)
|
||||||
|
connect(dq->pin_Address(idx), adr->pin(idx));
|
||||||
|
#if 0
|
||||||
|
/* Connect the Q bit to all the bits of the
|
||||||
|
output. This is a signal to a later stage that
|
||||||
|
the DFF should be replaced with a RAM to
|
||||||
|
support this port. */
|
||||||
|
for (unsigned idx = 0; idx < lsig->pin_count(); idx += 1){
|
||||||
|
unsigned ptr = find_nexus_in_set(nex_map, lsig->pin(idx).nexus());
|
||||||
|
connect(dq->pin_Q(0), nex_out->pin(ptr));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
connect(dq->pin_Data(0), rsig->pin(roff));
|
||||||
|
roff += cur->lwidth();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Bind the outputs that we do make to the nex_out. Use the
|
/* Bind the outputs that we do make to the nex_out. Use the
|
||||||
nex_map to map the l-value bit position to the nex_out bit
|
nex_map to map the l-value bit position to the nex_out bit
|
||||||
position. */
|
position. */
|
||||||
|
|
@ -300,9 +334,16 @@ bool NetCase::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* At this point, sel_ref represents the constant part of the
|
||||||
|
select input. That is, (select&sel_mask) == sel_ref for all
|
||||||
|
guard values that are reachable. We can use this to skip
|
||||||
|
unreachable guards. */
|
||||||
|
|
||||||
|
|
||||||
/* Build a map of guard values to mux select values. This
|
/* Build a map of guard values to mux select values. This
|
||||||
helps account for constant select bits that are being
|
helps account for constant select bits that are being
|
||||||
elided. */
|
elided. The guard2sel mapping will only be valid for
|
||||||
|
reachable guards. */
|
||||||
map<unsigned long,unsigned long>guard2sel;
|
map<unsigned long,unsigned long>guard2sel;
|
||||||
cur = 0;
|
cur = 0;
|
||||||
for (unsigned idx = 0 ; idx < (1U<<esig->pin_count()) ; idx += 1) {
|
for (unsigned idx = 0 ; idx < (1U<<esig->pin_count()) ; idx += 1) {
|
||||||
|
|
@ -355,6 +396,12 @@ bool NetCase::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||||
NetEConst*ge = dynamic_cast<NetEConst*>(items_[item].guard);
|
NetEConst*ge = dynamic_cast<NetEConst*>(items_[item].guard);
|
||||||
assert(ge);
|
assert(ge);
|
||||||
verinum gval = ge->value();
|
verinum gval = ge->value();
|
||||||
|
|
||||||
|
/* Skip guards that are unreachable. */
|
||||||
|
if ((sel_ref&~sel_mask) != (gval.as_ulong()&~sel_mask)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned sel_idx = guard2sel[gval.as_ulong()];
|
unsigned sel_idx = guard2sel[gval.as_ulong()];
|
||||||
|
|
||||||
assert(items_[item].statement);
|
assert(items_[item].statement);
|
||||||
|
|
@ -649,15 +696,6 @@ bool NetProcTop::synth_async(Design*des)
|
||||||
static bool merge_ff_slices(NetFF*ff1, unsigned idx1,
|
static bool merge_ff_slices(NetFF*ff1, unsigned idx1,
|
||||||
NetFF*ff2, unsigned idx2)
|
NetFF*ff2, unsigned idx2)
|
||||||
{
|
{
|
||||||
/* If the Data inputs to both FFs are connected, then there
|
|
||||||
are multiple descriptions of the inputs to this DFF
|
|
||||||
device. That is an error. */
|
|
||||||
if (ff1->pin_Data(idx1).is_linked() && ff2->pin_Data(idx2).is_linked()) {
|
|
||||||
cerr << ff2->get_line() << ": error: "
|
|
||||||
<< "Synchronous output conflicts with "
|
|
||||||
<< ff1->get_line() << "." << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the Aset inputs are connected, and not to each other
|
/* If the Aset inputs are connected, and not to each other
|
||||||
(possible since pre-existing Asets are carried forwards)
|
(possible since pre-existing Asets are carried forwards)
|
||||||
|
|
@ -680,12 +718,22 @@ static bool merge_ff_slices(NetFF*ff1, unsigned idx1,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if XXXX
|
||||||
if (ff2->pin_Data(idx2).is_linked())
|
if (ff2->pin_Data(idx2).is_linked())
|
||||||
connect(ff1->pin_Data(idx1), ff2->pin_Data(idx2));
|
connect(ff1->pin_Data(idx1), ff2->pin_Data(idx2));
|
||||||
if (ff2->pin_Aset().is_linked())
|
if (ff2->pin_Aset().is_linked())
|
||||||
connect(ff1->pin_Aset(), ff2->pin_Aset());
|
connect(ff1->pin_Aset(), ff2->pin_Aset());
|
||||||
if (ff2->pin_Aclr().is_linked())
|
if (ff2->pin_Aclr().is_linked())
|
||||||
connect(ff1->pin_Aclr(), ff2->pin_Aclr());
|
connect(ff1->pin_Aclr(), ff2->pin_Aclr());
|
||||||
|
if (ff2->pin_Sclr().is_linked())
|
||||||
|
connect(ff1->pin_Sclr(), ff2->pin_Sclr());
|
||||||
|
if (ff2->pin_Sset().is_linked())
|
||||||
|
connect(ff1->pin_Sset(), ff2->pin_Sset());
|
||||||
|
if (ff2->pin_Clock().is_linked())
|
||||||
|
connect(ff1->pin_Clock(), ff2->pin_Clock());
|
||||||
|
#endif
|
||||||
|
if (ff2->pin_Enable().is_linked())
|
||||||
|
connect(ff1->pin_Enable(),ff2->pin_Enable());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -704,7 +752,8 @@ static bool merge_ff_slices(NetFF*ff1, unsigned idx1,
|
||||||
* This needs to be split into a DFF bank for each statement, because
|
* This needs to be split into a DFF bank for each statement, because
|
||||||
* the statements may each infer different reset and enable signals.
|
* the statements may each infer different reset and enable signals.
|
||||||
*/
|
*/
|
||||||
bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
bool NetBlock::synth_sync(Design*des, NetScope*scope,
|
||||||
|
struct sync_accounting_cell*nex_ff,
|
||||||
NetNet*nex_map, NetNet*nex_out,
|
NetNet*nex_map, NetNet*nex_out,
|
||||||
const svector<NetEvProbe*>&events_in)
|
const svector<NetEvProbe*>&events_in)
|
||||||
{
|
{
|
||||||
|
|
@ -712,25 +761,21 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
||||||
if (last_ == 0)
|
if (last_ == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
/* Assert that this region still represents a single DFF. */
|
||||||
|
for (unsigned idx = 1 ; idx < nex_out->pin_count() ; idx += 1) {
|
||||||
|
assert(nex_ff[0].ff == nex_ff[idx].ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
NetFF*ff = nex_ff[0].ff;
|
||||||
|
|
||||||
|
assert(ff->width() == nex_out->pin_count());
|
||||||
|
unsigned block_width = nex_out->pin_count();
|
||||||
|
|
||||||
bool flag = true;
|
bool flag = true;
|
||||||
|
|
||||||
const perm_string tmp1 = perm_string::literal("tmp1");
|
const perm_string tmp1 = perm_string::literal("tmp1");
|
||||||
const perm_string tmp2 = perm_string::literal("tmp2");
|
const perm_string tmp2 = perm_string::literal("tmp2");
|
||||||
|
|
||||||
/* Keep an accounting of which statement accounts for which
|
|
||||||
bit slice of the FF bank. This is used for error
|
|
||||||
checking. */
|
|
||||||
struct accounting_struct {
|
|
||||||
NetProc*proc;
|
|
||||||
NetFF*ff;
|
|
||||||
unsigned pin;
|
|
||||||
};
|
|
||||||
struct accounting_struct*pin_accounting
|
|
||||||
= new accounting_struct [ff->pin_count()];
|
|
||||||
for (unsigned idx = 0 ; idx < ff->pin_count() ; idx += 1) {
|
|
||||||
pin_accounting[idx].proc = 0;
|
|
||||||
pin_accounting[idx].ff = 0;
|
|
||||||
}
|
|
||||||
NetProc*cur = last_;
|
NetProc*cur = last_;
|
||||||
do {
|
do {
|
||||||
cur = cur->next_;
|
cur = cur->next_;
|
||||||
|
|
@ -767,6 +812,9 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
||||||
ff2->set_line(*cur);
|
ff2->set_line(*cur);
|
||||||
des->add_node(ff2);
|
des->add_node(ff2);
|
||||||
|
|
||||||
|
struct sync_accounting_cell*tmp_ff
|
||||||
|
= new struct sync_accounting_cell[ff2->width()];
|
||||||
|
|
||||||
verinum aset_value2 (verinum::V1, ff2->width());
|
verinum aset_value2 (verinum::V1, ff2->width());
|
||||||
verinum sset_value2 (verinum::V1, ff2->width());
|
verinum sset_value2 (verinum::V1, ff2->width());
|
||||||
for (unsigned idx = 0 ; idx < ff2->width() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < ff2->width() ; idx += 1) {
|
||||||
|
|
@ -781,17 +829,13 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
||||||
if (ptr < tmp_sset.len())
|
if (ptr < tmp_sset.len())
|
||||||
sset_value2.set(idx, tmp_sset[ptr]);
|
sset_value2.set(idx, tmp_sset[ptr]);
|
||||||
|
|
||||||
if (pin_accounting[ptr].proc != 0) {
|
// Connect the tmp_out vector, what the
|
||||||
|
// sub-synthesis is linking, to the inputs of this
|
||||||
} else {
|
// new FF.
|
||||||
pin_accounting[ptr].proc = cur;
|
connect(tmp_out->pin(idx), ff2->pin_Data(idx));
|
||||||
pin_accounting[ptr].ff = ff2;
|
tmp_ff[idx].ff = ff2;
|
||||||
pin_accounting[ptr].pin = idx;
|
tmp_ff[idx].pin = idx;
|
||||||
|
tmp_ff[idx].proc = cur;
|
||||||
/* Connect Data and Q bits to the new FF. */
|
|
||||||
connect(ff->pin_Data(ptr), ff2->pin_Data(idx));
|
|
||||||
connect(ff->pin_Q(ptr), ff2->pin_Q(idx));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PUll the non-sliced inputs (clock, set, reset, etc)
|
/* PUll the non-sliced inputs (clock, set, reset, etc)
|
||||||
|
|
@ -818,8 +862,8 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
||||||
&& ff2->pin_Aset().is_linked()
|
&& ff2->pin_Aset().is_linked()
|
||||||
&& !ff2->pin_Aclr().is_linked()) {
|
&& !ff2->pin_Aclr().is_linked()) {
|
||||||
|
|
||||||
connect(ff2->pin_Aclr(), ff2->pin_Aset());
|
|
||||||
ff2->pin_Aset().unlink();
|
ff2->pin_Aset().unlink();
|
||||||
|
connect(ff2->pin_Aclr(), ff->pin_Aset());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ff2->aset_value(aset_value2);
|
ff2->aset_value(aset_value2);
|
||||||
|
|
@ -830,73 +874,83 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
||||||
statement of the block. The tmp_map is the output
|
statement of the block. The tmp_map is the output
|
||||||
nexa that we expect, and the tmp_out is where we want
|
nexa that we expect, and the tmp_out is where we want
|
||||||
those outputs connected. */
|
those outputs connected. */
|
||||||
NetFF*ff2_tmp = ff2;
|
bool ok_flag = cur->synth_sync(des, scope,
|
||||||
bool ok_flag = cur->synth_sync(des, scope, ff2_tmp, tmp_map,
|
tmp_ff, tmp_map, tmp_out,
|
||||||
tmp_out, events_in);
|
events_in);
|
||||||
|
ff2 = 0; // NOTE: The synth_sync may delete ff2.
|
||||||
flag = flag && ok_flag;
|
flag = flag && ok_flag;
|
||||||
|
|
||||||
if (ok_flag == false)
|
if (ok_flag == false)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ff2_tmp != 0) {
|
|
||||||
unsigned ff2_pins_used = ff2->width();
|
|
||||||
for (unsigned idx = 0 ; idx < ff2->width() ; idx += 1) {
|
|
||||||
unsigned ptr = find_nexus_in_set(nex_map,
|
|
||||||
tmp_map->pin(idx).nexus());
|
|
||||||
if (pin_accounting[ptr].ff == ff2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
assert(ff2_pins_used > 0);
|
|
||||||
ff2_pins_used -= 1;
|
|
||||||
bool tflag = merge_ff_slices(pin_accounting[ptr].ff,
|
|
||||||
pin_accounting[ptr].pin,
|
|
||||||
ff2, idx);
|
|
||||||
if (! tflag) {
|
|
||||||
flag = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ff2_pins_used == 0)
|
|
||||||
delete ff2;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* Oh, the cur->synth_sync deleted my ff2 DFF, so
|
|
||||||
erase any mention of it from the pin
|
|
||||||
accounting. */
|
|
||||||
for (unsigned idx = 0 ; idx < ff->width() ; idx += 1) {
|
|
||||||
if (pin_accounting[idx].ff != ff2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
pin_accounting[idx].ff = 0;
|
|
||||||
pin_accounting[idx].pin = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ff2 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use the nex_map to link up the output from the
|
/* Use the nex_map to link up the output from the
|
||||||
substatement to the output of the block as a
|
substatement to the output of the block as a
|
||||||
whole. It is occasionally possible to have outputs
|
whole. It is occasionally possible to have outputs
|
||||||
beyond the input set, for example when the l-value of
|
beyond the input set, for example when the l-value of
|
||||||
an assignment is smaller then the r-value. */
|
an assignment is smaller then the r-value. */
|
||||||
for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1) {
|
||||||
|
ff2 = tmp_ff[idx].ff;
|
||||||
|
unsigned ff2_pin = tmp_ff[idx].pin;
|
||||||
unsigned ptr = find_nexus_in_set(nex_map,
|
unsigned ptr = find_nexus_in_set(nex_map,
|
||||||
tmp_map->pin(idx).nexus());
|
tmp_map->pin(idx).nexus());
|
||||||
|
|
||||||
if (ptr < nex_out->pin_count())
|
if (ptr >= nex_out->pin_count())
|
||||||
connect(nex_out->pin(ptr), tmp_out->pin(idx));
|
continue;
|
||||||
|
|
||||||
|
// This is the current DFF for this bit slice...
|
||||||
|
NetFF*ff1 = nex_ff[ptr].ff;
|
||||||
|
unsigned ff1_pin = nex_ff[ptr].pin;
|
||||||
|
|
||||||
|
// Connect the new NetFF to the baseline
|
||||||
|
// NetFF Q and D pins.
|
||||||
|
connect(ff1->pin_Data(ff1_pin), ff2->pin_Data(ff2_pin));
|
||||||
|
connect(ff1->pin_Q(ff1_pin), ff2->pin_Q(ff2_pin));
|
||||||
|
// Merge the new ff2 with the current ff1. This
|
||||||
|
// brings all the non-sliced bits forward from
|
||||||
|
// ff1, as well as any other merging needed.
|
||||||
|
merge_ff_slices(ff2, ff2_pin, ff1, ff1_pin);
|
||||||
|
|
||||||
|
// Save the bit slice map as the new referece.
|
||||||
|
nex_ff[ptr] = tmp_ff[idx];
|
||||||
|
|
||||||
|
// If the (old) current DFF is not the same as the
|
||||||
|
// baseline DFF, then it is possible that the
|
||||||
|
// slice update rendered ff1 obsolete. If so, it
|
||||||
|
// will no longer appear in the nex_ff map, so
|
||||||
|
// remove it.
|
||||||
|
if (ff1 != ff) {
|
||||||
|
bool found_flag = false;
|
||||||
|
for (unsigned scan=0
|
||||||
|
; scan < ff->width() && !found_flag
|
||||||
|
; scan += 1) {
|
||||||
|
if (nex_ff[scan].ff == ff1)
|
||||||
|
found_flag = true;
|
||||||
|
}
|
||||||
|
if (! found_flag) {
|
||||||
|
delete ff1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete tmp_map;
|
delete tmp_map;
|
||||||
delete tmp_out;
|
delete tmp_out;
|
||||||
|
delete tmp_ff;
|
||||||
|
|
||||||
} while (cur != last_);
|
} while (cur != last_);
|
||||||
|
|
||||||
|
/* Done. The large NetFF is no longer needed, as it has been
|
||||||
|
taken up by the smaller NetFF devices. */
|
||||||
|
delete ff;
|
||||||
|
ff = 0;
|
||||||
|
|
||||||
/* Run through the pin accounting one more time to make sure
|
/* Run through the pin accounting one more time to make sure
|
||||||
the data inputs are all connected. */
|
the data inputs are all connected. */
|
||||||
for (unsigned idx = 0 ; idx < ff->pin_count() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < block_width ; idx += 1) {
|
||||||
NetFF*ff2 = pin_accounting[idx].ff;
|
if (nex_ff[idx].proc == 0)
|
||||||
unsigned pin = pin_accounting[idx].pin;
|
continue;
|
||||||
|
|
||||||
|
NetFF*ff2 = nex_ff[idx].ff;
|
||||||
|
unsigned pin = nex_ff[idx].pin;
|
||||||
/* Skip this output if it is not handled in this block. */
|
/* Skip this output if it is not handled in this block. */
|
||||||
if (ff2 == 0)
|
if (ff2 == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -911,19 +965,12 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
||||||
been set here. */
|
been set here. */
|
||||||
} else if (!ff2->pin_Data(pin).is_linked()) {
|
} else if (!ff2->pin_Data(pin).is_linked()) {
|
||||||
cerr << ff2->get_line() << ": error: "
|
cerr << ff2->get_line() << ": error: "
|
||||||
<< "DFF introduced here is missing Data inputs."
|
<< "DFF introduced here is missing Data "
|
||||||
<< endl;
|
<< pin << " input." << endl;
|
||||||
flag = false;
|
flag = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[]pin_accounting;
|
|
||||||
|
|
||||||
/* Done. The large NetFF is no longer needed, as it has been
|
|
||||||
taken up by the smaller NetFF devices. */
|
|
||||||
delete ff;
|
|
||||||
ff = 0;
|
|
||||||
|
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -933,10 +980,17 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
||||||
* asynchronous set/reset, depending on whether the pin of the
|
* asynchronous set/reset, depending on whether the pin of the
|
||||||
* expression is connected to an event, or not.
|
* expression is connected to an event, or not.
|
||||||
*/
|
*/
|
||||||
bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
bool NetCondit::synth_sync(Design*des, NetScope*scope,
|
||||||
|
struct sync_accounting_cell*nex_ff,
|
||||||
NetNet*nex_map, NetNet*nex_out,
|
NetNet*nex_map, NetNet*nex_out,
|
||||||
const svector<NetEvProbe*>&events_in)
|
const svector<NetEvProbe*>&events_in)
|
||||||
{
|
{
|
||||||
|
for (unsigned idx = 1 ; idx < nex_out->pin_count() ; idx += 1) {
|
||||||
|
assert(nex_ff[0].ff == nex_ff[idx].ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
NetFF*ff = nex_ff[0].ff;
|
||||||
|
|
||||||
/* First try to turn the condition expression into an
|
/* First try to turn the condition expression into an
|
||||||
asynchronous set/reset. If the condition expression has
|
asynchronous set/reset. If the condition expression has
|
||||||
inputs that are included in the sensitivity list, then it
|
inputs that are included in the sensitivity list, then it
|
||||||
|
|
@ -1043,7 +1097,8 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
||||||
events_tmp[count_events++] = events_in[tmp];
|
events_tmp[count_events++] = events_in[tmp];
|
||||||
}
|
}
|
||||||
|
|
||||||
flag = flag && else_->synth_sync(des, scope, ff, nex_map,
|
flag = flag && else_->synth_sync(des, scope,
|
||||||
|
nex_ff, nex_map,
|
||||||
nex_out, events_tmp);
|
nex_out, events_tmp);
|
||||||
|
|
||||||
return flag;
|
return flag;
|
||||||
|
|
@ -1108,8 +1163,9 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
||||||
delete a_set;
|
delete a_set;
|
||||||
|
|
||||||
assert(else_ != 0);
|
assert(else_ != 0);
|
||||||
flag = else_->synth_sync(des, scope, ff, nex_map,
|
flag = else_->synth_sync(des, scope,
|
||||||
nex_out, svector<NetEvProbe*>(0))
|
nex_ff, nex_map, nex_out,
|
||||||
|
svector<NetEvProbe*>(0))
|
||||||
&& flag;
|
&& flag;
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
@ -1173,12 +1229,15 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
||||||
connect(ff->pin_Enable(), ce->pin(0));
|
connect(ff->pin_Enable(), ce->pin(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool flag = if_->synth_sync(des, scope, ff, nex_map, nex_out, events_in);
|
bool flag = if_->synth_sync(des, scope,
|
||||||
|
nex_ff, nex_map, nex_out,
|
||||||
|
events_in);
|
||||||
|
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
bool NetEvWait::synth_sync(Design*des, NetScope*scope,
|
||||||
|
struct sync_accounting_cell*nex_ff,
|
||||||
NetNet*nex_map, NetNet*nex_out,
|
NetNet*nex_map, NetNet*nex_out,
|
||||||
const svector<NetEvProbe*>&events_in)
|
const svector<NetEvProbe*>&events_in)
|
||||||
{
|
{
|
||||||
|
|
@ -1238,12 +1297,13 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetFF*ff = nex_ff[0].ff;
|
||||||
connect(ff->pin_Clock(), pclk->pin(0));
|
connect(ff->pin_Clock(), pclk->pin(0));
|
||||||
if (pclk->edge() == NetEvProbe::NEGEDGE)
|
if (pclk->edge() == NetEvProbe::NEGEDGE)
|
||||||
ff->attribute(perm_string::literal("Clock:LPM_Polarity"), verinum("INVERT"));
|
ff->attribute(perm_string::literal("Clock:LPM_Polarity"), verinum("INVERT"));
|
||||||
|
|
||||||
/* Synthesize the input to the DFF. */
|
/* Synthesize the input to the DFF. */
|
||||||
bool flag = statement_->synth_sync(des, scope, ff,
|
bool flag = statement_->synth_sync(des, scope, nex_ff,
|
||||||
nex_map, nex_out, events);
|
nex_map, nex_out, events);
|
||||||
|
|
||||||
DEBUG_SYNTH2_EXIT("NetEvWait",flag)
|
DEBUG_SYNTH2_EXIT("NetEvWait",flag)
|
||||||
|
|
@ -1252,7 +1312,6 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*&ff,
|
||||||
|
|
||||||
bool NetProcTop::synth_sync(Design*des)
|
bool NetProcTop::synth_sync(Design*des)
|
||||||
{
|
{
|
||||||
DEBUG_SYNTH2_ENTRY("NetProcTop")
|
|
||||||
NexusSet nex_set;
|
NexusSet nex_set;
|
||||||
statement_->nex_output(nex_set);
|
statement_->nex_output(nex_set);
|
||||||
|
|
||||||
|
|
@ -1261,6 +1320,14 @@ bool NetProcTop::synth_sync(Design*des)
|
||||||
des->add_node(ff);
|
des->add_node(ff);
|
||||||
ff->attribute(perm_string::literal("LPM_FFType"), verinum("DFF"));
|
ff->attribute(perm_string::literal("LPM_FFType"), verinum("DFF"));
|
||||||
|
|
||||||
|
struct sync_accounting_cell*nex_ff
|
||||||
|
= new struct sync_accounting_cell[ff->pin_count()];
|
||||||
|
for (unsigned idx = 0 ; idx < ff->pin_count() ; idx += 1) {
|
||||||
|
nex_ff[idx].ff = ff;
|
||||||
|
nex_ff[idx].pin = idx;
|
||||||
|
nex_ff[idx].proc = statement_;
|
||||||
|
}
|
||||||
|
|
||||||
/* The D inputs to the DFF device will receive the output from
|
/* The D inputs to the DFF device will receive the output from
|
||||||
the statements of the process. */
|
the statements of the process. */
|
||||||
NetNet*nex_d = new NetNet(scope(), scope()->local_symbol(),
|
NetNet*nex_d = new NetNet(scope(), scope()->local_symbol(),
|
||||||
|
|
@ -1282,13 +1349,14 @@ bool NetProcTop::synth_sync(Design*des)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Synthesize the input to the DFF. */
|
/* Synthesize the input to the DFF. */
|
||||||
bool flag = statement_->synth_sync(des, scope(), ff,
|
bool flag = statement_->synth_sync(des, scope(),
|
||||||
|
nex_ff,
|
||||||
nex_q, nex_d,
|
nex_q, nex_d,
|
||||||
svector<NetEvProbe*>());
|
svector<NetEvProbe*>());
|
||||||
|
|
||||||
delete nex_q;
|
delete nex_q;
|
||||||
|
delete[]nex_ff;
|
||||||
|
|
||||||
DEBUG_SYNTH2_EXIT("NetProcTop",flag)
|
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1371,6 +1439,9 @@ void synth2(Design*des)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: synth2.cc,v $
|
* $Log: synth2.cc,v $
|
||||||
|
* Revision 1.39.2.16 2006/01/18 01:23:25 steve
|
||||||
|
* Rework l-value handling to allow for more l-value type flexibility.
|
||||||
|
*
|
||||||
* Revision 1.39.2.15 2006/01/01 02:25:07 steve
|
* Revision 1.39.2.15 2006/01/01 02:25:07 steve
|
||||||
* Case statement handles partial outputs.
|
* Case statement handles partial outputs.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue