From c77b7343d0412a009436a57764d907e2ae332da2 Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Fri, 21 Oct 2022 15:41:20 +0200 Subject: Consistent $mux undef handling * Change simlib's $mux cell to use the ternary operator as $_MUX_ already does * Stop opt_expr -keepdc from changing S=x to S=0 * Change const eval of $mux and $pmux to match the updated simlib (fixes sim) * The sat behavior of $mux already matches the updated simlib The verilog frontend uses $mux for the ternary operators and this changes all interpreations of the $mux cell (that I found) to match the verilog simulation behavior for the ternary operator. For 'if' and 'case' expressions the frontend may also use $mux but uses $eqx if the verilog simulation behavior is requested with the '-ifx' option. For $pmux there is a remaining mismatch between the sat behavior and the simlib behavior. Resolving this requires more discussion, as the $pmux cell does not directly correspond to a specific verilog construct. --- kernel/calc.cc | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'kernel/calc.cc') diff --git a/kernel/calc.cc b/kernel/calc.cc index 0865db526..32e8a49fe 100644 --- a/kernel/calc.cc +++ b/kernel/calc.cc @@ -609,6 +609,36 @@ RTLIL::Const RTLIL::const_neg(const RTLIL::Const &arg1, const RTLIL::Const&, boo return RTLIL::const_sub(zero, arg1_ext, true, signed1, result_len); } +RTLIL::Const RTLIL::const_mux(const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3) +{ + log_assert(arg2.size() == arg1.size()); + if (arg3[0] == State::S0) + return arg1; + else if (arg3[0] == State::S1) + return arg2; + + RTLIL::Const ret = arg1; + for (int i = 0; i < ret.size(); i++) + if (ret[i] != arg2[i]) + ret[i] = State::Sx; + return ret; +} + +RTLIL::Const RTLIL::const_pmux(const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3) +{ + if (arg3.is_fully_zero()) + return arg1; + + if (!arg3.is_onehot()) + return RTLIL::Const(State::Sx, arg1.size()); + + for (int i = 0; i < arg3.size(); i++) + if (arg3[i] == State::S1) + return RTLIL::Const(std::vector(arg2.bits.begin() + i*arg1.bits.size(), arg2.bits.begin() + (i+1)*arg1.bits.size())); + + log_abort(); // unreachable +} + RTLIL::Const RTLIL::const_bmux(const RTLIL::Const &arg1, const RTLIL::Const &arg2) { std::vector t = arg1.bits; -- cgit v1.2.3