Skip to content

Commit 485489e

Browse files
committed
SMV: convert typecasts to SMV
This adds conversion for a variety of typecast expressions into SMV syntax.
1 parent 3f0410b commit 485489e

File tree

5 files changed

+161
-4
lines changed

5 files changed

+161
-4
lines changed

regression/ebmc/smv-word-level/verilog1.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ verilog1.sv
66
^INIT main\.x = 0ud32_0$
77
^INVAR Verilog::main\.x_aux0 = main\.x \+ 0ud32_1$
88
^TRANS next\(main\.x\) = Verilog::main\.x_aux0$
9-
^LTLSPEC F main\.x = 0sd32_10$
9+
^LTLSPEC F main\.x = unsigned\(0sd32_10\)$
1010
^EXIT=0$
1111
^SIGNAL=0$
1212
--
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
CORE
2+
verilog2.sv
3+
--smv-word-level
4+
^MODULE main$
5+
^INIT main\.sw1 = extend\(signed\(main\.ui\), 24\)$
6+
^INIT main\.sw2 = extend\(main\.si, 24\)$
7+
^INIT main\.uw1 = extend\(main\.ui, 24\)$
8+
^INIT main\.uw2 = unsigned\(extend\(main\.si, 24\)\)$
9+
^INIT main\.sn1 = signed\(resize\(main\.ui, 4\)\)$
10+
^INIT main\.sn2 = typecast$
11+
^INIT main\.un1 = resize\(main\.ui, 4\)$
12+
^INIT main\.un2 = resize\(unsigned\(main\.si\), 4\)$
13+
^INIT main\.sb1 = signed\(main\.ui\)$
14+
^INIT main\.sb2 = main\.si$
15+
^INIT main\.ub1 = main\.ui$
16+
^INIT main\.ub2 = unsigned\(main\.si\)$
17+
^EXIT=0$
18+
^SIGNAL=0$
19+
--
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
module main(input clk, input signed [7:0] si, input unsigned [7:0] ui);
2+
3+
// enlarge
4+
wire signed [31:0] sw1 = ui; // unsigned 8 to signed 32
5+
wire signed [31:0] sw2 = si; // signed 8 to signed 32
6+
wire unsigned [31:0] uw1 = ui; // unsigned 8 to unsigned 32
7+
wire unsigned [31:0] uw2 = si; // signed 8 to unsigned 32
8+
9+
// shrink
10+
wire signed [3:0] sn1 = ui; // unsigned 8 to signed 4
11+
wire signed [3:0] sn2 = si; // signed 8 to signed 4
12+
wire unsigned [3:0] un1 = ui; // unsigned 8 to unsigned 4
13+
wire unsigned [3:0] un2 = si; // signed 8 to unsigned 4
14+
15+
// same size
16+
wire signed [7:0] sb1 = ui; // unsigned 8 to signed 8
17+
wire signed [7:0] sb2 = si; // signed 8 to signed 8
18+
wire unsigned [7:0] ub1 = ui; // unsigned 8 to unsigned 8
19+
wire unsigned [7:0] ub2 = si; // signed 8 to unsigned 8
20+
21+
endmodule

src/smvlang/expr2smv.cpp

Lines changed: 118 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ Author: Daniel Kroening, [email protected]
99
#include "expr2smv.h"
1010
#include "expr2smv_class.h"
1111

12+
#include <util/mathematical_types.h>
13+
14+
#include "smv_expr.h"
15+
1216
/*******************************************************************\
1317
1418
Function: expr2smvt::convert_nondet_choice
@@ -221,6 +225,119 @@ expr2smvt::resultt expr2smvt::convert_function_application(
221225

222226
/*******************************************************************\
223227
228+
Function: expr2smvt::convert_typecast
229+
230+
Inputs:
231+
232+
Outputs:
233+
234+
Purpose:
235+
236+
\*******************************************************************/
237+
238+
expr2smvt::resultt expr2smvt::convert_typecast(const typecast_exprt &expr)
239+
{
240+
// typecasts can repesent a variety of functions
241+
auto &src_type = expr.op().type();
242+
auto &dest_type = expr.type();
243+
244+
if(src_type.id() == ID_unsignedbv && dest_type.id() == ID_signedbv)
245+
{
246+
// unsigned to signed
247+
auto src_width = to_unsignedbv_type(src_type).get_width();
248+
auto dest_width = to_signedbv_type(dest_type).get_width();
249+
250+
if(src_width == dest_width)
251+
{
252+
// signedness change only
253+
return convert_rec(smv_signed_cast_exprt{expr.op(), dest_type});
254+
}
255+
else if(dest_width > src_width)
256+
{
257+
// Signedness _and_ width change. First go to signed, then extend.
258+
return convert_rec(smv_extend_exprt{
259+
smv_signed_cast_exprt{expr.op(), signedbv_typet{src_width}},
260+
dest_width - src_width,
261+
dest_type});
262+
}
263+
else
264+
{
265+
// First shrink, then go signed.
266+
return convert_rec(smv_signed_cast_exprt{
267+
smv_resize_exprt{expr.op(), dest_width, unsignedbv_typet{dest_width}},
268+
dest_type});
269+
}
270+
}
271+
else if(src_type.id() == ID_signedbv && dest_type.id() == ID_unsignedbv)
272+
{
273+
// signed to unsigned
274+
auto src_width = to_signedbv_type(src_type).get_width();
275+
auto dest_width = to_unsignedbv_type(dest_type).get_width();
276+
277+
if(
278+
to_signedbv_type(src_type).get_width() ==
279+
to_unsignedbv_type(dest_type).get_width())
280+
{
281+
// signedness change only
282+
return convert_rec(smv_unsigned_cast_exprt{expr.op(), dest_type});
283+
}
284+
else if(dest_width > src_width)
285+
{
286+
// Signedness _and_ width change.
287+
// First enlarge, then go unsigned.
288+
return convert_rec(smv_unsigned_cast_exprt{
289+
smv_extend_exprt{
290+
expr.op(), dest_width - src_width, signedbv_typet{dest_width}},
291+
dest_type});
292+
}
293+
else
294+
{
295+
// First go unsigned, then shrink
296+
return convert_rec(smv_resize_exprt{
297+
smv_unsigned_cast_exprt{expr.op(), unsignedbv_typet{src_width}},
298+
dest_width,
299+
dest_type});
300+
}
301+
}
302+
else if(src_type.id() == ID_signedbv && dest_type.id() == ID_signedbv)
303+
{
304+
// signed to signed, width change.
305+
auto src_width = to_signedbv_type(src_type).get_width();
306+
auto dest_width = to_signedbv_type(dest_type).get_width();
307+
if(dest_width > src_width)
308+
{
309+
// enlarge using extend
310+
return convert_rec(
311+
smv_extend_exprt{expr.op(), dest_width - src_width, dest_type});
312+
}
313+
else
314+
{
315+
// No SMV representation.
316+
// Note that resize(...) preserves the sign bit, unlike our typecast.
317+
return convert_norep(expr);
318+
}
319+
}
320+
else if(src_type.id() == ID_unsignedbv && dest_type.id() == ID_unsignedbv)
321+
{
322+
// Unsigned to unsigned, width change. Use extend when enlarging.
323+
auto src_width = to_unsignedbv_type(src_type).get_width();
324+
auto dest_width = to_unsignedbv_type(dest_type).get_width();
325+
if(dest_width > src_width)
326+
{
327+
return convert_rec(
328+
smv_extend_exprt{expr.op(), dest_width - src_width, dest_type});
329+
}
330+
else
331+
{
332+
return convert_rec(smv_resize_exprt{expr.op(), dest_width, dest_type});
333+
}
334+
}
335+
else
336+
return convert_norep(expr);
337+
}
338+
339+
/*******************************************************************\
340+
224341
Function: expr2smvt::convert_rtctl
225342
226343
Inputs:
@@ -713,9 +830,7 @@ expr2smvt::resultt expr2smvt::convert_rec(const exprt &src)
713830
return convert_function_application("unsigned", src);
714831

715832
else if(src.id() == ID_typecast)
716-
{
717-
return convert_rec(to_typecast_expr(src).op());
718-
}
833+
return convert_typecast(to_typecast_expr(src));
719834

720835
else // no SMV language expression for internal representation
721836
return convert_norep(src);

src/smvlang/expr2smv_class.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ class expr2smvt
126126
resultt
127127
convert_function_application(const std::string &symbol, const exprt &);
128128

129+
resultt convert_typecast(const typecast_exprt &);
130+
129131
resultt convert_norep(const exprt &);
130132
};
131133

0 commit comments

Comments
 (0)