From ee5995641ebd7ff0d933213370c1d0dd4e7787e0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Mar 2020 16:33:54 -0700 Subject: [PATCH 1/7] opt_expr: optimise 1-bit $xor or $_XOR_ with constant input --- passes/opt/opt_expr.cc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 4a2f170b8..e4daf6fe6 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -496,6 +496,19 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } + if (cell->type == ID($_XOR_) || (cell->type == ID($xor) && GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::B)) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool())) + { + SigBit sig_a = assign_map(cell->getPort(ID::A)); + SigBit sig_b = assign_map(cell->getPort(ID::B)); + if (!sig_a.wire) + std::swap(sig_a, sig_b); + if (sig_b == State::S0 || sig_b == State::S1) { + cover("opt.opt_expr.xor_buffer"); + replace_cell(assign_map, module, cell, "xor_buffer", ID::Y, sig_b == State::S1 ? module->NotGate(NEW_ID, sig_a) : sig_a); + goto next_cell; + } + } + if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool), ID($reduce_xor), ID($reduce_xnor), ID($neg)) && GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::Y)) == 1) { @@ -1590,7 +1603,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } int const_bit_set = get_highest_hot_index(const_sig); - if(const_bit_set >= var_width) + if (const_bit_set >= var_width) { string cmp_name; if (cmp_type == ID($lt) || cmp_type == ID($le)) From 01f9aabc2fc4d52d1fc531313b6e06dd0753056d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Mar 2020 16:56:39 -0700 Subject: [PATCH 2/7] opt_expr: extend to $xnor and $_XNOR_ --- passes/opt/opt_expr.cc | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index e4daf6fe6..f9bf3c194 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -496,17 +496,23 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (cell->type == ID($_XOR_) || (cell->type == ID($xor) && GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::B)) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool())) + if (cell->type.in(ID($_XOR_), ID($_XNOR_)) || (cell->type.in(ID($xor), ID($xnor)) && GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::B)) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool())) { SigBit sig_a = assign_map(cell->getPort(ID::A)); SigBit sig_b = assign_map(cell->getPort(ID::B)); if (!sig_a.wire) std::swap(sig_a, sig_b); - if (sig_b == State::S0 || sig_b == State::S1) { - cover("opt.opt_expr.xor_buffer"); - replace_cell(assign_map, module, cell, "xor_buffer", ID::Y, sig_b == State::S1 ? module->NotGate(NEW_ID, sig_a) : sig_a); - goto next_cell; - } + if (sig_b == State::S0 || sig_b == State::S1) + if (cell->type.in(ID($xor), ID($_XOR_))) { + cover("opt.opt_expr.xor_buffer"); + replace_cell(assign_map, module, cell, "xor_buffer", ID::Y, sig_b == State::S1 ? module->NotGate(NEW_ID, sig_a) : sig_a); + goto next_cell; + } + if (cell->type.in(ID($xnor), ID($_XNOR_))) { + cover("opt.opt_expr.xnor_buffer"); + replace_cell(assign_map, module, cell, "xor_buffer", ID::Y, sig_b == State::S1 ? sig_a : module->NotGate(NEW_ID, sig_a)); + goto next_cell; + } } if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool), ID($reduce_xor), ID($reduce_xnor), ID($neg)) && @@ -855,8 +861,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (input.match("11")) ACTION_DO_Y(0); if (input.match(" *")) ACTION_DO_Y(x); if (input.match("* ")) ACTION_DO_Y(x); - if (input.match(" 0")) ACTION_DO(ID::Y, input.extract(1, 1)); - if (input.match("0 ")) ACTION_DO(ID::Y, input.extract(0, 1)); } if (cell->type == ID($_MUX_)) { From 81ca776ea44e126b3946fcdd076c2d2e4d2ab34d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 19 Mar 2020 16:59:11 -0700 Subject: [PATCH 3/7] opt_expr: add $xor/$xnor/$_XOR_/$_XNOR_ tests --- tests/opt/opt_expr_xor.ys | 40 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 tests/opt/opt_expr_xor.ys diff --git a/tests/opt/opt_expr_xor.ys b/tests/opt/opt_expr_xor.ys new file mode 100644 index 000000000..a458c9a27 --- /dev/null +++ b/tests/opt/opt_expr_xor.ys @@ -0,0 +1,40 @@ +read_verilog < $_XOR_+$_NOT_ +select -assert-count 3 t:$_NOT_ + + +design -reset +read_verilog -icells < $_XOR_+$_NOT_ +select -assert-count 1 t:$_NOT_ From af16ca9dd4abdbb7c6a2f54f15abb493a4584ce6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Mar 2020 09:17:53 -0700 Subject: [PATCH 4/7] opt_expr: fix missing brace --- passes/opt/opt_expr.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index f9bf3c194..4163c31f0 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -502,7 +502,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons SigBit sig_b = assign_map(cell->getPort(ID::B)); if (!sig_a.wire) std::swap(sig_a, sig_b); - if (sig_b == State::S0 || sig_b == State::S1) + if (sig_b == State::S0 || sig_b == State::S1) { if (cell->type.in(ID($xor), ID($_XOR_))) { cover("opt.opt_expr.xor_buffer"); replace_cell(assign_map, module, cell, "xor_buffer", ID::Y, sig_b == State::S1 ? module->NotGate(NEW_ID, sig_a) : sig_a); @@ -510,9 +510,11 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } if (cell->type.in(ID($xnor), ID($_XNOR_))) { cover("opt.opt_expr.xnor_buffer"); - replace_cell(assign_map, module, cell, "xor_buffer", ID::Y, sig_b == State::S1 ? sig_a : module->NotGate(NEW_ID, sig_a)); + replace_cell(assign_map, module, cell, "xnor_buffer", ID::Y, sig_b == State::S1 ? sig_a : module->NotGate(NEW_ID, sig_a)); goto next_cell; } + log_abort(); + } } if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool), ID($reduce_xor), ID($reduce_xnor), ID($neg)) && From 317c18fc6fe22f6b5ad4f0ac82f6abbcfaec2bca Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Mar 2020 11:25:17 -0700 Subject: [PATCH 5/7] Simplify breaking tests/arch/*/fsm.ys tests --- tests/arch/anlogic/fsm.ys | 5 +---- tests/arch/efinix/fsm.ys | 5 ++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/tests/arch/anlogic/fsm.ys b/tests/arch/anlogic/fsm.ys index 0bcc4e011..eb94177ad 100644 --- a/tests/arch/anlogic/fsm.ys +++ b/tests/arch/anlogic/fsm.ys @@ -10,9 +10,6 @@ sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd fsm # Constrain all select calls below inside the top module -select -assert-count 1 t:AL_MAP_LUT2 -select -assert-count 5 t:AL_MAP_LUT5 -select -assert-count 1 t:AL_MAP_LUT6 select -assert-count 6 t:AL_MAP_SEQ -select -assert-none t:AL_MAP_LUT2 t:AL_MAP_LUT5 t:AL_MAP_LUT6 t:AL_MAP_SEQ %% t:* %D +select -assert-none t:AL_MAP_LUT* t:AL_MAP_SEQ %% t:* %D diff --git a/tests/arch/efinix/fsm.ys b/tests/arch/efinix/fsm.ys index a2db2ad98..aef720d46 100644 --- a/tests/arch/efinix/fsm.ys +++ b/tests/arch/efinix/fsm.ys @@ -10,7 +10,6 @@ sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd fsm # Constrain all select calls below inside the top module -select -assert-count 1 t:EFX_GBUFCE -select -assert-count 6 t:EFX_FF -select -assert-count 15 t:EFX_LUT4 +select -assert-count 1 t:EFX_GBUFCE +select -assert-count 6 t:EFX_FF select -assert-none t:EFX_GBUFCE t:EFX_FF t:EFX_LUT4 %% t:* %D From 6274f0b075abba2af9193e2245eacee5cc66e4c5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 20 Mar 2020 14:38:50 -0700 Subject: [PATCH 6/7] opt_expr: add failing $xnor test --- tests/opt/opt_expr_xor.ys | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/opt/opt_expr_xor.ys b/tests/opt/opt_expr_xor.ys index a458c9a27..21439fd53 100644 --- a/tests/opt/opt_expr_xor.ys +++ b/tests/opt/opt_expr_xor.ys @@ -14,7 +14,7 @@ equiv_opt opt_expr design -load postopt select -assert-none t:$xor select -assert-none t:$xnor -select -assert-count 2 t:$_NOT_ +select -assert-count 2 t:$not design -load read @@ -38,3 +38,15 @@ equiv_opt opt_expr design -load postopt select -assert-none t:$_XNOR_ # NB: simplemap does $xnor -> $_XOR_+$_NOT_ select -assert-count 1 t:$_NOT_ + + +design -reset +read_verilog < Date: Fri, 20 Mar 2020 14:39:08 -0700 Subject: [PATCH 7/7] opt_expr: fix failing $xnor test --- passes/opt/opt_expr.cc | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 4163c31f0..1a586711c 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -505,12 +505,27 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (sig_b == State::S0 || sig_b == State::S1) { if (cell->type.in(ID($xor), ID($_XOR_))) { cover("opt.opt_expr.xor_buffer"); - replace_cell(assign_map, module, cell, "xor_buffer", ID::Y, sig_b == State::S1 ? module->NotGate(NEW_ID, sig_a) : sig_a); + SigSpec sig_y; + if (cell->type == ID($xor)) + sig_y = (sig_b == State::S1 ? module->Not(NEW_ID, sig_a).as_bit() : sig_a); + else if (cell->type == ID($_XOR_)) + sig_y = (sig_b == State::S1 ? module->NotGate(NEW_ID, sig_a) : sig_a); + else log_abort(); + replace_cell(assign_map, module, cell, "xor_buffer", ID::Y, sig_y); goto next_cell; } if (cell->type.in(ID($xnor), ID($_XNOR_))) { cover("opt.opt_expr.xnor_buffer"); - replace_cell(assign_map, module, cell, "xnor_buffer", ID::Y, sig_b == State::S1 ? sig_a : module->NotGate(NEW_ID, sig_a)); + SigSpec sig_y; + if (cell->type == ID($xnor)) { + sig_y = (sig_b == State::S1 ? sig_a : module->Not(NEW_ID, sig_a).as_bit()); + int width = cell->getParam(ID(Y_WIDTH)).as_int(); + sig_y.append(RTLIL::Const(State::S1, width-1)); + } + else if (cell->type == ID($_XNOR_)) + sig_y = (sig_b == State::S1 ? sig_a : module->NotGate(NEW_ID, sig_a)); + else log_abort(); + replace_cell(assign_map, module, cell, "xnor_buffer", ID::Y, sig_y); goto next_cell; } log_abort();