Skip to content

Commit c607cd1

Browse files
committed
Verilog: use zero_extend_exprt
This replaces two typecasts by zero_extend_exprt.
1 parent e565db7 commit c607cd1

File tree

8 files changed

+153
-15
lines changed

8 files changed

+153
-15
lines changed

src/smvlang/expr2smv.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,100 @@ expr2smvt::resultt expr2smvt::convert_typecast(const typecast_exprt &expr)
343343

344344
/*******************************************************************\
345345
346+
Function: expr2smvt::convert_zero_extend
347+
348+
Inputs:
349+
350+
Outputs:
351+
352+
Purpose:
353+
354+
\*******************************************************************/
355+
356+
expr2smvt::resultt expr2smvt::convert_zero_extend(const zero_extend_exprt &expr)
357+
{
358+
// these may apply to a variety of operand/result types
359+
auto &src_type = expr.op().type();
360+
auto &dest_type = expr.type();
361+
362+
if(src_type.id() == ID_unsignedbv && dest_type.id() == ID_signedbv)
363+
{
364+
// unsigned to signed
365+
auto src_width = to_unsignedbv_type(src_type).get_width();
366+
auto dest_width = to_signedbv_type(dest_type).get_width();
367+
368+
if(src_width == dest_width)
369+
{
370+
// signedness change only
371+
return convert_rec(smv_signed_cast_exprt{expr.op(), dest_type});
372+
}
373+
else
374+
{
375+
PRECONDITION(dest_width > src_width);
376+
377+
// Signedness _and_ width change. First extend, then go signed
378+
return convert_rec(smv_signed_cast_exprt{
379+
smv_extend_exprt{
380+
expr.op(), dest_width - src_width, unsignedbv_typet{dest_width}},
381+
dest_type});
382+
}
383+
}
384+
else if(src_type.id() == ID_signedbv && dest_type.id() == ID_unsignedbv)
385+
{
386+
// signed to unsigned
387+
auto src_width = to_signedbv_type(src_type).get_width();
388+
auto dest_width = to_unsignedbv_type(dest_type).get_width();
389+
390+
if(src_width == dest_width)
391+
{
392+
// signedness change only
393+
return convert_rec(smv_unsigned_cast_exprt{expr.op(), dest_type});
394+
}
395+
else
396+
{
397+
PRECONDITION(dest_width > src_width);
398+
399+
// Signedness _and_ width change. First go unsigned, then enlarge.
400+
return convert_rec(smv_extend_exprt{
401+
smv_unsigned_cast_exprt{expr.op(), unsignedbv_typet{src_width}},
402+
dest_width - src_width,
403+
dest_type});
404+
}
405+
}
406+
else if(src_type.id() == ID_signedbv && dest_type.id() == ID_signedbv)
407+
{
408+
// Note that SMV's resize(...) preserves the sign bit, unlike our typecast.
409+
// We therefore first go unsigned, then resize, then go signed again.
410+
auto src_width = to_signedbv_type(src_type).get_width();
411+
auto dest_width = to_signedbv_type(dest_type).get_width();
412+
PRECONDITION(dest_width >= src_width);
413+
return convert_rec(smv_signed_cast_exprt{
414+
smv_extend_exprt{
415+
smv_unsigned_cast_exprt{expr.op(), unsignedbv_typet{src_width}},
416+
dest_width - src_width,
417+
unsignedbv_typet{dest_width}},
418+
dest_type});
419+
}
420+
else if(src_type.id() == ID_unsignedbv && dest_type.id() == ID_unsignedbv)
421+
{
422+
// Unsigned to unsigned, possible width change.
423+
auto src_width = to_unsignedbv_type(src_type).get_width();
424+
auto dest_width = to_unsignedbv_type(dest_type).get_width();
425+
if(dest_width == src_width)
426+
return convert_rec(expr.op()); // no change
427+
else
428+
{
429+
PRECONDITION(dest_width > src_width);
430+
return convert_rec(
431+
smv_extend_exprt{expr.op(), dest_width - src_width, dest_type});
432+
}
433+
}
434+
else
435+
return convert_norep(expr);
436+
}
437+
438+
/*******************************************************************\
439+
346440
Function: expr2smvt::convert_rtctl
347441
348442
Inputs:
@@ -839,6 +933,11 @@ expr2smvt::resultt expr2smvt::convert_rec(const exprt &src)
839933
return convert_typecast(to_typecast_expr(src));
840934
}
841935

936+
else if(src.id() == ID_zero_extend)
937+
{
938+
return convert_zero_extend(to_zero_extend_expr(src));
939+
}
940+
842941
else // no SMV language expression for internal representation
843942
return convert_norep(src);
844943
}

src/smvlang/expr2smv_class.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Author: Daniel Kroening, [email protected]
1010
#define CPROVER_SMV_EXPR2SMV_CLASS_H
1111

1212
#include <util/arith_tools.h>
13+
#include <util/bitvector_expr.h>
1314
#include <util/bitvector_types.h>
1415
#include <util/namespace.h>
1516
#include <util/std_expr.h>
@@ -128,6 +129,8 @@ class expr2smvt
128129

129130
resultt convert_typecast(const typecast_exprt &);
130131

132+
resultt convert_zero_extend(const zero_extend_exprt &);
133+
131134
resultt convert_norep(const exprt &);
132135
};
133136

src/verilog/aval_bval_encoding.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,3 +470,8 @@ exprt aval_bval(const shift_exprt &expr)
470470
auto x = make_x(expr.type());
471471
return if_exprt{distance_has_xz, x, combined};
472472
}
473+
474+
exprt aval_bval(const zero_extend_exprt &expr)
475+
{
476+
abort();
477+
}

src/verilog/aval_bval_encoding.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,7 @@ exprt aval_bval(const verilog_implies_exprt &);
6565
exprt aval_bval(const typecast_exprt &);
6666
/// lowering for shifts
6767
exprt aval_bval(const shift_exprt &);
68+
/// lowering for zero extension
69+
exprt aval_bval(const zero_extend_exprt &);
6870

6971
#endif

src/verilog/expr2verilog.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,25 @@ expr2verilogt::resultt expr2verilogt::convert_explicit_size_cast(
896896

897897
/*******************************************************************\
898898
899+
Function: expr2verilogt::convert_zero_extend
900+
901+
Inputs:
902+
903+
Outputs:
904+
905+
Purpose:
906+
907+
\*******************************************************************/
908+
909+
expr2verilogt::resultt
910+
expr2verilogt::convert_zero_extend(const zero_extend_exprt &src)
911+
{
912+
// added by the type checker; igore
913+
return convert_rec(src.op());
914+
}
915+
916+
/*******************************************************************\
917+
899918
Function: expr2verilogt::convert_index
900919
901920
Inputs:
@@ -1664,6 +1683,9 @@ expr2verilogt::resultt expr2verilogt::convert_rec(const exprt &src)
16641683
else if(src.id()==ID_typecast)
16651684
return convert_typecast(to_typecast_expr(src));
16661685

1686+
else if(src.id() == ID_zero_extend)
1687+
return convert_zero_extend(to_zero_extend_expr(src));
1688+
16671689
else if(src.id()==ID_and)
16681690
return convert_binary(
16691691
to_multi_ary_expr(src), "&&", precedence = verilog_precedencet::AND);

src/verilog/expr2verilog_class.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ class expr2verilogt
117117

118118
resultt convert_typecast(const typecast_exprt &);
119119

120+
resultt convert_zero_extend(const zero_extend_exprt &);
121+
120122
resultt
121123
convert_explicit_size_cast(const class verilog_explicit_size_cast_exprt &);
122124

src/verilog/verilog_lowering.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,20 @@ exprt verilog_lowering(exprt expr)
615615
else
616616
return expr;
617617
}
618+
else if(expr.id() == ID_zero_extend)
619+
{
620+
auto &zero_extend = to_zero_extend_expr(expr);
621+
622+
if(
623+
is_four_valued(zero_extend.type()) ||
624+
is_four_valued(zero_extend.op().type()))
625+
{
626+
// encode into aval/bval
627+
return aval_bval(zero_extend);
628+
}
629+
else
630+
return expr; // leave as is
631+
}
618632
else
619633
return expr; // leave as is
620634

src/verilog/verilog_typecheck_expr.cpp

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2316,23 +2316,14 @@ Function: zero_extend
23162316

23172317
static exprt zero_extend(const exprt &expr, const typet &type)
23182318
{
2319-
auto old_width = expr.type().id() == ID_bool ? 1
2320-
: expr.type().id() == ID_integer
2321-
? 32
2322-
: to_bitvector_type(expr.type()).get_width();
2319+
exprt result = expr;
23232320

2324-
// first make unsigned
2325-
typet tmp_type;
2321+
if(expr.type().id() == ID_bool)
2322+
result = typecast_exprt{expr, unsignedbv_typet{1}};
2323+
else if(expr.type().id() == ID_integer)
2324+
result = typecast_exprt{expr, unsignedbv_typet{32}};
23262325

2327-
if(type.id() == ID_unsignedbv)
2328-
tmp_type = unsignedbv_typet{old_width};
2329-
else if(type.id() == ID_verilog_unsignedbv)
2330-
tmp_type = verilog_unsignedbv_typet{old_width};
2331-
else
2332-
PRECONDITION(false);
2333-
2334-
return typecast_exprt::conditional_cast(
2335-
typecast_exprt::conditional_cast(expr, tmp_type), type);
2326+
return zero_extend_exprt{std::move(result), type};
23362327
}
23372328

23382329
/*******************************************************************\

0 commit comments

Comments
 (0)