From 410c8207ef19a6cede227b4fa925bd007ddddf25 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 4 Oct 2022 00:09:25 +0200 Subject: [PATCH 1/2] 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 --- parse.y | 76 +++++++++++++++++--------------------------------------- pform.cc | 24 ++++++++++++++++++ pform.h | 3 +++ 3 files changed, 50 insertions(+), 53 deletions(-) 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 From 9553a872daf24cb3bb7bacd1ac864f93122c6284 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 4 Dec 2022 14:16:13 -0800 Subject: [PATCH 2/2] Add regression test for compressed assignment statement in genvar loops Check that compressed assignment statements are supported for genvar loops. This is supported in SystemVerilog, but not in Verilog. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/genvar_compressed.v | 123 ++++++++++++++++++++++++++++ ivtest/regress-sv.list | 1 + ivtest/regress-vlog95.list | 1 + 3 files changed, 125 insertions(+) create mode 100644 ivtest/ivltests/genvar_compressed.v diff --git a/ivtest/ivltests/genvar_compressed.v b/ivtest/ivltests/genvar_compressed.v new file mode 100644 index 000000000..e6ea2eb04 --- /dev/null +++ b/ivtest/ivltests/genvar_compressed.v @@ -0,0 +1,123 @@ +// Check that compressed assignment statements are supported for genvar loops. +// This is supported in SystemVerilog, but not in Verilog. + +module test; + +integer array1[0:3]; +integer array2[1:4]; +integer array3[1:8]; +integer array4[1:16]; +integer array5[10:10]; +integer array6[1:8]; +integer array7[1:16]; +integer array8[1:16]; +integer array9[0:3]; +integer array10[4:7]; +integer array11[0:3]; + +for (genvar i = 0; i < 4; i += 1) begin + initial array1[i] = i; +end + +for (genvar i = 4; i > 0; i -= 1) begin + initial array2[i] = i; +end + +for (genvar i = 1; i < 16; i *= 2) begin + initial array3[i] = i; +end + +for (genvar i = 16; i > 0; i /= 2) begin + initial array4[i] = i; +end + +for (genvar i = 10; i > 0; i %= 2) begin + initial array5[i] = i; +end + +for (genvar i = 1; i < 16; i <<= 1) begin + initial array6[i] = i; +end + +for (genvar i = 16; i > 0; i >>= 1) begin + initial array7[i] = i; +end + +for (genvar i = 16; i > 0; i >>>= 1) begin + initial array8[i] = i; +end + +for (genvar i = 0; i < 4; i |= i + 1) begin + initial array9[i] = i; +end + +for (genvar i = 7; i > 0; i &= i - 1) begin + initial array10[i] = i; +end + +for (genvar i = 0; i < 4; i ^= i + 1) begin + initial array11[i] = i; +end + +`define check(a) if (a[i] !== i) begin \ + failed = 1; \ + $display("FAILED(%d): Expected %0d, got %0d.", `__LINE__, i, a[i]); \ + end + + +integer i; +reg failed = 1'b0; + +initial begin + #1 + for (i = 0; i < 4; i = i + 1) begin + `check(array1) + end + + for (i = 4; i > 0; i = i - 1) begin + `check(array2) + end + + for (i = 1; i < 16; i = i * 2) begin + `check(array3) + end + + for (i = 16; i > 0; i = i / 2) begin + `check(array4) + end + + for (i = 10; i != 0; i = i % 2) begin + `check(array5) + end + + for (i = 1; i < 16; i = i << 2) begin + `check(array6) + end + + for (i = 16; i > 0; i = i >> 2) begin + `check(array7) + end + + for (i = 16; i > 0; i = i >>> 2) begin + `check(array8) + end + + for (i = 1; i < 4; i = i | (i + 1)) begin + `check(array9) + end + + for (i = 7; i > 0; i = i & (i - 1)) begin + `check(array10) + end + + for (i = 0; i < 4; i = i ^ (i + 1)) begin + `check(array11) + end + + if (failed) + $display("FAILED"); + else + $display("PASSED"); +end + +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index e653d9ccc..cf7a8f06a 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -311,6 +311,7 @@ function10 CO,-g2005-sv ivltests function11 CE,-g2005-sv ivltests function12 normal,-g2005-sv ivltests gold=function12.gold genvar_inc_dec normal,-g2009 ivltests +genvar_compressed normal,-g2009 ivltests generate_module CE,-g2005-sv ivltests generate_timeunit CE,-g2005-sv ivltests ibit_test normal,-g2005-sv ivltests diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index bec2bf336..30cbdc3e6 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -618,6 +618,7 @@ generate_case CE ivltests generate_case2 CE ivltests generate_case3 CE ivltests genvar_inc_dec CE,-g2009 ivltests # also integer arrays +genvar_compressed CE,-g2009 ivltests # also integer arrays packeda2 CE,-g2009,-pallowsigned=1 ivltests pr1565699b CE ivltests pr1623097 CE ivltests