Merge pull request #798 from larsclausen/genvar-compressed
Support compressed assignment statements for genvar loops
This commit is contained in:
commit
3bea115c51
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
76
parse.y
|
|
@ -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
|
||||
|
|
|
|||
24
pform.cc
24
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)) {
|
||||
|
|
|
|||
3
pform.h
3
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue