Skip to content

Commit 32329e3

Browse files
committed
Verilog: strong typing for enums
The SystemVerilog 1800-2017 standard requires that enums are strongly typed, i.e., that automatic conversion to an enum type is prohibited.
1 parent 63c6f4b commit 32329e3

13 files changed

+111
-35
lines changed
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
KNOWNBUG
1+
CORE
22
enum2.sv
33

4-
^EXIT=10$
4+
^file .* line 4: assignment to enum requires enum of the same type$
5+
^EXIT=2$
56
^SIGNAL=0$
67
--
7-
--
8-
enum constants must be strongly typed.
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
KNOWNBUG
1+
CORE
22
enum4.sv
33
--bound 0
4-
^EXIT=10$
4+
^EXIT=0$
55
^SIGNAL=0$
6-
^\[main\.property\.p1\] always main\.my_light != 0 \+ 1 \+ 1 \+ 1: PROVED up to bound 0$
6+
^\[main\.property\.p1\] always 1 == 1: PROVED up to bound 0$
77
--
8-
--
9-
Type conversion not working
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
enum_base_type1.sv
3+
--bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[.*\] always 8 == 8: PROVED up to bound 0$
7+
--
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module main;
2+
3+
typedef enum bit [7:0] { A } enum_t;
4+
5+
// expected to pass
6+
p1: assert property ($bits(A) == 8);
7+
8+
endmodule
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
enum_cast1.sv
3+
--bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main\.property\.p1\] always 1 == 1: PROVED up to bound 0$
7+
^\[main\.property\.p2\] always 2 == 2: PROVED up to bound 0$
8+
--
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module main;
2+
3+
typedef enum { A = 1, B = 2 } enum_t;
4+
5+
// expected to pass
6+
p1: assert property (A == enum_t'(1));
7+
p2: assert property (B == enum_t'(2));
8+
9+
endmodule

src/hw_cbmc_irep_ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ IREP_ID_ONE(uwire)
106106
IREP_ID_ONE(wand)
107107
IREP_ID_ONE(automatic)
108108
IREP_ID_ONE(verilog_enum)
109+
IREP_ID_TWO(C_verilog_type, #verilog_type)
109110
IREP_ID_ONE(verilog_type_reference)
110111
IREP_ID_ONE(enum_names)
111112
IREP_ID_ONE(var)

src/verilog/parser.y

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,11 @@ data_type:
12531253
init($$, ID_verilog_enum);
12541254
stack_type($$).add_subtype() = std::move(stack_type($2));
12551255
stack_type($$).set(ID_enum_names, stack_type($4));
1256+
1257+
// We attach a dummy id to distinguish two syntactically
1258+
// identical enum types.
1259+
auto id = PARSER.current_scope->prefix + "enum-" + PARSER.get_next_id();
1260+
stack_expr($$).set(ID_identifier, id);
12561261
}
12571262
| TOK_STRING
12581263
{ init($$, ID_string); }
@@ -1328,7 +1333,9 @@ enum_base_type_opt:
13281333
{ init($$, ID_nil); }
13291334
| integer_atom_type signing_opt
13301335
| integer_vector_type signing_opt packed_dimension_opt
1336+
{ $$ = $3; add_as_subtype(stack_type($$), stack_type($1)); }
13311337
| type_identifier packed_dimension_opt
1338+
{ $$ = $2; add_as_subtype(stack_type($$), stack_type($1)); }
13321339
;
13331340

13341341
non_integer_type:
@@ -2125,7 +2132,7 @@ gate_instance:
21252132

21262133
name_of_gate_instance_opt:
21272134
/* Optional */
2128-
{ init($$, "$_&#ANON" + PARSER.get_dummy_id()); }
2135+
{ init($$, "$_&#ANON" + PARSER.get_next_id()); }
21292136
| name_of_gate_instance
21302137
;
21312138

@@ -2192,7 +2199,7 @@ module_instance:
21922199
;
21932200

21942201
name_of_instance:
2195-
{ init($$, "$_&#ANON" + PARSER.get_dummy_id());}
2202+
{ init($$, "$_&#ANON" + PARSER.get_next_id());}
21962203
| TOK_NON_TYPE_IDENTIFIER
21972204
;
21982205

src/verilog/verilog_elaborate.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,8 @@ void verilog_typecheckt::collect_symbols(const typet &type)
102102
if(enum_type.has_base_type())
103103
collect_symbols(enum_type.base_type());
104104

105-
// The default base type is 'int'.
106-
auto base_type =
107-
enum_type.has_base_type() ? enum_type.base_type() : signedbv_typet(32);
105+
// convert the type now
106+
auto converted_type = convert_type(enum_type);
108107

109108
// Add the enum names to the symbol table for subsequent elaboration.
110109
// Values are given, or the previous plus one, starting with value '0'.
@@ -113,13 +112,17 @@ void verilog_typecheckt::collect_symbols(const typet &type)
113112
for(auto &enum_name : enum_type.enum_names())
114113
{
115114
if(enum_name.value().is_not_nil())
116-
initializer = enum_name.value();
115+
{
116+
exprt tmp = enum_name.value();
117+
convert_expr(tmp);
118+
initializer = std::move(tmp);
119+
}
117120

118-
exprt value = typecast_exprt(initializer, base_type);
121+
exprt value = typecast_exprt(initializer, converted_type);
119122

120123
const auto base_name = enum_name.base_name();
121124
const auto identifier = hierarchical_identifier(base_name);
122-
symbolt enum_name_symbol(identifier, base_type, mode);
125+
symbolt enum_name_symbol(identifier, converted_type, mode);
123126
enum_name_symbol.module = module_identifier;
124127
enum_name_symbol.base_name = base_name;
125128
enum_name_symbol.value = std::move(value);
@@ -128,8 +131,8 @@ void verilog_typecheckt::collect_symbols(const typet &type)
128131
add_symbol(std::move(enum_name_symbol));
129132

130133
initializer = plus_exprt(
131-
typecast_exprt(initializer, base_type),
132-
typecast_exprt(from_integer(1, integer_typet()), base_type));
134+
typecast_exprt(initializer, converted_type),
135+
typecast_exprt(from_integer(1, integer_typet()), converted_type));
133136
}
134137
}
135138
}

src/verilog/verilog_parser.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ class verilog_parsert:public parsert
4646

4747
verilog_parsert():mode(VIS_VERILOG)
4848
{
49-
dummy_id=0;
5049
}
5150

5251
// parser scopes and identifiers
@@ -118,12 +117,14 @@ class verilog_parsert:public parsert
118117
return scope_ptr == nullptr ? false : scope_ptr->is_type;
119118
}
120119

121-
unsigned dummy_id;
120+
// These are used for anonymous gate instances
121+
// and to create a unique identifier for enum types.
122+
std::size_t next_id_counter = 0;
122123

123-
std::string get_dummy_id()
124+
std::string get_next_id()
124125
{
125-
dummy_id++;
126-
return integer2string(dummy_id-1);
126+
next_id_counter++;
127+
return integer2string(next_id_counter - 1);
127128
}
128129
};
129130

0 commit comments

Comments
 (0)