Improved undef handling in == and != for ConstEval
authorClifford Wolf <clifford@clifford.at>
Wed, 6 Nov 2013 21:21:58 +0000 (22:21 +0100)
committerClifford Wolf <clifford@clifford.at>
Wed, 6 Nov 2013 21:25:35 +0000 (22:25 +0100)
kernel/calc.cc

index 6b4c50d51180db806ea687839b2bc503b4ead13c..e998e5b3a62cdb72389384e3cb6a95147c39342b 100644 (file)
@@ -334,23 +334,37 @@ RTLIL::Const RTLIL::const_le(const RTLIL::Const &arg1, const RTLIL::Const &arg2,
 
 RTLIL::Const RTLIL::const_eq(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
 {
-       int undef_bit_pos = -1;
-       bool y = const2big(arg1, signed1, undef_bit_pos) == const2big(arg2, signed2, undef_bit_pos);
-       RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
+       RTLIL::Const arg1_ext = arg1;
+       RTLIL::Const arg2_ext = arg2;
+       RTLIL::Const result(RTLIL::State::S0, result_len);
+
+       while (arg1_ext.bits.size() < arg2_ext.bits.size())
+               arg1_ext.bits.push_back(signed1 && signed2 && arg1_ext.bits.size() > 0 ? arg1_ext.bits.back() : RTLIL::State::S0);
+
+       while (arg2_ext.bits.size() < arg1_ext.bits.size())
+               arg2_ext.bits.push_back(signed1 && signed2 && arg2_ext.bits.size() > 0 ? arg2_ext.bits.back() : RTLIL::State::S0);
+
+       RTLIL::State matched_status = RTLIL::State::S1;
+       for (size_t i = 0; i < arg1_ext.bits.size(); i++) {
+               if (arg1_ext.bits.at(i) == RTLIL::State::S0 && arg2_ext.bits.at(i) == RTLIL::State::S1)
+                       return result;
+               if (arg1_ext.bits.at(i) == RTLIL::State::S1 && arg2_ext.bits.at(i) == RTLIL::State::S0)
+                       return result;
+               if (arg1_ext.bits.at(i) > RTLIL::State::S1 || arg2_ext.bits.at(i) > RTLIL::State::S1)
+                       matched_status = RTLIL::State::Sx;
+       }
 
-       while (int(result.bits.size()) < result_len)
-               result.bits.push_back(RTLIL::State::S0);
+       result.bits.front() = matched_status;
        return result;
 }
 
 RTLIL::Const RTLIL::const_ne(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
 {
-       int undef_bit_pos = -1;
-       bool y = const2big(arg1, signed1, undef_bit_pos) != const2big(arg2, signed2, undef_bit_pos);
-       RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
-
-       while (int(result.bits.size()) < result_len)
-               result.bits.push_back(RTLIL::State::S0);
+       RTLIL::Const result = RTLIL::const_eq(arg1, arg2, signed1, signed2, result_len);
+       if (result.bits.front() == RTLIL::State::S0)
+               result.bits.front() = RTLIL::State::S1;
+       else if (result.bits.front() == RTLIL::State::S1)
+               result.bits.front() = RTLIL::State::S0;
        return result;
 }