Fixed SAT and ConstEval undef handling for $pmux and $safe_pmux
authorClifford Wolf <clifford@clifford.at>
Fri, 3 Jan 2014 16:30:50 +0000 (17:30 +0100)
committerClifford Wolf <clifford@clifford.at>
Fri, 3 Jan 2014 16:30:50 +0000 (17:30 +0100)
kernel/consteval.h
kernel/satgen.h

index a424007ef7a8b7b04753a415522479f30b1ebd9b..10116ccfec9e8095046e88ffc35bc7467405d240 100644 (file)
@@ -110,6 +110,7 @@ struct ConstEval
                if (cell->type == "$mux" || cell->type == "$pmux" || cell->type == "$safe_pmux" || cell->type == "$_MUX_")
                {
                        std::vector<RTLIL::SigSpec> y_candidates;
+                       int count_maybe_set_s_bits = 0;
                        int count_set_s_bits = 0;
 
                        for (int i = 0; i < sig_s.width; i++)
@@ -120,16 +121,17 @@ struct ConstEval
                                if (s_bit == RTLIL::State::Sx || s_bit == RTLIL::State::S1)
                                        y_candidates.push_back(b_slice);
 
+                               if (s_bit == RTLIL::State::S1 || s_bit == RTLIL::State::Sx)
+                                       count_maybe_set_s_bits++;
+
                                if (s_bit == RTLIL::State::S1)
                                        count_set_s_bits++;
                        }
 
-                       if (cell->type == "$safe_pmux" && count_set_s_bits > 1) {
+                       if (cell->type == "$safe_pmux" && count_set_s_bits > 1)
                                y_candidates.clear();
-                               count_set_s_bits = 0;
-                       }
 
-                       if (count_set_s_bits == 0)
+                       if ((cell->type == "$safe_pmux" && count_maybe_set_s_bits > 1) || count_set_s_bits == 0)
                                y_candidates.push_back(sig_a);
 
                        std::vector<RTLIL::Const> y_values;
index 208ae1658eaf5147eed4ee918f0d35612c1c1243..a668c73a405f9256737516ff9f5ec338766bb3c4 100644 (file)
@@ -318,14 +318,45 @@ struct SatGen
                                std::vector<int> undef_s = importUndefSigSpec(cell->connections.at("\\S"), timestep);
                                std::vector<int> undef_y = importUndefSigSpec(cell->connections.at("\\Y"), timestep);
 
-                               tmp = a;
-                               for (size_t i = 0; i < s.size(); i++) {
+                               int maybe_one_hot = ez->FALSE;
+                               int maybe_many_hot = ez->FALSE;
+
+                               int sure_one_hot = ez->FALSE;
+                               int sure_many_hot = ez->FALSE;
+
+                               std::vector<int> bits_set = std::vector<int>(undef_y.size(), ez->FALSE);
+                               std::vector<int> bits_clr = std::vector<int>(undef_y.size(), ez->FALSE);
+
+                               for (size_t i = 0; i < s.size(); i++)
+                               {
+                                       std::vector<int> part_of_b(b.begin()+i*a.size(), b.begin()+(i+1)*a.size());
                                        std::vector<int> part_of_undef_b(undef_b.begin()+i*a.size(), undef_b.begin()+(i+1)*a.size());
-                                       tmp = ez->vec_ite(s.at(i), part_of_undef_b, tmp);
+
+                                       int maybe_s = ez->OR(s.at(i), undef_s.at(i));
+                                       int sure_s = ez->AND(s.at(i), ez->NOT(undef_s.at(i)));
+
+                                       maybe_one_hot = ez->OR(maybe_one_hot, maybe_s);
+                                       maybe_many_hot = ez->OR(maybe_many_hot, ez->AND(maybe_one_hot, maybe_s));
+
+                                       sure_one_hot = ez->OR(sure_one_hot, sure_s);
+                                       sure_many_hot = ez->OR(sure_many_hot, ez->AND(sure_one_hot, sure_s));
+
+                                       bits_set = ez->vec_ite(maybe_s, ez->vec_or(bits_set, ez->vec_or(bits_set, ez->vec_or(part_of_b, part_of_undef_b))), bits_set);
+                                       bits_clr = ez->vec_ite(maybe_s, ez->vec_or(bits_clr, ez->vec_or(bits_clr, ez->vec_or(ez->vec_not(part_of_b), part_of_undef_b))), bits_clr);
+                               }
+
+                               int maybe_a = ez->NOT(maybe_one_hot);
+
+                               if (cell->type == "$safe_pmux") {
+                                       maybe_a = ez->OR(maybe_a, maybe_many_hot);
+                                       bits_set = ez->vec_ite(sure_many_hot, ez->vec_or(a, undef_a), bits_set);
+                                       bits_clr = ez->vec_ite(sure_many_hot, ez->vec_or(ez->vec_not(a), undef_a), bits_clr);
                                }
-                               tmp = ez->vec_ite(ez->onehot(s, true), tmp, cell->type == "$safe_pmux" ? a : std::vector<int>(tmp.size(), ez->TRUE));
-                               tmp = ez->vec_ite(ez->expression(ezSAT::OpOr, undef_s), std::vector<int>(tmp.size(), ez->TRUE), tmp);
-                               ez->assume(ez->vec_eq(tmp, undef_y));
+
+                               bits_set = ez->vec_ite(maybe_a, ez->vec_or(bits_set, ez->vec_or(bits_set, ez->vec_or(a, undef_a))), bits_set);
+                               bits_clr = ez->vec_ite(maybe_a, ez->vec_or(bits_clr, ez->vec_or(bits_clr, ez->vec_or(ez->vec_not(a), undef_a))), bits_clr);
+
+                               ez->assume(ez->vec_eq(ez->vec_not(ez->vec_xor(bits_set, bits_clr)), undef_y));
                                undefGating(y, yy, undef_y);
                        }
                        return true;