Skip to content

Commit e57e9c7

Browse files
committed
Merge branch 'main' of https://github.com/ShashankVM/hw-cbmc into vcd_for_all_cover
2 parents 47d163d + bd5b05e commit e57e9c7

File tree

10 files changed

+151
-101
lines changed

10 files changed

+151
-101
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
KNOWNBUG
2+
unpacked_array_concatenation1.sv
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
--
8+
This yields a type checking error.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module main;
2+
3+
// 1800-2017 10.10 Unpacked array concatenation
4+
byte my_bytes [1:4] = { 1, 2, 3, 4 };
5+
6+
assert final(my_bytes[1] == 1);
7+
assert final(my_bytes[2] == 2);
8+
assert final(my_bytes[3] == 3);
9+
assert final(my_bytes[4] == 4);
10+
11+
endmodule

regression/verilog/structs/structs4.sv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module main;
1212
s.field3 = 'b1110011;
1313
end
1414

15-
// structs can be converted without cast to bit-vectors
15+
// packed structs can be converted without cast to bit-vectors
1616
wire [8:0] w = s;
1717

1818
// Expected to pass.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
unpacked_struct1.sv
3+
4+
^file .* line 9: failed to convert `struct' to `\[8:0\]'$
5+
^EXIT=2$
6+
^SIGNAL=0$
7+
--
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module main;
2+
3+
// an unpacked struct
4+
struct {
5+
bit field;
6+
} s;
7+
8+
// unpacked structs cannot be converted to bit-vectors
9+
wire [8:0] w = s;
10+
11+
endmodule

src/verilog/expr2verilog.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2149,7 +2149,10 @@ std::string expr2verilogt::convert(const typet &type)
21492149
}
21502150
else if(type.id() == ID_struct)
21512151
{
2152-
return "struct";
2152+
if(type.get_bool(ID_packed))
2153+
return "struct packed";
2154+
else
2155+
return "struct";
21532156
}
21542157
else if(type.id() == ID_union)
21552158
{

src/verilog/parser.y

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1552,6 +1552,8 @@ data_type:
15521552
| struct_union packed_opt signing_opt
15531553
'{' struct_union_member_brace '}' packed_dimension_brace
15541554
{ $$=$1;
1555+
if(stack_expr($2).id() == ID_packed)
1556+
stack_type($1).set(ID_packed, true);
15551557
addswap($$, ID_declaration_list, $5); }
15561558
| TOK_ENUM enum_base_type_opt '{' enum_name_declaration_list '}'
15571559
{ // Like in C, these do _not_ create a scope.

src/verilog/verilog_elaborate_type.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,8 +425,14 @@ typet verilog_typecheck_exprt::elaborate_type(const typet &src)
425425
}
426426
}
427427

428-
return struct_union_typet{src.id(), std::move(components)}
429-
.with_source_location(src.source_location());
428+
auto result =
429+
struct_union_typet{src.id(), std::move(components)}.with_source_location(
430+
src.source_location());
431+
432+
if(src.get_bool(ID_packed))
433+
result.set(ID_packed, true);
434+
435+
return result;
430436
}
431437
else if(src.id() == ID_verilog_string)
432438
{

src/verilog/verilog_typecheck.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,104 @@ void verilog_typecheckt::assignment_conversion(
4141
exprt &rhs,
4242
const typet &lhs_type)
4343
{
44+
// 1800-2017 10.9
45+
if(rhs.type().id() == ID_verilog_assignment_pattern)
46+
{
47+
DATA_INVARIANT(
48+
rhs.id() == ID_verilog_assignment_pattern,
49+
"verilog_assignment_pattern expression expected");
50+
if(lhs_type.id() == ID_struct)
51+
{
52+
auto &struct_type = to_struct_type(lhs_type);
53+
auto &components = struct_type.components();
54+
55+
if(
56+
!rhs.operands().empty() &&
57+
rhs.operands().front().id() == ID_member_initializer)
58+
{
59+
exprt::operandst initializers{components.size(), nil_exprt{}};
60+
61+
for(auto &op : rhs.operands())
62+
{
63+
PRECONDITION(op.id() == ID_member_initializer);
64+
auto member_name = op.get(ID_member_name);
65+
if(!struct_type.has_component(member_name))
66+
{
67+
throw errort().with_location(op.source_location())
68+
<< "struct does not have a member `" << member_name << "'";
69+
}
70+
auto nr = struct_type.component_number(member_name);
71+
auto value = to_unary_expr(op).op();
72+
// rec. call
73+
assignment_conversion(value, components[nr].type());
74+
initializers[nr] = std::move(value);
75+
}
76+
77+
// Is every member covered?
78+
for(std::size_t i = 0; i < components.size(); i++)
79+
if(initializers[i].is_nil())
80+
{
81+
throw errort().with_location(rhs.source_location())
82+
<< "assignment pattern does not assign member `"
83+
<< components[i].get_name() << "'";
84+
}
85+
86+
rhs = struct_exprt{std::move(initializers), struct_type}
87+
.with_source_location(rhs.source_location());
88+
}
89+
else
90+
{
91+
if(rhs.operands().size() != components.size())
92+
{
93+
throw errort().with_location(rhs.source_location())
94+
<< "number of expressions does not match number of struct members";
95+
}
96+
97+
for(std::size_t i = 0; i < components.size(); i++)
98+
{
99+
// rec. call
100+
assignment_conversion(rhs.operands()[i], components[i].type());
101+
}
102+
103+
// turn into struct expression
104+
rhs.id(ID_struct);
105+
rhs.type() = lhs_type;
106+
}
107+
108+
return;
109+
}
110+
else if(lhs_type.id() == ID_array)
111+
{
112+
auto &array_type = to_array_type(lhs_type);
113+
auto &element_type = array_type.element_type();
114+
auto array_size =
115+
numeric_cast_v<mp_integer>(to_constant_expr(array_type.size()));
116+
117+
if(array_size != rhs.operands().size())
118+
{
119+
throw errort().with_location(rhs.source_location())
120+
<< "number of expressions does not match number of array elements";
121+
}
122+
123+
for(std::size_t i = 0; i < array_size; i++)
124+
{
125+
// rec. call
126+
assignment_conversion(rhs.operands()[i], element_type);
127+
}
128+
129+
// turn into array expression
130+
rhs.id(ID_array);
131+
rhs.type() = lhs_type;
132+
return;
133+
}
134+
else
135+
{
136+
throw errort().with_location(rhs.source_location())
137+
<< "cannot convert assignment pattern to '" << to_string(lhs_type)
138+
<< '\'';
139+
}
140+
}
141+
44142
// Implements 1800-2017 10.7
45143
// If the RHS is smaller than the LHS:
46144
// * if the RHS is unsigned, it is zero-padded

src/verilog/verilog_typecheck_expr.cpp

Lines changed: 1 addition & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,102 +2191,6 @@ void verilog_typecheck_exprt::implicit_typecast(
21912191
return;
21922192
}
21932193
}
2194-
else if(src_type.id() == ID_verilog_assignment_pattern)
2195-
{
2196-
DATA_INVARIANT(
2197-
expr.id() == ID_verilog_assignment_pattern,
2198-
"verilog_assignment_pattern expression expected");
2199-
if(dest_type.id() == ID_struct)
2200-
{
2201-
auto &struct_type = to_struct_type(dest_type);
2202-
auto &components = struct_type.components();
2203-
2204-
if(
2205-
!expr.operands().empty() &&
2206-
expr.operands().front().id() == ID_member_initializer)
2207-
{
2208-
exprt::operandst initializers{components.size(), nil_exprt{}};
2209-
2210-
for(auto &op : expr.operands())
2211-
{
2212-
PRECONDITION(op.id() == ID_member_initializer);
2213-
auto member_name = op.get(ID_member_name);
2214-
if(!struct_type.has_component(member_name))
2215-
{
2216-
throw errort().with_location(op.source_location())
2217-
<< "struct does not have a member `" << member_name << "'";
2218-
}
2219-
auto nr = struct_type.component_number(member_name);
2220-
auto value = to_unary_expr(op).op();
2221-
// rec. call
2222-
implicit_typecast(value, components[nr].type());
2223-
initializers[nr] = std::move(value);
2224-
}
2225-
2226-
// Is every member covered?
2227-
for(std::size_t i = 0; i < components.size(); i++)
2228-
if(initializers[i].is_nil())
2229-
{
2230-
throw errort().with_location(expr.source_location())
2231-
<< "assignment pattern does not assign member `"
2232-
<< components[i].get_name() << "'";
2233-
}
2234-
2235-
expr = struct_exprt{std::move(initializers), struct_type}
2236-
.with_source_location(expr.source_location());
2237-
}
2238-
else
2239-
{
2240-
if(expr.operands().size() != components.size())
2241-
{
2242-
throw errort().with_location(expr.source_location())
2243-
<< "number of expressions does not match number of struct members";
2244-
}
2245-
2246-
for(std::size_t i = 0; i < components.size(); i++)
2247-
{
2248-
// rec. call
2249-
implicit_typecast(expr.operands()[i], components[i].type());
2250-
}
2251-
2252-
// turn into struct expression
2253-
expr.id(ID_struct);
2254-
expr.type() = dest_type;
2255-
}
2256-
2257-
return;
2258-
}
2259-
else if(dest_type.id() == ID_array)
2260-
{
2261-
auto &array_type = to_array_type(dest_type);
2262-
auto &element_type = array_type.element_type();
2263-
auto array_size =
2264-
numeric_cast_v<mp_integer>(to_constant_expr(array_type.size()));
2265-
2266-
if(array_size != expr.operands().size())
2267-
{
2268-
throw errort().with_location(expr.source_location())
2269-
<< "number of expressions does not match number of array elements";
2270-
}
2271-
2272-
for(std::size_t i = 0; i < array_size; i++)
2273-
{
2274-
// rec. call
2275-
implicit_typecast(expr.operands()[i], element_type);
2276-
}
2277-
2278-
// turn into array expression
2279-
expr.id(ID_array);
2280-
expr.type() = dest_type;
2281-
return;
2282-
}
2283-
else
2284-
{
2285-
throw errort().with_location(expr.source_location())
2286-
<< "cannot convert assignment pattern to '" << to_string(dest_type)
2287-
<< '\'';
2288-
}
2289-
}
22902194
else if(src_type.id() == ID_verilog_real)
22912195
{
22922196
if(
@@ -2481,7 +2385,7 @@ void verilog_typecheck_exprt::struct_decay(exprt &expr) const
24812385
// Verilog packed struct types decay to a vector type [$bits(t)-1:0]
24822386
// when used in relational or arithmetic expressions.
24832387
auto &type = expr.type();
2484-
if(type.id() == ID_struct)
2388+
if(type.id() == ID_struct && type.get_bool(ID_packed))
24852389
{
24862390
auto new_type =
24872391
unsignedbv_typet{numeric_cast_v<std::size_t>(get_width(type))};

0 commit comments

Comments
 (0)