aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/calc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/calc.cc')
-rw-r--r--kernel/calc.cc113
1 files changed, 72 insertions, 41 deletions
diff --git a/kernel/calc.cc b/kernel/calc.cc
index ae18809d3..0865db526 100644
--- a/kernel/calc.cc
+++ b/kernel/calc.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -275,10 +275,15 @@ RTLIL::Const RTLIL::const_logic_or(const RTLIL::Const &arg1, const RTLIL::Const
return result;
}
-static RTLIL::Const const_shift_worker(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool sign_ext, int direction, int result_len)
+// Shift `arg1` by `arg2` bits.
+// If `direction` is +1, `arg1` is shifted right by `arg2` bits; if `direction` is -1, `arg1` is shifted left by `arg2` bits.
+// If `signed2` is true, `arg2` is interpreted as a signed integer; a negative `arg2` will cause a shift in the opposite direction.
+// Any required bits outside the bounds of `arg1` are padded with `vacant_bits` unless `sign_ext` is true, in which case any bits outside the left
+// bounds are filled with the leftmost bit of `arg1` (arithmetic shift).
+static RTLIL::Const const_shift_worker(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool sign_ext, bool signed2, int direction, int result_len, RTLIL::State vacant_bits = RTLIL::State::S0)
{
int undef_bit_pos = -1;
- BigInteger offset = const2big(arg2, false, undef_bit_pos) * direction;
+ BigInteger offset = const2big(arg2, signed2, undef_bit_pos) * direction;
if (result_len < 0)
result_len = arg1.bits.size();
@@ -290,9 +295,9 @@ static RTLIL::Const const_shift_worker(const RTLIL::Const &arg1, const RTLIL::Co
for (int i = 0; i < result_len; i++) {
BigInteger pos = BigInteger(i) + offset;
if (pos < 0)
- result.bits[i] = RTLIL::State::S0;
+ result.bits[i] = vacant_bits;
else if (pos >= BigInteger(int(arg1.bits.size())))
- result.bits[i] = sign_ext ? arg1.bits.back() : RTLIL::State::S0;
+ result.bits[i] = sign_ext ? arg1.bits.back() : vacant_bits;
else
result.bits[i] = arg1.bits[pos.toInt()];
}
@@ -304,61 +309,36 @@ RTLIL::Const RTLIL::const_shl(const RTLIL::Const &arg1, const RTLIL::Const &arg2
{
RTLIL::Const arg1_ext = arg1;
extend_u0(arg1_ext, result_len, signed1);
- return const_shift_worker(arg1_ext, arg2, false, -1, result_len);
+ return const_shift_worker(arg1_ext, arg2, false, false, -1, result_len);
}
RTLIL::Const RTLIL::const_shr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool, int result_len)
{
RTLIL::Const arg1_ext = arg1;
extend_u0(arg1_ext, max(result_len, GetSize(arg1)), signed1);
- return const_shift_worker(arg1_ext, arg2, false, +1, result_len);
+ return const_shift_worker(arg1_ext, arg2, false, false, +1, result_len);
}
-RTLIL::Const RTLIL::const_sshl(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
+RTLIL::Const RTLIL::const_sshl(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool, int result_len)
{
- if (!signed1)
- return const_shl(arg1, arg2, signed1, signed2, result_len);
- return const_shift_worker(arg1, arg2, true, -1, result_len);
+ return const_shift_worker(arg1, arg2, signed1, false, -1, result_len);
}
-RTLIL::Const RTLIL::const_sshr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
+RTLIL::Const RTLIL::const_sshr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool, int result_len)
{
- if (!signed1)
- return const_shr(arg1, arg2, signed1, signed2, result_len);
- return const_shift_worker(arg1, arg2, true, +1, result_len);
-}
-
-static RTLIL::Const const_shift_shiftx(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool, bool signed2, int result_len, RTLIL::State other_bits)
-{
- int undef_bit_pos = -1;
- BigInteger offset = const2big(arg2, signed2, undef_bit_pos);
-
- if (result_len < 0)
- result_len = arg1.bits.size();
-
- RTLIL::Const result(RTLIL::State::Sx, result_len);
- if (undef_bit_pos >= 0)
- return result;
-
- for (int i = 0; i < result_len; i++) {
- BigInteger pos = BigInteger(i) + offset;
- if (pos < 0 || pos >= BigInteger(int(arg1.bits.size())))
- result.bits[i] = other_bits;
- else
- result.bits[i] = arg1.bits[pos.toInt()];
- }
-
- return result;
+ return const_shift_worker(arg1, arg2, signed1, false, +1, result_len);
}
RTLIL::Const RTLIL::const_shift(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
{
- return const_shift_shiftx(arg1, arg2, signed1, signed2, result_len, RTLIL::State::S0);
+ RTLIL::Const arg1_ext = arg1;
+ extend_u0(arg1_ext, max(result_len, GetSize(arg1)), signed1);
+ return const_shift_worker(arg1_ext, arg2, false, signed2, +1, result_len);
}
-RTLIL::Const RTLIL::const_shiftx(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
+RTLIL::Const RTLIL::const_shiftx(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool, bool signed2, int result_len)
{
- return const_shift_shiftx(arg1, arg2, signed1, signed2, result_len, RTLIL::State::Sx);
+ return const_shift_worker(arg1, arg2, false, signed2, +1, result_len, RTLIL::State::Sx);
}
RTLIL::Const RTLIL::const_lt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
@@ -629,5 +609,56 @@ RTLIL::Const RTLIL::const_neg(const RTLIL::Const &arg1, const RTLIL::Const&, boo
return RTLIL::const_sub(zero, arg1_ext, true, signed1, result_len);
}
+RTLIL::Const RTLIL::const_bmux(const RTLIL::Const &arg1, const RTLIL::Const &arg2)
+{
+ std::vector<RTLIL::State> t = arg1.bits;
+
+ for (int i = GetSize(arg2)-1; i >= 0; i--)
+ {
+ RTLIL::State sel = arg2.bits.at(i);
+ std::vector<RTLIL::State> new_t;
+ if (sel == State::S0)
+ new_t = std::vector<RTLIL::State>(t.begin(), t.begin() + GetSize(t)/2);
+ else if (sel == State::S1)
+ new_t = std::vector<RTLIL::State>(t.begin() + GetSize(t)/2, t.end());
+ else
+ for (int j = 0; j < GetSize(t)/2; j++)
+ new_t.push_back(t[j] == t[j + GetSize(t)/2] ? t[j] : RTLIL::Sx);
+ t.swap(new_t);
+ }
+
+ return t;
+}
+
+RTLIL::Const RTLIL::const_demux(const RTLIL::Const &arg1, const RTLIL::Const &arg2)
+{
+ int width = GetSize(arg1);
+ int s_width = GetSize(arg2);
+ std::vector<RTLIL::State> res;
+ for (int i = 0; i < (1 << s_width); i++)
+ {
+ bool ne = false;
+ bool x = false;
+ for (int j = 0; j < s_width; j++) {
+ bool bit = i & 1 << j;
+ if (arg2[j] == (bit ? RTLIL::S0 : RTLIL::S1))
+ ne = true;
+ else if (arg2[j] != RTLIL::S0 && arg2[j] != RTLIL::S1)
+ x = true;
+ }
+ if (ne) {
+ for (int j = 0; j < width; j++)
+ res.push_back(State::S0);
+ } else if (x) {
+ for (int j = 0; j < width; j++)
+ res.push_back(arg1.bits[j] == State::S0 ? State::S0 : State::Sx);
+ } else {
+ for (int j = 0; j < width; j++)
+ res.push_back(arg1.bits[j]);
+ }
+ }
+ return res;
+}
+
YOSYS_NAMESPACE_END