Skip to content

Commit 839add1

Browse files
authored
Merge pull request #1350 from diffblue/four-valued-size-casts
Verilog: four-valued size casts
2 parents 0f7cfc1 + 8d77887 commit 839add1

File tree

5 files changed

+68
-12
lines changed

5 files changed

+68
-12
lines changed

regression/verilog/expressions/signed2.sv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module main;
1212
// base 8
1313
pB0: assert final ('so7 == -1);
1414
pB1: assert final ('so1 == 1);
15-
pB2: assert final ('so7x === 'so3777777777x);
15+
pB2: assert final ('so7x === 32'so3777777777x);
1616
pB3: assert final ($bits('so1) == 32);
1717
pB4: assert final ('so77 == -1);
1818
pB5: assert final (4'so7 == 7);
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
KNOWNBUG
1+
CORE
22
size_cast2.sv
33
--module main
44
^EXIT=0$
55
^SIGNAL=0$
66
--
77
^warning: ignoring
88
--
9-
This is not yet implemented.

src/verilog/aval_bval_encoding.cpp

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -188,22 +188,51 @@ exprt aval_bval_conversion(const exprt &src, const typet &dest)
188188

189189
if(is_aval_bval(src.type()))
190190
{
191+
// four-valued to four-valued
191192
auto src_width = aval_bval_width(src.type());
192193

193194
if(src_width == dest_width)
194195
{
195196
// same size
196197
return typecast_exprt{src, dest};
197198
}
198-
else
199+
else if(src_width > dest_width)
199200
{
201+
// shrink
200202
auto new_aval = adjust_size(aval(src), dest_width);
201203
auto new_bval = adjust_size(bval(src), dest_width);
202204
return combine_aval_bval(new_aval, new_bval, dest);
203205
}
206+
else
207+
{
208+
// extend
209+
auto underlying_src = aval_bval_underlying(src.type());
210+
auto underlying_dest = aval_bval_underlying(dest);
211+
212+
if(underlying_src.id() == ID_signedbv)
213+
{
214+
// sign extend both aval and bval
215+
auto new_aval = typecast_exprt{
216+
typecast_exprt{
217+
typecast_exprt{aval(src), underlying_src}, underlying_dest},
218+
bv_typet{dest_width}};
219+
auto new_bval = typecast_exprt{
220+
typecast_exprt{
221+
typecast_exprt{bval(src), underlying_src}, underlying_dest},
222+
bv_typet{dest_width}};
223+
return combine_aval_bval(new_aval, new_bval, dest);
224+
}
225+
else
226+
{
227+
auto new_aval = adjust_size(aval(src), dest_width);
228+
auto new_bval = adjust_size(bval(src), dest_width);
229+
return combine_aval_bval(new_aval, new_bval, dest);
230+
}
231+
}
204232
}
205233
else
206234
{
235+
// two-valued to four-valued
207236
const bv_typet bv_type{dest_width};
208237
auto aval =
209238
typecast_exprt{typecast_exprt{src, aval_bval_underlying(dest)}, bv_type};
@@ -501,14 +530,34 @@ exprt aval_bval(const verilog_implies_exprt &expr)
501530

502531
exprt aval_bval(const typecast_exprt &expr)
503532
{
504-
// 'true' is defined as a "nonzero known value" (1800-2017 12.4).
533+
auto &dest_type = expr.type();
534+
505535
PRECONDITION(is_aval_bval(expr.op()));
506-
PRECONDITION(expr.type().id() == ID_bool);
507536

508-
auto op_has_xz = ::has_xz(expr.op());
509-
auto op_aval = aval(expr.op());
510-
auto op_aval_zero = to_bv_type(op_aval.type()).all_zeros_expr();
511-
return and_exprt{not_exprt{op_has_xz}, notequal_exprt{op_aval, op_aval_zero}};
537+
if(dest_type.id() == ID_bool)
538+
{
539+
// 'true' is defined as a "nonzero known value" (1800-2017 12.4).
540+
auto op_has_xz = ::has_xz(expr.op());
541+
auto op_aval = aval(expr.op());
542+
auto op_aval_zero = to_bv_type(op_aval.type()).all_zeros_expr();
543+
return and_exprt{
544+
not_exprt{op_has_xz}, notequal_exprt{op_aval, op_aval_zero}};
545+
}
546+
else if(
547+
dest_type.id() == ID_verilog_unsignedbv ||
548+
dest_type.id() == ID_verilog_signedbv)
549+
{
550+
// four-valued to four-valued
551+
auto aval_bval_type = lower_to_aval_bval(dest_type);
552+
return aval_bval_conversion(expr.op(), aval_bval_type);
553+
}
554+
else if(dest_type.id() == ID_unsignedbv || dest_type.id() == ID_signedbv)
555+
{
556+
// four-valued to two-valued
557+
return typecast_exprt{aval(expr.op()), dest_type};
558+
}
559+
else
560+
PRECONDITION(false);
512561
}
513562

514563
exprt aval_bval(const shift_exprt &expr)

src/verilog/verilog_lowering.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ exprt verilog_lowering_cast(typecast_exprt expr)
303303
return std::move(new_cast);
304304
}
305305

306-
if(is_aval_bval(src_type) && dest_type.id() == ID_bool)
306+
if(is_aval_bval(src_type))
307307
{
308308
// When casting a four-valued scalar to bool,
309309
// 'true' is defined as a "nonzero known value" (1800-2017 12.4).
@@ -480,7 +480,7 @@ exprt verilog_lowering(exprt expr)
480480
}
481481
else if(expr.id() == ID_verilog_explicit_size_cast)
482482
{
483-
return to_verilog_explicit_size_cast_expr(expr).lower();
483+
return verilog_lowering(to_verilog_explicit_size_cast_expr(expr).lower());
484484
}
485485
else if(
486486
expr.id() == ID_verilog_streaming_concatenation_left_to_right ||

src/verilog/verilog_typecheck_expr.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3309,10 +3309,18 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
33093309
{
33103310
expr.type() = signedbv_typet{new_size_int};
33113311
}
3312+
else if(op_type.id() == ID_verilog_signedbv)
3313+
{
3314+
expr.type() = verilog_signedbv_typet{new_size_int};
3315+
}
33123316
else if(op_type.id() == ID_unsignedbv || op_type.id() == ID_bool)
33133317
{
33143318
expr.type() = unsignedbv_typet{new_size_int};
33153319
}
3320+
else if(op_type.id() == ID_verilog_unsignedbv)
3321+
{
3322+
expr.type() = verilog_unsignedbv_typet{new_size_int};
3323+
}
33163324
else
33173325
{
33183326
throw errort().with_location(expr.source_location())

0 commit comments

Comments
 (0)