22 for(std::size_t i=0; i<width; i++)
30 const std::size_t width = bv.size();
31 std::string s(width,
'0');
32 for(std::size_t i = 0; i < width; i++)
33 s[width - i - 1] = bv[i].
is_true() ?
'1' :
'0';
42 tmp.erase(tmp.begin(), tmp.begin()+1);
49 for(std::size_t i=0; i<a.size(); i++)
50 prop.set_equal(a[i], b[i]);
61 result.resize(last+1);
63 result.erase(result.begin(), result.begin()+first);
75 result.erase(result.begin(), result.begin()+(result.size()-n));
95 result.resize(a.size()+b.size());
97 for(std::size_t i=0; i<a.size(); i++)
100 for(std::size_t i=0; i<b.size(); i++)
101 result[i+a.size()]=b[i];
113 result.resize(a.size());
114 for(std::size_t i=0; i<result.size(); i++)
115 result[i]=
prop.lselect(s, a[i], b[i]);
122 std::size_t new_size,
125 std::size_t old_size=bv.size();
129 result.resize(new_size);
135 for(std::size_t i=old_size; i<new_size; i++)
136 result[i]=extend_with;
149#define OPTIMAL_FULL_ADDER
157 #ifdef OPTIMAL_FULL_ADDER
158 if(
prop.has_set_to() &&
prop.cnf_handled_well())
162 int constantProp = -1;
168 constantProp = (a.
is_true()) ? 1 : 0;
174 constantProp = (b.
is_true()) ? 1 : 0;
180 constantProp = (carry_in.
is_true()) ? 1 : 0;
186 if(constantProp == 1)
190 sum =
prop.lequal(x, y);
192 else if(constantProp == 0)
196 sum =
prop.lxor(x, y);
201 sum =
prop.new_variable();
224 prop.lcnf(!a, !b, !carry_in, sum);
225 prop.lcnf(a, b, carry_in, !sum);
235 return prop.lxor(
prop.lxor(a, b), carry_in);
245 if(
prop.has_set_to() &&
prop.cnf_handled_well())
248 const auto const_count =
286 prop.lcnf(a, !b, c, !x);
287 prop.lcnf(a, !b, !c, x);
288 prop.lcnf(!a, b, c, !x);
289 prop.lcnf(!a, b, !c, x);
290 prop.lcnf(!a, !b, x);
300 tmp.push_back(
prop.land(a, b));
301 tmp.push_back(
prop.land(a, c));
302 tmp.push_back(
prop.land(b, c));
304 return prop.lor(tmp);
308std::pair<bvt, literalt>
313 std::pair<bvt, literalt> result{
bvt{}, carry_in};
314 result.first.reserve(op0.size());
317 for(std::size_t i = 0; i < op0.size(); i++)
334 for(std::size_t i=0; i<op0.size(); i++)
358 return adder(op0, tmp_op1, carry_in).first;
363 const bvt op1_sign_applied=
367 return adder(op0, op1_sign_applied, subtract).first;
384 auto add_sub_result =
adder(op0, tmp_op1, carry_in);
388 result.reserve(add_sub_result.first.size());
396 for(
const auto &literal : add_sub_result.first)
424 for(std::size_t i = 0; i < add_sub_result.first.size() - 1; ++i)
426 const auto &literal = add_sub_result.first[i];
427 result.push_back(
prop.land(
428 prop.lor(overflow_to_max_int, literal), !overflow_to_min_int));
431 result.push_back(
prop.land(
432 prop.lor(overflow_to_min_int,
sign_bit(add_sub_result.first)),
433 !overflow_to_max_int));
474 prop.lselect(op1_is_int_min,
515 "representation has either value signed or unsigned");
517 prop.l_set_to(result.second, subtract);
518 return std::move(result.first);
529 std::size_t d=1, width=op.size();
532 for(std::size_t stage=0; stage<dist.size(); stage++)
538 for(std::size_t i=0; i<width; i++)
539 result[i]=
prop.lselect(dist[stage], tmp[i], result[i]);
551 result.resize(src.size());
557 for(std::size_t i=0; i<src.size(); i++)
571 l = dist < src.size() - i ? src[i + dist] :
sign_bit(src);
582 l=src[(src.size()+i-(dist%src.size()))%src.size()];
587 l=src[(i+(dist%src.size()))%src.size()];
619 bvt should_be_zeros(bv);
620 should_be_zeros.pop_back();
632 for(
auto &literal : bv)
651 for(
auto &literal : result)
662 else if(pps.size()==2)
663 return add(pps[0], pps[1]);
666 std::vector<bvt> new_pps;
667 std::size_t no_full_adders=pps.size()/3;
670 for(std::size_t i=0; i<no_full_adders; i++)
672 const bvt &a=pps[i*3+0],
676 INVARIANT(a.size() == b.size(),
"groups should be of equal size");
677 INVARIANT(a.size() == c.size(),
"groups should be of equal size");
682 for(std::size_t bit=0; bit<a.size(); bit++)
686 if(bit + 1 < a.size())
690 new_pps.push_back(std::move(s));
691 new_pps.push_back(std::move(t));
695 for(std::size_t i=no_full_adders*3; i<pps.size(); i++)
696 new_pps.push_back(pps[i]);
707 using columnt = std::list<literalt>;
708 std::vector<columnt> columns(pps.front().size());
709 for(
const auto &pp : pps)
712 for(std::size_t i = 0; i < pp.size(); ++i)
715 columns[i].push_back(pp[i]);
719 std::list<std::size_t> dadda_sequence;
720 for(std::size_t d = 2; d < pps.front().size(); d = (d * 3) / 2)
721 dadda_sequence.push_front(d);
723 for(
auto d : dadda_sequence)
725 for(
auto col_it = columns.begin(); col_it != columns.end();)
727 if(col_it->size() <= d)
729 else if(col_it->size() == d + 1)
736 *std::next(col_it->begin()),
741 if(std::next(col_it) != columns.end())
752 *std::next(col_it->begin()),
753 *std::next(std::next(col_it->begin())),
758 if(std::next(col_it) != columns.end())
765 a.reserve(pps.front().size());
766 b.reserve(pps.front().size());
768 for(
const auto &col : columns)
778 a.push_back(col.front());
782 a.push_back(col.front());
783 b.push_back(col.back());
932 bvt op0=_op0, op1=_op1;
938 std::vector<bvt> pps;
939 pps.reserve(op0.size());
941 for(std::size_t bit=0; bit<op0.size(); bit++)
948 pp.reserve(op0.size());
950 for(std::size_t idx = bit; idx < op0.size(); idx++)
951 pp.push_back(
prop.land(op1[idx - bit], op0[bit]));
957 return zeros(op0.size());
962#elif defined(DADDA_TREE)
965 bvt product = pps.front();
967 for(
auto it = std::next(pps.begin()); it != pps.end(); ++it)
968 product =
add(product, *it);
979 bvt _op0=op0, _op1=op1;
987 product.resize(_op0.size());
989 for(std::size_t i=0; i<product.size(); i++)
992 for(std::size_t sum=0; sum<op0.size(); sum++)
997 tmpop.reserve(product.size());
999 for(std::size_t idx=0; idx<sum; idx++)
1002 for(std::size_t idx=sum; idx<product.size(); idx++)
1003 tmpop.push_back(
prop.land(op1[idx-sum], op0[sum]));
1007 for(std::size_t idx=op1.size()-sum; idx<op1.size(); idx++)
1008 prop.l_set_to_false(
prop.land(op1[idx], op0[sum]));
1016 if(op0.empty() || op1.empty())
1037 result.resize(bv.size());
1039 for(std::size_t i=0; i<bv.size(); i++)
1040 result[i]=
prop.lselect(cond, neg_bv[i], bv[i]);
1062 if(op0.empty() || op1.empty())
1121 if(op0.empty() || op1.empty())
1124 bvt _op0(op0), _op1(op1);
1131 for(std::size_t i=0; i<_op0.size(); i++)
1132 _op0[i]=(
prop.lselect(sign_0, neg_0[i], _op0[i]));
1134 for(std::size_t i=0; i<_op1.size(); i++)
1135 _op1[i]=(
prop.lselect(sign_1, neg_1[i], _op1[i]));
1143 for(std::size_t i=0; i<res.size(); i++)
1144 res[i]=
prop.lselect(result_sign, neg_res[i], res[i]);
1146 for(std::size_t i=0; i<res.size(); i++)
1147 rem[i]=
prop.lselect(sign_0, neg_rem[i], rem[i]);
1175 std::size_t width=op0.size();
1196 std::size_t one_count=0, non_const_count=0, one_pos=0;
1198 for(std::size_t i=0; i<op1.size(); i++)
1210 if(non_const_count==0 && one_count==1 && one_pos!=0)
1213 res=
shift(op0, LRIGHT, one_pos);
1217 for(std::size_t i=one_pos; i<rem.size(); i++)
1233 res =
prop.new_variables(width);
1234 rem =
prop.new_variables(width);
1263#ifdef COMPACT_EQUAL_CONST
1269void bv_utilst::equal_const_register(
const bvt &var)
1272 equal_const_registered.insert(var);
1284 std::size_t size = var.size();
1292 literalt comp =
prop.lequal(var[size - 1], constant[size - 1]);
1294 constant.pop_back();
1299 var_constant_pairt index(var, constant);
1301 equal_const_cachet::iterator entry = equal_const_cache.find(index);
1303 if(entry != equal_const_cache.end())
1305 return entry->second;
1309 literalt comp =
prop.lequal(var[size - 1], constant[size - 1]);
1311 constant.pop_back();
1313 literalt rec = equal_const_rec(var, constant);
1314 literalt compare =
prop.land(rec, comp);
1316 equal_const_cache.insert(
1317 std::pair<var_constant_pairt, literalt>(index, compare));
1332literalt bv_utilst::equal_const(
const bvt &var,
const bvt &constant)
1334 std::size_t size = constant.size();
1352 literalt top_bit = constant[size - 1];
1354 std::size_t split = size - 1;
1355 var_upper.push_back(var[size - 1]);
1356 constant_upper.push_back(constant[size - 1]);
1358 for(split = size - 2; split != 0; --split)
1360 if(constant[split] != top_bit)
1366 var_upper.push_back(var[split]);
1367 constant_upper.push_back(constant[split]);
1371 for(std::size_t i = 0; i <= split; ++i)
1373 var_lower.push_back(var[i]);
1374 constant_lower.push_back(constant[i]);
1379 var_upper.size() + var_lower.size() == size,
1380 "lower size plus upper size should equal the total size");
1382 constant_upper.size() + constant_lower.size() == size,
1383 "lower size plus upper size should equal the total size");
1385 literalt top_comparison = equal_const_rec(var_upper, constant_upper);
1386 literalt bottom_comparison = equal_const_rec(var_lower, constant_lower);
1388 return prop.land(top_comparison, bottom_comparison);
1401 #ifdef COMPACT_EQUAL_CONST
1405 equal_const_registered.find(op1) != equal_const_registered.end())
1406 return equal_const(op1, op0);
1408 equal_const_registered.find(op0) != equal_const_registered.end())
1409 return equal_const(op0, op1);
1413 equal_bv.resize(op0.size());
1415 for(std::size_t i=0; i<op0.size(); i++)
1416 equal_bv[i]=
prop.lequal(op0[i], op1[i]);
1418 return prop.land(equal_bv);
1426#define COMPACT_LT_OR_LE
1441#ifdef COMPACT_LT_OR_LE
1442 if(
prop.has_set_to() &&
prop.cnf_handled_well())
1448 if(top0.
is_false() && top1.is_true())
1450 else if(top0.
is_true() && top1.is_false())
1457 return prop.lor(top0, !top1);
1459 return prop.land(top0, !top1);
1464 "the compact signed comparison encoding requires at least two bits");
1466 bvt compareBelow =
prop.new_variables(bv0.size() - 1);
1467 size_t start = compareBelow.size() - 1;
1469 literalt &firstComp = compareBelow[start];
1474 else if(top1.is_false())
1476 else if(top1.is_true())
1483 prop.lcnf(top0, top1, firstComp);
1484 prop.lcnf(top0, !top1, !result);
1485 prop.lcnf(!top0, top1, result);
1486 prop.lcnf(!top0, !top1, firstComp);
1488#ifdef INCLUDE_REDUNDANT_CLAUSES
1489 prop.lcnf(top0, !top1, !firstComp);
1490 prop.lcnf(!top0, top1, !firstComp);
1502 prop.lcnf(!compareBelow[i], bv0[i], !bv1[i], result);
1503 prop.lcnf(!compareBelow[i], !bv0[i], bv1[i], !result);
1509 for(i = start; i > 0; i--)
1511 prop.lcnf(!compareBelow[i], !bv0[i], !bv1[i], compareBelow[i - 1]);
1512 prop.lcnf(!compareBelow[i], bv0[i], bv1[i], compareBelow[i - 1]);
1515# ifdef INCLUDE_REDUNDANT_CLAUSES
1520 for(i = start; i > 0; i--)
1522 prop.lcnf(compareBelow[i], !compareBelow[i - 1]);
1523 prop.lcnf(!compareBelow[i], bv0[i], !bv1[i], !compareBelow[i - 1]);
1524 prop.lcnf(!compareBelow[i], !bv0[i], bv1[i], !compareBelow[i - 1]);
1530 !compareBelow[0], !bv0[0], !bv1[0], (or_equal) ? result : !result);
1532 !compareBelow[0], bv0[0], bv1[0], (or_equal) ? result : !result);
1542 size_t start = bv0.size() - 1;
1547 bool same_prefix =
true;
1556 return prop.lor(!bv0[0], bv1[0]);
1558 return prop.land(!bv0[0], bv1[0]);
1560 else if(bv0[i] == bv1[i])
1568 same_prefix =
false;
1570 compareBelow =
prop.new_variables(i);
1572 result =
prop.new_variable();
1576 prop.lcnf(!compareBelow[i], bv0[i], !bv1[i], result);
1577 prop.lcnf(!compareBelow[i], !bv0[i], bv1[i], !result);
1583 for(i = start; i > 0; i--)
1585 prop.lcnf(!compareBelow[i], !bv0[i], !bv1[i], compareBelow[i - 1]);
1586 prop.lcnf(!compareBelow[i], bv0[i], bv1[i], compareBelow[i - 1]);
1589#ifdef INCLUDE_REDUNDANT_CLAUSES
1594 for(i = start; i > 0; i--)
1596 prop.lcnf(compareBelow[i], !compareBelow[i - 1]);
1597 prop.lcnf(!compareBelow[i], bv0[i], !bv1[i], !compareBelow[i - 1]);
1598 prop.lcnf(!compareBelow[i], !bv0[i], bv1[i], !compareBelow[i - 1]);
1604 !compareBelow[0], !bv0[0], !bv1[0], (or_equal) ? result : !result);
1606 !compareBelow[0], bv0[0], bv1[0], (or_equal) ? result : !result);
1626 "representation has either value signed or unsigned");
1631 result=
prop.lor(result,
equal(bv0, bv1));
1658 return equal(bv0, bv1);
1659 else if(
id==ID_notequal)
1660 return !
equal(bv0, bv1);
1662 return lt_or_le(
true, bv0, bv1, rep);
1664 return lt_or_le(
false, bv0, bv1, rep);
1666 return lt_or_le(
true, bv1, bv0, rep);
1668 return lt_or_le(
false, bv1, bv0, rep);
1675 for(
const auto &literal : bv)
1677 if(!literal.is_constant())
1691 if(
prop.cnf_handled_well())
1693 for(std::size_t i=0; i<a.size(); i++)
1695 prop.lcnf(!cond, a[i], !b[i]);
1696 prop.lcnf(!cond, !a[i], b[i]);
1710 odd_bits.reserve(src.size()/2);
1713 for(std::size_t i=0; i<src.size(); i++)
1716 odd_bits.push_back(src[i]);
1719 return prop.lor(odd_bits);
1725 even_bits.reserve(src.size()/2);
1728 for(std::size_t i=0; i<src.size(); i++)
1731 even_bits.push_back(src[i]);
1757 for(std::size_t stage = 0; stage < log2; ++stage)
1759 std::size_t shift_amount = 1 << stage;
1760 std::size_t field_size = 2 * shift_amount;
1763 if(x.size() <= shift_amount)
1772 mask.reserve(x.size());
1773 for(std::size_t i = 0; i < x.size(); i++)
1775 if((i % field_size) < shift_amount)
1782 bvt masked_x, masked_shifted;
1783 masked_x.reserve(x.size());
1784 masked_shifted.reserve(x.size());
1786 for(std::size_t i = 0; i < x.size(); i++)
1788 masked_x.push_back(
prop.land(x[i],
mask[i]));
1789 masked_shifted.push_back(
prop.land(x_shifted[i],
mask[i]));
1793 x =
add(masked_x, masked_shifted);
static bvt inverted(const bvt &op)
literalt signed_less_than(const bvt &bv0, const bvt &bv1)
static bool is_constant(const bvt &bv)
std::pair< bvt, literalt > adder(const bvt &op0, const bvt &op1, literalt carry_in)
Return the sum and carry-out when adding op0 and op1 under initial carry carry_in.
bvt wallace_tree(const std::vector< bvt > &pps)
literalt is_not_zero(const bvt &op)
static bvt verilog_bv_normal_bits(const bvt &)
literalt is_int_min(const bvt &op)
static bvt extract_msb(const bvt &a, std::size_t n)
static mp_integer from_constant(const bvt &bv)
Returns the unsigned integer value of the constant bitvector bv.
void set_equal(const bvt &a, const bvt &b)
static literalt sign_bit(const bvt &op)
bvt multiplier_no_overflow(const bvt &op0, const bvt &op1, representationt rep)
bvt add_sub_no_overflow(const bvt &op0, const bvt &op1, bool subtract, representationt rep)
bvt add(const bvt &op0, const bvt &op1)
bvt absolute_value(const bvt &op)
bvt select(literalt s, const bvt &a, const bvt &b)
If s is true, selects a otherwise selects b.
static bvt build_constant(const mp_integer &i, std::size_t width)
void signed_divider(const bvt &op0, const bvt &op1, bvt &res, bvt &rem)
literalt is_zero(const bvt &op)
literalt equal(const bvt &op0, const bvt &op1)
Bit-blasting ID_equal and use in other encodings.
bvt popcount(const bvt &bv)
Symbolic implementation of popcount (count of 1 bits in a bit vector) Based on the pop0 algorithm fro...
bvt signed_multiplier(const bvt &op0, const bvt &op1)
literalt overflow_add(const bvt &op0, const bvt &op1, representationt rep)
literalt is_one(const bvt &op)
bvt cond_negate_no_overflow(const bvt &bv, const literalt cond)
literalt overflow_sub(const bvt &op0, const bvt &op1, representationt rep)
void cond_implies_equal(literalt cond, const bvt &a, const bvt &b)
literalt unsigned_less_than(const bvt &bv0, const bvt &bv1)
bvt signed_multiplier_no_overflow(const bvt &op0, const bvt &op1)
bvt incrementer(const bvt &op, literalt carry_in)
bvt add_sub(const bvt &op0, const bvt &op1, bool subtract)
static bvt shift(const bvt &op, const shiftt shift, std::size_t distance)
literalt lt_or_le(bool or_equal, const bvt &bv0, const bvt &bv1, representationt rep)
literalt overflow_negate(const bvt &op)
static bvt concatenate(const bvt &a, const bvt &b)
literalt full_adder(const literalt a, const literalt b, const literalt carry_in, literalt &carry_out)
bvt negate_no_overflow(const bvt &op)
static bvt extract(const bvt &a, std::size_t first, std::size_t last)
bvt unsigned_multiplier(const bvt &op0, const bvt &op1)
bvt divider(const bvt &op0, const bvt &op1, representationt rep)
void unsigned_divider(const bvt &op0, const bvt &op1, bvt &res, bvt &rem)
bvt multiplier(const bvt &op0, const bvt &op1, representationt rep)
bvt cond_negate(const bvt &bv, const literalt cond)
bvt dadda_tree(const std::vector< bvt > &pps)
literalt carry_out(const bvt &op0, const bvt &op1, literalt carry_in)
bvt negate(const bvt &op)
static bvt extension(const bvt &bv, std::size_t new_size, representationt rep)
static bvt extract_lsb(const bvt &a, std::size_t n)
literalt verilog_bv_has_x_or_z(const bvt &)
literalt carry(literalt a, literalt b, literalt c)
bvt unsigned_multiplier_no_overflow(const bvt &op0, const bvt &op1)
static bvt zeros(std::size_t new_size)
literalt rel(const bvt &bv0, irep_idt id, const bvt &bv1, representationt rep)
bvt adder_no_overflow(const bvt &op0, const bvt &op1, bool subtract, representationt rep)
bvt saturating_add_sub(const bvt &op0, const bvt &op1, bool subtract, representationt rep)
bool is_false(const literalt &l)
bool is_true(const literalt &l)
std::vector< literalt > bvt
literalt const_literal(bool value)
const mp_integer binary2integer(const std::string &n, bool is_signed)
convert binary string representation to mp_integer
const std::string integer2binary(const mp_integer &n, std::size_t width)
const std::size_t sharing_mapt< keyT, valueT, fail_if_equal, hashT, equalT >::mask
#define CHECK_RETURN(CONDITION)
#define UNREACHABLE
This should be used to mark dead code.
#define PRECONDITION(CONDITION)
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
#define POSTCONDITION(CONDITION)