From cc9bbff78d41f55b1cd3bc7e479deac56ca752e7 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 27 Nov 2011 11:16:39 -0800 Subject: [PATCH] Rework parse of compression assignments. --- Statement.cc | 13 +++-- Statement.h | 7 +++ elaborate.cc | 23 +++++++++ parse.y | 142 ++++++++++++++++++++++----------------------------- 4 files changed, 99 insertions(+), 86 deletions(-) diff --git a/Statement.cc b/Statement.cc index 415dffc12..e726099bb 100644 --- a/Statement.cc +++ b/Statement.cc @@ -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) { } diff --git a/Statement.h b/Statement.h index 3f3c14010..cef5833c1 100644 --- a/Statement.h +++ b/Statement.h @@ -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_ { diff --git a/elaborate.cc b/elaborate.cc index 3fb9c60a8..8f020bae4 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -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); diff --git a/parse.y b/parse.y index 5e69c41dc..c783a21e4 100644 --- a/parse.y +++ b/parse.y @@ -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