Add blocking repeat event control, make repeat sign aware
This patch adds blocking repeat event controls and also makes the
base repeat statement sign aware. If the argument to repeat is
negative (it must be a signed variable) then this is treated just
like an argument of 0 (there is no looping). Doing this allows us
to model the repeat event control as follows.
lhs = repeat(count) @(event) rhs;
is translated to:
begin
temp = rhs;
repeat (count) @(event);
lhs = temp;
end
This patch also pushes the non-blocking event control
information to the elaboration phase where it will report they
are not currently supported.
This commit is contained in:
parent
60169f6353
commit
7beb059d90
57
Statement.cc
57
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)
|
||||
*/
|
||||
|
||||
|
|
|
|||
11
Statement.h
11
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:
|
||||
|
|
|
|||
100
elaborate.cc
100
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 = #<d> 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<NetEConst*>(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<NetEConst*>(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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
13
parse.y
13
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
Loading…
Reference in New Issue