diff --git a/parse.y b/parse.y index e27c35cd4..4b7748057 100644 --- a/parse.y +++ b/parse.y @@ -704,6 +704,8 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector package_scope +%type compressed_operator + %token K_TAND %nonassoc K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ %nonassoc K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ K_NB_TRIGGER @@ -1495,6 +1497,10 @@ genvar_iteration /* IEEE1800-2012: A.4.2 */ { $$.text = $1; $$.expr = $3; } + | IDENTIFIER compressed_operator expression + { $$.text = $1; + $$.expr = pform_genvar_compressed(@1, $1, $2, $3);; + } | IDENTIFIER K_INCR { $$.text = $1; $$.expr = pform_genvar_inc_dec(@1, $1, true); @@ -6633,63 +6639,27 @@ statement_item /* This is roughly statement_item in the LRM */ ; +compressed_operator + : K_PLUS_EQ { $$ = '+'; } + | K_MINUS_EQ { $$ = '-'; } + | K_MUL_EQ { $$ = '*'; } + | K_DIV_EQ { $$ = '/'; } + | K_MOD_EQ { $$ = '%'; } + | K_AND_EQ { $$ = '&'; } + | K_OR_EQ { $$ = '|'; } + | K_XOR_EQ { $$ = '^'; } + | K_LS_EQ { $$ = 'l'; } + | K_RS_EQ { $$ = 'r'; } + | K_RSS_EQ { $$ = 'R'; } + ; + compressed_statement - : lpvalue K_PLUS_EQ expression - { PAssign*tmp = new PAssign($1, '+', $3); + : lpvalue compressed_operator expression + { PAssign*tmp = new PAssign($1, $2, $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_or_null_list_opt diff --git a/pform.cc b/pform.cc index b28a72735..a266ab043 100644 --- a/pform.cc +++ b/pform.cc @@ -2873,6 +2873,30 @@ PExpr* pform_genvar_inc_dec(const struct vlltype&loc, const char*name, bool inc_ return tmp; } +PExpr* pform_genvar_compressed(const struct vlltype &loc, const char *name, + char op, PExpr *rval) +{ + pform_requires_sv(loc, "Compressed assignment operator"); + + PExpr *lval = new PEIdent(lex_strings.make(name)); + FILE_NAME(lval, loc); + + PExpr *expr; + switch (op) { + case 'l': + case 'r': + case 'R': + expr = new PEBShift(op, lval, rval); + break; + default: + expr = new PEBinary(op, lval, rval); + break; + } + FILE_NAME(expr, loc); + + return expr; +} + void pform_set_attrib(perm_string name, perm_string key, char*value) { if (PWire*cur = lexical_scope->wires_find(name)) { diff --git a/pform.h b/pform.h index 6e7d617d6..928dcf97b 100644 --- a/pform.h +++ b/pform.h @@ -477,6 +477,9 @@ extern PAssign* pform_compressed_assign_from_inc_dec(const struct vlltype&loc, extern PExpr* pform_genvar_inc_dec(const struct vlltype&loc, const char*name, bool inc_flag); +extern PExpr* pform_genvar_compressed(const struct vlltype &loc, + const char *name, char op, PExpr *rval); + /* * These are functions that the outside-the-parser code uses the do * interesting things to the Verilog. The parse function reads and