From 397b00252dc0c4af725614bd12fc299147ba8efa Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 29 Jul 2014 14:42:33 +0200 Subject: Added $shift and $shiftx cell types (needed for correct part select behavior) --- kernel/calc.cc | 43 ++++++++++++++++++++++++++++++++++++++----- kernel/celltypes.h | 6 +++++- kernel/rtlil.cc | 5 ++++- kernel/rtlil.h | 22 ++++++++++++++-------- kernel/satgen.h | 18 ++++++++++++++---- 5 files changed, 75 insertions(+), 19 deletions(-) (limited to 'kernel') diff --git a/kernel/calc.cc b/kernel/calc.cc index b413760d..b3ff3cf2 100644 --- a/kernel/calc.cc +++ b/kernel/calc.cc @@ -276,7 +276,7 @@ RTLIL::Const RTLIL::const_logic_or(const RTLIL::Const &arg1, const RTLIL::Const return result; } -static RTLIL::Const const_shift(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool sign_ext, int direction, int result_len) +static RTLIL::Const const_shift_worker(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool sign_ext, int direction, int result_len) { int undef_bit_pos = -1; BigInteger offset = const2big(arg2, false, undef_bit_pos) * direction; @@ -305,28 +305,61 @@ 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(arg1_ext, arg2, false, -1, result_len); + return const_shift_worker(arg1_ext, arg2, 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, result_len, signed1); - return const_shift(arg1_ext, arg2, false, +1, result_len); + return const_shift_worker(arg1_ext, arg2, false, +1, result_len); } RTLIL::Const RTLIL::const_sshl(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len) { if (!signed1) return const_shl(arg1, arg2, signed1, signed2, result_len); - return const_shift(arg1, arg2, true, -1, result_len); + return const_shift_worker(arg1, arg2, true, -1, result_len); } RTLIL::Const RTLIL::const_sshr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len) { if (!signed1) return const_shr(arg1, arg2, signed1, signed2, result_len); - return const_shift(arg1, arg2, true, +1, 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 >= arg1.bits.size()) + result.bits[i] = other_bits; + else + result.bits[i] = arg1.bits[pos.toInt()]; + } + + return result; +} + +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 RTLIL::const_shiftx(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::Sx); } RTLIL::Const RTLIL::const_lt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len) diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 43c23add..e1a1110d 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -75,6 +75,8 @@ struct CellTypes cell_types.insert("$shr"); cell_types.insert("$sshl"); cell_types.insert("$sshr"); + cell_types.insert("$shift"); + cell_types.insert("$shiftx"); cell_types.insert("$lt"); cell_types.insert("$le"); cell_types.insert("$eq"); @@ -224,7 +226,7 @@ struct CellTypes if (type == "$sshl" && !signed1) type = "$shl"; - if (type != "$sshr" && type != "$sshl" && type != "$shr" && type != "$shl" && + if (type != "$sshr" && type != "$sshl" && type != "$shr" && type != "$shl" && type != "$shift" && type != "$shiftx" && type != "$pos" && type != "$neg" && type != "$not" && type != "$bu0") { if (!signed1 || !signed2) signed1 = false, signed2 = false; @@ -248,6 +250,8 @@ struct CellTypes HANDLE_CELL_TYPE(shr) HANDLE_CELL_TYPE(sshl) HANDLE_CELL_TYPE(sshr) + HANDLE_CELL_TYPE(shift) + HANDLE_CELL_TYPE(shiftx) HANDLE_CELL_TYPE(lt) HANDLE_CELL_TYPE(le) HANDLE_CELL_TYPE(eq) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index b562e2af..83bbd7b1 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -474,7 +474,8 @@ namespace { return; } - if (cell->type == "$shl" || cell->type == "$shr" || cell->type == "$sshl" || cell->type == "$sshr") { + if (cell->type == "$shl" || cell->type == "$shr" || cell->type == "$sshl" || cell->type == "$sshr" || + cell->type == "$shift" || cell->type == "$shiftx") { param_bool("\\A_SIGNED"); param_bool("\\B_SIGNED"); port("\\A", param("\\A_WIDTH")); @@ -1101,6 +1102,8 @@ DEF_METHOD(Shl, sig_a.size(), "$shl") DEF_METHOD(Shr, sig_a.size(), "$shr") DEF_METHOD(Sshl, sig_a.size(), "$sshl") DEF_METHOD(Sshr, sig_a.size(), "$sshr") +DEF_METHOD(Shift, sig_a.size(), "$shift") +DEF_METHOD(Shiftx, sig_a.size(), "$shiftx") DEF_METHOD(Lt, 1, "$lt") DEF_METHOD(Le, 1, "$le") DEF_METHOD(Eq, 1, "$eq") diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 097af9d2..e8d05e7e 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -172,6 +172,8 @@ namespace RTLIL RTLIL::Const const_shr (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_sshl (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_sshr (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); + RTLIL::Const const_shift (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); + RTLIL::Const const_shiftx (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_lt (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); RTLIL::Const const_le (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len); @@ -474,10 +476,12 @@ public: RTLIL::Cell* addReduceXnor (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false); RTLIL::Cell* addReduceBool (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false); - RTLIL::Cell* addShl (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false); - RTLIL::Cell* addShr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false); - RTLIL::Cell* addSshl (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false); - RTLIL::Cell* addSshr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false); + RTLIL::Cell* addShl (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false); + RTLIL::Cell* addShr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false); + RTLIL::Cell* addSshl (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false); + RTLIL::Cell* addSshr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false); + RTLIL::Cell* addShift (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false); + RTLIL::Cell* addShiftx (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false); RTLIL::Cell* addLt (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false); RTLIL::Cell* addLe (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false); @@ -551,10 +555,12 @@ public: RTLIL::SigSpec ReduceXnor (RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed = false); RTLIL::SigSpec ReduceBool (RTLIL::IdString name, RTLIL::SigSpec sig_a, bool is_signed = false); - RTLIL::SigSpec Shl (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false); - RTLIL::SigSpec Shr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false); - RTLIL::SigSpec Sshl (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false); - RTLIL::SigSpec Sshr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false); + RTLIL::SigSpec Shl (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false); + RTLIL::SigSpec Shr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false); + RTLIL::SigSpec Sshl (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false); + RTLIL::SigSpec Sshr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false); + RTLIL::SigSpec Shift (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false); + RTLIL::SigSpec Shiftx (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false); RTLIL::SigSpec Lt (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false); RTLIL::SigSpec Le (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, bool is_signed = false); diff --git a/kernel/satgen.h b/kernel/satgen.h index 27a29cb5..a079b42f 100644 --- a/kernel/satgen.h +++ b/kernel/satgen.h @@ -597,7 +597,7 @@ struct SatGen return true; } - if (cell->type == "$shl" || cell->type == "$shr" || cell->type == "$sshl" || cell->type == "$sshr") + if (cell->type == "$shl" || cell->type == "$shr" || cell->type == "$sshl" || cell->type == "$sshr" || cell->type == "$shift" || cell->type == "$shiftx") { std::vector a = importDefSigSpec(cell->get("\\A"), timestep); std::vector b = importDefSigSpec(cell->get("\\B"), timestep); @@ -605,6 +605,7 @@ struct SatGen char shift_left = cell->type == "$shl" || cell->type == "$sshl"; bool sign_extend = cell->type == "$sshr" && cell->parameters["\\A_SIGNED"].as_bool(); + bool shift_shiftx = cell->type == "$shift" || cell->type == "$shiftx"; while (y.size() < a.size()) y.push_back(ez->literal()); @@ -616,9 +617,13 @@ struct SatGen std::vector tmp = a; for (size_t i = 0; i < b.size(); i++) { + bool shift_left_this = shift_left; + if (shift_shiftx && i == b.size()-1 && cell->parameters["\\B_SIGNED"].as_bool()) + shift_left_this = true; + std::vector tmp_shifted(tmp.size()); for (size_t j = 0; j < tmp.size(); j++) { - int idx = j + (1 << (i > 30 ? 30 : i)) * (shift_left ? -1 : +1); + int idx = j + (1 << (i > 30 ? 30 : i)) * (shift_left_this ? -1 : +1); tmp_shifted.at(j) = (0 <= idx && idx < int(tmp.size())) ? tmp.at(idx) : sign_extend ? tmp.back() : ez->FALSE; } tmp = ez->vec_ite(b.at(i), tmp_shifted, tmp); @@ -639,10 +644,15 @@ struct SatGen tmp = undef_a; for (size_t i = 0; i < b.size(); i++) { + bool shift_left_this = shift_left; + if (shift_shiftx && i == b.size()-1 && cell->parameters["\\B_SIGNED"].as_bool()) + shift_left_this = true; + std::vector tmp_shifted(tmp.size()); for (size_t j = 0; j < tmp.size(); j++) { - int idx = j + (1 << (i > 30 ? 30 : i)) * (shift_left ? -1 : +1); - tmp_shifted.at(j) = (0 <= idx && idx < int(tmp.size())) ? tmp.at(idx) : sign_extend ? tmp.back() : ez->FALSE; + int idx = j + (1 << (i > 30 ? 30 : i)) * (shift_left_this ? -1 : +1); + tmp_shifted.at(j) = (0 <= idx && idx < int(tmp.size())) ? tmp.at(idx) : + sign_extend ? tmp.back() : cell->type == "$shiftx" ? ez->TRUE : ez->FALSE; } tmp = ez->vec_ite(b.at(i), tmp_shifted, tmp); } -- cgit v1.2.3