Skip to content

Commit bb810fd

Browse files
authored
Merge pull request #411 from diffblue/structs
SystemVerilog: structs
2 parents c6deb50 + c5c0b42 commit bb810fd

14 files changed

+316
-71
lines changed
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
KNOWNBUG
2+
structs1.sv
3+
--bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
--
8+
cast bitvector to struct missing
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module main;
2+
3+
// The first field is the most-significant bit.
4+
struct packed {
5+
bit field1, field2;
6+
bit [6:0] field3;
7+
} s;
8+
9+
// bit-vectors can be converted without cast to packed structs
10+
initial s = 8'b1011111;
11+
12+
// Expected to pass.
13+
p0: assert property ($bits(s) == 9);
14+
p1: assert property (s.field1 == 1);
15+
p2: assert property (s.field2 == 0);
16+
p3: assert property (s.field3 == 'b111111);
17+
18+
endmodule
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CORE
2+
structs2.sv
3+
--bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module main;
2+
3+
// The first field is the most-significant bit.
4+
struct packed {
5+
bit field1, field2;
6+
bit [6:0] field3;
7+
} s;
8+
9+
initial begin
10+
s.field1 = 1;
11+
s.field2 = 0;
12+
s.field3 = 127;
13+
end
14+
15+
// Expected to pass.
16+
p1: assert property (s.field1 == 1);
17+
p2: assert property (s.field2 == 0);
18+
p3: assert property (s.field3 == 'b1111111);
19+
20+
endmodule
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CORE
2+
structs3.sv
3+
--bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module main;
2+
3+
struct packed {
4+
// a struct inside a struct
5+
struct packed {
6+
bit [7:0] field1;
7+
} field1;
8+
} s;
9+
10+
initial begin
11+
s.field1.field1 = 123;
12+
end
13+
14+
// Expected to pass.
15+
p1: assert property (s.field1.field1 == 123);
16+
17+
endmodule

src/verilog/expr2verilog.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,14 @@ std::string expr2verilogt::convert(const typet &type)
12511251
{
12521252
return "enum";
12531253
}
1254+
else if(type.id() == ID_struct)
1255+
{
1256+
return "struct";
1257+
}
1258+
else if(type.id() == ID_union)
1259+
{
1260+
return "union";
1261+
}
12541262
else if(type.id() == ID_verilog_type_reference)
12551263
{
12561264
auto &type_reference = to_verilog_type_reference(type);

src/verilog/parser.y

+22-3
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,11 @@ property_qualifier:
982982
| class_item_qualifier
983983
;
984984

985+
random_qualifier_opt:
986+
/* Optional */
987+
| random_qualifier
988+
;
989+
985990
random_qualifier:
986991
TOK_RAND
987992
| TOK_RANDC
@@ -1257,8 +1262,9 @@ data_type:
12571262
}
12581263
| non_integer_type
12591264
| struct_union packed_opt signing_opt
1260-
'{' struct_union_member_list '}' packed_dimension_brace
1261-
{ /* todo */ }
1265+
'{' struct_union_member_brace '}' packed_dimension_brace
1266+
{ $$=$1;
1267+
addswap($$, ID_declaration_list, $5); }
12621268
| TOK_ENUM enum_base_type_opt '{' enum_name_declaration_list '}'
12631269
{ // Like in C, these do _not_ create a scope.
12641270
// The enum names go into the current scope.
@@ -1337,7 +1343,20 @@ integer_atom_type:
13371343
class_type: class_identifier
13381344
;
13391345

1340-
struct_union_member_list:
1346+
struct_union_member_brace:
1347+
/* Not optional! No empty structs. */
1348+
struct_union_member
1349+
{ init($$); mts($$, $1); }
1350+
| struct_union_member_brace struct_union_member
1351+
{ $$=$1; mts($$, $2); }
1352+
;
1353+
1354+
struct_union_member:
1355+
attribute_instance_brace
1356+
random_qualifier_opt
1357+
data_type_or_void
1358+
list_of_variable_decl_assignments ';'
1359+
{ $$=$4; stack_expr($$).id(ID_decl); addswap($$, ID_type, $3); }
13411360
;
13421361

13431362
enum_base_type_opt:

src/verilog/verilog_expr.h

+45-41
Original file line numberDiff line numberDiff line change
@@ -412,55 +412,59 @@ inline verilog_set_genvarst &to_verilog_set_genvars(exprt &expr)
412412
return static_cast<verilog_set_genvarst &>(expr);
413413
}
414414

415-
class verilog_parameter_declt : public verilog_module_itemt
415+
// This class is used for all declarators in the parse tree
416+
class verilog_declaratort : public exprt
416417
{
417418
public:
418-
inline verilog_parameter_declt() : verilog_module_itemt(ID_parameter_decl)
419+
const irep_idt &identifier() const
419420
{
421+
return get(ID_identifier);
420422
}
421423

422-
class declaratort : public exprt
424+
void identifier(irep_idt _identifier)
423425
{
424-
public:
425-
const irep_idt &identifier() const
426-
{
427-
return get(ID_identifier);
428-
}
426+
set(ID_identifier, _identifier);
427+
}
429428

430-
void identifier(irep_idt _identifier)
431-
{
432-
set(ID_identifier, _identifier);
433-
}
429+
const irep_idt &base_name() const
430+
{
431+
return get(ID_base_name);
432+
}
434433

435-
const irep_idt &base_name() const
436-
{
437-
return get(ID_base_name);
438-
}
434+
const exprt &value() const
435+
{
436+
return static_cast<const exprt &>(find(ID_value));
437+
}
439438

440-
const exprt &value() const
441-
{
442-
return static_cast<const exprt &>(find(ID_value));
443-
}
439+
exprt &value()
440+
{
441+
return static_cast<exprt &>(add(ID_value));
442+
}
444443

445-
exprt &value()
446-
{
447-
return static_cast<exprt &>(add(ID_value));
448-
}
444+
bool has_value() const
445+
{
446+
return find(ID_value).is_not_nil();
447+
}
449448

450-
bool has_value() const
451-
{
452-
return find(ID_value).is_not_nil();
453-
}
449+
// helper to generate a symbol expression
450+
symbol_exprt symbol_expr() const
451+
{
452+
return symbol_exprt(identifier(), type())
453+
.with_source_location<symbol_exprt>(*this);
454+
}
455+
};
454456

455-
// helper to generate a symbol expression
456-
symbol_exprt symbol_expr() const
457-
{
458-
return symbol_exprt(identifier(), type())
459-
.with_source_location<symbol_exprt>(*this);
460-
}
461-
};
457+
using verilog_declaratorst = std::vector<verilog_declaratort>;
458+
459+
class verilog_parameter_declt : public verilog_module_itemt
460+
{
461+
public:
462+
inline verilog_parameter_declt() : verilog_module_itemt(ID_parameter_decl)
463+
{
464+
}
462465

463-
using declaratorst = std::vector<declaratort>;
466+
using declaratort = verilog_declaratort;
467+
using declaratorst = verilog_declaratorst;
464468

465469
const declaratorst &declarations() const
466470
{
@@ -494,8 +498,8 @@ class verilog_local_parameter_declt : public verilog_module_itemt
494498
{
495499
}
496500

497-
using declaratort = verilog_parameter_declt::declaratort;
498-
using declaratorst = std::vector<declaratort>;
501+
using declaratort = verilog_declaratort;
502+
using declaratorst = verilog_declaratorst;
499503

500504
const declaratorst &declarations() const
501505
{
@@ -526,7 +530,7 @@ class verilog_lett : public verilog_module_itemt
526530
{
527531
public:
528532
// These have a single declarator.
529-
using declaratort = verilog_parameter_declt::declaratort;
533+
using declaratort = verilog_declaratort;
530534

531535
const declaratort &declarator() const
532536
{
@@ -715,8 +719,8 @@ class verilog_declt:public verilog_statementt
715719
}
716720

717721
// When it's not a function or task, there are declarators.
718-
using declaratort = verilog_parameter_declt::declaratort;
719-
using declaratorst = verilog_parameter_declt::declaratorst;
722+
using declaratort = verilog_declaratort;
723+
using declaratorst = verilog_declaratorst;
720724

721725
declaratorst &declarators()
722726
{

src/verilog/verilog_synthesis.cpp

+35-1
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,31 @@ void verilog_synthesist::assignment_rec(
571571

572572
new_value.swap(last_value);
573573
}
574+
else if(lhs.id() == ID_member)
575+
{
576+
const auto &member_expr = to_member_expr(lhs);
577+
const exprt &lhs_compound = member_expr.struct_op();
578+
auto component_name = member_expr.get_component_name();
579+
580+
if(lhs_compound.type().id() == ID_struct)
581+
{
582+
// turn
583+
// s.m=e
584+
// into
585+
// s'==s WITH [m:=e]
586+
auto synth_compound = synth_expr(lhs_compound, symbol_statet::FINAL);
587+
588+
with_exprt new_rhs{
589+
synth_compound, member_designatort{component_name}, rhs};
590+
591+
// recursive call
592+
assignment_rec(lhs_compound, new_rhs, new_value); // recursive call
593+
}
594+
else
595+
{
596+
throw errort() << "unexpected member lhs: " << lhs_compound.type().id();
597+
}
598+
}
574599
else
575600
{
576601
throw errort() << "unexpected lhs: " << lhs.id();
@@ -730,6 +755,10 @@ void verilog_synthesist::assignment_member_rec(
730755

731756
member.pop_back();
732757
}
758+
else if(lhs.id() == ID_member)
759+
{
760+
add_assignment_member(lhs, member, data);
761+
}
733762
else
734763
{
735764
throw errort() << "unexpected lhs: " << lhs.id();
@@ -861,9 +890,14 @@ const symbolt &verilog_synthesist::assignment_symbol(const exprt &lhs)
861890

862891
return it->second;
863892
}
893+
else if(e->id() == ID_member)
894+
{
895+
e = &to_member_expr(*e).struct_op();
896+
}
864897
else
865898
{
866-
throw errort() << "synthesis: failed to get identifier";
899+
throw errort().with_location(e->source_location())
900+
<< "synthesis: failed to get identifier";
867901
}
868902
}
869903
}

src/verilog/verilog_typecheck.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,10 @@ void verilog_typecheckt::check_lhs(
804804
break;
805805
}
806806
}
807+
else if(lhs.id() == ID_member)
808+
{
809+
check_lhs(to_member_expr(lhs).struct_op(), vassign);
810+
}
807811
else
808812
{
809813
throw errort() << "typechecking: failed to get identifier on LHS "

src/verilog/verilog_typecheck_base.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,15 @@ std::size_t verilog_typecheck_baset::get_width(const typet &type)
182182
return (array_size(to_array_type(type)) * element_width).to_ulong();
183183
}
184184

185+
if(type.id() == ID_struct)
186+
{
187+
// add them up
188+
mp_integer sum = 0;
189+
for(auto &component : to_struct_type(type).components())
190+
sum += get_width(component.type());
191+
return sum.to_ulong();
192+
}
193+
185194
if(type.id() == ID_verilog_shortint)
186195
return 16;
187196
else if(type.id() == ID_verilog_int)

0 commit comments

Comments
 (0)