Finally remove the NetNEvent and NetPEvent classes,

Get synthesis working with the NetEvWait class,
 and get started supporting multiple events in a
 wait in vvm.
This commit is contained in:
steve 2000-04-12 20:02:52 +00:00
parent 59bbc27268
commit 4493e968da
12 changed files with 211 additions and 519 deletions

View File

@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.43 2000/04/04 03:20:15 steve Exp $"
#ident "$Id: Makefile.in,v 1.44 2000/04/12 20:02:52 steve Exp $"
#
#
SHELL = /bin/sh
@ -67,7 +67,7 @@ distclean: clean
rm -f Makefile
TT = t-null.o t-verilog.o t-vvm.o t-xnf.o
FF = nobufz.o nodangle.o propinit.o synth.o xnfio.o xnfsyn.o
FF = nobufz.o nodangle.o propinit.o synth.o xnfio.o
O = main.o cprop.o design_dump.o dup_expr.o elaborate.o elab_expr.o \
elab_net.o elab_pexpr.o elab_scope.o emit.o eval.o eval_tree.o \

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: design_dump.cc,v 1.75 2000/04/12 04:23:57 steve Exp $"
#ident "$Id: design_dump.cc,v 1.76 2000/04/12 20:02:52 steve Exp $"
#endif
/*
@ -370,29 +370,6 @@ void NetUDP_COMB::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetNEvent::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "event: ";
switch (edge_) {
case ANYEDGE:
o << "anyedge ";
break;
case POSEDGE:
o << "posedge ";
break;
case NEGEDGE:
o << "negedge ";
break;
case POSITIVE:
o << "positive ";
break;
}
o << name() << " --> " << event_->name() << endl;
dump_node_pins(o, ind+4);
}
void NetProcTop::dump(ostream&o, unsigned ind) const
{
switch (type_) {
@ -595,47 +572,6 @@ void NetPDelay::dump(ostream&o, unsigned ind) const
}
}
void NetPEvent::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "@(";
if (src_) {
const NetNEvent*cur = src_;
for (cur = src_->next_ ; cur ; cur = cur->next_) {
o << " or ";
cur->dump_proc(o);
}
}
o << ") /* " << name_ << " */";
if (statement_) {
o << endl;
statement_->dump(o, ind+2);
} else {
o << " /* noop */;" << endl;
}
}
void NetNEvent::dump_proc(ostream&o) const
{
switch (edge_) {
case ANYEDGE:
o << "anyedge ";
break;
case POSEDGE:
o << "posedge ";
break;
case NEGEDGE:
o << "negedge ";
break;
case POSITIVE:
o << "positive ";
break;
}
o << name();
}
void NetRepeat::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "repeat (" << *expr_ << ")" << endl;
@ -954,6 +890,12 @@ void Design::dump(ostream&o) const
/*
* $Log: design_dump.cc,v $
* Revision 1.76 2000/04/12 20:02:52 steve
* Finally remove the NetNEvent and NetPEvent classes,
* Get synthesis working with the NetEvWait class,
* and get started supporting multiple events in a
* wait in vvm.
*
* Revision 1.75 2000/04/12 04:23:57 steve
* Named events really should be expressed with PEIdent
* objects in the pform,

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: functor.cc,v 1.13 2000/04/01 21:40:22 steve Exp $"
#ident "$Id: functor.cc,v 1.14 2000/04/12 20:02:53 steve Exp $"
#endif
# include "functor.h"
@ -177,18 +177,24 @@ int NetCondit::match_proc(proc_match_t*that)
return that->condit(this);
}
int proc_match_t::pevent(NetPEvent*)
int NetEvWait::match_proc(proc_match_t*that)
{
return that->event_wait(this);
}
int proc_match_t::event_wait(NetEvWait*)
{
return 0;
}
int NetPEvent::match_proc(proc_match_t*that)
{
return that->pevent(this);
}
/*
* $Log: functor.cc,v $
* Revision 1.14 2000/04/12 20:02:53 steve
* Finally remove the NetNEvent and NetPEvent classes,
* Get synthesis working with the NetEvWait class,
* and get started supporting multiple events in a
* wait in vvm.
*
* Revision 1.13 2000/04/01 21:40:22 steve
* Add support for integer division.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: functor.h,v 1.10 2000/04/01 21:40:22 steve Exp $"
#ident "$Id: functor.h,v 1.11 2000/04/12 20:02:53 steve Exp $"
#endif
/*
@ -67,13 +67,19 @@ struct proc_match_t {
virtual int assign(class NetAssign*);
virtual int assign_mem(class NetAssignMem*);
virtual int condit(class NetCondit*);
virtual int pevent(class NetPEvent*);
virtual int event_wait(class NetEvWait*);
virtual int block(class NetBlock*);
};
/*
* $Log: functor.h,v $
* Revision 1.11 2000/04/12 20:02:53 steve
* Finally remove the NetNEvent and NetPEvent classes,
* Get synthesis working with the NetEvWait class,
* and get started supporting multiple events in a
* wait in vvm.
*
* Revision 1.10 2000/04/01 21:40:22 steve
* Add support for integer division.
*

10
main.cc
View File

@ -19,7 +19,7 @@ const char COPYRIGHT[] =
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: main.cc,v 1.30 2000/03/17 21:50:25 steve Exp $"
#ident "$Id: main.cc,v 1.31 2000/04/12 20:02:53 steve Exp $"
#endif
const char NOTICE[] =
@ -92,7 +92,6 @@ extern void synth(Design*des);
extern void nobufz(Design*des);
extern void nodangle(Design*des);
extern void xnfio(Design*des);
extern void xnfsyn(Design*des);
typedef void (*net_func)(Design*);
static struct net_func_map {
@ -105,7 +104,6 @@ static struct net_func_map {
{ "propinit",&propinit },
{ "synth", &synth },
{ "xnfio", &xnfio },
{ "xnfsyn", &xnfsyn },
{ 0, 0 }
};
@ -307,6 +305,12 @@ int main(int argc, char*argv[])
/*
* $Log: main.cc,v $
* Revision 1.31 2000/04/12 20:02:53 steve
* Finally remove the NetNEvent and NetPEvent classes,
* Get synthesis working with the NetEvWait class,
* and get started supporting multiple events in a
* wait in vvm.
*
* Revision 1.30 2000/03/17 21:50:25 steve
* Switch to control warnings.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: net_event.cc,v 1.3 2000/04/12 04:23:58 steve Exp $"
#ident "$Id: net_event.cc,v 1.4 2000/04/12 20:02:53 steve Exp $"
#endif
# include "netlist.h"
@ -27,6 +27,7 @@ NetEvent::NetEvent(const string&n)
{
scope_ = 0;
snext_ = 0;
probes_ = 0;
}
NetEvent::~NetEvent()
@ -44,6 +45,28 @@ string NetEvent::full_name() const
return scope_->name() + "." + name_;
}
unsigned NetEvent::nprobe() const
{
unsigned cnt = 0;
NetEvProbe*cur = probes_;
while (cur) {
cnt += 1;
cur = cur->enext_;
}
return cnt;
}
NetEvProbe* NetEvent::probe(unsigned idx)
{
NetEvProbe*cur = probes_;
while (cur && idx) {
cur = cur->enext_;
idx -= 1;
}
return cur;
}
NetEvTrig::NetEvTrig(NetEvent*ev)
: event_(ev)
{
@ -66,6 +89,9 @@ NetEvProbe::NetEvProbe(const string&n, NetEvent*tgt,
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name("P", idx);
}
enext_ = event_->probes_;
event_->probes_ = this;
}
NetEvProbe::~NetEvProbe()
@ -124,8 +150,25 @@ const NetEvent* NetEvWait::event(unsigned idx) const
return events_[idx];
}
NetEvent* NetEvWait::event(unsigned idx)
{
assert(idx < nevents_);
return events_[idx];
}
NetProc* NetEvWait::statement()
{
return statement_;
}
/*
* $Log: net_event.cc,v $
* Revision 1.4 2000/04/12 20:02:53 steve
* Finally remove the NetNEvent and NetPEvent classes,
* Get synthesis working with the NetEvWait class,
* and get started supporting multiple events in a
* wait in vvm.
*
* Revision 1.3 2000/04/12 04:23:58 steve
* Named events really should be expressed with PEIdent
* objects in the pform,

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: netlist.cc,v 1.112 2000/04/04 03:20:15 steve Exp $"
#ident "$Id: netlist.cc,v 1.113 2000/04/12 20:02:53 steve Exp $"
#endif
# include <cassert>
@ -1461,7 +1461,7 @@ NetAssign_::~NetAssign_()
void NetAssign_::set_rval(NetExpr*r)
{
assert(rval_ == 0);
if (rval_) delete rval_;
rval_ = r;
}
@ -1755,90 +1755,6 @@ const NetNet* NetFuncDef::port(unsigned idx) const
return ports_[idx];
}
NetNEvent::NetNEvent(const string&ev, unsigned wid, Type e, NetPEvent*pe)
: NetNode(ev, wid), edge_(e)
{
event_ = pe;
next_ = pe->src_;
pe->src_ = this;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
pin(idx).set_name("P", idx);
}
}
NetNEvent::~NetNEvent()
{
}
NetNEvent::Type NetNEvent::type() const
{
return edge_;
}
const NetPEvent* NetNEvent::pevent() const
{
return event_;
}
NetPEvent::NetPEvent(const string&n, NetProc*st)
: name_(n), statement_(st), src_(0)
{
idx_ = 0;
}
NetPEvent::~NetPEvent()
{
while (src_) {
NetNEvent*cur = src_;
src_ = src_->next_;
delete cur;
}
delete statement_;
}
string NetPEvent::name() const
{
return name_;
}
NetProc* NetPEvent::statement()
{
return statement_;
}
const NetProc* NetPEvent::statement() const
{
return statement_;
}
NetNEvent* NetPEvent::first()
{
idx_ = src_;
return idx_;
}
NetNEvent* NetPEvent::next()
{
assert(idx_);
idx_ = idx_->next_;
return idx_;
}
const NetNEvent* NetPEvent::first() const
{
idx_ = src_;
return idx_;
}
const NetNEvent* NetPEvent::next() const
{
assert(idx_);
idx_ = idx_->next_;
return idx_;
}
NetSTask::NetSTask(const string&na, const svector<NetExpr*>&pa)
: name_(na), parms_(pa)
{
@ -2530,6 +2446,12 @@ bool NetUDP::sequ_glob_(string input, char output)
/*
* $Log: netlist.cc,v $
* Revision 1.113 2000/04/12 20:02:53 steve
* Finally remove the NetNEvent and NetPEvent classes,
* Get synthesis working with the NetEvWait class,
* and get started supporting multiple events in a
* wait in vvm.
*
* Revision 1.112 2000/04/04 03:20:15 steve
* Simulate named event trigger and waits.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: netlist.h,v 1.120 2000/04/12 04:23:58 steve Exp $"
#ident "$Id: netlist.h,v 1.121 2000/04/12 20:02:53 steve Exp $"
#endif
/*
@ -1044,11 +1044,12 @@ class NetAssign_ : public NetProc, public NetNode {
// the pin that gets the value.
const NetExpr*bmux() const;
void set_rval(NetExpr*);
protected:
NetAssign_(const string&n, unsigned w);
virtual ~NetAssign_() =0;
void set_rval(NetExpr*);
void set_bmux(NetExpr*);
private:
@ -1271,6 +1272,7 @@ class NetCondit : public NetProc {
class NetEvent : public LineInfo {
friend class NetScope;
friend class NetEvProbe;
public:
explicit NetEvent (const string&n);
@ -1279,6 +1281,10 @@ class NetEvent : public LineInfo {
string name() const;
string full_name() const;
// Get information about probes connected to me.
unsigned nprobe() const;
NetEvProbe* probe(unsigned);
NetScope* scope();
const NetScope* scope() const;
@ -1289,6 +1295,9 @@ class NetEvent : public LineInfo {
NetScope*scope_;
NetEvent*snext_;
// Use these methods to list the probes attached to me.
NetEvProbe*probes_;
private: // not implemented
NetEvent(const NetEvent&);
NetEvent& operator= (const NetEvent&);
@ -1319,9 +1328,13 @@ class NetEvWait : public NetProc {
unsigned nevents() const;
const NetEvent*event(unsigned) const;
NetEvent*event(unsigned);
NetProc*statement();
virtual bool emit_proc(ostream&, struct target_t*) const;
bool emit_recurse(ostream&, struct target_t*) const;
virtual int match_proc(struct proc_match_t*);
virtual void dump(ostream&, unsigned ind) const;
private:
@ -1333,6 +1346,8 @@ class NetEvWait : public NetProc {
class NetEvProbe : public NetNode {
friend class NetEvent;
public:
enum edge_t { ANYEDGE, POSEDGE, NEGEDGE };
@ -1349,6 +1364,8 @@ class NetEvProbe : public NetNode {
private:
NetEvent*event_;
edge_t edge_;
// The NetEvent class uses this to list me.
NetEvProbe*enext_;
};
/*
@ -1417,78 +1434,6 @@ class NetPDelay : public NetProc {
NetProc*statement_;
};
/*
* The NetPEvent is associated with NetNEvents. The NetPEvent receives
* events from any one of the associated NetNEvents and in response
* causes the attached statement to be executed. Objects of this type
* are not nodes, but require a name anyhow so that backends can
* generate objects to refer to it.
*
* The NetPEvent is the procedural part of the event.
*/
class NetPEvent : public NetProc {
friend class NetNEvent;
public:
NetPEvent(const string&n, NetProc*st);
~NetPEvent();
string name() const;
NetProc* statement();
const NetProc* statement() const;
NetNEvent* first();
NetNEvent* next();
const NetNEvent* first() const;
const NetNEvent* next() const;
virtual int match_proc(struct proc_match_t*);
virtual void dump(ostream&, unsigned ind) const;
private:
string name_;
NetProc*statement_;
// This is a list of the source events that can trigger me.
NetNEvent*src_;
mutable NetNEvent*idx_;
};
/*
* The NetNEvent is a NetNode that connects to the structural part of
* the design. It has only inputs, which cause the side effect of
* triggering an event that the procedural part of the design can use.
*
* The NetNEvent may have wide input if is is an ANYEDGE type
* device. This allows detecting changes in wide expressions.
*/
class NetNEvent : public NetNode {
friend class NetPEvent;
public:
enum Type { ANYEDGE, POSEDGE, NEGEDGE, POSITIVE };
// Use this constructor to create NEvent objects that receive
// their status from the structural netlist.
NetNEvent(const string&ev, unsigned wid, Type e, NetPEvent*pe);
~NetNEvent();
Type type() const;
const NetPEvent*pevent() const;
void dump_proc(ostream&) const;
virtual void dump_node(ostream&, unsigned ind) const;
private:
Type edge_;
NetPEvent*event_;
NetNEvent*next_;
};
/*
* A repeat statement is executed some fixed number of times.
*/
@ -2399,6 +2344,12 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.121 2000/04/12 20:02:53 steve
* Finally remove the NetNEvent and NetPEvent classes,
* Get synthesis working with the NetEvWait class,
* and get started supporting multiple events in a
* wait in vvm.
*
* Revision 1.120 2000/04/12 04:23:58 steve
* Named events really should be expressed with PEIdent
* objects in the pform,

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: pform_dump.cc,v 1.53 2000/04/12 04:23:58 steve Exp $"
#ident "$Id: pform_dump.cc,v 1.54 2000/04/12 20:02:53 steve Exp $"
#endif
/*
@ -82,15 +82,15 @@ void PECallFunction::dump(ostream &out) const
void PEEvent::dump(ostream&out) const
{
switch (type_) {
case NetNEvent::ANYEDGE:
case PEEvent::ANYEDGE:
break;
case NetNEvent::POSEDGE:
case PEEvent::POSEDGE:
out << "posedge ";
break;
case NetNEvent::NEGEDGE:
case PEEvent::NEGEDGE:
out << "negedge ";
break;
case NetNEvent::POSITIVE:
case PEEvent::POSITIVE:
out << "positive ";
break;
}
@ -733,6 +733,12 @@ void PUdp::dump(ostream&out) const
/*
* $Log: pform_dump.cc,v $
* Revision 1.54 2000/04/12 20:02:53 steve
* Finally remove the NetNEvent and NetPEvent classes,
* Get synthesis working with the NetEvWait class,
* and get started supporting multiple events in a
* wait in vvm.
*
* Revision 1.53 2000/04/12 04:23:58 steve
* Named events really should be expressed with PEIdent
* objects in the pform,

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: synth.cc,v 1.7 2000/04/02 04:26:07 steve Exp $"
#ident "$Id: synth.cc,v 1.8 2000/04/12 20:02:53 steve Exp $"
#endif
/*
@ -30,6 +30,55 @@
# include "functor.h"
# include "netlist.h"
/*
* This functor scans the behavioral code, looking for expressions to
* synthesize. Although it uses the proc_match_t class, it doesn't
* actually match anything, but transforms expressions into structural
* netlists. The product of this should be a process where all the
* expressions have been reduced to a signal ident, which references
* the NetNet of the now synthesized expression.
*/
class do_expr : public proc_match_t {
public:
do_expr(Design*d)
: des_(d) { }
private:
Design*des_;
virtual int assign(NetAssign*);
virtual int event_wait(NetEvWait*);
//virtual int assign_mem(NetAssignMem*);
//virtual int condit(NetCondit*);
};
int do_expr::assign(NetAssign*stmt)
{
if (dynamic_cast<NetESignal*>(stmt->rval()))
return 0;
NetNet*tmp = stmt->rval()->synthesize(des_);
if (tmp == 0)
return 0;
NetESignal*tmpe = new NetESignal(tmp);
stmt->set_rval(tmpe);
return 0;
}
int do_expr::event_wait(NetEvWait*stmt)
{
NetProc*tmp = stmt->statement();
if (tmp)
return tmp->match_proc(this);
else
return 0;
}
/*
* This transform recognizes the following patterns:
*
@ -55,7 +104,7 @@ class match_dff : public proc_match_t {
public:
match_dff(Design*d, NetProcTop*t)
: des_(d), top_(t), pclk_(0), nclk_(0), con_(0), ce_(0),
: des_(d), top_(t), wclk_(0), eclk_(0), pclk_(0), con_(0), ce_(0),
asn_(0), asm_(0), d_(0)
{ }
@ -70,12 +119,14 @@ class match_dff : public proc_match_t {
virtual int assign(NetAssign*);
virtual int assign_mem(NetAssignMem*);
virtual int condit(NetCondit*);
virtual int pevent(NetPEvent*);
virtual int event_wait(NetEvWait*);
Design*des_;
NetProcTop*top_;
NetPEvent*pclk_;
NetNEvent*nclk_;
NetEvWait*wclk_;
NetEvent *eclk_;
NetEvProbe*pclk_;
NetCondit *con_;
NetNet*ce_;
@ -133,21 +184,20 @@ int match_dff::condit(NetCondit*co)
return con_->if_clause()->match_proc(this);
}
int match_dff::pevent(NetPEvent*pe)
int match_dff::event_wait(NetEvWait*evw)
{
if (pclk_ || con_ || asn_ || asm_)
if (evw->nevents() != 1)
return 0;
pclk_ = pe;
wclk_ = evw;
eclk_ = evw->event(0);
NetNEvent*tmp = pclk_->first();
if (tmp == 0)
return 0;
if (pclk_->next())
if (eclk_->nprobe() != 1)
return 0;
nclk_ = tmp;
return pclk_->statement()->match_proc(this);
pclk_ = eclk_->probe(0);
return wclk_->statement()->match_proc(this);
}
void match_dff::make_it()
@ -170,11 +220,11 @@ void match_dff::make_dff_()
connect(ff->pin_Q(idx), asn_->pin(idx));
}
connect(ff->pin_Clock(), nclk_->pin(0));
connect(ff->pin_Clock(), pclk_->pin(0));
if (ce_) connect(ff->pin_Enable(), ce_->pin(0));
ff->attribute("LPM_FFType", "DFF");
if (nclk_->type() == NetNEvent::NEGEDGE)
if (pclk_->edge() == NetEvProbe::NEGEDGE)
ff->attribute("Clock:LPM_Polarity", "INVERT");
des_->add_node(ff);
@ -195,8 +245,8 @@ void match_dff::make_ram_()
if (ce_)
connect(ram->pin_WE(), ce_->pin(0));
assert(nclk_->type() == NetNEvent::POSEDGE);
connect(ram->pin_InClock(), nclk_->pin(0));
assert(pclk_->edge() == NetEvProbe::POSEDGE);
connect(ram->pin_InClock(), pclk_->pin(0));
ram->absorb_partners();
des_->add_node(ram);
@ -248,6 +298,9 @@ void synth_f::process(class Design*des, class NetProcTop*top)
*/
void synth_f::proc_always_(class Design*des)
{
do_expr expr_pat(des);
top_->statement()->match_proc(&expr_pat);
match_dff dff_pat(des, top_);
if (top_->statement()->match_proc(&dff_pat)) {
dff_pat.make_it();
@ -270,6 +323,12 @@ void synth(Design*des)
/*
* $Log: synth.cc,v $
* Revision 1.8 2000/04/12 20:02:53 steve
* Finally remove the NetNEvent and NetPEvent classes,
* Get synthesis working with the NetEvWait class,
* and get started supporting multiple events in a
* wait in vvm.
*
* Revision 1.7 2000/04/02 04:26:07 steve
* Remove the useless sref template.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: t-vvm.cc,v 1.133 2000/04/12 04:23:58 steve Exp $"
#ident "$Id: t-vvm.cc,v 1.134 2000/04/12 20:02:53 steve Exp $"
#endif
# include <iostream>
@ -1760,14 +1760,14 @@ void target_vvm::net_probe(ostream&os, const NetEvProbe*net)
<< "(&" << mevent << ");" << endl;
break;
case NetNEvent::NEGEDGE:
case NetEvProbe::NEGEDGE:
assert(net->pin_count() == 1);
os << "static vvm_negedge " << mname
<< "(&" << mevent << ");" << endl;
break;
case NetNEvent::ANYEDGE:
case NetEvProbe::ANYEDGE:
os << "static vvm_anyedge " << mname
<< "(&" << mevent << ", " << net->pin_count() << ");" << endl;
break;
@ -2509,6 +2509,12 @@ extern const struct target tgt_vvm = {
};
/*
* $Log: t-vvm.cc,v $
* Revision 1.134 2000/04/12 20:02:53 steve
* Finally remove the NetNEvent and NetPEvent classes,
* Get synthesis working with the NetEvWait class,
* and get started supporting multiple events in a
* wait in vvm.
*
* Revision 1.133 2000/04/12 04:23:58 steve
* Named events really should be expressed with PEIdent
* objects in the pform,

253
xnfsyn.cc
View File

@ -1,253 +0,0 @@
/*
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: xnfsyn.cc,v 1.5 2000/04/02 04:26:07 steve Exp $"
#endif
/*
* The xnfsyn function searches the behavioral description for
* patterns that are known to represent XNF library components. This
* is especially interesting for the sequential components such as
* flip flops and latches. As threads are transformed into components,
* the design is rewritten.
*
* Currently, this transform recognizes the following patterns:
*
* always @(posedge CLK) Q = D // DFF:D,Q,C
* always @(negedge CLK) Q = D // DFF:D,Q,~C
*
* always @(posedge CLK) if (CE) Q = D;
* always @(negedge CLK) if (CE) Q = D;
*
* The r-value of the assignments must be identifiers (i.e. wires or
* registers) and the CE must be single-bine identifiers. Enough
* devices will be created to accommodate the width of Q and D, though
* the CLK and CE will be shared by all the devices.
*/
# include "functor.h"
# include "netlist.h"
class xnfsyn_f : public functor_t {
public:
void process(class Design*, class NetProcTop*);
private:
void proc_always_(class Design*);
void proc_casn_(class Design*);
void proc_ccon_(class Design*);
// The matcher does something like a recursive descent search
// for the templates. These variables are filled in as the
// searcher finds them.
class NetProcTop*top_;
class NetPEvent *pclk_;
class NetNEvent *nclk_;
class NetCondit *con_;
class NetAssign *asn_;
};
/*
* Look at a process, and divide the problem into always and initial
* threads.
*/
void xnfsyn_f::process(class Design*des, class NetProcTop*top)
{
switch (top->type()) {
case NetProcTop::KALWAYS:
top_ = top;
proc_always_(des);
break;
}
}
/*
* An "always ..." statement has been found.
*/
void xnfsyn_f::proc_always_(class Design*des)
{
// The statement must be a NetPEvent, ...
pclk_ = dynamic_cast<class NetPEvent*>(top_->statement());
if (pclk_ == 0)
return;
NetNEvent*tmp = pclk_->first();
if (tmp == 0)
return;
if (pclk_->next())
return;
nclk_ = tmp;
// ... the event must be an edge, ...
switch (nclk_->type()) {
case NetNEvent::POSEDGE:
case NetNEvent::NEGEDGE:
break;
default:
return;
}
// Is this a clocked assignment?
asn_ = dynamic_cast<NetAssign*>(pclk_->statement());
if (asn_) {
proc_casn_(des);
return;
}
con_ = dynamic_cast<NetCondit*>(pclk_->statement());
if (con_) {
proc_ccon_(des);
return;
}
}
/*
* The process so far has been matched as:
*
* always @(posedge nclk_) asn_ = <r>;
* always @(negedge nclk_) asn_ = <r>;
*/
void xnfsyn_f::proc_casn_(class Design*des)
{
// ... and the rval must be a simple signal.
NetESignal*sig = dynamic_cast<NetESignal*>(asn_->rval());
if (sig == 0) {
cerr << "Noted complex rval in DFF, name " << asn_->name() <<
", not yet implemented" << endl;
return ;
}
// The signal and the assignment must be the same width...
assert(asn_->pin_count() == sig->pin_count());
// Generate enough DFF objects to handle the entire width.
for (unsigned idx = 0 ; idx < asn_->pin_count() ; idx += 1) {
// XXXX FIXME: Objects need unique names!
NetUDP*dff = new NetUDP(asn_->name(), 3, true);
connect(dff->pin(0), asn_->pin(idx));
connect(dff->pin(1), sig->pin(idx));
connect(dff->pin(2), nclk_->pin(0));
switch (nclk_->type()) {
case NetNEvent::POSEDGE:
dff->attribute("XNF-LCA", "DFF:Q,D,C");
break;
case NetNEvent::NEGEDGE:
dff->attribute("XNF-LCA", "DFF:Q,D,~C");
break;
}
des->add_node(dff);
}
// This process is matched and replaced with a DFF. Get
// rid of the now useless NetProcTop.
des->delete_process(top_);
}
/*
* The process so far has been matched as:
*
* always @(posedge nclk_) if ...;
* always @(negedge nclk_) if ...;
*/
void xnfsyn_f::proc_ccon_(class Design*des)
{
if (con_->else_clause())
return;
asn_ = dynamic_cast<NetAssign*>(con_->if_clause());
if (asn_ == 0)
return;
NetESignal*sig = dynamic_cast<NetESignal*>(asn_->rval());
if (sig == 0)
return;
// The signal and the assignment must be the same width...
assert(asn_->pin_count() == sig->pin_count());
NetESignal*ce = dynamic_cast<NetESignal*>(con_->expr());
if (ce == 0)
return;
if (ce->pin_count() != 1)
return;
// Generate enough DFF objects to handle the entire width.
for (unsigned idx = 0 ; idx < asn_->pin_count() ; idx += 1) {
// XXXX FIXME: Objects need unique names!
NetUDP*dff = new NetUDP(asn_->name(), 4, true);
connect(dff->pin(0), asn_->pin(idx));
connect(dff->pin(1), sig->pin(idx));
connect(dff->pin(2), nclk_->pin(0));
connect(dff->pin(3), ce->pin(0));
switch (nclk_->type()) {
case NetNEvent::POSEDGE:
dff->attribute("XNF-LCA", "DFF:Q,D,C,CE");
break;
case NetNEvent::NEGEDGE:
dff->attribute("XNF-LCA", "DFF:Q,D,~C,CE");
break;
}
des->add_node(dff);
}
// This process is matched and replaced with a DFF. Get
// rid of the now useless NetProcTop.
des->delete_process(top_);
}
void xnfsyn(Design*des)
{
xnfsyn_f xnfsyn_obj;
des->functor(&xnfsyn_obj);
}
/*
* $Log: xnfsyn.cc,v $
* Revision 1.5 2000/04/02 04:26:07 steve
* Remove the useless sref template.
*
* Revision 1.4 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.3 1999/08/18 04:00:02 steve
* Fixup spelling and some error messages. <LRDoolittle@lbl.gov>
*
* Revision 1.2 1999/07/18 21:17:51 steve
* Add support for CE input to XNF DFF, and do
* complete cleanup of replaced design nodes.
*
* Revision 1.1 1999/07/18 05:52:47 steve
* xnfsyn generates DFF objects for XNF output, and
* properly rewrites the Design netlist in the process.
*
*/