diff options
-rw-r--r-- | CHECKLISTS | 2 | ||||
-rw-r--r-- | backends/btor/btor.cc | 4 | ||||
-rw-r--r-- | frontends/ast/genrtlil.cc | 16 | ||||
-rw-r--r-- | kernel/calc.cc | 43 | ||||
-rw-r--r-- | kernel/celltypes.h | 6 | ||||
-rw-r--r-- | kernel/rtlil.cc | 5 | ||||
-rw-r--r-- | kernel/rtlil.h | 22 | ||||
-rw-r--r-- | kernel/satgen.h | 18 | ||||
-rw-r--r-- | passes/memory/memory_share.cc | 2 | ||||
-rw-r--r-- | passes/opt/opt_const.cc | 16 | ||||
-rw-r--r-- | techlibs/common/simlib.v | 48 | ||||
-rw-r--r-- | techlibs/common/stdcells.v | 72 |
12 files changed, 214 insertions, 40 deletions
diff --git a/CHECKLISTS b/CHECKLISTS index 3f824fc28..8a149a539 100644 --- a/CHECKLISTS +++ b/CHECKLISTS @@ -123,6 +123,8 @@ Things to do right away: - Add to kernel/celltypes.h (incl. eval() handling for non-mem cells) - Add to InternalCellChecker::check() in kernel/rtlil.cc + - Add to techlibs/common/simlib.v + - Add to techlibs/common/stdcells.v Things to do after finalizing the cell interface: diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index f721fdc99..43c036690 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -111,6 +111,8 @@ struct BtorDumper cell_type_translation["$shl"] = "sll"; cell_type_translation["$sshr"] = "sra"; cell_type_translation["$sshl"] = "sll"; + cell_type_translation["$shift"] = "srl"; + cell_type_translation["$shiftx"] = "srl"; cell_type_translation["$lt"] = "ult"; cell_type_translation["$le"] = "ulte"; cell_type_translation["$gt"] = "ugt"; @@ -540,7 +542,7 @@ struct BtorDumper } line_ref[cell->name]=line_num; } - else if(cell->type == "$shr" || cell->type == "$shl" || cell->type == "$sshr" || cell->type == "$sshl") + else if(cell->type == "$shr" || cell->type == "$shl" || cell->type == "$sshr" || cell->type == "$sshl" || cell->type == "$shift" || cell->type == "$shiftx") { log("writing binary cell - %s\n", cstr(cell->type)); int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index cb666679b..b7f336354 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -917,11 +917,17 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) children[0]->children[1]->clone() : children[0]->children[0]->clone()); fake_ast->children[0]->delete_children(); RTLIL::SigSpec shift_val = fake_ast->children[1]->genRTLIL(); - if (id2ast->range_right != 0) - shift_val = current_module->Sub(NEW_ID, shift_val, id2ast->range_right); - if (id2ast->range_swapped) - shift_val = current_module->Sub(NEW_ID, RTLIL::SigSpec(source_width - width), shift_val); - RTLIL::SigSpec sig = binop2rtlil(fake_ast, "$shr", width, fake_ast->children[0]->genRTLIL(), shift_val); + if (id2ast->range_right != 0) { + shift_val = current_module->Sub(NEW_ID, shift_val, id2ast->range_right, fake_ast->children[1]->is_signed); + fake_ast->children[1]->is_signed = true; + } + if (id2ast->range_swapped) { + shift_val = current_module->Sub(NEW_ID, RTLIL::SigSpec(source_width - width), shift_val, fake_ast->children[1]->is_signed); + fake_ast->children[1]->is_signed = true; + } + if (SIZE(shift_val) >= 32) + fake_ast->children[1]->is_signed = true; + RTLIL::SigSpec sig = binop2rtlil(fake_ast, "$shiftx", width, fake_ast->children[0]->genRTLIL(), shift_val); delete left_at_zero_ast; delete right_at_zero_ast; delete fake_ast; diff --git a/kernel/calc.cc b/kernel/calc.cc index b413760d1..b3ff3cf2a 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 43c23add3..e1a1110d3 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 b562e2afb..83bbd7b17 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 097af9d28..e8d05e7e4 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 27a29cb57..a079b42f0 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<int> a = importDefSigSpec(cell->get("\\A"), timestep); std::vector<int> 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<int> 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<int> 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<int> 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); } diff --git a/passes/memory/memory_share.cc b/passes/memory/memory_share.cc index e61661a20..b1629b7c4 100644 --- a/passes/memory/memory_share.cc +++ b/passes/memory/memory_share.cc @@ -695,6 +695,8 @@ struct MemoryShareWorker cone_ct.cell_types.erase("$shr"); cone_ct.cell_types.erase("$sshl"); cone_ct.cell_types.erase("$sshr"); + cone_ct.cell_types.erase("$shift"); + cone_ct.cell_types.erase("$shiftx"); modwalker.setup(design, module, &cone_ct); diff --git a/passes/opt/opt_const.cc b/passes/opt/opt_const.cc index 254fe5bb4..3e7487c39 100644 --- a/passes/opt/opt_const.cc +++ b/passes/opt/opt_const.cc @@ -338,7 +338,7 @@ static void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bo goto next_cell; } - if (cell->type == "$reduce_xor" || cell->type == "$reduce_xnor" || + if (cell->type == "$reduce_xor" || cell->type == "$reduce_xnor" || cell->type == "$shift" || cell->type == "$shiftx" || cell->type == "$shl" || cell->type == "$shr" || cell->type == "$sshl" || cell->type == "$sshr" || cell->type == "$lt" || cell->type == "$le" || cell->type == "$ge" || cell->type == "$gt" || cell->type == "$neg" || cell->type == "$add" || cell->type == "$sub" || @@ -347,7 +347,7 @@ static void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bo RTLIL::SigSpec sig_a = assign_map(cell->get("\\A")); RTLIL::SigSpec sig_b = cell->has("\\B") ? assign_map(cell->get("\\B")) : RTLIL::SigSpec(); - 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") sig_a = RTLIL::SigSpec(); for (auto &bit : sig_a.to_sigbit_vector()) @@ -360,8 +360,8 @@ static void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bo if (0) { found_the_x_bit: - cover_list("opt.opt_const.xbit", "$reduce_xor", "$reduce_xnor", "$shl", "$shr", "$sshl", "$sshr", "$lt", "$le", "$ge", "$gt", - "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$pow", cell->type); + cover_list("opt.opt_const.xbit", "$reduce_xor", "$reduce_xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", + "$lt", "$le", "$ge", "$gt", "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$pow", cell->type); if (cell->type == "$reduce_xor" || cell->type == "$reduce_xnor" || cell->type == "$lt" || cell->type == "$le" || cell->type == "$ge" || cell->type == "$gt") replace_cell(assign_map, module, cell, "x-bit in input", "\\Y", RTLIL::State::Sx); @@ -572,7 +572,7 @@ static void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bo identity_wrt_a = 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") { RTLIL::SigSpec b = assign_map(cell->get("\\B")); @@ -603,9 +603,9 @@ static void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bo if (identity_wrt_a || identity_wrt_b) { if (identity_wrt_a) - cover_list("opt.opt_const.identwrt.a", "$add", "$sub", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$mul", "$div", cell->type); + cover_list("opt.opt_const.identwrt.a", "$add", "$sub", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type); if (identity_wrt_b) - cover_list("opt.opt_const.identwrt.b", "$add", "$sub", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$mul", "$div", cell->type); + cover_list("opt.opt_const.identwrt.b", "$add", "$sub", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type); log("Replacing %s cell `%s' in module `%s' with identity for port %c.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), identity_wrt_a ? 'A' : 'B'); @@ -792,6 +792,8 @@ static void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bo FOLD_2ARG_CELL(shr) FOLD_2ARG_CELL(sshl) FOLD_2ARG_CELL(sshr) + FOLD_2ARG_CELL(shift) + FOLD_2ARG_CELL(shiftx) FOLD_2ARG_CELL(lt) FOLD_2ARG_CELL(le) diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 1b50959c9..76aa4a52d 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -418,6 +418,54 @@ endmodule // -------------------------------------------------------- +module \$shift (A, B, Y); + +parameter A_SIGNED = 0; +parameter B_SIGNED = 0; +parameter A_WIDTH = 0; +parameter B_WIDTH = 0; +parameter Y_WIDTH = 0; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output [Y_WIDTH-1:0] Y; + +generate + if (B_SIGNED) begin:BLOCK1 + assign Y = $signed(B) < 0 ? A << -B : A >> B; + end else begin:BLOCK2 + assign Y = A >> B; + end +endgenerate + +endmodule + +// -------------------------------------------------------- + +module \$shiftx (A, B, Y); + +parameter A_SIGNED = 0; +parameter B_SIGNED = 0; +parameter A_WIDTH = 0; +parameter B_WIDTH = 0; +parameter Y_WIDTH = 0; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output [Y_WIDTH-1:0] Y; + +generate + if (B_SIGNED) begin:BLOCK1 + assign Y = A[$signed(B) +: Y_WIDTH]; + end else begin:BLOCK2 + assign Y = A[B +: Y_WIDTH]; + end +endgenerate + +endmodule + +// -------------------------------------------------------- + module \$lt (A, B, Y); parameter A_SIGNED = 0; diff --git a/techlibs/common/stdcells.v b/techlibs/common/stdcells.v index a05ea2786..ee59048c3 100644 --- a/techlibs/common/stdcells.v +++ b/techlibs/common/stdcells.v @@ -129,12 +129,12 @@ endmodule // -------------------------------------------------------- -module \$__shift (X, A, Y); +module \$__shift (XL, XR, A, Y); parameter WIDTH = 1; parameter SHIFT = 0; -input X; +input XL, XR; input [WIDTH-1:0] A; output [WIDTH-1:0] Y; @@ -142,12 +142,12 @@ genvar i; generate for (i = 0; i < WIDTH; i = i + 1) begin:V if (i+SHIFT < 0) begin - assign Y[i] = 0; + assign Y[i] = XR; end else if (i+SHIFT < WIDTH) begin assign Y[i] = A[i+SHIFT]; end else begin - assign Y[i] = X; + assign Y[i] = XL; end end endgenerate @@ -196,7 +196,8 @@ generate .WIDTH(WIDTH), .SHIFT(0 - (2 ** (i > 30 ? 30 : i))) ) sh ( - .X(0), + .XL(1'b0), + .XR(1'b0), .A(unshifted), .Y(shifted) ); @@ -255,7 +256,8 @@ generate .WIDTH(WIDTH), .SHIFT(2 ** (i > 30 ? 30 : i)) ) sh ( - .X(0), + .XL(1'b0), + .XR(1'b0), .A(unshifted), .Y(shifted) ); @@ -314,7 +316,8 @@ generate .WIDTH(WIDTH), .SHIFT(0 - (2 ** (i > 30 ? 30 : i))) ) sh ( - .X(0), + .XL(1'b0), + .XR(1'b0), .A(unshifted), .Y(shifted) ); @@ -382,7 +385,8 @@ generate .WIDTH(WIDTH), .SHIFT(2 ** (i > 30 ? 30 : i)) ) sh ( - .X(A_SIGNED && A[A_WIDTH-1]), + .XL(A_SIGNED && A[A_WIDTH-1]), + .XR(1'b0), .A(unshifted), .Y(shifted) ); @@ -401,6 +405,58 @@ endmodule // -------------------------------------------------------- +module \$shift (A, B, Y); + +parameter A_SIGNED = 0; +parameter B_SIGNED = 0; +parameter A_WIDTH = 1; +parameter B_WIDTH = 1; +parameter Y_WIDTH = 1; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output [Y_WIDTH-1:0] Y; + +generate + if (B_SIGNED) begin:BLOCK1 + assign Y = $signed(B) < 0 ? A << -B : A >> B; + end else begin:BLOCK2 + assign Y = A >> B; + end +endgenerate + +endmodule + +// -------------------------------------------------------- + +module \$shiftx (A, B, Y); + +parameter A_SIGNED = 0; +parameter B_SIGNED = 0; +parameter A_WIDTH = 1; +parameter B_WIDTH = 1; +parameter Y_WIDTH = 1; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output [Y_WIDTH-1:0] Y; + +\$shift #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH), +) sh ( + .A(A), + .B(B), + .Y(Y) +); + +endmodule + +// -------------------------------------------------------- + module \$__fulladd (A, B, C, X, Y); // {X, Y} = A + B + C |