Added $shift and $shiftx cell types (needed for correct part select behavior)
authorClifford Wolf <clifford@clifford.at>
Tue, 29 Jul 2014 12:42:33 +0000 (14:42 +0200)
committerClifford Wolf <clifford@clifford.at>
Tue, 29 Jul 2014 14:35:13 +0000 (16:35 +0200)
12 files changed:
CHECKLISTS
backends/btor/btor.cc
frontends/ast/genrtlil.cc
kernel/calc.cc
kernel/celltypes.h
kernel/rtlil.cc
kernel/rtlil.h
kernel/satgen.h
passes/memory/memory_share.cc
passes/opt/opt_const.cc
techlibs/common/simlib.v
techlibs/common/stdcells.v

index 3f824fc28797d70285407903752b7edf9ad53e5d..8a149a539935bcdd60a3767983fdd69465ae2feb 100644 (file)
@@ -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:
 
index f721fdc99e5aacb9dd0f97f62635aa2f1ba58d7f..43c036690eef5bfd7d4bb4335bc2af455083e1ff 100644 (file)
@@ -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();
index cb666679b846ec762e939ebbff9ebe510c6157ba..b7f3363546cf985971c0829822cb40af035c3fef 100644 (file)
@@ -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;
index b413760d160062c1e24d67e8a171c20e33e2d3ee..b3ff3cf2a04fa6283c67b951610b774a8df5c3f9 100644 (file)
@@ -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)
index 43c23add36468f22e03cab38b2c51e3612c1561f..e1a1110d391211785ce1953c05f7f24b6b895633 100644 (file)
@@ -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)
index b562e2afb92eeeffc44c8e312d7b68a364df8606..83bbd7b17012b02c7355aa4ade50bdc0293635cc 100644 (file)
@@ -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")
index 097af9d2870a6522753c09ef1eb590e6b8bbcb71..e8d05e7e4407ae637e3ac4843eee4d5918735649 100644 (file)
@@ -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);
index 27a29cb576260d6c0cab4dfaca96edfd7260bc6b..a079b42f0352ac0e4adc5fe7c60d9ecc47cc5aad 100644 (file)
@@ -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);
                                }
index e61661a20426511da058d341ce537e047aac6704..b1629b7c4e1a6df8250e868df09332674cd7d594 100644 (file)
@@ -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);
 
index 254fe5bb49a45975b1a81d8c78035d1afb23c1b5..3e7487c3992f3afc870c674343ea066a3e1d9d41 100644 (file)
@@ -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)
index 1b50959c91187e319631b3199f65342982b10465..76aa4a52d0f133f06741ac12e884e5a51e173c21 100644 (file)
@@ -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;
index a05ea2786da2d2a210eec7b1573a6c6b38e1a006..ee59048c389e0aa8f5e1b924fc3d21eee895fc5b 100644 (file)
@@ -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