Skip to content

Commit e3b8fda

Browse files
committed
Verilog: fix assignment context semantics
1 parent 4240ae8 commit e3b8fda

File tree

2 files changed

+38
-12
lines changed

2 files changed

+38
-12
lines changed
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
KNOWNBUG
1+
CORE
22
assignment-context1.sv
33

44
^EXIT=0$
55
^SIGNAL=0$
66
--
77
^warning: ignoring
88
--
9-
The variants that enlarge give a wrong answer.

src/verilog/verilog_typecheck.cpp

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,43 @@ void verilog_typecheckt::assignment_conversion(
4141
exprt &rhs,
4242
const typet &lhs_type)
4343
{
44-
// Implements 1800-2017 10.7
45-
// If the RHS is smaller than the LHS:
46-
// * if the RHS is unsigned, it is zero-padded
47-
// * if the RHS is signed, it is sign-extended
48-
// If the RHS is larger than the LHS, it is truncated.
49-
50-
// This matches our typecast, but differs from the steps taken
51-
// when evaluating binary expressions (11.8.2), where sign
52-
// extension only happens when the propagated type is signed.
53-
implicit_typecast(rhs, lhs_type);
44+
// Implements 1800-2017 10.7 and 1800-2017 11.8.3.
45+
//
46+
// "The size of the left-hand side of an assignment forms
47+
// the context for the right-hand expression."
48+
49+
// Get the width of LHS and RHS
50+
auto lhs_width = get_width(lhs_type);
51+
auto rhs_width = get_width(rhs.type());
52+
53+
if(lhs_width > rhs_width)
54+
{
55+
// Need to enlarge the RHS.
56+
//
57+
// "If needed, extend the size of the right-hand side,
58+
// performing sign extension if, and only if, the type
59+
// of the right-hand side is signed.
60+
if((rhs.type().id() == ID_signedbv || rhs.type().id() == ID_verilog_signedbv) &&
61+
(lhs_type.id() == ID_unsignedbv || lhs_type.id() == ID_verilog_unsignedbv))
62+
{
63+
// LHS is unsigned, RHS is signed. Must sign-extend.
64+
auto new_rhs_type = to_bitvector_type(rhs.type());
65+
new_rhs_type.set_width(numeric_cast_v<std::size_t>(lhs_width));
66+
67+
downwards_type_propagation(rhs, new_rhs_type);
68+
69+
// then cast
70+
rhs = typecast_exprt::conditional_cast(rhs, lhs_type);
71+
}
72+
else
73+
downwards_type_propagation(rhs, lhs_type);
74+
}
75+
else
76+
{
77+
// no need to enlarge
78+
rhs = typecast_exprt::conditional_cast(rhs, lhs_type);
79+
}
80+
5481
}
5582

5683
/*******************************************************************\

0 commit comments

Comments
 (0)