diff --git a/kernel/yosys_common.h b/kernel/yosys_common.h index b4ba6377b..839332eb7 100644 --- a/kernel/yosys_common.h +++ b/kernel/yosys_common.h @@ -290,8 +290,8 @@ inline std::string removeNumericSuffix(const std::string& str) { return str; // Return unchanged if no numeric suffix found } -#define NEW_ID2 module->uniquify(removeNumericSuffix(cell->name.str())) -#define NEW_ID2_SUFFIX(suffix) module->uniquify(cell->name.str() + "_" + suffix) +#define NEW_ID2 cell->module->uniquify(removeNumericSuffix(cell->name.str())) +#define NEW_ID2_SUFFIX(suffix) cell->module->uniquify(cell->name.str() + "_" + suffix) #define NEW_ID3 module->uniquify(cell_name.str()) #define NEW_ID3_SUFFIX(suffix) module->uniquify(cell_name.str() + "_" + suffix) #define NEW_ID4 module->uniquify(name.str()) diff --git a/passes/silimate/Makefile.inc b/passes/silimate/Makefile.inc index 34de35452..7c434eb1d 100644 --- a/passes/silimate/Makefile.inc +++ b/passes/silimate/Makefile.inc @@ -21,3 +21,14 @@ PEEPOPT_PATTERN = passes/silimate/peepopt_expand.pmg passes/silimate/peepopt_expand.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN) $(P) mkdir -p $(dir $@) && $(PYTHON_EXECUTABLE) $< -o $@ -p peepopt $(filter-out $<,$^) + +OBJS += passes/silimate/muxmode.o +GENFILES += passes/silimate/peepopt_muxmode.h +passes/silimate/muxmode.o: passes/silimate/peepopt_muxmode.h +$(eval $(call add_extra_objs,passes/silimate/peepopt_muxmode.h)) + +PEEPOPT_PATTERN = passes/silimate/peepopt_muxmode.pmg +PEEPOPT_PATTERN += passes/silimate/peepopt_muxinvprop.pmg + +passes/silimate/peepopt_muxmode.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN) + $(P) mkdir -p $(dir $@) && $(PYTHON_EXECUTABLE) $< -o $@ -p peepopt $(filter-out $<,$^) diff --git a/passes/silimate/muxmode.cc b/passes/silimate/muxmode.cc new file mode 100644 index 000000000..c9c6bff9a --- /dev/null +++ b/passes/silimate/muxmode.cc @@ -0,0 +1,64 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Claire Xenia Wolf + * Akash Levy + * + * 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 + +bool did_something; + +#include "passes/silimate/peepopt_muxmode.h" + +struct MuxmodePass : public Pass { + MuxmodePass() : Pass("muxmode", "convert primitives to muxes") { } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" muxmode [selection]\n"); + log("\n"); + log("This pass makes muxes of 1-bit primitives having an input coming from a mux.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) override + { + log_header(design, "Executing MUXMODE pass (make muxes from 1-bit primitives).\n"); + + size_t argidx = 1; + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + { + did_something = true; + for (int i = 0; did_something; i++) + { + log("ITERATION %d OF MUXMODE\n", i); + did_something = false; + peepopt_pm pm(module); + pm.setup(module->selected_cells()); + pm.run_muxmode(); + pm.run_muxinvprop(); + } + } + } +} PeepoptPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/silimate/peepopt_muxinvprop.pmg b/passes/silimate/peepopt_muxinvprop.pmg new file mode 100644 index 000000000..0f198bf30 --- /dev/null +++ b/passes/silimate/peepopt_muxinvprop.pmg @@ -0,0 +1,60 @@ +pattern muxinvprop +// +// Authored by Akash Levy of Silimate, Inc. under ISC license. +// +// Propagate inverters from mux outputs to inputs +// +// ~ (S ? A : B) ==> S ? ~A : ~B +// + +state mux_a mux_b mux_y inv_a inv_y + +match mux_gate + // Select mux + select mux_gate->type.in($mux) + set mux_a port(mux_gate, \A) + set mux_b port(mux_gate, \B) + set mux_y port(mux_gate, \Y) +endmatch + +code + // Fanout of each MUX gate Y bit should be 1 (no bit-split) + if (nusers(mux_y) != 2) + reject; +endcode + +match inv_gate + // Select inverter + select inv_gate->type.in($not) + set inv_a port(inv_gate, \A) + set inv_y port(inv_gate, \Y) + + // Connection + index port(inv_gate, \A) === mux_y +endmatch + +code mux_a mux_b mux_y inv_a inv_y + // Disconnect all ports + mux_gate->unsetPort(\A); + mux_gate->unsetPort(\B); + mux_gate->unsetPort(\Y); + inv_gate->unsetPort(\A); + inv_gate->unsetPort(\Y); + + // Set cell to mux_gate for naming + Cell *cell = mux_gate; + + // Set new ports + mux_gate->setPort(\A, module->Not(NEW_ID2_SUFFIX("not_a"), mux_a, false, mux_gate->get_src_attribute())); + mux_gate->setPort(\B, module->Not(NEW_ID2_SUFFIX("not_b"), mux_b, false, mux_gate->get_src_attribute())); + mux_gate->setPort(\Y, inv_y); + + // Rename MUX gate for formal + module->rename(mux_gate, NEW_ID2_SUFFIX("not")); + + // Log, fixup, accept + log("muxinvprop pattern in %s: mux=%s, not=%s\n", log_id(module), log_id(mux_gate), log_id(inv_gate)); + autoremove(inv_gate); + did_something = true; + accept; +endcode diff --git a/passes/silimate/peepopt_muxmode.pmg b/passes/silimate/peepopt_muxmode.pmg new file mode 100644 index 000000000..48bf62061 --- /dev/null +++ b/passes/silimate/peepopt_muxmode.pmg @@ -0,0 +1,77 @@ +pattern muxmode +// +// Authored by Akash Levy of Silimate, Inc. under ISC license. +// +// Make muxes of 1-bit primitives having an input coming from a mux +// +// A & B ==> A ? B : 0 +// A | B ==> A ? 1 : B +// A ^ B ==> A ? ~B : B +// A ^~ B ==> A ? B : ~B +// + +state mux_y prim_a prim_b + +match mux_gate + // Select MUX that connects to one of the primitives' inputs + select mux_gate->type.in($mux) + filter param(mux_gate, \WIDTH) == 1 + set mux_y port(mux_gate, \Y) +endmatch + +match prim_gate + // Select AND/OR (not XOR/XNOR for now) + select prim_gate->type.in($and, $or) + filter param(prim_gate, \A_WIDTH) == 1 + filter param(prim_gate, \B_WIDTH) == 1 + + // Set ports, allowing A and B to be swapped + choice A {\A, \B} + define B (A == \A ? \B : \A) + set prim_a port(prim_gate, A) + set prim_b port(prim_gate, B) + + // Connection + index port(prim_gate, B) === mux_y +endmatch + +code mux_y prim_a prim_b + // Unset ports/params of primitive + prim_gate->unsetPort(\A); + prim_gate->unsetPort(\B); + prim_gate->unsetParam(\A_WIDTH); + prim_gate->unsetParam(\A_SIGNED); + prim_gate->unsetParam(\B_WIDTH); + prim_gate->unsetParam(\B_SIGNED); + prim_gate->unsetParam(\Y_WIDTH); + + // Set mux's S port to primitive's A port + prim_gate->setPort(\S, prim_a); + + // Set cell to be prim_gate for naming + Cell *cell = prim_gate; + + // Set mux inputs + if (prim_gate->type == $and) { + prim_gate->setPort(\A, State::S0); + prim_gate->setPort(\B, prim_b); + } else if (prim_gate->type == $or) { + prim_gate->setPort(\A, prim_b); + prim_gate->setPort(\B, State::S1); + } else if (prim_gate->type == $xor) { + prim_gate->setPort(\A, prim_b); + prim_gate->setPort(\B, module->Not(NEW_ID2, prim_b, false, cell->get_src_attribute())); + } else if (prim_gate->type == $xnor) { + prim_gate->setPort(\A, module->Not(NEW_ID2, prim_b, false, cell->get_src_attribute())); + prim_gate->setPort(\B, prim_b); + } else { + log_abort(); + } + + // Log, fixup type and parameters, accept + log("muxmode pattern in %s: mux=%s, prim=%s, primtype=%s\n", log_id(module), log_id(mux_gate), log_id(prim_gate), log_id(prim_gate->type)); + prim_gate->type = $mux; + prim_gate->fixup_parameters(); + did_something = true; + accept; +endcode diff --git a/tests/silimate/muxinvprop.ys b/tests/silimate/muxinvprop.ys new file mode 100644 index 000000000..a9cbf3717 --- /dev/null +++ b/tests/silimate/muxinvprop.ys @@ -0,0 +1,77 @@ +log -header "Simple positive case with 4-long mux chain and 1 inverted component" +log -push +design -reset +read_verilog <