22 for(std::size_t i=0; i<width; i++)
32 tmp.erase(tmp.begin(), tmp.begin()+1);
39 for(std::size_t i=0; i<a.size(); i++)
40 prop.set_equal(a[i], b[i]);
51 result.resize(last+1);
53 result.erase(result.begin(), result.begin()+first);
65 result.erase(result.begin(), result.begin()+(result.size()-n));
85 result.resize(a.size()+b.size());
87 for(std::size_t i=0; i<a.size(); i++)
90 for(std::size_t i=0; i<b.size(); i++)
91 result[i+a.size()]=b[i];
103 result.resize(a.size());
104 for(std::size_t i=0; i<result.size(); i++)
105 result[i]=
prop.lselect(s, a[i], b[i]);
112 std::size_t new_size,
115 std::size_t old_size=bv.size();
119 result.resize(new_size);
125 for(std::size_t i=old_size; i<new_size; i++)
126 result[i]=extend_with;
139#define OPTIMAL_FULL_ADDER
147 #ifdef OPTIMAL_FULL_ADDER
148 if(
prop.has_set_to() &&
prop.cnf_handled_well())
152 int constantProp = -1;
158 constantProp = (a.
is_true()) ? 1 : 0;
164 constantProp = (b.
is_true()) ? 1 : 0;
170 constantProp = (carry_in.
is_true()) ? 1 : 0;
176 if(constantProp == 1)
180 sum =
prop.lequal(x, y);
182 else if(constantProp == 0)
186 sum =
prop.lxor(x, y);
191 sum =
prop.new_variable();
214 prop.lcnf(!a, !b, !carry_in, sum);
215 prop.lcnf(a, b, carry_in, !sum);
225 return prop.lxor(
prop.lxor(a, b), carry_in);
235 if(
prop.has_set_to() &&
prop.cnf_handled_well())
238 const auto const_count =
276 prop.lcnf(a, !b, c, !x);
277 prop.lcnf(a, !b, !c, x);
278 prop.lcnf(!a, b, c, !x);
279 prop.lcnf(!a, b, !c, x);
280 prop.lcnf(!a, !b, x);
290 tmp.push_back(
prop.land(a, b));
291 tmp.push_back(
prop.land(a, c));
292 tmp.push_back(
prop.land(b, c));
294 return prop.lor(tmp);
298std::pair<bvt, literalt>
303 std::pair<bvt, literalt> result{
bvt{}, carry_in};
304 result.first.reserve(op0.size());
307 for(std::size_t i = 0; i < op0.size(); i++)
324 for(std::size_t i=0; i<op0.size(); i++)
348 return adder(op0, tmp_op1, carry_in).first;
353 const bvt op1_sign_applied=
357 return adder(op0, op1_sign_applied, subtract).first;
374 auto add_sub_result =
adder(op0, tmp_op1, carry_in);
378 result.reserve(add_sub_result.first.size());
386 for(
const auto &literal : add_sub_result.first)
414 for(std::size_t i = 0; i < add_sub_result.first.size() - 1; ++i)
416 const auto &literal = add_sub_result.first[i];
417 result.push_back(
prop.land(
418 prop.lor(overflow_to_max_int, literal), !overflow_to_min_int));
421 result.push_back(
prop.land(
422 prop.lor(overflow_to_min_int,
sign_bit(add_sub_result.first)),
423 !overflow_to_max_int));
464 prop.lselect(op1_is_int_min,
505 "representation has either value signed or unsigned");
507 prop.l_set_to(result.second, subtract);
508 return std::move(result.first);
519 std::size_t d=1, width=op.size();
522 for(std::size_t stage=0; stage<dist.size(); stage++)
528 for(std::size_t i=0; i<width; i++)
529 result[i]=
prop.lselect(dist[stage], tmp[i], result[i]);
541 result.resize(src.size());
547 for(std::size_t i=0; i<src.size(); i++)
561 l = dist < src.size() - i ? src[i + dist] :
sign_bit(src);
572 l=src[(src.size()+i-(dist%src.size()))%src.size()];
577 l=src[(i+(dist%src.size()))%src.size()];
609 bvt should_be_zeros(bv);
610 should_be_zeros.pop_back();
622 for(
auto &literal : bv)
641 for(
auto &literal : result)
652 else if(pps.size()==2)
653 return add(pps[0], pps[1]);
656 std::vector<bvt> new_pps;
657 std::size_t no_full_adders=pps.size()/3;
660 for(std::size_t i=0; i<no_full_adders; i++)
662 const bvt &a=pps[i*3+0],
666 INVARIANT(a.size() == b.size(),
"groups should be of equal size");
667 INVARIANT(a.size() == c.size(),
"groups should be of equal size");
672 for(std::size_t bit=0; bit<a.size(); bit++)
676 if(bit + 1 < a.size())
680 new_pps.push_back(std::move(s));
681 new_pps.push_back(std::move(t));
685 for(std::size_t i=no_full_adders*3; i<pps.size(); i++)
686 new_pps.push_back(pps[i]);
697 using columnt = std::list<literalt>;
698 std::vector<columnt> columns(pps.front().size());
699 for(
const auto &pp : pps)
702 for(std::size_t i = 0; i < pp.size(); ++i)
705 columns[i].push_back(pp[i]);
709 std::list<std::size_t> dadda_sequence;
710 for(std::size_t d = 2; d < pps.front().size(); d = (d * 3) / 2)
711 dadda_sequence.push_front(d);
713 for(
auto d : dadda_sequence)
715 for(
auto col_it = columns.begin(); col_it != columns.end();)
717 if(col_it->size() <= d)
719 else if(col_it->size() == d + 1)
726 *std::next(col_it->begin()),
731 if(std::next(col_it) != columns.end())
742 *std::next(col_it->begin()),
743 *std::next(std::next(col_it->begin())),
748 if(std::next(col_it) != columns.end())
755 a.reserve(pps.front().size());
756 b.reserve(pps.front().size());
758 for(
const auto &col : columns)
768 a.push_back(col.front());
772 a.push_back(col.front());
773 b.push_back(col.back());
922 bvt op0=_op0, op1=_op1;
928 std::vector<bvt> pps;
929 pps.reserve(op0.size());
931 for(std::size_t bit=0; bit<op0.size(); bit++)
938 pp.reserve(op0.size());
940 for(std::size_t idx = bit; idx < op0.size(); idx++)
941 pp.push_back(
prop.land(op1[idx - bit], op0[bit]));
947 return zeros(op0.size());
952#elif defined(DADDA_TREE)
955 bvt product = pps.front();
957 for(
auto it = std::next(pps.begin()); it != pps.end(); ++it)
958 product =
add(product, *it);
969 bvt _op0=op0, _op1=op1;
977 product.resize(_op0.size());
979 for(std::size_t i=0; i<product.size(); i++)
982 for(std::size_t sum=0; sum<op0.size(); sum++)
987 tmpop.reserve(product.size());
989 for(std::size_t idx=0; idx<sum; idx++)
992 for(std::size_t idx=sum; idx<product.size(); idx++)
993 tmpop.push_back(
prop.land(op1[idx-sum], op0[sum]));
997 for(std::size_t idx=op1.size()-sum; idx<op1.size(); idx++)
998 prop.l_set_to_false(
prop.land(op1[idx], op0[sum]));
1006 if(op0.empty() || op1.empty())
1027 result.resize(bv.size());
1029 for(std::size_t i=0; i<bv.size(); i++)
1030 result[i]=
prop.lselect(cond, neg_bv[i], bv[i]);
1052 if(op0.empty() || op1.empty())
1111 if(op0.empty() || op1.empty())
1114 bvt _op0(op0), _op1(op1);
1121 for(std::size_t i=0; i<_op0.size(); i++)
1122 _op0[i]=(
prop.lselect(sign_0, neg_0[i], _op0[i]));
1124 for(std::size_t i=0; i<_op1.size(); i++)
1125 _op1[i]=(
prop.lselect(sign_1, neg_1[i], _op1[i]));
1133 for(std::size_t i=0; i<res.size(); i++)
1134 res[i]=
prop.lselect(result_sign, neg_res[i], res[i]);
1136 for(std::size_t i=0; i<res.size(); i++)
1137 rem[i]=
prop.lselect(sign_0, neg_rem[i], rem[i]);
1164 std::size_t width=op0.size();
1169 std::size_t one_count=0, non_const_count=0, one_pos=0;
1171 for(std::size_t i=0; i<op1.size(); i++)
1183 if(non_const_count==0 && one_count==1 && one_pos!=0)
1186 res=
shift(op0, LRIGHT, one_pos);
1190 for(std::size_t i=one_pos; i<rem.size(); i++)
1206 res =
prop.new_variables(width);
1207 rem =
prop.new_variables(width);
1236#ifdef COMPACT_EQUAL_CONST
1242void bv_utilst::equal_const_register(
const bvt &var)
1245 equal_const_registered.insert(var);
1257 std::size_t size = var.size();
1265 literalt comp =
prop.lequal(var[size - 1], constant[size - 1]);
1267 constant.pop_back();
1272 var_constant_pairt index(var, constant);
1274 equal_const_cachet::iterator entry = equal_const_cache.find(index);
1276 if(entry != equal_const_cache.end())
1278 return entry->second;
1282 literalt comp =
prop.lequal(var[size - 1], constant[size - 1]);
1284 constant.pop_back();
1286 literalt rec = equal_const_rec(var, constant);
1287 literalt compare =
prop.land(rec, comp);
1289 equal_const_cache.insert(
1290 std::pair<var_constant_pairt, literalt>(index, compare));
1305literalt bv_utilst::equal_const(
const bvt &var,
const bvt &constant)
1307 std::size_t size = constant.size();
1325 literalt top_bit = constant[size - 1];
1327 std::size_t split = size - 1;
1328 var_upper.push_back(var[size - 1]);
1329 constant_upper.push_back(constant[size - 1]);
1331 for(split = size - 2; split != 0; --split)
1333 if(constant[split] != top_bit)
1339 var_upper.push_back(var[split]);
1340 constant_upper.push_back(constant[split]);
1344 for(std::size_t i = 0; i <= split; ++i)
1346 var_lower.push_back(var[i]);
1347 constant_lower.push_back(constant[i]);
1352 var_upper.size() + var_lower.size() == size,
1353 "lower size plus upper size should equal the total size");
1355 constant_upper.size() + constant_lower.size() == size,
1356 "lower size plus upper size should equal the total size");
1358 literalt top_comparison = equal_const_rec(var_upper, constant_upper);
1359 literalt bottom_comparison = equal_const_rec(var_lower, constant_lower);
1361 return prop.land(top_comparison, bottom_comparison);
1374 #ifdef COMPACT_EQUAL_CONST
1378 equal_const_registered.find(op1) != equal_const_registered.end())
1379 return equal_const(op1, op0);
1381 equal_const_registered.find(op0) != equal_const_registered.end())
1382 return equal_const(op0, op1);
1386 equal_bv.resize(op0.size());
1388 for(std::size_t i=0; i<op0.size(); i++)
1389 equal_bv[i]=
prop.lequal(op0[i], op1[i]);
1391 return prop.land(equal_bv);
1399#define COMPACT_LT_OR_LE
1413#ifdef COMPACT_LT_OR_LE
1414 if(
prop.has_set_to() &&
prop.cnf_handled_well())
1420 if(top0.
is_false() && top1.is_true())
1422 else if(top0.
is_true() && top1.is_false())
1426 bv0.size() >= 2,
"signed bitvectors should have at least two bits");
1428 bvt compareBelow =
prop.new_variables(bv0.size() - 1);
1429 size_t start = compareBelow.size() - 1;
1431 literalt &firstComp = compareBelow[start];
1436 else if(top1.is_false())
1438 else if(top1.is_true())
1445 prop.lcnf(top0, top1, firstComp);
1446 prop.lcnf(top0, !top1, !result);
1447 prop.lcnf(!top0, top1, result);
1448 prop.lcnf(!top0, !top1, firstComp);
1450#ifdef INCLUDE_REDUNDANT_CLAUSES
1451 prop.lcnf(top0, !top1, !firstComp);
1452 prop.lcnf(!top0, top1, !firstComp);
1464 prop.lcnf(!compareBelow[i], bv0[i], !bv1[i], result);
1465 prop.lcnf(!compareBelow[i], !bv0[i], bv1[i], !result);
1471 for(i = start; i > 0; i--)
1473 prop.lcnf(!compareBelow[i], !bv0[i], !bv1[i], compareBelow[i - 1]);
1474 prop.lcnf(!compareBelow[i], bv0[i], bv1[i], compareBelow[i - 1]);
1477# ifdef INCLUDE_REDUNDANT_CLAUSES
1482 for(i = start; i > 0; i--)
1484 prop.lcnf(compareBelow[i], !compareBelow[i - 1]);
1485 prop.lcnf(!compareBelow[i], bv0[i], !bv1[i], !compareBelow[i - 1]);
1486 prop.lcnf(!compareBelow[i], !bv0[i], bv1[i], !compareBelow[i - 1]);
1492 !compareBelow[0], !bv0[0], !bv1[0], (or_equal) ? result : !result);
1494 !compareBelow[0], bv0[0], bv1[0], (or_equal) ? result : !result);
1504 size_t start = bv0.size() - 1;
1509 bool same_prefix =
true;
1518 return prop.lor(!bv0[0], bv1[0]);
1520 return prop.land(!bv0[0], bv1[0]);
1522 else if(bv0[i] == bv1[i])
1530 same_prefix =
false;
1532 compareBelow =
prop.new_variables(i);
1534 result =
prop.new_variable();
1538 prop.lcnf(!compareBelow[i], bv0[i], !bv1[i], result);
1539 prop.lcnf(!compareBelow[i], !bv0[i], bv1[i], !result);
1545 for(i = start; i > 0; i--)
1547 prop.lcnf(!compareBelow[i], !bv0[i], !bv1[i], compareBelow[i - 1]);
1548 prop.lcnf(!compareBelow[i], bv0[i], bv1[i], compareBelow[i - 1]);
1551#ifdef INCLUDE_REDUNDANT_CLAUSES
1556 for(i = start; i > 0; i--)
1558 prop.lcnf(compareBelow[i], !compareBelow[i - 1]);
1559 prop.lcnf(!compareBelow[i], bv0[i], !bv1[i], !compareBelow[i - 1]);
1560 prop.lcnf(!compareBelow[i], !bv0[i], bv1[i], !compareBelow[i - 1]);
1566 !compareBelow[0], !bv0[0], !bv1[0], (or_equal) ? result : !result);
1568 !compareBelow[0], bv0[0], bv1[0], (or_equal) ? result : !result);
1588 "representation has either value signed or unsigned");
1593 result=
prop.lor(result,
equal(bv0, bv1));
1620 return equal(bv0, bv1);
1621 else if(
id==ID_notequal)
1622 return !
equal(bv0, bv1);
1624 return lt_or_le(
true, bv0, bv1, rep);
1626 return lt_or_le(
false, bv0, bv1, rep);
1628 return lt_or_le(
true, bv1, bv0, rep);
1630 return lt_or_le(
false, bv1, bv0, rep);
1637 for(
const auto &literal : bv)
1639 if(!literal.is_constant())
1653 if(
prop.cnf_handled_well())
1655 for(std::size_t i=0; i<a.size(); i++)
1657 prop.lcnf(!cond, a[i], !b[i]);
1658 prop.lcnf(!cond, !a[i], b[i]);
1672 odd_bits.reserve(src.size()/2);
1675 for(std::size_t i=0; i<src.size(); i++)
1678 odd_bits.push_back(src[i]);
1681 return prop.lor(odd_bits);
1687 even_bits.reserve(src.size()/2);
1690 for(std::size_t i=0; i<src.size(); i++)
1693 even_bits.push_back(src[i]);
1719 for(std::size_t stage = 0; stage < log2; ++stage)
1721 std::size_t shift_amount = 1 << stage;
1722 std::size_t field_size = 2 * shift_amount;
1725 if(x.size() <= shift_amount)
1734 mask.reserve(x.size());
1735 for(std::size_t i = 0; i < x.size(); i++)
1737 if((i % field_size) < shift_amount)
1744 bvt masked_x, masked_shifted;
1745 masked_x.reserve(x.size());
1746 masked_shifted.reserve(x.size());
1748 for(std::size_t i = 0; i < x.size(); i++)
1750 masked_x.push_back(
prop.land(x[i],
mask[i]));
1751 masked_shifted.push_back(
prop.land(x_shifted[i],
mask[i]));
1755 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)
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 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)