From 8e53d2e0bf3584709cd320447ad5a89a80dcfd94 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 2 Jan 2019 02:45:49 +0000 Subject: [PATCH 1/4] opt_expr: simplify any unsigned comparisons with all-0 and all-1. Before this commit, only unsigned comparisons with all-0 would be simplified. This commit also makes the code handling such comparisons to be more rigorous and not abort on unexpected input. --- passes/opt/opt_expr.cc | 86 +++++++++++++++++++++++++++++++-------- tests/opt/opt_expr_cmp.v | 11 +++++ tests/opt/opt_expr_cmp.ys | 4 ++ 3 files changed, 84 insertions(+), 17 deletions(-) create mode 100644 tests/opt/opt_expr_cmp.v create mode 100644 tests/opt/opt_expr_cmp.ys diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 610edc5e9..87597ce57 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -1344,6 +1344,75 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } + // simplify comparisons + // currently, only replaces comparisons with an extreme of the signal range with a constant + // TODO: since, unlike the following optimization, this one does not assume that both inputs to the cell are constant, + // it is more robust; the following optimization should be folded into this one at some point + if (do_fine && (cell->type == "$lt" || cell->type == "$ge" || cell->type == "$gt" || cell->type == "$le")) + { + IdString cmp_type = cell->type; + SigSpec var_sig = cell->getPort("\\A"); + SigSpec const_sig = cell->getPort("\\B"); + int var_width = cell->parameters["\\A_WIDTH"].as_int(); + int const_width = cell->parameters["\\B_WIDTH"].as_int(); + bool is_signed = cell->getParam("\\A_SIGNED").as_bool(); + + if (!const_sig.is_fully_const()) + { + std::swap(var_sig, const_sig); + std::swap(var_width, const_width); + if (cmp_type == "$gt") + cmp_type = "$lt"; + else if (cmp_type == "$lt") + cmp_type = "$gt"; + else if (cmp_type == "$ge") + cmp_type = "$le"; + else if (cmp_type == "$le") + cmp_type = "$ge"; + } + + if (const_sig.is_fully_def() && const_sig.is_fully_const()) + { + const char *condition, *replacement; + SigSpec result_sig(State::S0, GetSize(cell->getPort("\\Y"))); + result_sig[0] = State::Sx; + + if (!is_signed) + { + if (const_sig.is_fully_zero() && cmp_type == "$lt") { + condition = "unsigned X<0"; + replacement = "constant 0"; + result_sig[0] = State::S0; + } + if (const_sig.is_fully_zero() && cmp_type == "$ge") { + condition = "unsigned X>=0"; + replacement = "constant 1"; + result_sig[0] = State::S1; + } + 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; + } + 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; + } + } + + if (result_sig.is_fully_def()) + { + log("Replacing %s cell `%s' (implementing %s) with %s.\n", + log_id(cell->type), log_id(cell), condition, replacement); + module->connect(cell->getPort("\\Y"), result_sig); + module->remove(cell); + did_something = true; + goto next_cell; + } + } + } + // replace a<0 or a>=0 with the top bit of a if (do_fine && (cell->type == "$lt" || cell->type == "$ge" || cell->type == "$gt" || cell->type == "$le")) { @@ -1405,23 +1474,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } else if (sigConst.is_fully_const() && sigConst.is_fully_def() && var_signed == false) { - if (sigConst.is_fully_zero()) { - RTLIL::SigSpec a_prime(RTLIL::State::S0, GetSize(cell->getPort("\\Y"))); - if (is_lt) { - log("Replacing %s cell `%s' (implementing unsigned X<0) with constant false.\n", - log_id(cell->type), log_id(cell)); - a_prime[0] = RTLIL::State::S0; - } else { - log("Replacing %s cell `%s' (implementing unsigned X>=0) with constant true.\n", - log_id(cell->type), log_id(cell)); - a_prime[0] = RTLIL::State::S1; - } - module->connect(cell->getPort("\\Y"), a_prime); - module->remove(cell); - did_something = true; - goto next_cell; - } - int const_bit_set = get_onehot_bit_index(sigConst); if (const_bit_set >= 0 && const_bit_set < width) { int bit_set = const_bit_set; diff --git a/tests/opt/opt_expr_cmp.v b/tests/opt/opt_expr_cmp.v new file mode 100644 index 000000000..7eb65d531 --- /dev/null +++ b/tests/opt/opt_expr_cmp.v @@ -0,0 +1,11 @@ +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; +endmodule diff --git a/tests/opt/opt_expr_cmp.ys b/tests/opt/opt_expr_cmp.ys new file mode 100644 index 000000000..214ce8b11 --- /dev/null +++ b/tests/opt/opt_expr_cmp.ys @@ -0,0 +1,4 @@ +read_verilog opt_expr_cmp.v +equiv_opt -assert opt_expr -fine +design -load postopt +select -assert-count 0 t:$gt t:$ge t:$lt t:$le From 9e9846a6ead700756fbd7a5e6c72ccb424006934 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 2 Jan 2019 03:01:25 +0000 Subject: [PATCH 2/4] opt_expr: refactor simplification of signed X>=0 and X<0. NFCI. --- passes/opt/opt_expr.cc | 50 +++++++++++++++++++++------------------- tests/opt/opt_expr_cmp.v | 22 +++++++++++------- 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 87597ce57..989c949ce 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -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); diff --git a/tests/opt/opt_expr_cmp.v b/tests/opt/opt_expr_cmp.v index 7eb65d531..72372bdf0 100644 --- a/tests/opt/opt_expr_cmp.v +++ b/tests/opt/opt_expr_cmp.v @@ -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 From 4fd458290c3da4c3f372f2e1fdd99829a9462a38 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 2 Jan 2019 04:31:20 +0000 Subject: [PATCH 3/4] opt_expr: refactor simplification of unsigned X=onehot. NFCI. --- passes/opt/opt_expr.cc | 68 ++++++++++++++++++++++------------------ tests/opt/opt_expr_cmp.v | 5 +++ 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 989c949ce..9abbdc6ac 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -1374,35 +1374,60 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (const_sig.is_fully_def() && const_sig.is_fully_const()) { std::string condition, replacement; - SigSpec result_sig(State::S0, GetSize(cell->getPort("\\Y"))); + SigSpec replace_sig(State::S0, GetSize(cell->getPort("\\Y"))); bool replace = false; + bool remove = 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_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_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_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_sig[0] = State::S1; replace = true; } + + int const_bit_set = get_onehot_bit_index(const_sig); + if (const_bit_set >= 0 && const_bit_set < var_width) + { + RTLIL::SigSpec var_high_sig(RTLIL::State::S0, var_width - const_bit_set); + for (int i = const_bit_set; i < var_width; i++) { + var_high_sig[i - const_bit_set] = var_sig[i]; + } + + if (cmp_type == "$lt") + { + condition = stringf("unsigned X<%s", log_signal(const_sig)); + replacement = stringf("!X[%d:%d]", var_width - 1, const_bit_set); + module->addLogicNot(NEW_ID, var_high_sig, cell->getPort("\\Y")); + remove = true; + } + if (cmp_type == "$ge") + { + condition = stringf("unsigned X>=%s", log_signal(const_sig)); + replacement = stringf("|X[%d:%d]", var_width - 1, const_bit_set); + module->addReduceOr(NEW_ID, var_high_sig, cell->getPort("\\Y")); + remove = true; + } + } } else { /* signed */ @@ -1410,23 +1435,24 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons { condition = "signed X<0"; replacement = stringf("X[%d]", var_width - 1); - result_sig[0] = var_sig[var_width - 1]; + replace_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; + module->addNot(NEW_ID, var_sig[var_width - 1], cell->getPort("\\Y")); + remove = true; } } - if (replace) + if (replace || remove) { log("Replacing %s cell `%s' (implementing %s) with %s.\n", log_id(cell->type), log_id(cell), condition.c_str(), replacement.c_str()); - module->connect(cell->getPort("\\Y"), result_sig); + if (replace) + module->connect(cell->getPort("\\Y"), replace_sig); module->remove(cell); did_something = true; goto next_cell; @@ -1477,26 +1503,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (sigConst.is_fully_const() && sigConst.is_fully_def() && var_signed == false) { int const_bit_set = get_onehot_bit_index(sigConst); - if (const_bit_set >= 0 && const_bit_set < width) { - int bit_set = const_bit_set; - RTLIL::SigSpec a_prime(RTLIL::State::S0, width - bit_set); - for (int i = bit_set; i < width; i++) { - a_prime[i - bit_set] = sigVar[i]; - } - if (is_lt) { - log("Replacing %s cell `%s' (implementing unsigned X<%s) with !X[%d:%d]: %s.\n", - log_id(cell->type), log_id(cell), log_signal(sigConst), width - 1, bit_set, log_signal(a_prime)); - module->addLogicNot(NEW_ID, a_prime, cell->getPort("\\Y")); - } else { - log("Replacing %s cell `%s' (implementing unsigned X>=%s) with |X[%d:%d]: %s.\n", - log_id(cell->type), log_id(cell), log_signal(sigConst), width - 1, bit_set, log_signal(a_prime)); - module->addReduceOr(NEW_ID, a_prime, cell->getPort("\\Y")); - } - module->remove(cell); - did_something = true; - goto next_cell; - } - else if(const_bit_set >= width && const_bit_set >= 0){ + if(const_bit_set >= width && const_bit_set >= 0){ RTLIL::SigSpec a_prime(RTLIL::State::S0, 1); if(is_lt){ a_prime[0] = RTLIL::State::S1; @@ -1509,7 +1516,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons module->remove(cell); did_something = true; goto next_cell; - } } } diff --git a/tests/opt/opt_expr_cmp.v b/tests/opt/opt_expr_cmp.v index 72372bdf0..500b15f1b 100644 --- a/tests/opt/opt_expr_cmp.v +++ b/tests/opt/opt_expr_cmp.v @@ -14,4 +14,9 @@ module top(...); output o2_2 = 4'sb0000 <= $signed(a); output o2_3 = $signed(a) < 4'sb0000; output o2_4 = $signed(a) >= 4'sb0000; + + output o3_1 = 4'b0100 > a; + output o3_2 = 4'b0100 <= a; + output o3_3 = a < 4'b0100; + output o3_4 = a >= 4'b0100; endmodule From bf8db55ef36f6839827cd8bc69f673fd3fd43cca Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 2 Jan 2019 05:04:28 +0000 Subject: [PATCH 4/4] opt_expr: improve simplification of comparisons with large constants. The idea behind this simplification is that a N-bit signal X being compared with an M-bit constant where M>N and the constant has Nth or higher bit set, it either always succeeds or always fails. However, the existing implementation only worked with one-hot signals for some reason. It also printed incorrect messages. This commit adjusts the simplification to have as much power as possible, and fixes other bugs. --- passes/opt/opt_expr.cc | 117 ++++++++++++++++----------------------- tests/opt/opt_expr_cmp.v | 18 ++++++ 2 files changed, 65 insertions(+), 70 deletions(-) diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 9abbdc6ac..76bcfd44f 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -259,6 +259,22 @@ bool is_one_or_minus_one(const Const &value, bool is_signed, bool &is_negative) return last_bit_one; } +int get_highest_hot_index(RTLIL::SigSpec signal) +{ + for (int i = GetSize(signal) - 1; i >= 0; i--) + { + if (signal[i] == RTLIL::State::S0) + continue; + + if (signal[i] == RTLIL::State::S1) + return i; + + break; + } + + return -1; +} + // if the signal has only one bit set, return the index of that bit. // otherwise return -1 int get_onehot_bit_index(RTLIL::SigSpec signal) @@ -1345,9 +1361,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } // simplify comparisons - // currently, only replaces comparisons with an extreme of the signal range with a constant - // TODO: since, unlike the following optimization, this one does not assume that both inputs to the cell are constant, - // it is more robust; the following optimization should be folded into this one at some point if (do_fine && (cell->type == "$lt" || cell->type == "$ge" || cell->type == "$gt" || cell->type == "$le")) { IdString cmp_type = cell->type; @@ -1405,29 +1418,53 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons replace = true; } - int const_bit_set = get_onehot_bit_index(const_sig); - if (const_bit_set >= 0 && const_bit_set < var_width) + int const_bit_hot = get_onehot_bit_index(const_sig); + if (const_bit_hot >= 0 && const_bit_hot < var_width) { - RTLIL::SigSpec var_high_sig(RTLIL::State::S0, var_width - const_bit_set); - for (int i = const_bit_set; i < var_width; i++) { - var_high_sig[i - const_bit_set] = var_sig[i]; + RTLIL::SigSpec var_high_sig(RTLIL::State::S0, var_width - const_bit_hot); + for (int i = const_bit_hot; i < var_width; i++) { + var_high_sig[i - const_bit_hot] = var_sig[i]; } if (cmp_type == "$lt") { condition = stringf("unsigned X<%s", log_signal(const_sig)); - replacement = stringf("!X[%d:%d]", var_width - 1, const_bit_set); + replacement = stringf("!X[%d:%d]", var_width - 1, const_bit_hot); module->addLogicNot(NEW_ID, var_high_sig, cell->getPort("\\Y")); remove = true; } if (cmp_type == "$ge") { condition = stringf("unsigned X>=%s", log_signal(const_sig)); - replacement = stringf("|X[%d:%d]", var_width - 1, const_bit_set); + replacement = stringf("|X[%d:%d]", var_width - 1, const_bit_hot); module->addReduceOr(NEW_ID, var_high_sig, cell->getPort("\\Y")); remove = true; } } + + int const_bit_set = get_highest_hot_index(const_sig); + if(const_bit_set >= var_width) + { + string cmp_name; + if (cmp_type == "$lt" || cmp_type == "$le") + { + if (cmp_type == "$lt") cmp_name = "<"; + if (cmp_type == "$le") cmp_name = "<="; + condition = stringf("unsigned X[%d:0]%s%s", var_width - 1, cmp_name.c_str(), log_signal(const_sig)); + replacement = "constant 1"; + replace_sig[0] = State::S1; + replace = true; + } + if (cmp_type == "$gt" || cmp_type == "$ge") + { + if (cmp_type == "$gt") cmp_name = ">"; + if (cmp_type == "$ge") cmp_name = ">="; + condition = stringf("unsigned X[%d:0]%s%s", var_width - 1, cmp_name.c_str(), log_signal(const_sig)); + replacement = "constant 0"; + replace_sig[0] = State::S0; + replace = true; + } + } } else { /* signed */ @@ -1460,66 +1497,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - // replace a<0 or a>=0 with the top bit of a - if (do_fine && (cell->type == "$lt" || cell->type == "$ge" || cell->type == "$gt" || cell->type == "$le")) - { - //used to decide whether the signal needs to be negated - bool is_lt = false; - - //references the variable signal in the comparison - RTLIL::SigSpec sigVar; - - //references the constant signal in the comparison - RTLIL::SigSpec sigConst; - - // note that this signal must be constant for the optimization - // to take place, but it is not checked beforehand. - // If new passes are added, this signal must be checked for const-ness - - //width of the variable port - int width; - int const_width; - - bool var_signed; - - if (cell->type == "$lt" || cell->type == "$ge") { - is_lt = cell->type == "$lt" ? 1 : 0; - sigVar = cell->getPort("\\A"); - sigConst = cell->getPort("\\B"); - width = cell->parameters["\\A_WIDTH"].as_int(); - const_width = cell->parameters["\\B_WIDTH"].as_int(); - var_signed = cell->parameters["\\A_SIGNED"].as_bool(); - } else - if (cell->type == "$gt" || cell->type == "$le") { - is_lt = cell->type == "$gt" ? 1 : 0; - sigVar = cell->getPort("\\B"); - sigConst = cell->getPort("\\A"); - width = cell->parameters["\\B_WIDTH"].as_int(); - const_width = cell->parameters["\\A_WIDTH"].as_int(); - var_signed = cell->parameters["\\B_SIGNED"].as_bool(); - } else - log_abort(); - - if (sigConst.is_fully_const() && sigConst.is_fully_def() && var_signed == false) - { - int const_bit_set = get_onehot_bit_index(sigConst); - if(const_bit_set >= width && const_bit_set >= 0){ - RTLIL::SigSpec a_prime(RTLIL::State::S0, 1); - if(is_lt){ - a_prime[0] = RTLIL::State::S1; - log("Replacing %s cell `%s' (implementing unsigned X[%d:0] < %s[%d:0]) with constant 0.\n", log_id(cell->type), log_id(cell), width-1, log_signal(sigConst),const_width-1); - } - else{ - log("Replacing %s cell `%s' (implementing unsigned X[%d:0]>= %s[%d:0]) with constant 1.\n", log_id(cell->type), log_id(cell), width-1, log_signal(sigConst),const_width-1); - } - module->connect(cell->getPort("\\Y"), a_prime); - module->remove(cell); - did_something = true; - goto next_cell; - } - } - } - next_cell:; #undef ACTION_DO #undef ACTION_DO_Y diff --git a/tests/opt/opt_expr_cmp.v b/tests/opt/opt_expr_cmp.v index 500b15f1b..5aff4b80f 100644 --- a/tests/opt/opt_expr_cmp.v +++ b/tests/opt/opt_expr_cmp.v @@ -19,4 +19,22 @@ module top(...); output o3_2 = 4'b0100 <= a; output o3_3 = a < 4'b0100; output o3_4 = a >= 4'b0100; + + output o4_1 = 5'b10000 > a; + output o4_2 = 5'b10000 >= a; + output o4_3 = 5'b10000 < a; + output o4_4 = 5'b10000 <= a; + output o4_5 = a < 5'b10000; + output o4_6 = a <= 5'b10000; + output o4_7 = a > 5'b10000; + output o4_8 = a >= 5'b10000; + + output o5_1 = 5'b10100 > a; + output o5_2 = 5'b10100 >= a; + output o5_3 = 5'b10100 < a; + output o5_4 = 5'b10100 <= a; + output o5_5 = a < 5'b10100; + output o5_6 = a <= 5'b10100; + output o5_7 = a > 5'b10100; + output o5_8 = a >= 5'b10100; endmodule