diff --git a/Statement.cc b/Statement.cc index ea26ccc3b..98b25a717 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) -#ident "$Id: Statement.cc,v 1.14 1999/09/04 19:11:46 steve Exp $" +#ident "$Id: Statement.cc,v 1.15 1999/09/22 02:00:48 steve Exp $" #endif # include "Statement.h" @@ -27,12 +27,22 @@ Statement::~Statement() { } +PAssign_::PAssign_(PExpr*lval, PExpr*ex) +: event_(0), lval_(lval), rval_(ex) +{ +} + PAssign_::PAssign_(PExpr*lval, PExpr*de, PExpr*ex) -: lval_(lval), rval_(ex) +: event_(0), lval_(lval), rval_(ex) { if (de) delay_.set_delay(de); } +PAssign_::PAssign_(PExpr*lval, PEventStatement*ev, PExpr*ex) +: event_(ev), lval_(lval), rval_(ex) +{ +} + PAssign_::~PAssign_() { delete lval_; @@ -40,7 +50,7 @@ PAssign_::~PAssign_() } PAssign::PAssign(PExpr*lval, PExpr*ex) -: PAssign_(lval, 0, ex) +: PAssign_(lval, ex) { } @@ -49,12 +59,17 @@ PAssign::PAssign(PExpr*lval, PExpr*d, PExpr*ex) { } +PAssign::PAssign(PExpr*lval, PEventStatement*d, PExpr*ex) +: PAssign_(lval, d, ex) +{ +} + PAssign::~PAssign() { } PAssignNB::PAssignNB(PExpr*lval, PExpr*ex) -: PAssign_(lval, 0, ex) +: PAssign_(lval, ex) { } @@ -148,6 +163,9 @@ PWhile::~PWhile() /* * $Log: Statement.cc,v $ + * Revision 1.15 1999/09/22 02:00:48 steve + * assignment with blocking event delay. + * * Revision 1.14 1999/09/04 19:11:46 steve * Add support for delayed non-blocking assignments. * diff --git a/Statement.h b/Statement.h index 690c8014a..1c11a7d1c 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) -#ident "$Id: Statement.h,v 1.18 1999/09/15 01:55:06 steve Exp $" +#ident "$Id: Statement.h,v 1.19 1999/09/22 02:00:48 steve Exp $" #endif # include @@ -29,6 +29,7 @@ # include "LineInfo.h" class PExpr; class Statement; +class PEventStatement; /* * The PProcess is the root of a behavioral process. Each process gets @@ -78,7 +79,9 @@ class Statement : public LineInfo { */ class PAssign_ : public Statement { public: + explicit PAssign_(PExpr*lval, PExpr*ex); explicit PAssign_(PExpr*lval, PExpr*de, PExpr*ex); + explicit PAssign_(PExpr*lval, PEventStatement*de, PExpr*ex); virtual ~PAssign_() =0; const PExpr* lval() const { return lval_; } @@ -90,6 +93,7 @@ class PAssign_ : public Statement { NetExpr*&mux) const; PDelays delay_; + PEventStatement*event_; private: PExpr* lval_; @@ -101,6 +105,7 @@ class PAssign : public PAssign_ { public: explicit PAssign(PExpr*lval, PExpr*ex); explicit PAssign(PExpr*lval, PExpr*de, PExpr*ex); + explicit PAssign(PExpr*lval, PEventStatement*de, PExpr*ex); ~PAssign(); virtual void dump(ostream&out, unsigned ind) const; @@ -260,6 +265,10 @@ class PEventStatement : public Statement { virtual void dump(ostream&out, unsigned ind) const; virtual NetProc* elaborate(Design*des, const string&path) const; + // This method is used to elaborate, but attach a previously + // elaborated statement to the event. + NetProc* elaborate_st(Design*des, const string&path, NetProc*st) const; + private: svectorexpr_; Statement*statement_; @@ -337,6 +346,9 @@ class PWhile : public Statement { /* * $Log: Statement.h,v $ + * Revision 1.19 1999/09/22 02:00:48 steve + * assignment with blocking event delay. + * * Revision 1.18 1999/09/15 01:55:06 steve * Elaborate non-blocking assignment to memories. * diff --git a/elaborate.cc b/elaborate.cc index fa2c0b5ae..208ad2903 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) -#ident "$Id: elaborate.cc,v 1.93 1999/09/20 02:21:10 steve Exp $" +#ident "$Id: elaborate.cc,v 1.94 1999/09/22 02:00:48 steve Exp $" #endif /* @@ -1618,11 +1618,15 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const # a = tmp; end + If the delay is an event delay, then the transform is + similar, with the event delay replacing the time delay. It + is an event delay if the event_ member has a value. + This rewriting of the expression allows me to not bother to actually and literally represent the delayed assign in the netlist. The compound statement is exactly equivalent. */ - if (rise_time) { + if (rise_time || event_) { string n = des->local_symbol(path); unsigned wid = reg->pin_count(); @@ -1658,12 +1662,31 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const for (unsigned idx = 0 ; idx < wid ; idx += 1) connect(a2->pin(idx), reg->pin(idx)); - /* And build up the complex statement. */ - NetPDelay*de = new NetPDelay(rise_time, a2); + /* Generate the delay statement with the final + assignment attached to it. If this is an event delay, + elaborate the PEventStatement. Otherwise, create the + right NetPDelay object. */ + NetProc*st; + if (event_) { + st = event_->elaborate_st(des, path, a2); + if (st == 0) { + cerr << event_->get_line() << ": error: " + "unable to elaborate event expression." + << endl; + des->errors += 1; + return 0; + } + assert(st); + } else { + NetPDelay*de = new NetPDelay(rise_time, a2); + st = de; + } + + /* And build up the complex statement. */ NetBlock*bl = new NetBlock(NetBlock::SEQU); bl->append(a1); - bl->append(de); + bl->append(st); return bl; } @@ -2132,14 +2155,9 @@ NetProc* PDelayStatement::elaborate(Design*des, const string&path) const * happens when the source has something like "@(E) ;". Note the null * statement. */ -NetProc* PEventStatement::elaborate(Design*des, const string&path) const +NetProc* PEventStatement::elaborate_st(Design*des, const string&path, + NetProc*enet) const { - NetProc*enet = 0; - if (statement_) { - enet = statement_->elaborate(des, path); - if (enet == 0) - return 0; - } /* Create a single NetPEvent, and a unique NetNEvent for each conjuctive event. An NetNEvent can have many pins only if @@ -2172,6 +2190,18 @@ NetProc* PEventStatement::elaborate(Design*des, const string&path) const return pe; } +NetProc* PEventStatement::elaborate(Design*des, const string&path) const +{ + NetProc*enet = 0; + if (statement_) { + enet = statement_->elaborate(des, path); + if (enet == 0) + return 0; + } + + return elaborate_st(des, path, enet); +} + /* * Forever statements are represented directly in the netlist. It is * theoretically possible to use a while structure with a constant @@ -2583,6 +2613,9 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.94 1999/09/22 02:00:48 steve + * assignment with blocking event delay. + * * Revision 1.93 1999/09/20 02:21:10 steve * Elaborate parameters in phases. * diff --git a/parse.y b/parse.y index 18c8662d7..c0b5e7bda 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) -#ident "$Id: parse.y,v 1.64 1999/09/17 02:06:26 steve Exp $" +#ident "$Id: parse.y,v 1.65 1999/09/22 02:00:48 steve Exp $" #endif # include "parse_misc.h" @@ -1578,7 +1578,7 @@ statement | lpvalue '=' delay expression ';' { PExpr*del = (*$3)[0]; if ($3->count() != 1) - yyerror(@1, "Sorry, delay lists not supported here."); + yyerror(@1, "sorry: Delay lists not supported here."); PAssign*tmp = new PAssign($1,del,$4); tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); @@ -1587,12 +1587,25 @@ statement | lpvalue K_LE delay expression ';' { PExpr*del = (*$3)[0]; if ($3->count() != 1) - yyerror(@1, "Sorry, delay lists not supported here."); + yyerror(@1, "sorry: Delay lists not supported here."); PAssignNB*tmp = new PAssignNB($1,del,$4); tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); $$ = tmp; } + | lpvalue '=' event_control expression ';' + { PAssign*tmp = new PAssign($1,$3,$4); + tmp->set_file(@1.text); + tmp->set_lineno(@1.first_line); + $$ = tmp; + } + | lpvalue K_LE event_control expression ';' + { yyerror(@1, "sorry: Event controls not supported here."); + PAssignNB*tmp = new PAssignNB($1,$4); + tmp->set_file(@1.text); + tmp->set_lineno(@1.first_line); + $$ = tmp; + } | K_wait '(' expression ')' statement_opt { PEventStatement*tmp; PEEvent*etmp = new PEEvent(NetNEvent::POSITIVE, $3);