Support compressed assignment statements for genvar loops

SystemVerilog supports using compressed assignment operators for the genvar
for loop variable update.

Add support for this in a similar way as increment/decrement operators by
transforming the statement to its uncompressed equivalent. E.g. `x += y`
gets transformed to `x = x + y`.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
Lars-Peter Clausen 2022-10-04 00:09:25 +02:00
parent 3438078c90
commit 410c8207ef
3 changed files with 50 additions and 53 deletions

76
parse.y
View File

@ -704,6 +704,8 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
%type <package> package_scope %type <package> package_scope
%type <letter> compressed_operator
%token K_TAND %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_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 %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; { $$.text = $1;
$$.expr = $3; $$.expr = $3;
} }
| IDENTIFIER compressed_operator expression
{ $$.text = $1;
$$.expr = pform_genvar_compressed(@1, $1, $2, $3);;
}
| IDENTIFIER K_INCR | IDENTIFIER K_INCR
{ $$.text = $1; { $$.text = $1;
$$.expr = pform_genvar_inc_dec(@1, $1, true); $$.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 compressed_statement
: lpvalue K_PLUS_EQ expression : lpvalue compressed_operator expression
{ PAssign*tmp = new PAssign($1, '+', $3); { PAssign*tmp = new PAssign($1, $2, $3);
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);
$$ = tmp; $$ = 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 statement_or_null_list_opt

View File

@ -2873,6 +2873,30 @@ PExpr* pform_genvar_inc_dec(const struct vlltype&loc, const char*name, bool inc_
return tmp; 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) void pform_set_attrib(perm_string name, perm_string key, char*value)
{ {
if (PWire*cur = lexical_scope->wires_find(name)) { if (PWire*cur = lexical_scope->wires_find(name)) {

View File

@ -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, extern PExpr* pform_genvar_inc_dec(const struct vlltype&loc, const char*name,
bool inc_flag); 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 * These are functions that the outside-the-parser code uses the do
* interesting things to the Verilog. The parse function reads and * interesting things to the Verilog. The parse function reads and