summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2015-04-09 13:20:19 +0200
committerClifford Wolf <clifford@clifford.at>2015-04-09 13:20:19 +0200
commit25781e329b51ca84e5fd697705cb0377af64f90b (patch)
tree89a3085c51267dc9f589cb5db04dbbdabf9cfea4
parentbe7b9b34ca3f62f38e707becc44451c820f220c0 (diff)
Fixed const2big performance bug
-rw-r--r--kernel/calc.cc35
1 files changed, 21 insertions, 14 deletions
diff --git a/kernel/calc.cc b/kernel/calc.cc
index aa3e8b91..99980e92 100644
--- a/kernel/calc.cc
+++ b/kernel/calc.cc
@@ -41,21 +41,28 @@ static void extend_u0(RTLIL::Const &arg, int width, bool is_signed)
static BigInteger const2big(const RTLIL::Const &val, bool as_signed, int &undef_bit_pos)
{
- BigInteger result = 0, this_bit = 1;
- for (size_t i = 0; i < val.bits.size(); i++) {
- if (val.bits[i] == RTLIL::State::S1) {
- if (as_signed && i+1 == val.bits.size())
- result -= this_bit;
- else
- result += this_bit;
- }
- else if (val.bits[i] != RTLIL::State::S0) {
- if (undef_bit_pos < 0)
- undef_bit_pos = i;
- }
- this_bit *= 2;
+ BigUnsigned mag;
+
+ BigInteger::Sign sign = BigInteger::positive;
+ State inv_sign_bit = RTLIL::State::S1;
+ size_t num_bits = val.bits.size();
+
+ if (as_signed && num_bits && val.bits[num_bits-1] == RTLIL::State::S1) {
+ inv_sign_bit = RTLIL::State::S0;
+ sign = BigInteger::negative;
+ num_bits--;
}
- return result;
+
+ for (size_t i = 0; i < num_bits; i++)
+ if (val.bits[i] == RTLIL::State::S0 || val.bits[i] == RTLIL::State::S1)
+ mag.setBit(i, val.bits[i] == inv_sign_bit);
+ else if (undef_bit_pos < 0)
+ undef_bit_pos = i;
+
+ if (sign == BigInteger::negative)
+ mag += 1;
+
+ return BigInteger(mag, sign);
}
static RTLIL::Const big2const(const BigInteger &val, int result_len, int undef_bit_pos)