diff --git a/PExpr.cc b/PExpr.cc index 34eea00ea..3aa9bd86b 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -17,13 +17,17 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: PExpr.cc,v 1.15 2000/04/01 19:31:57 steve Exp $" +#ident "$Id: PExpr.cc,v 1.16 2000/04/12 04:23:57 steve Exp $" #endif # include "PExpr.h" # include "Module.h" # include +PExpr::PExpr() +{ +} + PExpr::~PExpr() { } @@ -69,6 +73,11 @@ PECallFunction::~PECallFunction() { } +PEConcat::PEConcat(const svector&p, PExpr*r) +: parms_(p), repeat_(r) +{ +} + bool PEConcat::is_constant(Module *mod) const { bool constant = repeat_? repeat_->is_constant(mod) : true; @@ -83,21 +92,16 @@ PEConcat::~PEConcat() delete repeat_; } -PEEvent::PEEvent(NetNEvent::Type t, PExpr*e) +PEEvent::PEEvent(PEEvent::edge_t t, PExpr*e) : type_(t), expr_(e) { } -PEEvent::PEEvent(const string&n) -: name_(n) -{ -} - PEEvent::~PEEvent() { } -NetNEvent::Type PEEvent::type() const +PEEvent::edge_t PEEvent::type() const { return type_; } @@ -107,9 +111,18 @@ PExpr* PEEvent::expr() const return expr_; } -string PEEvent::name() const +PEIdent::PEIdent(const string&s) +: text_(s), msb_(0), lsb_(0), idx_(0) { - return name_; +} + +PEIdent::~PEIdent() +{ +} + +string PEIdent::name() const +{ + return text_; } /* @@ -129,6 +142,22 @@ bool PEIdent::is_constant(Module*mod) const return false; } +PENumber::PENumber(verinum*vp) +: value_(vp) +{ + assert(vp); +} + +PENumber::~PENumber() +{ + delete value_; +} + +const verinum& PENumber::value() const +{ + return *value_; +} + bool PENumber::is_the_same(const PExpr*that) const { const PENumber*obj = dynamic_cast(that); @@ -143,6 +172,20 @@ bool PENumber::is_constant(Module*) const return true; } +PEString::PEString(const string&s) +: text_(s) +{ +} + +PEString::~PEString() +{ +} + +string PEString::value() const +{ + return text_; +} + bool PEString::is_constant(Module*) const { return true; @@ -164,6 +207,19 @@ bool PETernary::is_constant(Module*) const /* * $Log: PExpr.cc,v $ + * Revision 1.16 2000/04/12 04:23:57 steve + * Named events really should be expressed with PEIdent + * objects in the pform, + * + * Handle named events within the mix of net events + * and edges. As a unified lot they get caught together. + * wait statements are broken into more complex statements + * that include a conditional. + * + * Do not generate NetPEvent or NetNEvent objects in + * elaboration. NetEvent, NetEvWait and NetEvProbe + * take over those functions in the netlist. + * * Revision 1.15 2000/04/01 19:31:57 steve * Named events as far as the pform. * diff --git a/PExpr.h b/PExpr.h index 2d693876d..06fc51dff 100644 --- a/PExpr.h +++ b/PExpr.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: PExpr.h,v 1.34 2000/04/01 21:40:22 steve Exp $" +#ident "$Id: PExpr.h,v 1.35 2000/04/12 04:23:57 steve Exp $" #endif # include @@ -44,7 +44,9 @@ class NetScope; */ class PExpr : public LineInfo { + public: + PExpr(); virtual ~PExpr(); virtual void dump(ostream&) const; @@ -86,6 +88,9 @@ class PExpr : public LineInfo { // of expresions. virtual bool is_constant(Module*) const; + private: // not implemented + PExpr(const PExpr&); + PExpr& operator= (const PExpr&); }; ostream& operator << (ostream&, const PExpr&); @@ -93,8 +98,7 @@ ostream& operator << (ostream&, const PExpr&); class PEConcat : public PExpr { public: - PEConcat(const svector&p, PExpr*r =0) - : parms_(p), repeat_(r) { } + PEConcat(const svector&p, PExpr*r =0); ~PEConcat(); virtual void dump(ostream&) const; @@ -122,30 +126,28 @@ class PEConcat : public PExpr { class PEEvent : public PExpr { public: + enum edge_t {ANYEDGE, POSEDGE, NEGEDGE, POSITIVE}; + // Use this constructor to create events based on edges or levels. - PEEvent(NetNEvent::Type t, PExpr*e); - // Use this to create named events. - PEEvent(const string&n); + PEEvent(edge_t t, PExpr*e); ~PEEvent(); - NetNEvent::Type type() const; - PExpr* expr() const; - string name() const; + edge_t type() const; + PExpr* expr() const; virtual void dump(ostream&) const; private: - NetNEvent::Type type_; - PExpr*expr_; - string name_; + edge_t type_; + PExpr *expr_; }; class PEIdent : public PExpr { public: - explicit PEIdent(const string&s) - : text_(s), msb_(0), lsb_(0), idx_(0) { } + explicit PEIdent(const string&s); + ~PEIdent(); virtual void dump(ostream&) const; @@ -165,8 +167,7 @@ class PEIdent : public PExpr { virtual bool is_constant(Module*) const; verinum* eval_const(const Design*des, const string&path) const; - // XXXX - string name() const { return text_; } + string name() const; private: string text_; @@ -190,11 +191,10 @@ class PEIdent : public PExpr { class PENumber : public PExpr { public: - explicit PENumber(verinum*vp) - : value_(vp) { assert(vp); } - ~PENumber() { delete value_; } + explicit PENumber(verinum*vp); + ~PENumber(); - const verinum& value() const { return *value_; } + const verinum& value() const; virtual void dump(ostream&) const; virtual NetNet* elaborate_net(Design*des, const string&path, @@ -216,10 +216,10 @@ class PENumber : public PExpr { class PEString : public PExpr { public: - explicit PEString(const string&s) - : text_(s) { } + explicit PEString(const string&s); + ~PEString(); - string value() const { return text_; } + string value() const; virtual void dump(ostream&) const; virtual NetEConst*elaborate_expr(Design*des, NetScope*) const; @@ -358,6 +358,19 @@ class PECallFunction : public PExpr { /* * $Log: PExpr.h,v $ + * Revision 1.35 2000/04/12 04:23:57 steve + * Named events really should be expressed with PEIdent + * objects in the pform, + * + * Handle named events within the mix of net events + * and edges. As a unified lot they get caught together. + * wait statements are broken into more complex statements + * that include a conditional. + * + * Do not generate NetPEvent or NetNEvent objects in + * elaboration. NetEvent, NetEvWait and NetEvProbe + * take over those functions in the netlist. + * * Revision 1.34 2000/04/01 21:40:22 steve * Add support for integer division. * diff --git a/Statement.cc b/Statement.cc index d4ae77d4d..60de14180 100644 --- a/Statement.cc +++ b/Statement.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: Statement.cc,v 1.18 2000/04/01 19:31:57 steve Exp $" +#ident "$Id: Statement.cc,v 1.19 2000/04/12 04:23:57 steve Exp $" #endif # include "Statement.h" @@ -122,6 +122,11 @@ PCase::~PCase() delete[]items_; } +PCondit::PCondit(PExpr*ex, Statement*i, Statement*e) +: expr_(ex), if_(i), else_(e) +{ +} + PCondit::~PCondit() { delete expr_; @@ -129,6 +134,17 @@ PCondit::~PCondit() delete else_; } + +PDelayStatement::PDelayStatement(PExpr*d, Statement*st) +: delay_(d), statement_(st) +{ +} + +PDelayStatement::~PDelayStatement() +{ +} + + PEventStatement::PEventStatement(const svector&ee) : expr_(ee), statement_(0) { @@ -146,6 +162,11 @@ PEventStatement::~PEventStatement() // delete the events and the statement? } +void PEventStatement::set_statement(Statement*st) +{ + statement_ = st; +} + PForever::PForever(Statement*s) : statement_(s) { @@ -189,6 +210,19 @@ PWhile::~PWhile() /* * $Log: Statement.cc,v $ + * Revision 1.19 2000/04/12 04:23:57 steve + * Named events really should be expressed with PEIdent + * objects in the pform, + * + * Handle named events within the mix of net events + * and edges. As a unified lot they get caught together. + * wait statements are broken into more complex statements + * that include a conditional. + * + * Do not generate NetPEvent or NetNEvent objects in + * elaboration. NetEvent, NetEvWait and NetEvProbe + * take over those functions in the netlist. + * * Revision 1.18 2000/04/01 19:31:57 steve * Named events as far as the pform. * diff --git a/Statement.h b/Statement.h index 419618503..36ca71e39 100644 --- a/Statement.h +++ b/Statement.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: Statement.h,v 1.23 2000/04/01 19:31:57 steve Exp $" +#ident "$Id: Statement.h,v 1.24 2000/04/12 04:23:57 steve Exp $" #endif # include @@ -225,8 +225,7 @@ class PCase : public Statement { class PCondit : public Statement { public: - PCondit(PExpr*ex, Statement*i, Statement*e) - : expr_(ex), if_(i), else_(e) { } + PCondit(PExpr*ex, Statement*i, Statement*e); ~PCondit(); virtual NetProc* elaborate(Design*des, const string&path) const; @@ -246,8 +245,8 @@ class PCondit : public Statement { class PDelayStatement : public Statement { public: - PDelayStatement(PExpr*d, Statement*st) - : delay_(d), statement_(st) { } + PDelayStatement(PExpr*d, Statement*st); + ~PDelayStatement(); virtual void dump(ostream&out, unsigned ind) const; virtual NetProc* elaborate(Design*des, const string&path) const; @@ -274,7 +273,7 @@ class PEventStatement : public Statement { ~PEventStatement(); - void set_statement(Statement*st) { statement_ = st; } + void set_statement(Statement*st); virtual void dump(ostream&out, unsigned ind) const; virtual NetProc* elaborate(Design*des, const string&path) const; @@ -382,6 +381,19 @@ class PWhile : public Statement { /* * $Log: Statement.h,v $ + * Revision 1.24 2000/04/12 04:23:57 steve + * Named events really should be expressed with PEIdent + * objects in the pform, + * + * Handle named events within the mix of net events + * and edges. As a unified lot they get caught together. + * wait statements are broken into more complex statements + * that include a conditional. + * + * Do not generate NetPEvent or NetNEvent objects in + * elaboration. NetEvent, NetEvWait and NetEvProbe + * take over those functions in the netlist. + * * Revision 1.23 2000/04/01 19:31:57 steve * Named events as far as the pform. * diff --git a/design_dump.cc b/design_dump.cc index 2a2d16583..836880d11 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -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.74 2000/04/10 05:26:05 steve Exp $" +#ident "$Id: design_dump.cc,v 1.75 2000/04/12 04:23:57 steve Exp $" #endif /* @@ -555,8 +555,14 @@ void NetEvTrig::dump(ostream&o, unsigned ind) const void NetEvWait::dump(ostream&o, unsigned ind) const { - o << setw(ind) << "" << "@" << event_->name() - << " // " << get_line() << endl; + assert(nevents() > 0); + o << setw(ind) <<"" << "@(" << event(0)->name(); + + for (unsigned idx = 1 ; idx < nevents() ; idx += 1) + o << " or " << event(idx)->name(); + + o << ") // " << get_line() << endl; + if (statement_) statement_->dump(o, ind+2); else @@ -948,6 +954,19 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.75 2000/04/12 04:23:57 steve + * Named events really should be expressed with PEIdent + * objects in the pform, + * + * Handle named events within the mix of net events + * and edges. As a unified lot they get caught together. + * wait statements are broken into more complex statements + * that include a conditional. + * + * Do not generate NetPEvent or NetNEvent objects in + * elaboration. NetEvent, NetEvWait and NetEvProbe + * take over those functions in the netlist. + * * Revision 1.74 2000/04/10 05:26:05 steve * All events now use the NetEvent class. * diff --git a/elaborate.cc b/elaborate.cc index 0f26158dc..d70dee178 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: elaborate.cc,v 1.157 2000/04/10 05:26:06 steve Exp $" +#ident "$Id: elaborate.cc,v 1.158 2000/04/12 04:23:58 steve Exp $" #endif /* @@ -1541,12 +1541,66 @@ NetProc* PDelayStatement::elaborate(Design*des, const string&path) const * * NetEvWait ---/---> NetEvent <----\---- NetEvProbe * ... | | ... - * NetEvWait ---+ +-----NetEvProbe + * NetEvWait ---+ +---- NetEvProbe + * | ... + * +---- NetEvTrig * * That is, many NetEvWait statements may wait on a single NetEvent * object, and Many NetEvProbe objects may trigger the NetEvent - * object. + * object. The many NetEvWait objects pointing to the NetEvent object + * reflects the possibility of different places in the code blocking + * on the same named event, like so: + * + * event foo; + * [...] + * always begin @foo ; @foo end + * + * This tends to not happen with signal edges. The multiple probes + * pointing to the same event reflect the possibility of many + * expressions in the same blocking statement, like so: + * + * wire reset, clk; + * [...] + * always @(reset or posedge clk) ; + * + * Conjunctions like this cause a NetEvent object be created to + * represent the overall conjuction, and NetEvProbe objects for each + * event expression. + * + * If the NetEvent object represents a named event from the source, + * then there are NetEvTrig objects that represent the trigger + * statements instead of the NetEvProbe objects representing signals. + * For example: + * + * event foo; + * always @foo ; + * initial begin + * [...] + * -> foo; + * [...] + * -> foo; + * [...] + * end + * + * Each trigger statement in the source generates a separate NetEvTrig + * object in the netlist. Those trigger objects are elaborated + * elsewhere. + * + * Additional complications arise when named events show up in + * conjunctions. An example of such a case is: + * + * event foo; + * wire bar; + * always @(foo or posedge bar) ; + * + * Since there is by definition a NetEvent object for the foo object, + * this is handled by allowing the NetEvWait object to point to + * multiple NetEvent objects. All the NetEvProbe based objects are + * collected and pointed as the synthetic NetEvent object, and all the + * named events are added into the list of NetEvent object that the + * NetEvWait object can refer to. */ + NetProc* PEventStatement::elaborate_st(Design*des, const string&path, NetProc*enet) const { @@ -1573,10 +1627,11 @@ NetProc* PEventStatement::elaborate_st(Design*des, const string&path, | +---> - This is quite a mouthful */ + This is quite a mouthful. Should I not move wait handling + to specialized objects? */ - if ((expr_.count() == 1) && (expr_[0]->type() == NetNEvent::POSITIVE)) { + if ((expr_.count() == 1) && (expr_[0]->type() == PEEvent::POSITIVE)) { NetBlock*bl = new NetBlock(NetBlock::SEQU); @@ -1592,7 +1647,8 @@ NetProc* PEventStatement::elaborate_st(Design*des, const string&path, NetEvent*ev = new NetEvent(scope->local_symbol()); scope->add_event(ev); - NetEvWait*we = new NetEvWait(ev, 0); + NetEvWait*we = new NetEvWait(0); + we->add_event(ev); NetEvProbe*po = new NetEvProbe(path+"."+scope->local_symbol(), ev, NetEvProbe::POSEDGE, 1); @@ -1604,34 +1660,26 @@ NetProc* PEventStatement::elaborate_st(Design*des, const string&path, NetCondit*co = new NetCondit(new NetEUnary('!', ce), we, 0); bl->append(co); bl->append(enet); + + ev->set_line(*this); + bl->set_line(*this); + we->set_line(*this); + co->set_line(*this); + return bl; } - /* Handle as a special case the block on an event. In this - case I generate a NetEvWait object to represent me. */ - - if ((expr_.count() == 1) && (expr_[0]->expr() == 0)) { - string ename = expr_[0]->name(); - NetEvent*ev = scope->find_event(ename); - if (ev == 0) { - cerr << get_line() << ": error: no such named event " - << "``" << ename << "''." << endl; - des->errors += 1; - return 0; - } - - NetEvWait*pr = new NetEvWait(ev, enet); - pr->set_line(*this); - return pr; - } /* Handle the special case of an event name as an identifier in an expression. Make a named event reference. */ + if (expr_.count() == 1) { + assert(expr_[0]->expr()); PEIdent*id = dynamic_cast(expr_[0]->expr()); NetEvent*ev; if (id && (ev = scope->find_event(id->name()))) { - NetEvWait*pr = new NetEvWait(ev, enet); + NetEvWait*pr = new NetEvWait(enet); + pr->add_event(ev); pr->set_line(*this); return pr; } @@ -1643,28 +1691,32 @@ NetProc* PEventStatement::elaborate_st(Design*des, const string&path, object. */ NetEvent*ev = new NetEvent(scope->local_symbol()); - scope->add_event(ev); + ev->set_line(*this); + unsigned expr_count = 0; - NetEvWait*wa = new NetEvWait(ev, enet); + NetEvWait*wa = new NetEvWait(enet); + wa->set_line(*this); for (unsigned idx = 0 ; idx < expr_.count() ; idx += 1) { - if (expr_[idx]->expr() == 0) { - cerr << get_line() << ": sorry: block on named events " - << "not supported." << endl; - des->errors += 1; - return 0; - } + + assert(expr_[idx]->expr()); + + /* If the expression is an identifier that matches a + named event, then handle this case all at once at + skip the rest of the expression handling. */ if (PEIdent*id = dynamic_cast(expr_[idx]->expr())) { - NetEvent*ev = scope->find_event(id->name()); - if (ev) { - cerr << get_line() << ": sorry: block on named events " - << "not supported." << endl; - des->errors += 1; - return 0; + NetEvent*tmp = scope->find_event(id->name()); + if (tmp) { + wa->add_event(tmp); + continue; } } + /* So now we have a normal event expression. Elaborate + the sub-expression as a net and decide how to handle + the edge. */ + NetNet*expr = expr_[idx]->expr()->elaborate_net(des, path, 0, 0, 0, 0); if (expr == 0) { @@ -1675,22 +1727,22 @@ NetProc* PEventStatement::elaborate_st(Design*des, const string&path, } assert(expr); - unsigned pins = (expr_[idx]->type() == NetNEvent::ANYEDGE) + unsigned pins = (expr_[idx]->type() == PEEvent::ANYEDGE) ? expr->pin_count() : 1; NetEvProbe*pr; switch (expr_[idx]->type()) { - case NetNEvent::POSEDGE: + case PEEvent::POSEDGE: pr = new NetEvProbe(des->local_symbol(path), ev, NetEvProbe::POSEDGE, pins); break; - case NetNEvent::NEGEDGE: + case PEEvent::NEGEDGE: pr = new NetEvProbe(des->local_symbol(path), ev, NetEvProbe::NEGEDGE, pins); break; - case NetNEvent::ANYEDGE: + case PEEvent::ANYEDGE: pr = new NetEvProbe(des->local_symbol(path), ev, NetEvProbe::ANYEDGE, pins); break; @@ -1703,6 +1755,17 @@ NetProc* PEventStatement::elaborate_st(Design*des, const string&path, connect(pr->pin(p), expr->pin(p)); des->add_node(pr); + expr_count += 1; + } + + /* If there was at least one conjunction that was an + expression (and not a named event) then add this + event. Otherwise, we didn't use it so delete it. */ + if (expr_count > 0) { + scope->add_event(ev); + wa->add_event(ev); + } else { + delete ev; } return wa; @@ -2161,6 +2224,19 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.158 2000/04/12 04:23:58 steve + * Named events really should be expressed with PEIdent + * objects in the pform, + * + * Handle named events within the mix of net events + * and edges. As a unified lot they get caught together. + * wait statements are broken into more complex statements + * that include a conditional. + * + * Do not generate NetPEvent or NetNEvent objects in + * elaboration. NetEvent, NetEvWait and NetEvProbe + * take over those functions in the netlist. + * * Revision 1.157 2000/04/10 05:26:06 steve * All events now use the NetEvent class. * diff --git a/emit.cc b/emit.cc index 37db19093..a41c9e133 100644 --- a/emit.cc +++ b/emit.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: emit.cc,v 1.38 2000/04/10 05:26:06 steve Exp $" +#ident "$Id: emit.cc,v 1.39 2000/04/12 04:23:58 steve Exp $" #endif /* @@ -110,11 +110,6 @@ void NetRamDq::emit_node(ostream&o, struct target_t*tgt) const tgt->lpm_ram_dq(o, this); } -void NetNEvent::emit_node(ostream&o, struct target_t*tgt) const -{ - tgt->net_event(o, this); -} - void NetBUFZ::emit_node(ostream&o, struct target_t*tgt) const { tgt->bufz(o, this); @@ -189,17 +184,6 @@ void NetPDelay::emit_proc_recurse(ostream&o, struct target_t*tgt) const if (statement_) statement_->emit_proc(o, tgt); } -bool NetPEvent::emit_proc(ostream&o, struct target_t*tgt) const -{ - tgt->proc_event(o, this); - return true; -} - -void NetPEvent::emit_proc_recurse(ostream&o, struct target_t*tgt) const -{ - if (statement_) statement_->emit_proc(o, tgt); -} - bool NetRepeat::emit_proc(ostream&o, struct target_t*tgt) const { tgt->proc_repeat(o, this); @@ -432,6 +416,19 @@ bool emit(ostream&o, const Design*des, const char*type) /* * $Log: emit.cc,v $ + * Revision 1.39 2000/04/12 04:23:58 steve + * Named events really should be expressed with PEIdent + * objects in the pform, + * + * Handle named events within the mix of net events + * and edges. As a unified lot they get caught together. + * wait statements are broken into more complex statements + * that include a conditional. + * + * Do not generate NetPEvent or NetNEvent objects in + * elaboration. NetEvent, NetEvWait and NetEvProbe + * take over those functions in the netlist. + * * Revision 1.38 2000/04/10 05:26:06 steve * All events now use the NetEvent class. * diff --git a/net_event.cc b/net_event.cc index 0129f6211..ff84782e5 100644 --- a/net_event.cc +++ b/net_event.cc @@ -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.2 2000/04/10 05:26:06 steve Exp $" +#ident "$Id: net_event.cc,v 1.3 2000/04/12 04:23:58 steve Exp $" #endif # include "netlist.h" @@ -82,23 +82,63 @@ const NetEvent* NetEvProbe::event() const return event_; } -NetEvWait::NetEvWait(NetEvent*ev, NetProc*pr) -: event_(ev), statement_(pr) +NetEvWait::NetEvWait(NetProc*pr) +: statement_(pr), nevents_(0), events_(0) { } NetEvWait::~NetEvWait() { + if (events_) delete[]events_; delete statement_; } -const NetEvent* NetEvWait::event() const +void NetEvWait::add_event(NetEvent*tgt) { - return event_; + assert(tgt); + if (nevents_ == 0) { + events_ = new NetEvent*[1]; + + } else { + NetEvent**tmp = new NetEvent*[nevents_+1]; + for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) { + tmp[idx] = events_[idx]; + assert(tmp[idx] != tgt); + } + delete[]events_; + events_ = tmp; + } + + events_[nevents_] = tgt; + nevents_ += 1; +} + +unsigned NetEvWait::nevents() const +{ + return nevents_; +} + +const NetEvent* NetEvWait::event(unsigned idx) const +{ + assert(idx < nevents_); + return events_[idx]; } /* * $Log: net_event.cc,v $ + * Revision 1.3 2000/04/12 04:23:58 steve + * Named events really should be expressed with PEIdent + * objects in the pform, + * + * Handle named events within the mix of net events + * and edges. As a unified lot they get caught together. + * wait statements are broken into more complex statements + * that include a conditional. + * + * Do not generate NetPEvent or NetNEvent objects in + * elaboration. NetEvent, NetEvWait and NetEvProbe + * take over those functions in the netlist. + * * Revision 1.2 2000/04/10 05:26:06 steve * All events now use the NetEvent class. * diff --git a/netlist.h b/netlist.h index 0d6c84950..ccf719038 100644 --- a/netlist.h +++ b/netlist.h @@ -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.119 2000/04/10 05:26:06 steve Exp $" +#ident "$Id: netlist.h,v 1.120 2000/04/12 04:23:58 steve Exp $" #endif /* @@ -1312,18 +1312,23 @@ class NetEvTrig : public NetProc { class NetEvWait : public NetProc { public: - explicit NetEvWait(NetEvent*tgt, NetProc*st); + explicit NetEvWait(NetProc*st); ~NetEvWait(); - const NetEvent*event() const; + void add_event(NetEvent*tgt); + + unsigned nevents() const; + const NetEvent*event(unsigned) const; virtual bool emit_proc(ostream&, struct target_t*) const; bool emit_recurse(ostream&, struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; private: - NetEvent*event_; NetProc*statement_; + + unsigned nevents_; + NetEvent**events_; }; class NetEvProbe : public NetNode { @@ -1440,11 +1445,8 @@ class NetPEvent : public NetProc { const NetNEvent* next() const; virtual int match_proc(struct proc_match_t*); - virtual bool emit_proc(ostream&, struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; - void emit_proc_recurse(ostream&, struct target_t*) const; - private: string name_; NetProc*statement_; @@ -1477,8 +1479,6 @@ class NetNEvent : public NetNode { Type type() const; const NetPEvent*pevent() const; - virtual void emit_node(ostream&, struct target_t*) const; - void dump_proc(ostream&) const; virtual void dump_node(ostream&, unsigned ind) const; @@ -2399,6 +2399,19 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.120 2000/04/12 04:23:58 steve + * Named events really should be expressed with PEIdent + * objects in the pform, + * + * Handle named events within the mix of net events + * and edges. As a unified lot they get caught together. + * wait statements are broken into more complex statements + * that include a conditional. + * + * Do not generate NetPEvent or NetNEvent objects in + * elaboration. NetEvent, NetEvWait and NetEvProbe + * take over those functions in the netlist. + * * Revision 1.119 2000/04/10 05:26:06 steve * All events now use the NetEvent class. * diff --git a/parse.y b/parse.y index 6e488e1ff..92655102c 100644 --- a/parse.y +++ b/parse.y @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: parse.y,v 1.88 2000/04/02 04:25:39 steve Exp $" +#ident "$Id: parse.y,v 1.89 2000/04/12 04:23:58 steve Exp $" #endif # include "parse_misc.h" @@ -398,10 +398,11 @@ dr_strength1 : K_supply1 | K_strong1 | K_pull1 | K_weak1 ; event_control : '@' IDENTIFIER - { PEEvent*tmpe = new PEEvent($2); - tmpe->set_file(@2.text); - tmpe->set_lineno(@2.first_line); + { PEIdent*tmpi = new PEIdent($2); + tmpi->set_file(@2.text); + tmpi->set_lineno(@2.first_line); delete[]$2; + PEEvent*tmpe = new PEEvent(PEEvent::ANYEDGE, tmpi); PEventStatement*tmps = new PEventStatement(tmpe); tmps->set_file(@1.text); tmps->set_lineno(@1.first_line); @@ -433,7 +434,7 @@ event_expression_list event_expression : K_posedge expression - { PEEvent*tmp = new PEEvent(NetNEvent::POSEDGE, $2); + { PEEvent*tmp = new PEEvent(PEEvent::POSEDGE, $2); tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); svector*tl = new svector(1); @@ -441,7 +442,7 @@ event_expression $$ = tl; } | K_negedge expression - { PEEvent*tmp = new PEEvent(NetNEvent::NEGEDGE, $2); + { PEEvent*tmp = new PEEvent(PEEvent::NEGEDGE, $2); tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); svector*tl = new svector(1); @@ -449,7 +450,7 @@ event_expression $$ = tl; } | expression - { PEEvent*tmp = new PEEvent(NetNEvent::ANYEDGE, $1); + { PEEvent*tmp = new PEEvent(PEEvent::ANYEDGE, $1); tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); svector*tl = new svector(1); @@ -1860,7 +1861,7 @@ statement } | K_wait '(' expression ')' statement_opt { PEventStatement*tmp; - PEEvent*etmp = new PEEvent(NetNEvent::POSITIVE, $3); + PEEvent*etmp = new PEEvent(PEEvent::POSITIVE, $3); tmp = new PEventStatement(etmp); tmp->set_statement($5); $$ = tmp; diff --git a/pform_dump.cc b/pform_dump.cc index 276e0c605..b7dc541b3 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -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.52 2000/04/01 19:31:57 steve Exp $" +#ident "$Id: pform_dump.cc,v 1.53 2000/04/12 04:23:58 steve Exp $" #endif /* @@ -81,24 +81,21 @@ void PECallFunction::dump(ostream &out) const void PEEvent::dump(ostream&out) const { - if (expr_) { - switch (type_) { - case NetNEvent::ANYEDGE: - break; - case NetNEvent::POSEDGE: - out << "posedge "; - break; - case NetNEvent::NEGEDGE: - out << "negedge "; - break; - case NetNEvent::POSITIVE: - out << "positive "; - break; - } - out << *expr_; - } else { - out << ""; + switch (type_) { + case NetNEvent::ANYEDGE: + break; + case NetNEvent::POSEDGE: + out << "posedge "; + break; + case NetNEvent::NEGEDGE: + out << "negedge "; + break; + case NetNEvent::POSITIVE: + out << "positive "; + break; } + out << *expr_; + } void PENumber::dump(ostream&out) const @@ -736,6 +733,19 @@ void PUdp::dump(ostream&out) const /* * $Log: pform_dump.cc,v $ + * Revision 1.53 2000/04/12 04:23:58 steve + * Named events really should be expressed with PEIdent + * objects in the pform, + * + * Handle named events within the mix of net events + * and edges. As a unified lot they get caught together. + * wait statements are broken into more complex statements + * that include a conditional. + * + * Do not generate NetPEvent or NetNEvent objects in + * elaboration. NetEvent, NetEvWait and NetEvProbe + * take over those functions in the netlist. + * * Revision 1.52 2000/04/01 19:31:57 steve * Named events as far as the pform. * diff --git a/t-null.cc b/t-null.cc index c7651f7fb..3836c08ac 100644 --- a/t-null.cc +++ b/t-null.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: t-null.cc,v 1.10 2000/02/23 02:56:55 steve Exp $" +#ident "$Id: t-null.cc,v 1.11 2000/04/12 04:23:58 steve Exp $" #endif # include "netlist.h" @@ -37,11 +37,9 @@ static class target_null_t : public target_t { void net_assign_nb(ostream&os, const NetAssignNB*) { } void net_const(ostream&, const NetConst*) { } void net_esignal(ostream&, const NetESignal*) { } - void net_event(ostream&, const NetNEvent*) { } bool proc_block(ostream&, const NetBlock*) { return true; } void proc_condit(ostream&, const NetCondit*) { } void proc_delay(ostream&, const NetPDelay*) { } - void proc_event(ostream&, const NetPEvent*) { } void proc_forever(ostream&, const NetForever*) { } void proc_repeat(ostream&, const NetRepeat*) { } void proc_stask(ostream&, const NetSTask*) { } @@ -52,6 +50,19 @@ static class target_null_t : public target_t { extern const struct target tgt_null = { "null", &target_null_obj }; /* * $Log: t-null.cc,v $ + * Revision 1.11 2000/04/12 04:23:58 steve + * Named events really should be expressed with PEIdent + * objects in the pform, + * + * Handle named events within the mix of net events + * and edges. As a unified lot they get caught together. + * wait statements are broken into more complex statements + * that include a conditional. + * + * Do not generate NetPEvent or NetNEvent objects in + * elaboration. NetEvent, NetEvWait and NetEvProbe + * take over those functions in the netlist. + * * Revision 1.10 2000/02/23 02:56:55 steve * Macintosh compilers do not support ident. * diff --git a/t-verilog.cc b/t-verilog.cc index f9f266269..fc5c7be3d 100644 --- a/t-verilog.cc +++ b/t-verilog.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: t-verilog.cc,v 1.9 2000/02/23 02:56:55 steve Exp $" +#ident "$Id: t-verilog.cc,v 1.10 2000/04/12 04:23:58 steve Exp $" #endif /* @@ -45,7 +45,6 @@ class target_verilog : public target_t { virtual void start_process(ostream&os, const NetProcTop*); virtual bool proc_block(ostream&os, const NetBlock*); virtual void proc_delay(ostream&os, const NetPDelay*); - virtual void proc_event(ostream&os, const NetPEvent*); virtual void proc_stask(ostream&os, const NetSTask*); virtual void end_design(ostream&os, const Design*); private: @@ -192,35 +191,6 @@ void target_verilog::proc_delay(ostream&os, const NetPDelay*net) indent_ -= 4; } -void target_verilog::proc_event(ostream&os, const NetPEvent*net) -{ - os << setw(indent_) << "" << "@"; - -#if 0 - unsigned sidx; - const NetNet*sig = find_link_signal(net, 0, sidx); - - switch (net->edge()) { - case NetNEvent::ANYEDGE: - os << mangle(sig->name()) << "[" << sidx << "]"; - break; - case NetNEvent::POSEDGE: - os << "(posedge " << mangle(sig->name()) << "[" << sidx << "])"; - break; - case NetNEvent::NEGEDGE: - os << "(negedge " << mangle(sig->name()) << "[" << sidx << "])"; - break; - } -#else - os << endl; - os << "#error \"proc_event temporarily out of order\""; -#endif - os << endl; - - indent_ += 4; - net->emit_proc_recurse(os, this); - indent_ -= 4; -} static void vtask_parm(ostream&os, const NetExpr*ex) { @@ -272,6 +242,19 @@ const struct target tgt_verilog = { /* * $Log: t-verilog.cc,v $ + * Revision 1.10 2000/04/12 04:23:58 steve + * Named events really should be expressed with PEIdent + * objects in the pform, + * + * Handle named events within the mix of net events + * and edges. As a unified lot they get caught together. + * wait statements are broken into more complex statements + * that include a conditional. + * + * Do not generate NetPEvent or NetNEvent objects in + * elaboration. NetEvent, NetEvWait and NetEvProbe + * take over those functions in the netlist. + * * Revision 1.9 2000/02/23 02:56:55 steve * Macintosh compilers do not support ident. * diff --git a/t-vvm.cc b/t-vvm.cc index b71669ad7..a1f960eb6 100644 --- a/t-vvm.cc +++ b/t-vvm.cc @@ -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.132 2000/04/10 05:26:06 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.133 2000/04/12 04:23:58 steve Exp $" #endif # include @@ -80,7 +80,6 @@ class target_vvm : public target_t { virtual void net_assign_nb(ostream&os, const NetAssignNB*); virtual void net_case_cmp(ostream&os, const NetCaseCmp*); virtual void net_const(ostream&os, const NetConst*); - virtual void net_event(ostream&os, const NetNEvent*); virtual void net_probe(ostream&os, const NetEvProbe*); virtual bool process(ostream&os, const NetProcTop*); virtual void proc_assign(ostream&os, const NetAssign*); @@ -99,7 +98,6 @@ class target_vvm : public target_t { virtual void proc_utask(ostream&os, const NetUTask*); virtual bool proc_wait(ostream&os, const NetEvWait*); virtual void proc_while(ostream&os, const NetWhile*); - virtual void proc_event(ostream&os, const NetPEvent*); virtual void proc_delay(ostream&os, const NetPDelay*); virtual void end_design(ostream&os, const Design*); @@ -1749,63 +1747,6 @@ void target_vvm::net_const(ostream&os, const NetConst*gate) emit_init_value_(gate->pin(idx), gate->value(idx)); } -/* - * The net_event device is a synthetic device type--a fabrication of - * the elaboration phase. An event device receives value changes from - * the attached signal. It is an input only device, its only value - * being the side-effects that threads waiting on events can be - * awakened. - * - * The proc_event method handles the other half of this, the process - * that blocks on the event. - */ -void target_vvm::net_event(ostream&os, const NetNEvent*gate) -{ - string gname = mangle(gate->name()); - string pevent = mangle(gate->pevent()->name()); - os << " /* " << gate->name() << " */" << endl; - - bool&printed = pevent_printed_flag[pevent]; - if (! printed) { - printed = true; - os << "static vvm_sync " << pevent << ";" << endl; - } - - switch (gate->type()) { - - case NetNEvent::POSEDGE: - case NetNEvent::POSITIVE: - assert(gate->pin_count() == 1); - os << "static vvm_posedge " << gname - << "(&" << pevent << ");" << endl; - break; - - case NetNEvent::NEGEDGE: - assert(gate->pin_count() == 1); - os << "static vvm_negedge " << gname - << "(&" << pevent << ");" << endl; - break; - - - case NetNEvent::ANYEDGE: - assert(gate->pin_count() == 1); - os << "static vvm_anyedge " << gname - << "(&" << pevent << ");" << endl; - break; - } - - - /* Connect this device as a receiver to the nexus that is my - source. Write the connect calls into the init code. */ - - for (unsigned idx = 0 ; idx < gate->pin_count() ; idx += 1) { - string nexus = nexus_from_link(&gate->pin(idx)); - unsigned ncode = nexus_wire_map[nexus]; - - init_code << " nexus_wire_table["<name()) << ", " << idx << ");" << endl; - } -} void target_vvm::net_probe(ostream&os, const NetEvProbe*net) { @@ -2446,15 +2387,17 @@ bool target_vvm::proc_wait(ostream&os, const NetEvWait*wait) { unsigned out_step = ++thread_step_; - const NetEvent*ev = wait->event(); - assert(ev); - - string ename = mangle(ev->full_name()); - defn << " step_ = &" << thread_class_ << "::step_" << out_step << "_;" << endl; - defn << " " << ename << ".wait(this); // " - << wait->get_line() << ": @" << ev->full_name() << "..." << endl; + + for (unsigned idx = 0 ; idx < wait->nevents() ; idx+= 1) { + const NetEvent*ev = wait->event(idx); + assert(ev); + string ename = mangle(ev->full_name()); + defn << " " << ename << ".wait(this); // " + << wait->get_line() << ": @" << ev->full_name() + << "..." << endl; + } defn << " return false;" << endl; defn << "}" << endl; @@ -2521,69 +2464,6 @@ void target_vvm::proc_while(ostream&os, const NetWhile*net) "_() {" << endl; } -/* - * Within a process, the proc_event is a statement that is blocked - * until the event is signalled. - */ -void target_vvm::proc_event(ostream&os, const NetPEvent*proc) -{ - thread_step_ += 1; - defn << " step_ = &" << thread_class_ << "::step_" << - thread_step_ << "_;" << endl; - - /* POSITIVE is for the wait construct, and needs to be handled - specially. The structure of the generated code is: - - if (event.get(0)==V1) { - return true; - } else { - event.wait(this); - return false; - } - - This causes the wait to not even block the thread if the - event value is already positive, otherwise wait for a - rising edge. All the edge triggers look like this: - - event.wait(vvm_pevent::POSEDGE, this); - return false; - - POSEDGE is replaced with the correct type for the desired - edge. */ - - const NetNEvent*tmp = proc->first(); - if (tmp && (tmp->type() == NetNEvent::POSITIVE)) { - // POSITIVE can have only one input. - assert(0 == proc->next()); - - defn << " if (B_IS1(" << mangle(tmp->name()) << - ".get(0))) {" << endl; - defn << " return true;" << endl; - defn << " } else {" << endl; - defn << " " << mangle(proc->name()) << - ".wait(this);" << endl; - defn << " return false;" << endl; - defn << " }" << endl; - - } else { - /* The canonical wait for an edge puts the thread into - the correct wait object, then returns false from the - thread to suspend execution. When things are ready to - proceed, the correct vvm_pevent will send a wakeup to - start the next basic block. */ - defn << " " << mangle(proc->name()) << ".wait(this);" << endl; - defn << " return false;" << endl; - } - - defn << "}" << endl; - - os << " bool step_" << thread_step_ << "_();" << endl; - - defn << "bool " << thread_class_ << "::step_" << thread_step_ << - "_() {" << endl; - - proc->emit_proc_recurse(os, this); -} /* * A delay suspends the thread for a period of time. @@ -2629,6 +2509,19 @@ extern const struct target tgt_vvm = { }; /* * $Log: t-vvm.cc,v $ + * Revision 1.133 2000/04/12 04:23:58 steve + * Named events really should be expressed with PEIdent + * objects in the pform, + * + * Handle named events within the mix of net events + * and edges. As a unified lot they get caught together. + * wait statements are broken into more complex statements + * that include a conditional. + * + * Do not generate NetPEvent or NetNEvent objects in + * elaboration. NetEvent, NetEvWait and NetEvProbe + * take over those functions in the netlist. + * * Revision 1.132 2000/04/10 05:26:06 steve * All events now use the NetEvent class. * diff --git a/target.cc b/target.cc index 7b4e16700..69a4bbec1 100644 --- a/target.cc +++ b/target.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: target.cc,v 1.34 2000/04/10 05:26:06 steve Exp $" +#ident "$Id: target.cc,v 1.35 2000/04/12 04:23:58 steve Exp $" #endif # include "target.h" @@ -155,13 +155,6 @@ void target_t::net_const(ostream&os, const NetConst*) "Unhandled CONSTANT node." << endl; } -void target_t::net_event(ostream&os, const NetNEvent*net) -{ - cerr << "target (" << typeid(*this).name() << "): " - "Unhandled EVENT net node." << endl; - net->dump_node(cerr, 4); -} - void target_t::net_probe(ostream&os, const NetEvProbe*net) { cerr << "target (" << typeid(*this).name() << "): " @@ -225,13 +218,6 @@ void target_t::proc_delay(ostream&os, const NetPDelay*) "Unhandled proc_delay." << endl; } -void target_t::proc_event(ostream&os, const NetPEvent*net) -{ - cerr << "target (" << typeid(*this).name() << "): " - "Unhandled proc_event." << endl; - net->dump(cerr, 4); -} - void target_t::proc_forever(ostream&os, const NetForever*) { cerr << "target (" << typeid(*this).name() << "): " @@ -353,6 +339,19 @@ void expr_scan_t::expr_binary(const NetEBinary*ex) /* * $Log: target.cc,v $ + * Revision 1.35 2000/04/12 04:23:58 steve + * Named events really should be expressed with PEIdent + * objects in the pform, + * + * Handle named events within the mix of net events + * and edges. As a unified lot they get caught together. + * wait statements are broken into more complex statements + * that include a conditional. + * + * Do not generate NetPEvent or NetNEvent objects in + * elaboration. NetEvent, NetEvWait and NetEvProbe + * take over those functions in the netlist. + * * Revision 1.34 2000/04/10 05:26:06 steve * All events now use the NetEvent class. * diff --git a/target.h b/target.h index f3288d790..0a8b9e3de 100644 --- a/target.h +++ b/target.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: target.h,v 1.33 2000/04/10 05:26:06 steve Exp $" +#ident "$Id: target.h,v 1.34 2000/04/12 04:23:58 steve Exp $" #endif # include "netlist.h" @@ -91,7 +91,6 @@ struct target_t { virtual void net_assign_nb(ostream&os, const NetAssignNB*); virtual void net_case_cmp(ostream&os, const NetCaseCmp*); virtual void net_const(ostream&os, const NetConst*); - virtual void net_event(ostream&os, const NetNEvent*); virtual void net_probe(ostream&os, const NetEvProbe*); /* Output a process (called for each process). It is up to the @@ -113,8 +112,6 @@ struct target_t { virtual void proc_utask(ostream&os, const NetUTask*); virtual bool proc_wait(ostream&os, const NetEvWait*); virtual void proc_while(ostream&os, const NetWhile*); - - virtual void proc_event(ostream&os, const NetPEvent*); virtual void proc_delay(ostream&os, const NetPDelay*); /* Done with the design. */ @@ -155,6 +152,19 @@ extern const struct target *target_table[]; /* * $Log: target.h,v $ + * Revision 1.34 2000/04/12 04:23:58 steve + * Named events really should be expressed with PEIdent + * objects in the pform, + * + * Handle named events within the mix of net events + * and edges. As a unified lot they get caught together. + * wait statements are broken into more complex statements + * that include a conditional. + * + * Do not generate NetPEvent or NetNEvent objects in + * elaboration. NetEvent, NetEvWait and NetEvProbe + * take over those functions in the netlist. + * * Revision 1.33 2000/04/10 05:26:06 steve * All events now use the NetEvent class. *