Rework parse of compression assignments.

This commit is contained in:
Stephen Williams 2011-11-27 11:16:39 -08:00
parent 5e9e309be8
commit cc9bbff78d
4 changed files with 99 additions and 86 deletions

View File

@ -51,22 +51,27 @@ PAssign_::~PAssign_()
}
PAssign::PAssign(PExpr*lval__, PExpr*ex)
: PAssign_(lval__, ex, false)
: PAssign_(lval__, ex, false), op_(0)
{
}
PAssign::PAssign(PExpr*lval__, char op, PExpr*ex)
: PAssign_(lval__, ex, false), op_(op)
{
}
PAssign::PAssign(PExpr*lval__, PExpr*d, PExpr*ex)
: PAssign_(lval__, d, ex)
: PAssign_(lval__, d, ex), op_(0)
{
}
PAssign::PAssign(PExpr*lval__, PExpr*cnt, PEventStatement*d, PExpr*ex)
: PAssign_(lval__, cnt, d, ex)
: PAssign_(lval__, cnt, d, ex), op_(0)
{
}
PAssign::PAssign(PExpr*lval__, PExpr*ex, bool is_constant)
: PAssign_(lval__, ex, is_constant)
: PAssign_(lval__, ex, is_constant), op_(0)
{
}

View File

@ -120,7 +120,12 @@ class PAssign_ : public Statement {
class PAssign : public PAssign_ {
public:
// lval - assignment l-value
// ex - assignment r-value
// op - compressed assignment operator (i.e. '+', '-', ...)
// de - delayed assignment delay expression
explicit PAssign(PExpr*lval, PExpr*ex);
explicit PAssign(PExpr*lval, char op, PExpr*ex);
explicit PAssign(PExpr*lval, PExpr*de, PExpr*ex);
explicit PAssign(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
explicit PAssign(PExpr*lval, PExpr*ex, bool is_constant);
@ -130,6 +135,8 @@ class PAssign : public PAssign_ {
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
private:
NetProc* elaborate_compressed_(Design*des, NetScope*scope) const;
char op_;
};
class PAssignNB : public PAssign_ {

View File

@ -2259,10 +2259,33 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
return dex;
}
NetProc* PAssign::elaborate_compressed_(Design*des, NetScope*scope) const
{
ivl_assert(*this, ! delay_);
ivl_assert(*this, ! count_);
ivl_assert(*this, ! event_);
NetAssign_*lv = elaborate_lval(des, scope);
if (lv == 0) return 0;
NetExpr*rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type());
if (rv == 0) return 0;
NetAssign*cur = new NetAssign(lv, rv);
cur->set_line(*this);
return cur;
}
NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
{
assert(scope);
/* If this is a compressed assignment, then handle the
elaboration in a specialized function. */
if (op_ != 0)
return elaborate_compressed_(des, scope);
/* elaborate the lval. This detects any part selects and mux
expressions that might exist. */
NetAssign_*lv = elaborate_lval(des, scope);

142
parse.y
View File

@ -4552,11 +4552,11 @@ statement
tmp->set_statement($6);
$$ = tmp;
}
| lpvalue '=' expression ';'
{ PAssign*tmp = new PAssign($1,$3);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue '=' expression ';'
{ PAssign*tmp = new PAssign($1,$3);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| error '=' expression ';'
{ yyerror(@2, "Syntax in assignment statement l-value.");
yyerrok;
@ -4663,83 +4663,61 @@ statement
;
compressed_statement
: lpvalue K_PLUS_EQ expression
{
PEBinary *t = new PEBinary('+', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_MINUS_EQ expression
{
PEBinary *t = new PEBinary('-', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_MUL_EQ expression
{
PEBinary *t = new PEBinary('*', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_DIV_EQ expression
{
PEBinary *t = new PEBinary('/', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_MOD_EQ expression
{
PEBinary *t = new PEBinary('%', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_AND_EQ expression
{
PEBinary *t = new PEBinary('&', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_OR_EQ expression
{
PEBinary *t = new PEBinary('|', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_XOR_EQ expression
{
PEBinary *t = new PEBinary('^', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_LS_EQ expression
{
PEBShift *t = new PEBShift('l', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_RS_EQ expression
{
PEBShift *t = new PEBShift('r', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_RSS_EQ expression
{
PEBShift *t = new PEBShift('R', $1, $3);
PAssign *tmp = new PAssign($1, t);
FILE_NAME(tmp, @1);
$$ = tmp;
}
: lpvalue K_PLUS_EQ expression
{ PAssign*tmp = new PAssign($1, '+', $3);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_MINUS_EQ expression
{ PAssign*tmp = new PAssign($1, '-', $3);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_MUL_EQ expression
{ PAssign*tmp = new PAssign($1, '*', $3);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_DIV_EQ expression
{ PAssign*tmp = new PAssign($1, '/', $3);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_MOD_EQ expression
{ PAssign*tmp = new PAssign($1, '%', $3);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_AND_EQ expression
{ PAssign*tmp = new PAssign($1, '&', $3);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_OR_EQ expression
{ PAssign*tmp = new PAssign($1, '|', $3);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_XOR_EQ expression
{ PAssign*tmp = new PAssign($1, '^', $3);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_LS_EQ expression
{ PAssign *tmp = new PAssign($1, 'l', $3);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_RS_EQ expression
{ PAssign*tmp = new PAssign($1, 'r', $3);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| lpvalue K_RSS_EQ expression
{ PAssign *tmp = new PAssign($1, 'R', $3);
FILE_NAME(tmp, @1);
$$ = tmp;
}
;
statement_list_or_null