aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJannis Harder <me@jix.one>2022-10-21 15:41:20 +0200
committerJannis Harder <me@jix.one>2022-10-24 12:03:01 +0200
commitc77b7343d0412a009436a57764d907e2ae332da2 (patch)
tree3213d3d6940c16b58b369034bfc2cbf875967f10 /kernel
parent4f4cff00800dec70796d4d5ec70c73eef837f948 (diff)
downloadyosys-c77b7343d0412a009436a57764d907e2ae332da2.tar.gz
yosys-c77b7343d0412a009436a57764d907e2ae332da2.tar.bz2
yosys-c77b7343d0412a009436a57764d907e2ae332da2.zip
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.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/calc.cc30
-rw-r--r--kernel/celltypes.h14
-rw-r--r--kernel/rtlil.h2
3 files changed, 36 insertions, 10 deletions
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<RTLIL::State>(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<RTLIL::State> t = arg1.bits;
diff --git a/kernel/celltypes.h b/kernel/celltypes.h
index d62ba1506..e617b4603 100644
--- a/kernel/celltypes.h
+++ b/kernel/celltypes.h
@@ -488,16 +488,10 @@ struct CellTypes
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, bool *errp = nullptr)
{
- if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_))) {
- RTLIL::Const ret = arg1;
- for (size_t i = 0; i < arg3.bits.size(); i++)
- if (arg3.bits[i] == RTLIL::State::S1) {
- std::vector<RTLIL::State> bits(arg2.bits.begin() + i*arg1.bits.size(), arg2.bits.begin() + (i+1)*arg1.bits.size());
- ret = RTLIL::Const(bits);
- }
- return ret;
- }
-
+ if (cell->type.in(ID($mux), ID($_MUX_)))
+ return const_mux(arg1, arg2, arg3);
+ if (cell->type == ID($pmux))
+ return const_pmux(arg1, arg2, arg3);
if (cell->type == ID($_AOI3_))
return eval_not(const_or(const_and(arg1, arg2, false, false, 1), arg3, false, false, 1));
if (cell->type == ID($_OAI3_))
diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index 27ffdff1f..755abf534 100644
--- a/kernel/rtlil.h
+++ b/kernel/rtlil.h
@@ -500,6 +500,8 @@ namespace RTLIL
RTLIL::Const const_pos (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_neg (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
+ RTLIL::Const const_mux (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3);
+ RTLIL::Const const_pmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3);
RTLIL::Const const_bmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2);
RTLIL::Const const_demux (const RTLIL::Const &arg1, const RTLIL::Const &arg2);