Skip to content

Commit bd5891b

Browse files
authored
Merge pull request #560 from diffblue/unions
SystemVerilog Unions
2 parents c9fe05c + e88774a commit bd5891b

12 files changed

+153
-7
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
KNOWNBUG
2+
unions1.sv
3+
--bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
--
8+
cast bitvector to union missing

regression/verilog/unions/unions1.sv

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module main;
2+
3+
union packed {
4+
bit [6:0] field1;
5+
bit [6:0] field2;
6+
} u;
7+
8+
// bit-vectors can be converted without cast to packed unions
9+
initial u = 7'b1010101;
10+
11+
// Expected to pass.
12+
p0: assert property ($bits(u) == 7);
13+
p1: assert property (u.field1 == 7'b1010101);
14+
p2: assert property (u.field2 == 7'b1010101);
15+
16+
endmodule
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
unions2.sv
3+
--bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
--

regression/verilog/unions/unions2.sv

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module main;
2+
3+
union {
4+
bit field1;
5+
bit [6:0] field2;
6+
} u;
7+
8+
initial begin
9+
u.field2 = 0;
10+
u.field1 = 1;
11+
end
12+
13+
// Expected to pass.
14+
p1: assert property (u.field1 == 1);
15+
p2: assert property (u.field2 == 1);
16+
p3: assert property ($bits(u) == 7);
17+
18+
endmodule
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
unions3.sv
3+
--bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
--

regression/verilog/unions/unions3.sv

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module main;
2+
3+
union packed {
4+
// a struct inside a union
5+
struct packed {
6+
bit [7:0] field1;
7+
} field1;
8+
9+
bit [7:0] field2;
10+
} u;
11+
12+
initial begin
13+
u.field1.field1 = 123;
14+
end
15+
16+
// Expected to pass.
17+
p1: assert property (u.field2 == 123);
18+
19+
endmodule

src/hw_cbmc_irep_ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ IREP_ID_ONE(automatic)
150150
IREP_ID_TWO(C_verilog_type, #verilog_type)
151151
IREP_ID_TWO(C_verilog_aval_bval, #verilog_aval_bval)
152152
IREP_ID_ONE(verilog_enum)
153+
IREP_ID_ONE(verilog_packed)
153154
IREP_ID_ONE(verilog_packed_array)
154155
IREP_ID_ONE(verilog_type_reference)
155156
IREP_ID_ONE(verilog_unpacked_array)

src/verilog/verilog_synthesis.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -857,7 +857,9 @@ void verilog_synthesist::assignment_rec(
857857
const exprt &lhs_compound = member_expr.struct_op();
858858
auto component_name = member_expr.get_component_name();
859859

860-
if(lhs_compound.type().id() == ID_struct)
860+
if(
861+
lhs_compound.type().id() == ID_struct ||
862+
lhs_compound.type().id() == ID_union)
861863
{
862864
// turn
863865
// s.m=e

src/verilog/verilog_typecheck_base.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@ Author: Daniel Kroening, [email protected]
66
77
\*******************************************************************/
88

9-
#include <cassert>
9+
#include "verilog_typecheck_base.h"
1010

1111
#include <util/ebmc_util.h>
1212
#include <util/expr_util.h>
1313
#include <util/prefix.h>
1414
#include <util/std_types.h>
1515

1616
#include "expr2verilog.h"
17-
#include "verilog_typecheck_base.h"
17+
#include "verilog_types.h"
18+
19+
#include <cassert>
1820

1921
/*******************************************************************\
2022
@@ -200,6 +202,15 @@ verilog_typecheck_baset::get_width_opt(const typet &type)
200202
return sum;
201203
}
202204

205+
if(type.id() == ID_union)
206+
{
207+
// find the biggest
208+
mp_integer max = 0;
209+
for(auto &component : to_verilog_union_type(type).components())
210+
max = std::max(max, get_width(component.type()));
211+
return max;
212+
}
213+
203214
if(type.id() == ID_verilog_shortint)
204215
return 16;
205216
else if(type.id() == ID_verilog_int)

src/verilog/verilog_typecheck_base.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Author: Daniel Kroening, [email protected]
99
#ifndef CPROVER_VERILOG_TYPECHEK_BASE_H
1010
#define CPROVER_VERILOG_TYPECHEK_BASE_H
1111

12+
#include <util/expr.h>
1213
#include <util/mp_arith.h>
1314
#include <util/namespace.h>
1415
#include <util/typecheck.h>

src/verilog/verilog_typecheck_expr.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,16 +1593,17 @@ void verilog_typecheck_exprt::implicit_typecast(
15931593
expr = typecast_exprt{expr, dest_type};
15941594
return;
15951595
}
1596-
else if(dest_type.id() == ID_struct)
1596+
else if(dest_type.id() == ID_struct || dest_type.id() == ID_union)
15971597
{
1598-
// bit-vectors can be converted to packed structs
1598+
// bit-vectors can be converted to
1599+
// packed structs and packed unions
15991600
expr = typecast_exprt{expr, dest_type};
16001601
return;
16011602
}
16021603
}
1603-
else if(src_type.id() == ID_struct)
1604+
else if(src_type.id() == ID_struct || src_type.id() == ID_union)
16041605
{
1605-
// packed structs can be converted to bits
1606+
// packed structs and packed unions can be converted to bits
16061607
if(
16071608
dest_type.id() == ID_bool || dest_type.id() == ID_unsignedbv ||
16081609
dest_type.id() == ID_signedbv ||

src/verilog/verilog_types.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,4 +484,59 @@ inline verilog_type_referencet &to_verilog_type_reference(typet &type)
484484
return static_cast<verilog_type_referencet &>(type);
485485
}
486486

487+
/// The SystemVerilog struct/union type
488+
class verilog_struct_union_typet : public struct_union_typet
489+
{
490+
public:
491+
verilog_struct_union_typet(
492+
irep_idt __id,
493+
bool __is_packed,
494+
componentst _components)
495+
: struct_union_typet(__id, std::move(_components))
496+
{
497+
is_packed(__is_packed);
498+
}
499+
500+
bool is_packed() const
501+
{
502+
return get_bool(ID_verilog_packed);
503+
}
504+
505+
void is_packed(bool __is_packed)
506+
{
507+
return set(ID_verilog_packed, __is_packed);
508+
}
509+
};
510+
511+
/// The SystemVerilog union type
512+
class verilog_union_typet : public verilog_struct_union_typet
513+
{
514+
public:
515+
verilog_union_typet(bool __is_packed, componentst _components)
516+
: verilog_struct_union_typet(ID_union, __is_packed, std::move(_components))
517+
{
518+
}
519+
};
520+
521+
/// \brief Cast a typet to a \ref verilog_union_typet
522+
///
523+
/// This is an unchecked conversion. \a type must be known to be \ref
524+
/// verilog_union_typet. Will fail with a precondition violation if type
525+
/// doesn't match.
526+
///
527+
/// \param type: Source type.
528+
/// \return Object of type \ref verilog_union_typet
529+
inline const verilog_union_typet &to_verilog_union_type(const typet &type)
530+
{
531+
PRECONDITION(type.id() == ID_union);
532+
return static_cast<const verilog_union_typet &>(type);
533+
}
534+
535+
/// \copydoc to_union_type(const typet &)
536+
inline verilog_union_typet &to_verilog_union_type(typet &type)
537+
{
538+
PRECONDITION(type.id() == ID_union);
539+
return static_cast<verilog_union_typet &>(type);
540+
}
541+
487542
#endif

0 commit comments

Comments
 (0)