From: Clifford Wolf Date: Fri, 16 Aug 2019 09:47:51 +0000 (+0200) Subject: Refactor demo_reduce into test_pmgen X-Git-Tag: working-ls180~1124^2~11 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4a57b7e1abe148b36827a393fd7fe62e46c2b1a7;p=yosys.git Refactor demo_reduce into test_pmgen Signed-off-by: Clifford Wolf --- diff --git a/passes/pmgen/.gitignore b/passes/pmgen/.gitignore index a1fe9a7dc..849b73fd4 100644 --- a/passes/pmgen/.gitignore +++ b/passes/pmgen/.gitignore @@ -1,3 +1,3 @@ -/demo_reduce_pm.h +/test_pmgen_pm.h /ice40_dsp_pm.h /peepopt_pm.h diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index 3aaee4047..bea21d971 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -9,9 +9,9 @@ $(eval $(call add_extra_objs,passes/pmgen/ice40_dsp_pm.h)) # -------------------------------------- -OBJS += passes/pmgen/demo_reduce.o -passes/pmgen/demo_reduce.o: passes/pmgen/demo_reduce_pm.h -$(eval $(call add_extra_objs,passes/pmgen/demo_reduce_pm.h)) +OBJS += passes/pmgen/test_pmgen.o +passes/pmgen/test_pmgen.o: passes/pmgen/test_pmgen_pm.h +$(eval $(call add_extra_objs,passes/pmgen/test_pmgen_pm.h)) # -------------------------------------- diff --git a/passes/pmgen/demo_reduce.cc b/passes/pmgen/demo_reduce.cc deleted file mode 100644 index dd8c66f56..000000000 --- a/passes/pmgen/demo_reduce.cc +++ /dev/null @@ -1,99 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "kernel/yosys.h" -#include "kernel/sigtools.h" - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -#include "passes/pmgen/demo_reduce_pm.h" - -void create_reduce(demo_reduce_pm &pm) -{ - auto &st = pm.st_reduce; - auto &ud = pm.ud_reduce; - - if (ud.longest_chain.empty()) - return; - - log("Found chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type)); - - SigSpec A; - SigSpec Y = ud.longest_chain.front().first->getPort(ID(Y)); - auto last_cell = ud.longest_chain.back().first; - - for (auto it : ud.longest_chain) { - auto cell = it.first; - if (cell == last_cell) { - A.append(cell->getPort(ID(A))); - A.append(cell->getPort(ID(B))); - } else { - A.append(cell->getPort(it.second == ID(A) ? ID(B) : ID(A))); - } - log(" %s\n", log_id(cell)); - pm.autoremove(cell); - } - - Cell *c; - - if (last_cell->type == ID($_AND_)) - c = pm.module->addReduceAnd(NEW_ID, A, Y); - else if (last_cell->type == ID($_OR_)) - c = pm.module->addReduceOr(NEW_ID, A, Y); - else if (last_cell->type == ID($_XOR_)) - c = pm.module->addReduceXor(NEW_ID, A, Y); - else - log_abort(); - - log(" -> %s (%s)\n", log_id(c), log_id(c->type)); -} - -struct DemoReducePass : public Pass { - DemoReducePass() : Pass("demo_reduce", "map chains of AND/OR/XOR") { } - void help() YS_OVERRIDE - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" demo_reduce [options] [selection]\n"); - log("\n"); - log("Demo for recursive pmgen patterns. Map chains of AND/OR/XOR to $reduce_*.\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE - { - log_header(design, "Executing DEMO_REDUCE pass.\n"); - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) - { - // if (args[argidx] == "-singleton") { - // singleton_mode = true; - // continue; - // } - break; - } - extra_args(args, argidx, design); - - for (auto module : design->selected_modules()) - demo_reduce_pm(module, module->selected_cells()).run_reduce(create_reduce); - } -} DemoReducePass; - -PRIVATE_NAMESPACE_END diff --git a/passes/pmgen/demo_reduce.pmg b/passes/pmgen/demo_reduce.pmg deleted file mode 100644 index 09856e9ae..000000000 --- a/passes/pmgen/demo_reduce.pmg +++ /dev/null @@ -1,80 +0,0 @@ -pattern reduce - -state portname -udata >> chain longest_chain -udata > non_first_cells - -code - non_first_cells.clear(); - subpattern(setup); -endcode - -match first - select first->type.in($_AND_, $_OR_, $_XOR_) - filter !non_first_cells.count(first) -endmatch - -code - longest_chain.clear(); - chain.push_back(make_pair(first, \A)); - subpattern(tail); - chain.back().second = \B; - subpattern(tail); -finally - chain.pop_back(); - log_assert(chain.empty()); - accept; -endcode - -// ------------------------------------------------------------------ - -subpattern setup - -match first - select first->type.in($_AND_, $_OR_, $_XOR_) -endmatch - -code portname - portname = \A; - branch; - portname = \B; -endcode - -match next - select nusers(port(next, \Y)) == 2 - select next->type.in($_AND_, $_OR_, $_XOR_) - index next->type === first->type - index port(next, \Y) === port(first, portname) -endmatch - -code - non_first_cells.insert(next); -endcode - -// ------------------------------------------------------------------ - -subpattern tail -arg first - -match next - semioptional - select nusers(port(next, \Y)) == 2 - select next->type.in($_AND_, $_OR_, $_XOR_) - index next->type === chain.back().first->type - index port(next, \Y) === port(chain.back().first, chain.back().second) -endmatch - -code - if (next) { - chain.push_back(make_pair(next, \A)); - subpattern(tail); - chain.back().second = \B; - subpattern(tail); - } else { - if (GetSize(chain) > GetSize(longest_chain)) - longest_chain = chain; - } -finally - if (next) - chain.pop_back(); -endcode diff --git a/passes/pmgen/test_pmgen.cc b/passes/pmgen/test_pmgen.cc new file mode 100644 index 000000000..3bff9ae12 --- /dev/null +++ b/passes/pmgen/test_pmgen.cc @@ -0,0 +1,165 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +#include "passes/pmgen/test_pmgen_pm.h" + +void reduce_chain(test_pmgen_pm &pm) +{ + auto &st = pm.st_reduce; + auto &ud = pm.ud_reduce; + + if (ud.longest_chain.empty()) + return; + + log("Found chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type)); + + SigSpec A; + SigSpec Y = ud.longest_chain.front().first->getPort(ID(Y)); + auto last_cell = ud.longest_chain.back().first; + + for (auto it : ud.longest_chain) { + auto cell = it.first; + if (cell == last_cell) { + A.append(cell->getPort(ID(A))); + A.append(cell->getPort(ID(B))); + } else { + A.append(cell->getPort(it.second == ID(A) ? ID(B) : ID(A))); + } + log(" %s\n", log_id(cell)); + pm.autoremove(cell); + } + + Cell *c; + + if (last_cell->type == ID($_AND_)) + c = pm.module->addReduceAnd(NEW_ID, A, Y); + else if (last_cell->type == ID($_OR_)) + c = pm.module->addReduceOr(NEW_ID, A, Y); + else if (last_cell->type == ID($_XOR_)) + c = pm.module->addReduceXor(NEW_ID, A, Y); + else + log_abort(); + + log(" -> %s (%s)\n", log_id(c), log_id(c->type)); +} + +void reduce_tree(test_pmgen_pm &pm) +{ + auto &st = pm.st_reduce; + auto &ud = pm.ud_reduce; + + if (ud.longest_chain.empty()) + return; + + SigSpec A = ud.leaves; + SigSpec Y = st.first->getPort(ID(Y)); + pm.autoremove(st.first); + + log("Found %s tree with %d leaves for %s (%s).\n", log_id(st.first->type), + GetSize(A), log_signal(Y), log_id(st.first)); + + Cell *c; + + if (st.first->type == ID($_AND_)) + c = pm.module->addReduceAnd(NEW_ID, A, Y); + else if (st.first->type == ID($_OR_)) + c = pm.module->addReduceOr(NEW_ID, A, Y); + else if (st.first->type == ID($_XOR_)) + c = pm.module->addReduceXor(NEW_ID, A, Y); + else + log_abort(); + + log(" -> %s (%s)\n", log_id(c), log_id(c->type)); +} + +struct TestPmgenPass : public Pass { + TestPmgenPass() : Pass("test_pmgen", "test pass for pmgen") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" test_pmgen -reduce_chain [options] [selection]\n"); + log("\n"); + log("Demo for recursive pmgen patterns. Map chains of AND/OR/XOR to $reduce_*.\n"); + log("\n"); + log("\n"); + log(" test_pmgen -reduce_tree [options] [selection]\n"); + log("\n"); + log("Demo for recursive pmgen patterns. Map trees of AND/OR/XOR to $reduce_*.\n"); + log("\n"); + } + + void execute_reduce_chain(std::vector args, RTLIL::Design *design) + { + log_header(design, "Executing TEST_PMGEN pass (-reduce_chain).\n"); + + size_t argidx; + for (argidx = 2; argidx < args.size(); argidx++) + { + // if (args[argidx] == "-singleton") { + // singleton_mode = true; + // continue; + // } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + test_pmgen_pm(module, module->selected_cells()).run_reduce(reduce_chain); + } + + void execute_reduce_tree(std::vector args, RTLIL::Design *design) + { + log_header(design, "Executing TEST_PMGEN pass (-reduce_tree).\n"); + + size_t argidx; + for (argidx = 2; argidx < args.size(); argidx++) + { + // if (args[argidx] == "-singleton") { + // singleton_mode = true; + // continue; + // } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + test_pmgen_pm(module, module->selected_cells()).run_reduce(reduce_tree); + } + + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + if (GetSize(args) > 1) + { + if (args[1] == "-reduce_chain") + return execute_reduce_chain(args, design); + if (args[1] == "-reduce_tree") + return execute_reduce_tree(args, design); + } + log_cmd_error("Missing or unsupported mode parameter.\n"); + } +} TestPmgenPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/pmgen/test_pmgen.pmg b/passes/pmgen/test_pmgen.pmg new file mode 100644 index 000000000..ccb37e553 --- /dev/null +++ b/passes/pmgen/test_pmgen.pmg @@ -0,0 +1,83 @@ +pattern reduce + +state portname +udata >> chain longest_chain +udata > non_first_cells +udata leaves + +code + non_first_cells.clear(); + subpattern(setup); +endcode + +match first + select first->type.in($_AND_, $_OR_, $_XOR_) + filter !non_first_cells.count(first) +endmatch + +code + leaves = SigSpec(); + longest_chain.clear(); + chain.push_back(make_pair(first, \A)); + subpattern(tail); + chain.back().second = \B; + subpattern(tail); +finally + chain.pop_back(); + log_assert(chain.empty()); + accept; +endcode + +// ------------------------------------------------------------------ + +subpattern setup + +match first + select first->type.in($_AND_, $_OR_, $_XOR_) +endmatch + +code portname + portname = \A; + branch; + portname = \B; +endcode + +match next + select nusers(port(next, \Y)) == 2 + select next->type.in($_AND_, $_OR_, $_XOR_) + index next->type === first->type + index port(next, \Y) === port(first, portname) +endmatch + +code + non_first_cells.insert(next); +endcode + +// ------------------------------------------------------------------ + +subpattern tail +arg first + +match next + semioptional + select nusers(port(next, \Y)) == 2 + select next->type.in($_AND_, $_OR_, $_XOR_) + index next->type === chain.back().first->type + index port(next, \Y) === port(chain.back().first, chain.back().second) +endmatch + +code + if (next) { + chain.push_back(make_pair(next, \A)); + subpattern(tail); + chain.back().second = \B; + subpattern(tail); + } else { + if (GetSize(chain) > GetSize(longest_chain)) + longest_chain = chain; + leaves.append(port(chain.back().first, chain.back().second)); + } +finally + if (next) + chain.pop_back(); +endcode