Skip to content

Commit ec33684

Browse files
committed
SystemVerilog: assignment patterns with structure keys
This adds 1800-2017 assignment patters with keys for struct types.
1 parent c7a04c0 commit ec33684

File tree

5 files changed

+82
-11
lines changed

5 files changed

+82
-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

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: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2019,21 +2019,47 @@ 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(!expr.operands().empty() && expr.operands().front().id() == ID_member_initializer)
20232023
{
2024-
throw errort().with_location(expr.source_location())
2025-
<< "number of expressions does not match number of struct members";
2026-
}
2024+
exprt::operandst initializers{components.size(), nil_exprt{}};
2025+
2026+
for(auto &op : expr.operands())
2027+
{
2028+
PRECONDITION(op.id() == ID_member_initializer);
2029+
auto member_name = op.get(ID_member_name);
2030+
if(!struct_type.has_component(member_name))
2031+
{
2032+
throw errort().with_location(op.source_location())
2033+
<< "struct does not have a member `" << member_name << "'";
2034+
}
2035+
auto nr = struct_type.component_number(member_name);
2036+
auto value = to_unary_expr(op).op();
2037+
// rec. call
2038+
implicit_typecast(value, components[nr].type());
2039+
initializers[nr] = std::move(value);
2040+
}
20272041

2028-
for(std::size_t i = 0; i < components.size(); i++)
2042+
expr = struct_exprt{std::move(initializers), struct_type}.with_source_location(expr.source_location());
2043+
}
2044+
else
20292045
{
2030-
// rec. call
2031-
implicit_typecast(expr.operands()[i], components[i].type());
2046+
if(expr.operands().size() != components.size())
2047+
{
2048+
throw errort().with_location(expr.source_location())
2049+
<< "number of expressions does not match number of struct members";
2050+
}
2051+
2052+
for(std::size_t i = 0; i < components.size(); i++)
2053+
{
2054+
// rec. call
2055+
implicit_typecast(expr.operands()[i], components[i].type());
2056+
}
2057+
2058+
// turn into struct expression
2059+
expr.id(ID_struct);
2060+
expr.type() = dest_type;
20322061
}
20332062

2034-
// turn into struct expression
2035-
expr.id(ID_struct);
2036-
expr.type() = dest_type;
20372063
return;
20382064
}
20392065
else if(dest_type.id() == ID_array)
@@ -2620,6 +2646,11 @@ exprt verilog_typecheck_exprt::convert_unary_expr(unary_exprt expr)
26202646
// The type of these expressions is determined by their context.
26212647
expr.type() = typet(ID_verilog_new);
26222648
}
2649+
else if(expr.id() == ID_member_initializer)
2650+
{
2651+
// assignment patterns, 1800 2017 10.9
2652+
convert_expr(expr.op());
2653+
}
26232654
else
26242655
{
26252656
throw errort() << "no conversion for unary expression " << expr.id();

0 commit comments

Comments
 (0)