Skip to content

Commit f2f3a40

Browse files
authored
Merge pull request #578 from diffblue/assignment_pattern
Verilog: assignment pattern expressions
2 parents e746526 + 8ee5500 commit f2f3a40

File tree

9 files changed

+135
-0
lines changed

9 files changed

+135
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CORE
2+
array_literal1.sv
3+
--bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module main;
2+
3+
reg [7:0] my_array[10] = '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
4+
5+
initial p0: assert property (my_array[0] == 1);
6+
initial p1: assert property (my_array[9] == 10);
7+
8+
endmodule
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
array_literal2.sv
3+
4+
^file array_literal2\.sv line 3: number of expressions does not match number of array elements$
5+
^CONVERSION ERROR$
6+
^EXIT=2$
7+
^SIGNAL=0$
8+
--
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module main;
2+
3+
reg [7:0] my_array[10] = '{1, 2, 3, 4}; // too short
4+
5+
endmodule
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
structs5.sv
3+
--bound 0
4+
^\[main\.p1\] always main\.s\.field1 == 1: PROVED up to bound 0$
5+
^\[main\.p2\] always main\.s\.field2 == 0: PROVED up to bound 0$
6+
^\[main\.p3\] always main\.s\.field3 == 115: PROVED up to bound 0$
7+
^EXIT=0$
8+
^SIGNAL=0$
9+
--
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module main;
2+
3+
struct packed {
4+
bit field1, field2;
5+
bit [6:0] field3;
6+
} s = '{ 1, 0, 'b1110011 };
7+
8+
// Expected to pass.
9+
p1: assert property (s.field1 == 1);
10+
p2: assert property (s.field2 == 0);
11+
p3: assert property (s.field3 == 'b1110011);
12+
13+
endmodule

src/hw_cbmc_irep_ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ IREP_ID_TWO(C_little_endian, #little_endian)
5050
IREP_ID_ONE(ports)
5151
IREP_ID_ONE(inst)
5252
IREP_ID_ONE(Verilog)
53+
IREP_ID_ONE(verilog_assignment_pattern)
5354
IREP_ID_ONE(verilog_explicit_cast)
5455
IREP_ID_ONE(verilog_size_cast)
5556
IREP_ID_ONE(verilog_implicit_typecast)

src/verilog/parser.y

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3042,6 +3042,18 @@ case_item:
30423042
mto($$, $2); }
30433043
;
30443044

3045+
// System Verilog standard 1800-2017
3046+
// A.6.7.1 Patterns
3047+
3048+
assignment_pattern:
3049+
'\'' '{' expression_brace '}'
3050+
{ init($$, ID_verilog_assignment_pattern); swapop($$, $3); }
3051+
;
3052+
3053+
assignment_pattern_expression:
3054+
assignment_pattern
3055+
;
3056+
30453057
// System Verilog standard 1800-2017
30463058
// A.6.8 Looping statements
30473059
@@ -3364,6 +3376,7 @@ primary: primary_literal
33643376
| '(' mintypmax_expression ')'
33653377
{ $$ = $2; }
33663378
| cast
3379+
| assignment_pattern_expression
33673380
| TOK_NULL { init($$, ID_NULL); }
33683381
;
33693382

src/verilog/verilog_typecheck_expr.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,20 @@ exprt verilog_typecheck_exprt::convert_expr_rec(exprt expr)
318318
{
319319
return convert_expr_function_call(to_function_call_expr(expr));
320320
}
321+
else if(expr.id() == ID_verilog_assignment_pattern)
322+
{
323+
// multi-ary -- may become a struct or array, depending
324+
// on context.
325+
for(auto &op : expr.operands())
326+
convert_expr(op);
327+
328+
// Typechecking can only be completed once we know the type
329+
// from the usage context. We record "verilog_assignment_pattern"
330+
// to signal that.
331+
expr.type() = typet(ID_verilog_assignment_pattern);
332+
333+
return expr;
334+
}
321335
else
322336
{
323337
std::size_t no_op;
@@ -1814,6 +1828,64 @@ void verilog_typecheck_exprt::implicit_typecast(
18141828
return;
18151829
}
18161830
}
1831+
else if(src_type.id() == ID_verilog_assignment_pattern)
1832+
{
1833+
DATA_INVARIANT(
1834+
expr.id() == ID_verilog_assignment_pattern,
1835+
"verilog_assignment_pattern expression expected");
1836+
if(dest_type.id() == ID_struct)
1837+
{
1838+
auto &struct_type = to_struct_type(dest_type);
1839+
auto &components = struct_type.components();
1840+
1841+
if(expr.operands().size() != components.size())
1842+
{
1843+
throw errort().with_location(expr.source_location())
1844+
<< "number of expressions does not match number of struct members";
1845+
}
1846+
1847+
for(std::size_t i = 0; i < components.size(); i++)
1848+
{
1849+
// rec. call
1850+
implicit_typecast(expr.operands()[i], components[i].type());
1851+
}
1852+
1853+
// turn into struct expression
1854+
expr.id(ID_struct);
1855+
expr.type() = dest_type;
1856+
return;
1857+
}
1858+
else if(dest_type.id() == ID_array)
1859+
{
1860+
auto &array_type = to_array_type(dest_type);
1861+
auto &element_type = array_type.element_type();
1862+
auto array_size =
1863+
numeric_cast_v<mp_integer>(to_constant_expr(array_type.size()));
1864+
1865+
if(array_size != expr.operands().size())
1866+
{
1867+
throw errort().with_location(expr.source_location())
1868+
<< "number of expressions does not match number of array elements";
1869+
}
1870+
1871+
for(std::size_t i = 0; i < array_size; i++)
1872+
{
1873+
// rec. call
1874+
implicit_typecast(expr.operands()[i], element_type);
1875+
}
1876+
1877+
// turn into array expression
1878+
expr.id(ID_array);
1879+
expr.type() = dest_type;
1880+
return;
1881+
}
1882+
else
1883+
{
1884+
throw errort().with_location(expr.source_location())
1885+
<< "cannot convert assignment pattern to '" << to_string(dest_type)
1886+
<< '\'';
1887+
}
1888+
}
18171889

18181890
throw errort().with_location(expr.source_location())
18191891
<< "failed to convert `" << to_string(src_type) << "' to `"

0 commit comments

Comments
 (0)