diff --git a/Statement.cc b/Statement.cc index 02680d322..a8c9b9627 100644 --- a/Statement.cc +++ b/Statement.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2008 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 @@ -16,9 +16,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: Statement.cc,v 1.30 2007/05/24 04:07:11 steve Exp $" -#endif # include "config.h" @@ -30,19 +27,19 @@ Statement::~Statement() } PAssign_::PAssign_(PExpr*lval, PExpr*ex) -: event_(0), lval_(lval), rval_(ex) +: event_(0), count_(0), lval_(lval), rval_(ex) { delay_ = 0; } PAssign_::PAssign_(PExpr*lval, PExpr*de, PExpr*ex) -: event_(0), lval_(lval), rval_(ex) +: event_(0), count_(0), lval_(lval), rval_(ex) { delay_ = de; } -PAssign_::PAssign_(PExpr*lval, PEventStatement*ev, PExpr*ex) -: event_(ev), lval_(lval), rval_(ex) +PAssign_::PAssign_(PExpr*lval, PExpr*cnt, PEventStatement*ev, PExpr*ex) +: event_(ev), count_(cnt), lval_(lval), rval_(ex) { delay_ = 0; } @@ -63,8 +60,8 @@ PAssign::PAssign(PExpr*lval, PExpr*d, PExpr*ex) { } -PAssign::PAssign(PExpr*lval, PEventStatement*d, PExpr*ex) -: PAssign_(lval, d, ex) +PAssign::PAssign(PExpr*lval, PExpr*cnt, PEventStatement*d, PExpr*ex) +: PAssign_(lval, cnt, d, ex) { } @@ -82,6 +79,11 @@ PAssignNB::PAssignNB(PExpr*lval, PExpr*d, PExpr*ex) { } +PAssignNB::PAssignNB(PExpr*lval, PExpr*cnt, PEventStatement*d, PExpr*ex) +: PAssign_(lval, cnt, d, ex) +{ +} + PAssignNB::~PAssignNB() { } @@ -298,38 +300,3 @@ PWhile::~PWhile() delete cond_; delete statement_; } - -/* - * $Log: Statement.cc,v $ - * Revision 1.30 2007/05/24 04:07:11 steve - * Rework the heirarchical identifier parse syntax and pform - * to handle more general combinations of heirarch and bit selects. - * - * Revision 1.29 2004/02/18 17:11:54 steve - * Use perm_strings for named langiage items. - * - * Revision 1.28 2002/08/12 01:34:58 steve - * conditional ident string using autoconfig. - * - * Revision 1.27 2002/04/21 22:31:02 steve - * Redo handling of assignment internal delays. - * Leave it possible for them to be calculated - * at run time. - * - * Revision 1.26 2002/04/21 04:59:07 steve - * Add support for conbinational events by finding - * the inputs to expressions and some statements. - * Get case and assignment statements working. - * - * Revision 1.25 2001/12/03 04:47:14 steve - * Parser and pform use hierarchical names as hname_t - * objects instead of encoded strings. - * - * Revision 1.24 2001/11/22 06:20:59 steve - * Use NetScope instead of string for scope path. - * - * Revision 1.23 2001/07/25 03:10:48 steve - * Create a config.h.in file to hold all the config - * junk, and support gcc 3.0. (Stephan Boettcher) - */ - diff --git a/Statement.h b/Statement.h index 5bca41739..bcc033937 100644 --- a/Statement.h +++ b/Statement.h @@ -93,7 +93,7 @@ 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); + explicit PAssign_(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex); virtual ~PAssign_() =0; const PExpr* lval() const { return lval_; } @@ -104,6 +104,7 @@ class PAssign_ : public Statement { PExpr* delay_; PEventStatement*event_; + PExpr* count_; private: PExpr* lval_; @@ -115,7 +116,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); + explicit PAssign(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex); ~PAssign(); virtual void dump(ostream&out, unsigned ind) const; @@ -129,6 +130,7 @@ class PAssignNB : public PAssign_ { public: explicit PAssignNB(PExpr*lval, PExpr*ex); explicit PAssignNB(PExpr*lval, PExpr*de, PExpr*ex); + explicit PAssignNB(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex); ~PAssignNB(); virtual void dump(ostream&out, unsigned ind) const; @@ -333,6 +335,9 @@ class PEventStatement : public Statement { void set_statement(Statement*st); virtual void dump(ostream&out, unsigned ind) const; + // Call this with a NULL statement only. It is used to print + // the event expression for inter-assignment event controls. + virtual void dump_inline(ostream&out) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const; virtual void elaborate_scope(Design*des, NetScope*scope) const; virtual void elaborate_sig(Design*des, NetScope*scope) const; @@ -348,6 +353,8 @@ class PEventStatement : public Statement { Statement*statement_; }; +ostream& operator << (ostream&o, const PEventStatement&obj); + class PForce : public Statement { public: diff --git a/elaborate.cc b/elaborate.cc index f2927719e..e693f45d5 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -1803,6 +1803,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const if (rv == 0) return 0; assert(rv); + if (count_) assert(event_); /* Rewrite delayed assignments as assignments that are delayed. For example, a = # b; becomes: @@ -1855,19 +1856,58 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const /* 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. */ + right NetPDelay object. For a repeat event control + repeat the event and then do the final assignment. */ NetProc*st; if (event_) { - st = event_->elaborate_st(des, scope, a2); - if (st == 0) { - cerr << event_->get_fileline() << ": error: " - "unable to elaborate event expression." - << endl; - des->errors += 1; - return 0; - } - assert(st); + if (count_) { + NetExpr*count = elab_and_eval(des, scope, count_, -1); + if (count == 0) { + cerr << get_fileline() << ": Unable to " + "elaborate repeat expression." << endl; + des->errors += 1; + return 0; + } + st = event_->elaborate(des, scope); + if (st == 0) { + cerr << event_->get_fileline() << ": error: " + "unable to elaborate event expression." + << endl; + des->errors += 1; + return 0; + } + // If the expression is a constant, handle + // certain special iteration counts. + if (NetEConst*ce = dynamic_cast(count)) { + long val = ce->value().as_long(); + // We only need the real statement. + if (val <= 0) { + delete count; + delete st; + st = 0; + + // We don't need the repeat statement. + } else if (val == 1) { + delete count; + + // We need a repeat statement. + } else { + st = new NetRepeat(count, st); + } + } else { + st = new NetRepeat(count, st); + } + } else { + st = event_->elaborate_st(des, scope, a2); + if (st == 0) { + cerr << event_->get_fileline() << ": error: " + "unable to elaborate event expression." + << endl; + des->errors += 1; + return 0; + } + } } else { NetPDelay*de = new NetPDelay(delay, a2); de->set_line(*this); @@ -1877,7 +1917,8 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const /* And build up the complex statement. */ NetBlock*bl = new NetBlock(NetBlock::SEQU, 0); bl->append(a1); - bl->append(st); + if (st) bl->append(st); + if (count_) bl->append(a2); return bl; } @@ -1948,6 +1989,34 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const if (delay_ != 0) delay = elaborate_delay_expr(delay_, des, scope); + if (count_ != 0 || event_ != 0) { + NetExpr*count = 0; + if (count_ != 0) { + assert(event_ != 0); + count = elab_and_eval(des, scope, count_, -1); + if (count == 0) { + cerr << get_fileline() << ": Unable to elaborate " + "repeat expression." << endl; + des->errors += 1; +// return 0; + } + } + + NetProc* event = event_->elaborate(des, scope); + if (event == 0) { + cerr << get_fileline() << ": unable to elaborate " + "event expression." << endl; + des->errors += 1; +// return 0; + } + + cerr << get_fileline() << ": sorry: non blocking "; + if (count_) cerr << "repeat "; + cerr << "event controls are not supported." << endl; + des->errors += 1; + return 0; + } + /* All done with this node. Mark its line number and check it in. */ NetAssignNB*cur = new NetAssignNB(lv, rv); cur->set_delay(delay); @@ -3195,17 +3264,14 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const // If the expression is a constant, handle certain special // iteration counts. if (NetEConst*ce = dynamic_cast(expr)) { - verinum val = ce->value(); - switch (val.as_ulong()) { - case 0: + long val = ce->value().as_long(); + if (val <= 0) { delete expr; delete stat; return new NetBlock(NetBlock::SEQU, 0); - case 1: + } else if (val == 1) { delete expr; return stat; - default: - break; } } diff --git a/parse.y b/parse.y index 015034559..4f02bafc7 100644 --- a/parse.y +++ b/parse.y @@ -3648,28 +3648,23 @@ statement $$ = tmp; } | lpvalue '=' event_control expression ';' - { PAssign*tmp = new PAssign($1,$3,$4); + { PAssign*tmp = new PAssign($1,0,$3,$4); FILE_NAME(tmp, @1); $$ = tmp; } | lpvalue '=' K_repeat '(' expression ')' event_control expression ';' - { PAssign*tmp = new PAssign($1,$7,$8); + { PAssign*tmp = new PAssign($1,$5,$7,$8); FILE_NAME(tmp,@1); tmp->set_lineno(@1.first_line); - yyerror(@3, "sorry: repeat event control not supported."); - delete $5; $$ = tmp; } | lpvalue K_LE event_control expression ';' - { yyerror(@1, "sorry: Event controls not supported here."); - PAssignNB*tmp = new PAssignNB($1,$4); + { PAssignNB*tmp = new PAssignNB($1,0,$3,$4); FILE_NAME(tmp, @1); $$ = tmp; } | lpvalue K_LE K_repeat '(' expression ')' event_control expression ';' - { yyerror(@1, "sorry: Event controls not supported here."); - delete $5; - PAssignNB*tmp = new PAssignNB($1,$8); + { PAssignNB*tmp = new PAssignNB($1,$5,$7,$8); FILE_NAME(tmp, @1); $$ = tmp; } diff --git a/pform_dump.cc b/pform_dump.cc index 2d3cc5fd1..cb35237e8 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -40,6 +40,12 @@ ostream& operator << (ostream&out, const PExpr&obj) return out; } +ostream& operator << (ostream&out, const PEventStatement&obj) +{ + obj.dump_inline(out); + return out; +} + ostream& operator << (ostream&o, const PDelays&d) { d.dump_delays(o); @@ -554,16 +560,20 @@ void AContrib::dump(ostream&out, unsigned ind) const void PAssign::dump(ostream&out, unsigned ind) const { - out << setw(ind) << ""; - out << *lval() << " = " << delay_ << " " << *rval() << ";"; - out << " /* " << get_fileline() << " */" << endl; + out << setw(ind) << "" << *lval() << " = "; + if (delay_) out << "#" << *delay_ << " "; + if (count_) out << "repeat(" << *count_ << ") "; + if (event_) out << *event_ << " "; + out << *rval() << ";" << " /* " << get_fileline() << " */" << endl; } void PAssignNB::dump(ostream&out, unsigned ind) const { - out << setw(ind) << ""; - out << *lval() << " <= " << delay_ << " " << *rval() << ";"; - out << " /* " << get_fileline() << " */" << endl; + out << setw(ind) << "" << *lval() << " <= "; + if (delay_) out << "#" << *delay_ << " "; + if (count_) out << "repeat(" << *count_ << ") "; + if (event_) out << *event_ << " "; + out << *rval() << ";" << " /* " << get_fileline() << " */" << endl; } void PBlock::dump(ostream&out, unsigned ind) const @@ -713,6 +723,23 @@ void PEventStatement::dump(ostream&out, unsigned ind) const } } +void PEventStatement::dump_inline(ostream&out) const +{ + assert(statement_ == 0); + + if (expr_.count() == 0) { + out << "@* "; + + } else { + out << "@(" << *(expr_[0]); + if (expr_.count() > 1) + for (unsigned idx = 1 ; idx < expr_.count() ; idx += 1) + out << " or " << *(expr_[idx]); + + out << ")"; + } +} + void PForce::dump(ostream&out, unsigned ind) const { out << setw(ind) << "" << "force " << *lval_ << " = " << *expr_ diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 41220c832..302c1e3c4 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -1402,10 +1402,11 @@ static int show_stmt_repeat(ivl_statement_t net, ivl_scope_t sscope) unsigned lab_top = local_count++, lab_out = local_count++; ivl_expr_t exp = ivl_stmt_cond_expr(net); struct vector_info cnt = draw_eval_expr(exp, 0); + char *sign = ivl_expr_signed(exp) ? "s" : "u"; /* Test that 0 < expr */ - fprintf(vvp_out, "T_%u.%u %%cmp/u 0, %u, %u;\n", thread_count, - lab_top, cnt.base, cnt.wid); + fprintf(vvp_out, "T_%u.%u %%cmp/%s 0, %u, %u;\n", thread_count, + lab_top, sign, cnt.base, cnt.wid); clear_expression_lookaside(); fprintf(vvp_out, " %%jmp/0xz T_%u.%u, 5;\n", thread_count, lab_out); /* This adds -1 (all ones in 2's complement) to the count. */