Merge pull request #799 from larsclausen/foreach-omit
Allow to omit dimensions in foreach loop
This commit is contained in:
commit
1e84e78cd6
25
elaborate.cc
25
elaborate.cc
|
|
@ -5379,9 +5379,6 @@ NetProc* PForeach::elaborate_static_array_(Design*des, NetScope*scope,
|
||||||
<< "Handle as array with static dimensions." << endl;
|
<< "Handle as array with static dimensions." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
ivl_assert(*this, index_vars_.size() > 0);
|
|
||||||
ivl_assert(*this, dims.size() >= index_vars_.size());
|
|
||||||
|
|
||||||
NetProc*sub;
|
NetProc*sub;
|
||||||
if (statement_)
|
if (statement_)
|
||||||
sub = statement_->elaborate(des, scope);
|
sub = statement_->elaborate(des, scope);
|
||||||
|
|
@ -5389,9 +5386,23 @@ NetProc* PForeach::elaborate_static_array_(Design*des, NetScope*scope,
|
||||||
sub = new NetBlock(NetBlock::SEQU, 0);
|
sub = new NetBlock(NetBlock::SEQU, 0);
|
||||||
NetForLoop*stmt = 0;
|
NetForLoop*stmt = 0;
|
||||||
|
|
||||||
|
if (index_vars_.size() > dims.size()) {
|
||||||
|
delete sub;
|
||||||
|
cerr << get_fileline() << ": error: Number of foreach loop variables"
|
||||||
|
<< "(" << index_vars_.size() << ") must not exceed number of "
|
||||||
|
<< "array dimensions (" << dims.size() << ")." << endl;
|
||||||
|
des->errors++;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
for (int idx_idx = index_vars_.size()-1 ; idx_idx >= 0 ; idx_idx -= 1) {
|
for (int idx_idx = index_vars_.size()-1 ; idx_idx >= 0 ; idx_idx -= 1) {
|
||||||
const netrange_t&idx_range = dims[idx_idx];
|
const netrange_t&idx_range = dims[idx_idx];
|
||||||
|
|
||||||
|
// It is possible to skip dimensions by not providing a identifier
|
||||||
|
// name for it. E.g. `int x[1][2][3]; foreach(x[a,,b]) ...`
|
||||||
|
if (index_vars_[idx_idx].nil())
|
||||||
|
continue;
|
||||||
|
|
||||||
// Get the $high and $low constant values for this slice
|
// Get the $high and $low constant values for this slice
|
||||||
// of the array.
|
// of the array.
|
||||||
NetEConst*hig_expr = make_const_val_s(idx_range.get_msb());
|
NetEConst*hig_expr = make_const_val_s(idx_range.get_msb());
|
||||||
|
|
@ -5430,7 +5441,13 @@ NetProc* PForeach::elaborate_static_array_(Design*des, NetScope*scope,
|
||||||
sub = stmt;
|
sub = stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
return stmt? stmt : sub;
|
// If there are no loop variables elide the whole block
|
||||||
|
if (!stmt) {
|
||||||
|
delete sub;
|
||||||
|
return new NetBlock(NetBlock::SEQU, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
0 0
|
||||||
|
0 1
|
||||||
|
0 2
|
||||||
|
0 3
|
||||||
|
1 0
|
||||||
|
1 1
|
||||||
|
1 2
|
||||||
|
1 3
|
||||||
|
PASSED
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Check that foreach loops without an index list work as expected. This is not
|
||||||
|
// particularly useful, but it is legal code.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
logic a[10];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
foreach(a[]) begin
|
||||||
|
i++;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (i == 0) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Check that foreach loops with only empty indices works as expected. This is
|
||||||
|
// not particularly useful, but it is legal code.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
logic a[2][3][4];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
foreach(a[,,]) begin
|
||||||
|
i++;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (i == 0) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Check that it is possible to omit a dimensions in a foreach loop by not
|
||||||
|
// specifying a loop identifiers for the dimension.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
logic a[2][3][4];
|
||||||
|
int k = 0;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
foreach(a[i,,j]) begin
|
||||||
|
$display(i, j);
|
||||||
|
k++;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (k == 8) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
// Check that an error is reported if the number of loop indices exceeds the
|
||||||
|
// number of array dimensions in a foreach loop.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
logic a[10];
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
foreach(a[i,j]) begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -600,6 +600,10 @@ sv_foreach2 normal,-g2009 ivltests
|
||||||
sv_foreach3 normal,-g2009 ivltests
|
sv_foreach3 normal,-g2009 ivltests
|
||||||
sv_foreach4 normal,-g2009 ivltests
|
sv_foreach4 normal,-g2009 ivltests
|
||||||
sv_foreach5 normal,-g2009 ivltests
|
sv_foreach5 normal,-g2009 ivltests
|
||||||
|
sv_foreach6 normal,-g2009 ivltests
|
||||||
|
sv_foreach7 normal,-g2009 ivltests
|
||||||
|
sv_foreach8 normal,-g2009 ivltests gold=sv_foreach8.gold
|
||||||
|
sv_foreach_fail1 CE,-g2009 ivltests
|
||||||
sv_immediate_assert normal,-g2009 ivltests gold=sv_immediate_assert.gold
|
sv_immediate_assert normal,-g2009 ivltests gold=sv_immediate_assert.gold
|
||||||
sv_immediate_assume normal,-g2009 ivltests gold=sv_immediate_assume.gold
|
sv_immediate_assume normal,-g2009 ivltests gold=sv_immediate_assume.gold
|
||||||
sv_macro normal,-g2009 ivltests
|
sv_macro normal,-g2009 ivltests
|
||||||
|
|
|
||||||
|
|
@ -954,6 +954,9 @@ struct_signed normal,-g2009,-pallowsigned=1 ivltests
|
||||||
sv_for_variable normal,-g2009,-pallowsigned=1 ivltests
|
sv_for_variable normal,-g2009,-pallowsigned=1 ivltests
|
||||||
sv_foreach1 normal,-g2009,-pallowsigned=1 ivltests
|
sv_foreach1 normal,-g2009,-pallowsigned=1 ivltests
|
||||||
sv_foreach5 normal,-g2009,-pallowsigned=1 ivltests
|
sv_foreach5 normal,-g2009,-pallowsigned=1 ivltests
|
||||||
|
sv_foreach6 normal,-g2009,-pallowsigned=1 ivltests
|
||||||
|
sv_foreach7 normal,-g2009,-pallowsigned=1 ivltests
|
||||||
|
sv_foreach8 normal,-g2009,-pallowsigned=1 ivltests
|
||||||
sv_package normal,-g2009,-pallowsigned=1 ivltests
|
sv_package normal,-g2009,-pallowsigned=1 ivltests
|
||||||
sv_package2 normal,-g2009,-pallowsigned=1 ivltests
|
sv_package2 normal,-g2009,-pallowsigned=1 ivltests
|
||||||
sv_package5 normal,-g2009,-pallowsigned=1 ivltests
|
sv_package5 normal,-g2009,-pallowsigned=1 ivltests
|
||||||
|
|
|
||||||
10
parse.y
10
parse.y
|
|
@ -1799,12 +1799,22 @@ loop_variables /* IEEE1800-2005: A.6.8 */
|
||||||
delete[]$3;
|
delete[]$3;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
|
| loop_variables ','
|
||||||
|
{ std::list<perm_string>*tmp = $1;
|
||||||
|
tmp->push_back(perm_string());
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
| IDENTIFIER
|
| IDENTIFIER
|
||||||
{ std::list<perm_string>*tmp = new std::list<perm_string>;
|
{ std::list<perm_string>*tmp = new std::list<perm_string>;
|
||||||
tmp->push_back(lex_strings.make($1));
|
tmp->push_back(lex_strings.make($1));
|
||||||
delete[]$1;
|
delete[]$1;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
{ std::list<perm_string>*tmp = new std::list<perm_string>;
|
||||||
|
tmp->push_back(perm_string());
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
method_qualifier /* IEEE1800-2005: A.1.8 */
|
method_qualifier /* IEEE1800-2005: A.1.8 */
|
||||||
|
|
|
||||||
2
pform.cc
2
pform.cc
|
|
@ -994,6 +994,8 @@ void pform_make_foreach_declarations(const struct vlltype&loc,
|
||||||
list<decl_assignment_t*>assign_list;
|
list<decl_assignment_t*>assign_list;
|
||||||
for (list<perm_string>::const_iterator cur = loop_vars->begin()
|
for (list<perm_string>::const_iterator cur = loop_vars->begin()
|
||||||
; cur != loop_vars->end() ; ++ cur) {
|
; cur != loop_vars->end() ; ++ cur) {
|
||||||
|
if (cur->nil())
|
||||||
|
continue;
|
||||||
decl_assignment_t*tmp_assign = new decl_assignment_t;
|
decl_assignment_t*tmp_assign = new decl_assignment_t;
|
||||||
tmp_assign->name = lex_strings.make(*cur);
|
tmp_assign->name = lex_strings.make(*cur);
|
||||||
assign_list.push_back(tmp_assign);
|
assign_list.push_back(tmp_assign);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue