Skip to content

Commit b07f60d

Browse files
authored
Merge pull request #1000 from diffblue/structure_pattern_key
SystemVerilog: assignment patterns with structure keys
2 parents 5c5091d + 24d6e6d commit b07f60d

File tree

9 files changed

+120
-11
lines changed

9 files changed

+120
-11
lines changed

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# EBMC 5.6
22

33
* SystemVerilog: typedefs from package scopes
4+
* SystemVerilog: assignment patterns with keys for structs
45

56
# EBMC 5.5
67

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CORE
2+
assignment_pattern1.sv
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module main;
2+
3+
typedef struct {int a, b;} S;
4+
var S x = '{b:1, a:0};
5+
6+
assert final (x.a == 0);
7+
assert final (x.b == 1);
8+
9+
endmodule
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
assignment_pattern2.sv
3+
4+
^file .* line 4: struct does not have a member `something_else'$
5+
^EXIT=2$
6+
^SIGNAL=0$
7+
--
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module main;
2+
3+
typedef struct {int a, b;} S;
4+
var S x = '{b:1, something_else:0};
5+
6+
endmodule
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
assignment_pattern3.sv
3+
4+
^file .* line 4: assignment pattern does not assign member `a'$
5+
^EXIT=2$
6+
^SIGNAL=0$
7+
--
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module main;
2+
3+
typedef struct {int a, b;} S;
4+
var S x = '{b:1}; // forgot a
5+
6+
endmodule

src/verilog/parser.y

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3649,8 +3649,30 @@ open_value_range: value_range;
36493649
// A.6.7.1 Patterns
36503650

36513651
assignment_pattern:
3652-
'\'' '{' expression_brace '}'
3652+
'\'' '{' expression_brace '}'
36533653
{ init($$, ID_verilog_assignment_pattern); swapop($$, $3); }
3654+
| '\'' '{' structure_pattern_key_brace '}'
3655+
{ init($$, ID_verilog_assignment_pattern); swapop($$, $3); }
3656+
;
3657+
3658+
structure_pattern_key_and_expression:
3659+
structure_pattern_key TOK_COLON expression
3660+
{ $$ = $1; mto($$, $3); }
3661+
;
3662+
3663+
structure_pattern_key_brace:
3664+
structure_pattern_key_and_expression
3665+
{ init($$); mto($$, $1); }
3666+
| structure_pattern_key_brace ',' structure_pattern_key_and_expression
3667+
{ $$ = $1; mto($$, $3); }
3668+
;
3669+
3670+
structure_pattern_key:
3671+
member_identifier
3672+
{
3673+
init($$, ID_member_initializer);
3674+
stack_expr($$).set(ID_member_name, stack_expr($1).get(ID_base_name));
3675+
}
36543676
;
36553677

36563678
assignment_pattern_expression:
@@ -4456,6 +4478,8 @@ ps_covergroup_identifier:
44564478

44574479
memory_identifier: identifier;
44584480

4481+
member_identifier: identifier;
4482+
44594483
method_identifier: identifier;
44604484

44614485
signal_identifier: identifier;

src/verilog/verilog_typecheck_expr.cpp

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2019,21 +2019,59 @@ void verilog_typecheck_exprt::implicit_typecast(
20192019
auto &struct_type = to_struct_type(dest_type);
20202020
auto &components = struct_type.components();
20212021

2022-
if(expr.operands().size() != components.size())
2022+
if(
2023+
!expr.operands().empty() &&
2024+
expr.operands().front().id() == ID_member_initializer)
20232025
{
2024-
throw errort().with_location(expr.source_location())
2025-
<< "number of expressions does not match number of struct members";
2026-
}
2026+
exprt::operandst initializers{components.size(), nil_exprt{}};
2027+
2028+
for(auto &op : expr.operands())
2029+
{
2030+
PRECONDITION(op.id() == ID_member_initializer);
2031+
auto member_name = op.get(ID_member_name);
2032+
if(!struct_type.has_component(member_name))
2033+
{
2034+
throw errort().with_location(op.source_location())
2035+
<< "struct does not have a member `" << member_name << "'";
2036+
}
2037+
auto nr = struct_type.component_number(member_name);
2038+
auto value = to_unary_expr(op).op();
2039+
// rec. call
2040+
implicit_typecast(value, components[nr].type());
2041+
initializers[nr] = std::move(value);
2042+
}
20272043

2028-
for(std::size_t i = 0; i < components.size(); i++)
2044+
// Is every member covered?
2045+
for(std::size_t i = 0; i < components.size(); i++)
2046+
if(initializers[i].is_nil())
2047+
{
2048+
throw errort().with_location(expr.source_location())
2049+
<< "assignment pattern does not assign member `"
2050+
<< components[i].get_name() << "'";
2051+
}
2052+
2053+
expr = struct_exprt{std::move(initializers), struct_type}
2054+
.with_source_location(expr.source_location());
2055+
}
2056+
else
20292057
{
2030-
// rec. call
2031-
implicit_typecast(expr.operands()[i], components[i].type());
2058+
if(expr.operands().size() != components.size())
2059+
{
2060+
throw errort().with_location(expr.source_location())
2061+
<< "number of expressions does not match number of struct members";
2062+
}
2063+
2064+
for(std::size_t i = 0; i < components.size(); i++)
2065+
{
2066+
// rec. call
2067+
implicit_typecast(expr.operands()[i], components[i].type());
2068+
}
2069+
2070+
// turn into struct expression
2071+
expr.id(ID_struct);
2072+
expr.type() = dest_type;
20322073
}
20332074

2034-
// turn into struct expression
2035-
expr.id(ID_struct);
2036-
expr.type() = dest_type;
20372075
return;
20382076
}
20392077
else if(dest_type.id() == ID_array)
@@ -2620,6 +2658,11 @@ exprt verilog_typecheck_exprt::convert_unary_expr(unary_exprt expr)
26202658
// The type of these expressions is determined by their context.
26212659
expr.type() = typet(ID_verilog_new);
26222660
}
2661+
else if(expr.id() == ID_member_initializer)
2662+
{
2663+
// assignment patterns, 1800 2017 10.9
2664+
convert_expr(expr.op());
2665+
}
26232666
else
26242667
{
26252668
throw errort() << "no conversion for unary expression " << expr.id();

0 commit comments

Comments
 (0)