opt_expr: refactor simplification of signed X>=0 and X<0. NFCI.
authorwhitequark <whitequark@whitequark.org>
Wed, 2 Jan 2019 03:01:25 +0000 (03:01 +0000)
committerwhitequark <whitequark@whitequark.org>
Wed, 2 Jan 2019 03:01:25 +0000 (03:01 +0000)
passes/opt/opt_expr.cc
tests/opt/opt_expr_cmp.v

index 87597ce579a27483a76606528f946048a00a8d59..989c949ce5bf7ceb6c11cdfda3165ba2f4181d38 100644 (file)
@@ -1373,38 +1373,59 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 
                        if (const_sig.is_fully_def() && const_sig.is_fully_const())
                        {
-                               const char *condition, *replacement;
+                               std::string condition, replacement;
                                SigSpec result_sig(State::S0, GetSize(cell->getPort("\\Y")));
-                               result_sig[0] = State::Sx;
+                               bool replace = false;
 
                                if (!is_signed)
-                               {
+                               { /* unsigned */
                                        if (const_sig.is_fully_zero() && cmp_type == "$lt") {
                                                condition   = "unsigned X<0";
                                                replacement = "constant 0";
                                                result_sig[0] = State::S0;
+                                               replace = true;
                                        }
                                        if (const_sig.is_fully_zero() && cmp_type == "$ge") {
                                                condition   = "unsigned X>=0";
                                                replacement = "constant 1";
                                                result_sig[0] = State::S1;
+                                               replace = true;
                                        }
                                        if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == "$gt") {
                                                condition   = "unsigned X>~0";
                                                replacement = "constant 0";
                                                result_sig[0] = State::S0;
+                                               replace = true;
                                        }
                                        if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == "$le") {
                                                condition   = "unsigned X<=~0";
                                                replacement = "constant 1";
                                                result_sig[0] = State::S1;
+                                               replace = true;
+                                       }
+                               }
+                               else
+                               { /* signed */
+                                       if (const_sig.is_fully_zero() && cmp_type == "$lt")
+                                       {
+                                               condition   = "signed X<0";
+                                               replacement = stringf("X[%d]", var_width - 1);
+                                               result_sig[0] = var_sig[var_width - 1];
+                                               replace = true;
+                                       }
+                                       if (const_sig.is_fully_zero() && cmp_type == "$ge")
+                                       {
+                                               condition   = "signed X>=0";
+                                               replacement = stringf("X[%d]", var_width - 1);
+                                               module->addNot(NEW_ID, var_sig[var_width - 1], result_sig);
+                                               replace = true;
                                        }
                                }
 
-                               if (result_sig.is_fully_def())
+                               if (replace)
                                {
                                        log("Replacing %s cell `%s' (implementing %s) with %s.\n",
-                                                       log_id(cell->type), log_id(cell), condition, replacement);
+                                                       log_id(cell->type), log_id(cell), condition.c_str(), replacement.c_str());
                                        module->connect(cell->getPort("\\Y"), result_sig);
                                        module->remove(cell);
                                        did_something = true;
@@ -1453,25 +1474,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
                        } else
                                log_abort();
 
-                       // replace a(signed) < 0 with the high bit of a
-                       if (sigConst.is_fully_const() && sigConst.is_fully_zero() && var_signed == true)
-                       {
-                               RTLIL::SigSpec a_prime(RTLIL::State::S0, cell->parameters["\\Y_WIDTH"].as_int());
-                               a_prime[0] = sigVar[width - 1];
-                               if (is_lt) {
-                                       log("Replacing %s cell `%s' (implementing X<0) with X[%d]: %s\n",
-                                                       log_id(cell->type), log_id(cell), width-1, log_signal(a_prime));
-                                       module->connect(cell->getPort("\\Y"), a_prime);
-                                       module->remove(cell);
-                               } else {
-                                       log("Replacing %s cell `%s' (implementing X>=0) with ~X[%d]: %s\n",
-                                                       log_id(cell->type), log_id(cell), width-1, log_signal(a_prime));
-                                       module->addNot(NEW_ID, a_prime, cell->getPort("\\Y"));
-                                       module->remove(cell);
-                               }
-                               did_something = true;
-                               goto next_cell;
-                       } else
                        if (sigConst.is_fully_const() && sigConst.is_fully_def() && var_signed == false)
                        {
                                int const_bit_set = get_onehot_bit_index(sigConst);
index 7eb65d5316e9a1270913dd808505cbab05782bd8..72372bdf0aeec90c3db078abb46e04b4e344087a 100644 (file)
@@ -1,11 +1,17 @@
 module top(...);
   input [3:0] a;
-  output o1 = 4'b0000 >  a;
-  output o2 = 4'b0000 <= a;
-  output o3 = 4'b1111 <  a;
-  output o4 = 4'b1111 >= a;
-  output o5 = a <  4'b0000;
-  output o6 = a >= 4'b0000;
-  output o7 = a >  4'b1111;
-  output o8 = a <= 4'b1111;
+
+  output o1_1 = 4'b0000 >  a;
+  output o1_2 = 4'b0000 <= a;
+  output o1_3 = 4'b1111 <  a;
+  output o1_4 = 4'b1111 >= a;
+  output o1_5 = a <  4'b0000;
+  output o1_6 = a >= 4'b0000;
+  output o1_7 = a >  4'b1111;
+  output o1_8 = a <= 4'b1111;
+
+  output o2_1 = 4'sb0000 >  $signed(a);
+  output o2_2 = 4'sb0000 <= $signed(a);
+  output o2_3 = $signed(a) <  4'sb0000;
+  output o2_4 = $signed(a) >= 4'sb0000;
 endmodule