Fixed type of sign extension in opt_const $eq/$ne handling
authorClifford Wolf <clifford@clifford.at>
Thu, 7 Nov 2013 15:53:28 +0000 (16:53 +0100)
committerClifford Wolf <clifford@clifford.at>
Thu, 7 Nov 2013 15:53:28 +0000 (16:53 +0100)
kernel/rtlil.cc
kernel/rtlil.h
passes/opt/opt_const.cc

index d64a37bb86a5887e27c60ef1d3a70e51a5da774d..4388acb1d7b5b6910493b1cd59490d96d9ab6e6f 100644 (file)
@@ -940,6 +940,22 @@ void RTLIL::SigSpec::extend(int width, bool is_signed)
        optimize();
 }
 
+void RTLIL::SigSpec::extend_un0(int width, bool is_signed)
+{
+       if (this->width > width)
+               remove(width, this->width - width);
+       
+       if (this->width < width) {
+               RTLIL::SigSpec padding = this->width > 0 ? extract(this->width - 1, 1) : RTLIL::SigSpec(RTLIL::State::S0);
+               if (!is_signed)
+                       padding = RTLIL::SigSpec(RTLIL::State::S0);
+               while (this->width < width)
+                       append(padding);
+       }
+
+       optimize();
+}
+
 void RTLIL::SigSpec::check() const
 {
        int w = 0;
index 6cb471b586f244166d4350b92cdb5feb507a7002..376a09abf5a2ee762a227f31ca398b7029f48bdc 100644 (file)
@@ -342,6 +342,7 @@ struct RTLIL::SigSpec {
        void append(const RTLIL::SigSpec &signal);
        bool combine(RTLIL::SigSpec signal, RTLIL::State freeState = RTLIL::State::Sz, bool override = false);
        void extend(int width, bool is_signed = false);
+       void extend_un0(int width, bool is_signed = false);
        void check() const;
        bool operator <(const RTLIL::SigSpec &other) const;
        bool operator ==(const RTLIL::SigSpec &other) const;
index b04ed9e721ee865d47bf14a179cb54e6e4c742ae..f20181f1ebe57cff4ab591929583c87ce1b9b401 100644 (file)
@@ -151,8 +151,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 
                        if (cell->parameters["\\A_WIDTH"].as_int() != cell->parameters["\\B_WIDTH"].as_int()) {
                                int width = std::max(cell->parameters["\\A_WIDTH"].as_int(), cell->parameters["\\B_WIDTH"].as_int());
-                               a.extend(width, cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool());
-                               b.extend(width, cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool());
+                               a.extend_un0(width, cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool());
+                               b.extend_un0(width, cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool());
                        }
 
                        RTLIL::SigSpec new_a, new_b;
@@ -168,6 +168,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
                                new_b.append(b.chunks[i]);
                        }
 
+                       if (new_a.width == 0) {
+                               RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type == "$eq" ?  RTLIL::State::S1 : RTLIL::State::S0);
+                               new_y.extend(cell->parameters["\\Y_WIDTH"].as_int(), false);
+                               replace_cell(module, cell, "empty", "\\Y", new_y);
+                               goto next_cell;
+                       }
+
                        if (new_a.width != a.width) {
                                new_a.optimize();
                                new_b.optimize();
@@ -176,13 +183,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
                                cell->parameters["\\A_WIDTH"] = new_a.width;
                                cell->parameters["\\B_WIDTH"] = new_b.width;
                        }
-
-                       if (new_a.width == 0) {
-                               RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type == "$eq" ?  RTLIL::State::S1 : RTLIL::State::S0);
-                               new_y.extend(cell->parameters["\\Y_WIDTH"].as_int(), false);
-                               replace_cell(module, cell, "empty", "\\Y", new_y);
-                               goto next_cell;
-                       }
                }
 
                if ((cell->type == "$eq" || cell->type == "$ne") && cell->parameters["\\Y_WIDTH"].as_int() == 1 &&