Merge pull request #798 from larsclausen/genvar-compressed

Support compressed assignment statements for genvar loops
This commit is contained in:
Stephen Williams 2022-12-04 19:45:50 -08:00 committed by GitHub
commit 3bea115c51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 175 additions and 53 deletions

View File

@ -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

View File

@ -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

View File

@ -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

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 <letter> 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

View File

@ -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)) {

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,
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