From 1cf8e7c7db1be4c6b26bea796663581de21dd019 Mon Sep 17 00:00:00 2001 From: "N. Engelhardt" Date: Fri, 24 Jan 2025 18:48:09 +0100 Subject: [PATCH 01/11] add ioff inference for qlf_k6n10f --- techlibs/quicklogic/Makefile.inc | 3 +- techlibs/quicklogic/ql_ioff.cc | 82 +++++++++++++++++++++ techlibs/quicklogic/synth_quicklogic.cc | 13 +++- tests/arch/quicklogic/qlf_k6n10f/ioff.ys | 91 ++++++++++++++++++++++++ 4 files changed, 187 insertions(+), 2 deletions(-) create mode 100644 techlibs/quicklogic/ql_ioff.cc create mode 100644 tests/arch/quicklogic/qlf_k6n10f/ioff.ys diff --git a/techlibs/quicklogic/Makefile.inc b/techlibs/quicklogic/Makefile.inc index ade144371..a54a7ec03 100644 --- a/techlibs/quicklogic/Makefile.inc +++ b/techlibs/quicklogic/Makefile.inc @@ -6,6 +6,7 @@ OBJS += techlibs/quicklogic/ql_bram_merge.o OBJS += techlibs/quicklogic/ql_bram_types.o OBJS += techlibs/quicklogic/ql_dsp_simd.o OBJS += techlibs/quicklogic/ql_dsp_io_regs.o +OBJS += techlibs/quicklogic/ql_ioff.o # -------------------------------------- @@ -40,4 +41,4 @@ $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dsp_final_map.v)) $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/TDP18K_FIFO.v)) $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/ufifo_ctl.v)) -$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/sram1024x18_mem.v)) \ No newline at end of file +$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/sram1024x18_mem.v)) diff --git a/techlibs/quicklogic/ql_ioff.cc b/techlibs/quicklogic/ql_ioff.cc new file mode 100644 index 000000000..c857fc35d --- /dev/null +++ b/techlibs/quicklogic/ql_ioff.cc @@ -0,0 +1,82 @@ +#include "kernel/log.h" +#include "kernel/modtools.h" +#include "kernel/register.h" +#include "kernel/rtlil.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct QlIoffPass : public Pass { + QlIoffPass() : Pass("ql_ioff", "Infer I/O FFs for qlf_k6n10f architecture") {} + + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" ql_ioff [selection]\n"); + log("\n"); + log("This pass promotes qlf_k6n10f registers directly connected to a top-level I/O\n"); + log("port to I/O FFs.\n"); + log("\n"); + } + + void execute(std::vector, RTLIL::Design *design) override + { + log_header(design, "Executing QL_IOFF pass.\n"); + + ModWalker modwalker(design); + Module *module = design->top_module(); + if (!module) + return; + modwalker.setup(module); + pool cells_to_replace; + for (auto cell : module->selected_cells()) { + if (cell->type.in(ID(dffsre), ID(sdffsre))) { + bool e_const = cell->getPort(ID::E).is_fully_ones(); + bool r_const = cell->getPort(ID::R).is_fully_ones(); + bool s_const = cell->getPort(ID::S).is_fully_ones(); + + if (!(e_const && r_const && s_const)) + continue; + + auto d_sig = modwalker.sigmap(cell->getPort(ID::D)); + if (d_sig.is_wire() && d_sig.as_wire()->port_input) { + log_debug("Cell %s is potentially eligible for promotion to input IOFF.\n", cell->name.c_str()); + // check that d_sig has no other consumers + if (GetSize(d_sig) != 1) continue; + pool portbits; + modwalker.get_consumers(portbits, d_sig[0]); + if (GetSize(portbits) > 1) { + log_debug("not promoting: d_sig has other consumers\n"); + continue; + } + cells_to_replace.insert(cell); + continue; // no need to check Q if we already put it on the list + } + auto q_sig = modwalker.sigmap(cell->getPort(ID::Q)); + if (q_sig.is_wire() && q_sig.as_wire()->port_output) { + log_debug("Cell %s is potentially eligible for promotion to output IOFF.\n", cell->name.c_str()); + // check that q_sig has no other consumers + if (GetSize(q_sig) != 1) continue; + pool portbits; + modwalker.get_consumers(portbits, q_sig[0]); + if (GetSize(portbits) > 0) { + log_debug("not promoting: q_sig has other consumers\n"); + continue; + } + cells_to_replace.insert(cell); + } + } + } + + for (auto cell : cells_to_replace) { + log("Promoting register %s to IOFF.\n", log_signal(cell->getPort(ID::Q))); + cell->type = ID(dff); + cell->unsetPort(ID::E); + cell->unsetPort(ID::R); + cell->unsetPort(ID::S); + } + } +} QlIoffPass; + +PRIVATE_NAMESPACE_END diff --git a/techlibs/quicklogic/synth_quicklogic.cc b/techlibs/quicklogic/synth_quicklogic.cc index 76ef44570..16f660943 100644 --- a/techlibs/quicklogic/synth_quicklogic.cc +++ b/techlibs/quicklogic/synth_quicklogic.cc @@ -78,7 +78,7 @@ struct SynthQuickLogicPass : public ScriptPass { } string top_opt, blif_file, edif_file, family, currmodule, verilog_file, lib_path; - bool abc9, inferAdder, nobram, bramTypes, dsp; + bool abc9, inferAdder, nobram, bramTypes, dsp, ioff; void clear_flags() override { @@ -94,6 +94,7 @@ struct SynthQuickLogicPass : public ScriptPass { bramTypes = false; lib_path = "+/quicklogic/"; dsp = true; + ioff = true; } void set_scratchpad_defaults(RTLIL::Design *design) { @@ -158,6 +159,10 @@ struct SynthQuickLogicPass : public ScriptPass { dsp = false; continue; } + if (args[argidx] == "-noioff") { + ioff = false; + continue; + } break; } extra_args(args, argidx, design); @@ -328,6 +333,12 @@ struct SynthQuickLogicPass : public ScriptPass { run("clean"); run("opt_lut"); } + + if (check_label("iomap", "(for qlf_k6n10f)") && (family == "qlf_k6n10f" || help_mode)) { + if (ioff || help_mode) { + run("ql_ioff", "(unless -noioff)"); + } + } if (check_label("check")) { run("autoname"); diff --git a/tests/arch/quicklogic/qlf_k6n10f/ioff.ys b/tests/arch/quicklogic/qlf_k6n10f/ioff.ys new file mode 100644 index 000000000..bd69a28d4 --- /dev/null +++ b/tests/arch/quicklogic/qlf_k6n10f/ioff.ys @@ -0,0 +1,91 @@ +# test: acceptable for output IOFF promotion +read_verilog < Date: Fri, 24 Jan 2025 21:29:10 +0100 Subject: [PATCH 02/11] fix tests not expecting ioffs --- tests/arch/quicklogic/qlf_k6n10f/counter.ys | 2 +- tests/arch/quicklogic/qlf_k6n10f/dffs.ys | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/arch/quicklogic/qlf_k6n10f/counter.ys b/tests/arch/quicklogic/qlf_k6n10f/counter.ys index ebb6ce243..d1a9ec692 100644 --- a/tests/arch/quicklogic/qlf_k6n10f/counter.ys +++ b/tests/arch/quicklogic/qlf_k6n10f/counter.ys @@ -2,7 +2,7 @@ read_verilog ../../common/counter.v hierarchy -top top proc flatten -equiv_opt -assert -multiclock -map +/quicklogic/qlf_k6n10f/cells_sim.v -map +/quicklogic/common/cells_sim.v synth_quicklogic -family qlf_k6n10f # equivalency check +equiv_opt -assert -multiclock -map +/quicklogic/qlf_k6n10f/cells_sim.v -map +/quicklogic/common/cells_sim.v synth_quicklogic -family qlf_k6n10f -noioff # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 4 t:$lut diff --git a/tests/arch/quicklogic/qlf_k6n10f/dffs.ys b/tests/arch/quicklogic/qlf_k6n10f/dffs.ys index 79a16c941..e12963ae6 100644 --- a/tests/arch/quicklogic/qlf_k6n10f/dffs.ys +++ b/tests/arch/quicklogic/qlf_k6n10f/dffs.ys @@ -5,7 +5,7 @@ design -save read hierarchy -top my_dff proc -equiv_opt -async2sync -assert -map +/quicklogic/qlf_k6n10f/cells_sim.v -map +/quicklogic/common/cells_sim.v synth_quicklogic -family qlf_k6n10f # equivalency check +equiv_opt -async2sync -assert -map +/quicklogic/qlf_k6n10f/cells_sim.v -map +/quicklogic/common/cells_sim.v synth_quicklogic -family qlf_k6n10f -noioff # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd my_dff # Constrain all select calls below inside the top module select -assert-count 1 t:sdffsre @@ -14,7 +14,7 @@ select -assert-none t:sdffsre %% t:* %D design -load read hierarchy -top my_dffe proc -equiv_opt -async2sync -assert -map +/quicklogic/qlf_k6n10f/cells_sim.v -map +/quicklogic/common/cells_sim.v synth_quicklogic -family qlf_k6n10f # equivalency check +equiv_opt -async2sync -assert -map +/quicklogic/qlf_k6n10f/cells_sim.v -map +/quicklogic/common/cells_sim.v synth_quicklogic -family qlf_k6n10f -noioff # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd my_dffe # Constrain all select calls below inside the top module select -assert-count 1 t:sdffsre From 09ead2daa90a92236f162ef8a9612a740439393e Mon Sep 17 00:00:00 2001 From: David Sawatzke Date: Tue, 28 Jan 2025 09:42:39 +0100 Subject: [PATCH 03/11] tcl: Update help message to clarify usage of `result.string` In the current documentation, it's unclear if `result.string` serves as an example of a string name. It is furthermore unclear what the purpose of `result.string` is. Clarify this by adding a small explanation (and fix a typo) --- kernel/yosys.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index de25d20e2..4bccb1f14 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -754,9 +754,10 @@ struct TclPass : public Pass { log("If any arguments are specified, these arguments are provided to the script via\n"); log("the standard $argc and $argv variables.\n"); log("\n"); - log("Note, tcl will not recieve the output of any yosys command. If the output\n"); + log("Note, tcl will not receive the output of any yosys command. If the output\n"); log("of the tcl commands are needed, use the yosys command 'tee -s result.string'\n"); log("to redirect yosys's output to the 'result.string' scratchpad value.\n"); + log("The 'result.string' value is then used as the tcl output value of the command.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *) override { From 9da4fe747e96e68a0c8ca8420659ff016cc8481b Mon Sep 17 00:00:00 2001 From: "N. Engelhardt" Date: Tue, 28 Jan 2025 11:23:36 +0100 Subject: [PATCH 04/11] fix bus ioff inference --- techlibs/quicklogic/ql_ioff.cc | 18 +++--- tests/arch/quicklogic/qlf_k6n10f/ioff.ys | 81 ++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 8 deletions(-) diff --git a/techlibs/quicklogic/ql_ioff.cc b/techlibs/quicklogic/ql_ioff.cc index c857fc35d..e08850fb7 100644 --- a/techlibs/quicklogic/ql_ioff.cc +++ b/techlibs/quicklogic/ql_ioff.cc @@ -39,13 +39,14 @@ struct QlIoffPass : public Pass { if (!(e_const && r_const && s_const)) continue; - auto d_sig = modwalker.sigmap(cell->getPort(ID::D)); - if (d_sig.is_wire() && d_sig.as_wire()->port_input) { + SigSpec d = cell->getPort(ID::D); + if (GetSize(d) != 1) continue; + SigBit d_sig = modwalker.sigmap(d[0]); + if (d_sig.is_wire() && d_sig.wire->port_input) { log_debug("Cell %s is potentially eligible for promotion to input IOFF.\n", cell->name.c_str()); // check that d_sig has no other consumers - if (GetSize(d_sig) != 1) continue; pool portbits; - modwalker.get_consumers(portbits, d_sig[0]); + modwalker.get_consumers(portbits, d_sig); if (GetSize(portbits) > 1) { log_debug("not promoting: d_sig has other consumers\n"); continue; @@ -53,13 +54,14 @@ struct QlIoffPass : public Pass { cells_to_replace.insert(cell); continue; // no need to check Q if we already put it on the list } - auto q_sig = modwalker.sigmap(cell->getPort(ID::Q)); - if (q_sig.is_wire() && q_sig.as_wire()->port_output) { + SigSpec q = cell->getPort(ID::Q); + if (GetSize(q) != 1) continue; + SigBit q_sig = modwalker.sigmap(q[0]); + if (q_sig.is_wire() && q_sig.wire->port_output) { log_debug("Cell %s is potentially eligible for promotion to output IOFF.\n", cell->name.c_str()); // check that q_sig has no other consumers - if (GetSize(q_sig) != 1) continue; pool portbits; - modwalker.get_consumers(portbits, q_sig[0]); + modwalker.get_consumers(portbits, q_sig); if (GetSize(portbits) > 0) { log_debug("not promoting: q_sig has other consumers\n"); continue; diff --git a/tests/arch/quicklogic/qlf_k6n10f/ioff.ys b/tests/arch/quicklogic/qlf_k6n10f/ioff.ys index bd69a28d4..3144eda13 100644 --- a/tests/arch/quicklogic/qlf_k6n10f/ioff.ys +++ b/tests/arch/quicklogic/qlf_k6n10f/ioff.ys @@ -9,6 +9,18 @@ EOF synth_quicklogic -family qlf_k6n10f -top top select -assert-count 1 t:dff +design -reset +# test: acceptable for output IOFF promotion +read_verilog < Date: Tue, 28 Jan 2025 17:37:23 +0100 Subject: [PATCH 05/11] detect aliased I/O ports --- techlibs/quicklogic/ql_ioff.cc | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/techlibs/quicklogic/ql_ioff.cc b/techlibs/quicklogic/ql_ioff.cc index e08850fb7..4cc9785d5 100644 --- a/techlibs/quicklogic/ql_ioff.cc +++ b/techlibs/quicklogic/ql_ioff.cc @@ -32,38 +32,39 @@ struct QlIoffPass : public Pass { pool cells_to_replace; for (auto cell : module->selected_cells()) { if (cell->type.in(ID(dffsre), ID(sdffsre))) { + log_debug("Checking cell %s.\n", cell->name.c_str()); bool e_const = cell->getPort(ID::E).is_fully_ones(); bool r_const = cell->getPort(ID::R).is_fully_ones(); bool s_const = cell->getPort(ID::S).is_fully_ones(); - if (!(e_const && r_const && s_const)) + if (!(e_const && r_const && s_const)) { + log_debug("not promoting: E, R, or S is used\n"); continue; + } SigSpec d = cell->getPort(ID::D); - if (GetSize(d) != 1) continue; - SigBit d_sig = modwalker.sigmap(d[0]); - if (d_sig.is_wire() && d_sig.wire->port_input) { + log_assert(GetSize(d) == 1); + if (modwalker.has_inputs(d)) { log_debug("Cell %s is potentially eligible for promotion to input IOFF.\n", cell->name.c_str()); // check that d_sig has no other consumers pool portbits; - modwalker.get_consumers(portbits, d_sig); + modwalker.get_consumers(portbits, d); if (GetSize(portbits) > 1) { - log_debug("not promoting: d_sig has other consumers\n"); + log_debug("not promoting: D has other consumers\n"); continue; } cells_to_replace.insert(cell); continue; // no need to check Q if we already put it on the list } SigSpec q = cell->getPort(ID::Q); - if (GetSize(q) != 1) continue; - SigBit q_sig = modwalker.sigmap(q[0]); - if (q_sig.is_wire() && q_sig.wire->port_output) { + log_assert(GetSize(q) == 1); + if (modwalker.has_outputs(q)) { log_debug("Cell %s is potentially eligible for promotion to output IOFF.\n", cell->name.c_str()); // check that q_sig has no other consumers pool portbits; - modwalker.get_consumers(portbits, q_sig); + modwalker.get_consumers(portbits, q); if (GetSize(portbits) > 0) { - log_debug("not promoting: q_sig has other consumers\n"); + log_debug("not promoting: Q has other consumers\n"); continue; } cells_to_replace.insert(cell); From 0ec5f1b75608ab6d0511be331ff5ce9a4f01c9de Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 31 Jan 2025 15:06:09 +1300 Subject: [PATCH 06/11] pmgen: Move passes out of pmgen folder - Techlib pmgens are now in relevant techlibs/*. - `peepopt` pmgens are now in passes/opt. - `test_pmgen` is still in passes/pmgen. - Update `Makefile.inc` and `.gitignore` file(s) to match new `*_pm.h` location, as well as the `#include`s. - Change default `%_pm.h` make target to `techlibs/%_pm.h` and move it to the top level Makefile. - Update pmgen target to use `$(notdir $*)` (where `$*` is the part of the file name that matched the '%' in the target) instead of `$(subst _pm.h,,$(notdir $@))`. --- Makefile | 3 + passes/opt/.gitignore | 1 + passes/opt/Makefile.inc | 14 ++++ passes/{pmgen => opt}/peepopt.cc | 2 +- .../peepopt_formal_clockgateff.pmg | 0 passes/{pmgen => opt}/peepopt_muldiv.pmg | 0 passes/{pmgen => opt}/peepopt_shiftadd.pmg | 0 .../{pmgen => opt}/peepopt_shiftmul_left.pmg | 0 .../{pmgen => opt}/peepopt_shiftmul_right.pmg | 0 passes/pmgen/Makefile.inc | 66 +------------------ passes/pmgen/README.md | 2 +- passes/pmgen/test_pmgen.cc | 4 +- techlibs/.gitignore | 1 + techlibs/ice40/Makefile.inc | 10 +++ {passes/pmgen => techlibs/ice40}/ice40_dsp.cc | 2 +- .../pmgen => techlibs/ice40}/ice40_dsp.pmg | 0 .../ice40}/ice40_wrapcarry.cc | 2 +- .../ice40}/ice40_wrapcarry.pmg | 0 techlibs/microchip/Makefile.inc | 9 +++ .../microchip}/microchip_dsp.cc | 6 +- .../microchip}/microchip_dsp.pmg | 0 .../microchip}/microchip_dsp_CREG.pmg | 0 .../microchip}/microchip_dsp_cascade.pmg | 0 techlibs/xilinx/Makefile.inc | 16 +++++ .../pmgen => techlibs/xilinx}/xilinx_dsp.cc | 8 +-- .../pmgen => techlibs/xilinx}/xilinx_dsp.pmg | 0 .../xilinx}/xilinx_dsp48a.pmg | 0 .../xilinx}/xilinx_dsp_CREG.pmg | 0 .../xilinx}/xilinx_dsp_cascade.pmg | 0 .../pmgen => techlibs/xilinx}/xilinx_srl.cc | 2 +- .../pmgen => techlibs/xilinx}/xilinx_srl.pmg | 0 31 files changed, 71 insertions(+), 77 deletions(-) create mode 100644 passes/opt/.gitignore rename passes/{pmgen => opt}/peepopt.cc (99%) rename passes/{pmgen => opt}/peepopt_formal_clockgateff.pmg (100%) rename passes/{pmgen => opt}/peepopt_muldiv.pmg (100%) rename passes/{pmgen => opt}/peepopt_shiftadd.pmg (100%) rename passes/{pmgen => opt}/peepopt_shiftmul_left.pmg (100%) rename passes/{pmgen => opt}/peepopt_shiftmul_right.pmg (100%) rename {passes/pmgen => techlibs/ice40}/ice40_dsp.cc (99%) rename {passes/pmgen => techlibs/ice40}/ice40_dsp.pmg (100%) rename {passes/pmgen => techlibs/ice40}/ice40_wrapcarry.cc (99%) rename {passes/pmgen => techlibs/ice40}/ice40_wrapcarry.pmg (100%) rename {passes/pmgen => techlibs/microchip}/microchip_dsp.cc (98%) rename {passes/pmgen => techlibs/microchip}/microchip_dsp.pmg (100%) rename {passes/pmgen => techlibs/microchip}/microchip_dsp_CREG.pmg (100%) rename {passes/pmgen => techlibs/microchip}/microchip_dsp_cascade.pmg (100%) rename {passes/pmgen => techlibs/xilinx}/xilinx_dsp.cc (99%) rename {passes/pmgen => techlibs/xilinx}/xilinx_dsp.pmg (100%) rename {passes/pmgen => techlibs/xilinx}/xilinx_dsp48a.pmg (100%) rename {passes/pmgen => techlibs/xilinx}/xilinx_dsp_CREG.pmg (100%) rename {passes/pmgen => techlibs/xilinx}/xilinx_dsp_cascade.pmg (100%) rename {passes/pmgen => techlibs/xilinx}/xilinx_srl.cc (99%) rename {passes/pmgen => techlibs/xilinx}/xilinx_srl.pmg (100%) diff --git a/Makefile b/Makefile index fb3e5654e..e82d69124 100644 --- a/Makefile +++ b/Makefile @@ -651,6 +651,9 @@ OBJS += libs/fst/fastlz.o OBJS += libs/fst/lz4.o endif +techlibs/%_pm.h: passes/pmgen/pmgen.py techlibs/%.pmg + $(P) mkdir -p $(dir $@) && $(PYTHON_EXECUTABLE) $< -o $@ -p $(notdir $*) $(filter-out $<,$^) + ifneq ($(SMALL),1) OBJS += libs/subcircuit/subcircuit.o diff --git a/passes/opt/.gitignore b/passes/opt/.gitignore new file mode 100644 index 000000000..4b40d3505 --- /dev/null +++ b/passes/opt/.gitignore @@ -0,0 +1 @@ +/peepopt*_pm.h \ No newline at end of file diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc index 76bf8a84e..b796535e3 100644 --- a/passes/opt/Makefile.inc +++ b/passes/opt/Makefile.inc @@ -22,4 +22,18 @@ OBJS += passes/opt/opt_lut_ins.o OBJS += passes/opt/opt_ffinv.o OBJS += passes/opt/pmux2shiftx.o OBJS += passes/opt/muxpack.o + +OBJS += passes/opt/peepopt.o +GENFILES += passes/opt/peepopt_pm.h +passes/opt/peepopt.o: passes/opt/peepopt_pm.h +$(eval $(call add_extra_objs,passes/opt/peepopt_pm.h)) + +PEEPOPT_PATTERN = passes/opt/peepopt_shiftmul_right.pmg +PEEPOPT_PATTERN += passes/opt/peepopt_shiftmul_left.pmg +PEEPOPT_PATTERN += passes/opt/peepopt_shiftadd.pmg +PEEPOPT_PATTERN += passes/opt/peepopt_muldiv.pmg +PEEPOPT_PATTERN += passes/opt/peepopt_formal_clockgateff.pmg + +passes/opt/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN) + $(P) mkdir -p $(dir $@) && $(PYTHON_EXECUTABLE) $< -o $@ -p peepopt $(filter-out $<,$^) endif diff --git a/passes/pmgen/peepopt.cc b/passes/opt/peepopt.cc similarity index 99% rename from passes/pmgen/peepopt.cc rename to passes/opt/peepopt.cc index 5b678ee55..b12f4777e 100644 --- a/passes/pmgen/peepopt.cc +++ b/passes/opt/peepopt.cc @@ -28,7 +28,7 @@ bool did_something; // scratchpad configurations for pmgen int shiftadd_max_ratio; -#include "passes/pmgen/peepopt_pm.h" +#include "passes/opt/peepopt_pm.h" struct PeepoptPass : public Pass { PeepoptPass() : Pass("peepopt", "collection of peephole optimizers") { } diff --git a/passes/pmgen/peepopt_formal_clockgateff.pmg b/passes/opt/peepopt_formal_clockgateff.pmg similarity index 100% rename from passes/pmgen/peepopt_formal_clockgateff.pmg rename to passes/opt/peepopt_formal_clockgateff.pmg diff --git a/passes/pmgen/peepopt_muldiv.pmg b/passes/opt/peepopt_muldiv.pmg similarity index 100% rename from passes/pmgen/peepopt_muldiv.pmg rename to passes/opt/peepopt_muldiv.pmg diff --git a/passes/pmgen/peepopt_shiftadd.pmg b/passes/opt/peepopt_shiftadd.pmg similarity index 100% rename from passes/pmgen/peepopt_shiftadd.pmg rename to passes/opt/peepopt_shiftadd.pmg diff --git a/passes/pmgen/peepopt_shiftmul_left.pmg b/passes/opt/peepopt_shiftmul_left.pmg similarity index 100% rename from passes/pmgen/peepopt_shiftmul_left.pmg rename to passes/opt/peepopt_shiftmul_left.pmg diff --git a/passes/pmgen/peepopt_shiftmul_right.pmg b/passes/opt/peepopt_shiftmul_right.pmg similarity index 100% rename from passes/pmgen/peepopt_shiftmul_right.pmg rename to passes/opt/peepopt_shiftmul_right.pmg diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index 6fa7d1fd7..17abfd43e 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -1,70 +1,10 @@ -%_pm.h: passes/pmgen/pmgen.py %.pmg - $(P) mkdir -p $(dir $@) && $(PYTHON_EXECUTABLE) $< -o $@ -p $(subst _pm.h,,$(notdir $@)) $(filter-out $<,$^) +passes/pmgen/%_pm.h: passes/pmgen/pmgen.py passes/pmgen/%.pmg + $(P) mkdir -p $(dir $@) && $(PYTHON_EXECUTABLE) $< -o $@ -p $(notdir $*) $(filter-out $<,$^) # -------------------------------------- OBJS += passes/pmgen/test_pmgen.o GENFILES += passes/pmgen/test_pmgen_pm.h -passes/pmgen/test_pmgen.o: passes/pmgen/test_pmgen_pm.h passes/pmgen/ice40_dsp_pm.h passes/pmgen/peepopt_pm.h passes/pmgen/xilinx_srl_pm.h +passes/pmgen/test_pmgen.o: passes/pmgen/test_pmgen_pm.h techlibs/ice40/ice40_dsp_pm.h techlibs/xilinx/xilinx_srl_pm.h $(eval $(call add_extra_objs,passes/pmgen/test_pmgen_pm.h)) -# -------------------------------------- - -OBJS += passes/pmgen/ice40_dsp.o -GENFILES += passes/pmgen/ice40_dsp_pm.h -passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h -$(eval $(call add_extra_objs,passes/pmgen/ice40_dsp_pm.h)) - -# -------------------------------------- - -OBJS += passes/pmgen/ice40_wrapcarry.o -GENFILES += passes/pmgen/ice40_wrapcarry_pm.h -passes/pmgen/ice40_wrapcarry.o: passes/pmgen/ice40_wrapcarry_pm.h -$(eval $(call add_extra_objs,passes/pmgen/ice40_wrapcarry_pm.h)) - -# -------------------------------------- - -OBJS += passes/pmgen/xilinx_dsp.o -GENFILES += passes/pmgen/xilinx_dsp_pm.h -GENFILES += passes/pmgen/xilinx_dsp48a_pm.h -GENFILES += passes/pmgen/xilinx_dsp_CREG_pm.h -GENFILES += passes/pmgen/xilinx_dsp_cascade_pm.h -passes/pmgen/xilinx_dsp.o: passes/pmgen/xilinx_dsp_pm.h passes/pmgen/xilinx_dsp48a_pm.h passes/pmgen/xilinx_dsp_CREG_pm.h passes/pmgen/xilinx_dsp_cascade_pm.h -$(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_pm.h)) -$(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp48a_pm.h)) -$(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_CREG_pm.h)) -$(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_cascade_pm.h)) - -# -------------------------------------- - -OBJS += passes/pmgen/microchip_dsp.o -GENFILES += passes/pmgen/microchip_dsp_pm.h -GENFILES += passes/pmgen/microchip_dsp_CREG_pm.h -GENFILES += passes/pmgen/microchip_dsp_cascade_pm.h -passes/pmgen/microchip_dsp.o: passes/pmgen/microchip_dsp_pm.h passes/pmgen/microchip_dsp_CREG_pm.h passes/pmgen/microchip_dsp_cascade_pm.h -$(eval $(call add_extra_objs,passes/pmgen/microchip_dsp_pm.h)) -$(eval $(call add_extra_objs,passes/pmgen/microchip_dsp_CREG_pm.h)) -$(eval $(call add_extra_objs,passes/pmgen/microchip_dsp_cascade_pm.h)) - -# -------------------------------------- - -OBJS += passes/pmgen/peepopt.o -GENFILES += passes/pmgen/peepopt_pm.h -passes/pmgen/peepopt.o: passes/pmgen/peepopt_pm.h -$(eval $(call add_extra_objs,passes/pmgen/peepopt_pm.h)) - -PEEPOPT_PATTERN = passes/pmgen/peepopt_shiftmul_right.pmg -PEEPOPT_PATTERN += passes/pmgen/peepopt_shiftmul_left.pmg -PEEPOPT_PATTERN += passes/pmgen/peepopt_shiftadd.pmg -PEEPOPT_PATTERN += passes/pmgen/peepopt_muldiv.pmg -PEEPOPT_PATTERN += passes/pmgen/peepopt_formal_clockgateff.pmg - -passes/pmgen/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN) - $(P) mkdir -p passes/pmgen && $(PYTHON_EXECUTABLE) $< -o $@ -p peepopt $(filter-out $<,$^) - -# -------------------------------------- - -OBJS += passes/pmgen/xilinx_srl.o -GENFILES += passes/pmgen/xilinx_srl_pm.h -passes/pmgen/xilinx_srl.o: passes/pmgen/xilinx_srl_pm.h -$(eval $(call add_extra_objs,passes/pmgen/xilinx_srl_pm.h)) diff --git a/passes/pmgen/README.md b/passes/pmgen/README.md index 3205be1b5..15569ebfc 100644 --- a/passes/pmgen/README.md +++ b/passes/pmgen/README.md @@ -22,7 +22,7 @@ list of cells from that module: foobar_pm pm(module, module->selected_cells()); The caller must make sure that none of the cells in the 2nd argument are -deleted for as long as the patter matcher instance is used. +deleted for as long as the pattern matcher instance is used. At any time it is possible to disable cells, preventing them from showing up in any future matches: diff --git a/passes/pmgen/test_pmgen.cc b/passes/pmgen/test_pmgen.cc index beff59778..fc41848f7 100644 --- a/passes/pmgen/test_pmgen.cc +++ b/passes/pmgen/test_pmgen.cc @@ -24,8 +24,8 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN #include "passes/pmgen/test_pmgen_pm.h" -#include "passes/pmgen/ice40_dsp_pm.h" -#include "passes/pmgen/xilinx_srl_pm.h" +#include "techlibs/ice40/ice40_dsp_pm.h" +#include "techlibs/xilinx/xilinx_srl_pm.h" #include "generate.h" diff --git a/techlibs/.gitignore b/techlibs/.gitignore index e81e4e4b8..ddb102bec 100644 --- a/techlibs/.gitignore +++ b/techlibs/.gitignore @@ -1 +1,2 @@ blackbox.v +*_pm.h diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc index 4bf8e4e86..027a0dd33 100644 --- a/techlibs/ice40/Makefile.inc +++ b/techlibs/ice40/Makefile.inc @@ -14,3 +14,13 @@ $(eval $(call add_share_file,share/ice40,techlibs/ice40/spram.txt)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/spram_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/dsp_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/abc9_model.v)) + +OBJS += techlibs/ice40/ice40_dsp.o +GENFILES += techlibs/ice40/ice40_dsp_pm.h +techlibs/ice40/ice40_dsp.o: techlibs/ice40/ice40_dsp_pm.h +$(eval $(call add_extra_objs,techlibs/ice40/ice40_dsp_pm.h)) + +OBJS += techlibs/ice40/ice40_wrapcarry.o +GENFILES += techlibs/ice40/ice40_wrapcarry_pm.h +techlibs/ice40/ice40_wrapcarry.o: techlibs/ice40/ice40_wrapcarry_pm.h +$(eval $(call add_extra_objs,techlibs/ice40/ice40_wrapcarry_pm.h)) diff --git a/passes/pmgen/ice40_dsp.cc b/techlibs/ice40/ice40_dsp.cc similarity index 99% rename from passes/pmgen/ice40_dsp.cc rename to techlibs/ice40/ice40_dsp.cc index 5720c9b1e..3f00028c3 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/techlibs/ice40/ice40_dsp.cc @@ -23,7 +23,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -#include "passes/pmgen/ice40_dsp_pm.h" +#include "techlibs/ice40/ice40_dsp_pm.h" void create_ice40_dsp(ice40_dsp_pm &pm) { diff --git a/passes/pmgen/ice40_dsp.pmg b/techlibs/ice40/ice40_dsp.pmg similarity index 100% rename from passes/pmgen/ice40_dsp.pmg rename to techlibs/ice40/ice40_dsp.pmg diff --git a/passes/pmgen/ice40_wrapcarry.cc b/techlibs/ice40/ice40_wrapcarry.cc similarity index 99% rename from passes/pmgen/ice40_wrapcarry.cc rename to techlibs/ice40/ice40_wrapcarry.cc index c936d02dc..014490564 100644 --- a/passes/pmgen/ice40_wrapcarry.cc +++ b/techlibs/ice40/ice40_wrapcarry.cc @@ -23,7 +23,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -#include "passes/pmgen/ice40_wrapcarry_pm.h" +#include "techlibs/ice40/ice40_wrapcarry_pm.h" void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm) { diff --git a/passes/pmgen/ice40_wrapcarry.pmg b/techlibs/ice40/ice40_wrapcarry.pmg similarity index 100% rename from passes/pmgen/ice40_wrapcarry.pmg rename to techlibs/ice40/ice40_wrapcarry.pmg diff --git a/techlibs/microchip/Makefile.inc b/techlibs/microchip/Makefile.inc index b1905e2cf..ab294b465 100644 --- a/techlibs/microchip/Makefile.inc +++ b/techlibs/microchip/Makefile.inc @@ -29,3 +29,12 @@ $(eval $(call add_share_file,share/microchip,techlibs/microchip/LSRAM_map.v)) $(eval $(call add_share_file,share/microchip,techlibs/microchip/LSRAM.txt)) $(eval $(call add_share_file,share/microchip,techlibs/microchip/uSRAM_map.v)) $(eval $(call add_share_file,share/microchip,techlibs/microchip/uSRAM.txt)) + +OBJS += techlibs/microchip/microchip_dsp.o +GENFILES += techlibs/microchip/microchip_dsp_pm.h +GENFILES += techlibs/microchip/microchip_dsp_CREG_pm.h +GENFILES += techlibs/microchip/microchip_dsp_cascade_pm.h +techlibs/microchip/microchip_dsp.o: techlibs/microchip/microchip_dsp_pm.h techlibs/microchip/microchip_dsp_CREG_pm.h techlibs/microchip/microchip_dsp_cascade_pm.h +$(eval $(call add_extra_objs,techlibs/microchip/microchip_dsp_pm.h)) +$(eval $(call add_extra_objs,techlibs/microchip/microchip_dsp_CREG_pm.h)) +$(eval $(call add_extra_objs,techlibs/microchip/microchip_dsp_cascade_pm.h)) diff --git a/passes/pmgen/microchip_dsp.cc b/techlibs/microchip/microchip_dsp.cc similarity index 98% rename from passes/pmgen/microchip_dsp.cc rename to techlibs/microchip/microchip_dsp.cc index 31fd24194..3dfcb8905 100644 --- a/passes/pmgen/microchip_dsp.cc +++ b/techlibs/microchip/microchip_dsp.cc @@ -23,9 +23,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -#include "passes/pmgen/microchip_dsp_CREG_pm.h" -#include "passes/pmgen/microchip_dsp_cascade_pm.h" -#include "passes/pmgen/microchip_dsp_pm.h" +#include "techlibs/microchip/microchip_dsp_CREG_pm.h" +#include "techlibs/microchip/microchip_dsp_cascade_pm.h" +#include "techlibs/microchip/microchip_dsp_pm.h" void microchip_dsp_pack(microchip_dsp_pm &pm) { diff --git a/passes/pmgen/microchip_dsp.pmg b/techlibs/microchip/microchip_dsp.pmg similarity index 100% rename from passes/pmgen/microchip_dsp.pmg rename to techlibs/microchip/microchip_dsp.pmg diff --git a/passes/pmgen/microchip_dsp_CREG.pmg b/techlibs/microchip/microchip_dsp_CREG.pmg similarity index 100% rename from passes/pmgen/microchip_dsp_CREG.pmg rename to techlibs/microchip/microchip_dsp_CREG.pmg diff --git a/passes/pmgen/microchip_dsp_cascade.pmg b/techlibs/microchip/microchip_dsp_cascade.pmg similarity index 100% rename from passes/pmgen/microchip_dsp_cascade.pmg rename to techlibs/microchip/microchip_dsp_cascade.pmg diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 2d3d0f63c..a9ca35233 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -46,3 +46,19 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_dsp_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcu_dsp_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_model.v)) + +OBJS += techlibs/xilinx/xilinx_dsp.o +GENFILES += techlibs/xilinx/xilinx_dsp_pm.h +GENFILES += techlibs/xilinx/xilinx_dsp48a_pm.h +GENFILES += techlibs/xilinx/xilinx_dsp_CREG_pm.h +GENFILES += techlibs/xilinx/xilinx_dsp_cascade_pm.h +techlibs/xilinx/xilinx_dsp.o: techlibs/xilinx/xilinx_dsp_pm.h techlibs/xilinx/xilinx_dsp48a_pm.h techlibs/xilinx/xilinx_dsp_CREG_pm.h techlibs/xilinx/xilinx_dsp_cascade_pm.h +$(eval $(call add_extra_objs,techlibs/xilinx/xilinx_dsp_pm.h)) +$(eval $(call add_extra_objs,techlibs/xilinx/xilinx_dsp48a_pm.h)) +$(eval $(call add_extra_objs,techlibs/xilinx/xilinx_dsp_CREG_pm.h)) +$(eval $(call add_extra_objs,techlibs/xilinx/xilinx_dsp_cascade_pm.h)) + +OBJS += techlibs/xilinx/xilinx_srl.o +GENFILES += techlibs/xilinx/xilinx_srl_pm.h +techlibs/xilinx/xilinx_srl.o: techlibs/xilinx/xilinx_srl_pm.h +$(eval $(call add_extra_objs,techlibs/xilinx/xilinx_srl_pm.h)) diff --git a/passes/pmgen/xilinx_dsp.cc b/techlibs/xilinx/xilinx_dsp.cc similarity index 99% rename from passes/pmgen/xilinx_dsp.cc rename to techlibs/xilinx/xilinx_dsp.cc index 9af7d1eec..f95930a90 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/techlibs/xilinx/xilinx_dsp.cc @@ -25,10 +25,10 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -#include "passes/pmgen/xilinx_dsp_pm.h" -#include "passes/pmgen/xilinx_dsp48a_pm.h" -#include "passes/pmgen/xilinx_dsp_CREG_pm.h" -#include "passes/pmgen/xilinx_dsp_cascade_pm.h" +#include "techlibs/xilinx/xilinx_dsp_pm.h" +#include "techlibs/xilinx/xilinx_dsp48a_pm.h" +#include "techlibs/xilinx/xilinx_dsp_CREG_pm.h" +#include "techlibs/xilinx/xilinx_dsp_cascade_pm.h" static Cell* addDsp(Module *module) { Cell *cell = module->addCell(NEW_ID, ID(DSP48E1)); diff --git a/passes/pmgen/xilinx_dsp.pmg b/techlibs/xilinx/xilinx_dsp.pmg similarity index 100% rename from passes/pmgen/xilinx_dsp.pmg rename to techlibs/xilinx/xilinx_dsp.pmg diff --git a/passes/pmgen/xilinx_dsp48a.pmg b/techlibs/xilinx/xilinx_dsp48a.pmg similarity index 100% rename from passes/pmgen/xilinx_dsp48a.pmg rename to techlibs/xilinx/xilinx_dsp48a.pmg diff --git a/passes/pmgen/xilinx_dsp_CREG.pmg b/techlibs/xilinx/xilinx_dsp_CREG.pmg similarity index 100% rename from passes/pmgen/xilinx_dsp_CREG.pmg rename to techlibs/xilinx/xilinx_dsp_CREG.pmg diff --git a/passes/pmgen/xilinx_dsp_cascade.pmg b/techlibs/xilinx/xilinx_dsp_cascade.pmg similarity index 100% rename from passes/pmgen/xilinx_dsp_cascade.pmg rename to techlibs/xilinx/xilinx_dsp_cascade.pmg diff --git a/passes/pmgen/xilinx_srl.cc b/techlibs/xilinx/xilinx_srl.cc similarity index 99% rename from passes/pmgen/xilinx_srl.cc rename to techlibs/xilinx/xilinx_srl.cc index 7b20a7d40..32a0064a6 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/techlibs/xilinx/xilinx_srl.cc @@ -24,7 +24,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -#include "passes/pmgen/xilinx_srl_pm.h" +#include "techlibs/xilinx/xilinx_srl_pm.h" void run_fixed(xilinx_srl_pm &pm) { diff --git a/passes/pmgen/xilinx_srl.pmg b/techlibs/xilinx/xilinx_srl.pmg similarity index 100% rename from passes/pmgen/xilinx_srl.pmg rename to techlibs/xilinx/xilinx_srl.pmg From 303a386ecc89bbff7cfbc0d4a64535087826a372 Mon Sep 17 00:00:00 2001 From: "N. Engelhardt" Date: Fri, 31 Jan 2025 11:28:57 +0100 Subject: [PATCH 07/11] create duplicate IOFFs if multiple output ports are connected to the same register --- techlibs/quicklogic/ql_ioff.cc | 66 +++++++++++++++++++----- techlibs/quicklogic/synth_quicklogic.cc | 5 +- tests/arch/quicklogic/qlf_k6n10f/ioff.ys | 37 +++++++++++++ 3 files changed, 93 insertions(+), 15 deletions(-) diff --git a/techlibs/quicklogic/ql_ioff.cc b/techlibs/quicklogic/ql_ioff.cc index 4cc9785d5..87b62e855 100644 --- a/techlibs/quicklogic/ql_ioff.cc +++ b/techlibs/quicklogic/ql_ioff.cc @@ -29,7 +29,17 @@ struct QlIoffPass : public Pass { if (!module) return; modwalker.setup(module); - pool cells_to_replace; + pool input_ffs; + dict> output_ffs; + dict> output_bit_aliases; + + for (Wire* wire : module->wires()) + if (wire->port_output) { + output_ffs[wire].resize(wire->width, nullptr); + for (SigBit bit : SigSpec(wire)) + output_bit_aliases[modwalker.sigmap(bit)].insert(bit); + } + for (auto cell : module->selected_cells()) { if (cell->type.in(ID(dffsre), ID(sdffsre))) { log_debug("Checking cell %s.\n", cell->name.c_str()); @@ -53,32 +63,62 @@ struct QlIoffPass : public Pass { log_debug("not promoting: D has other consumers\n"); continue; } - cells_to_replace.insert(cell); - continue; // no need to check Q if we already put it on the list + input_ffs.insert(cell); + continue; // prefer input FFs over output FFs } + SigSpec q = cell->getPort(ID::Q); log_assert(GetSize(q) == 1); - if (modwalker.has_outputs(q)) { + if (modwalker.has_outputs(q) && !modwalker.has_consumers(q)) { log_debug("Cell %s is potentially eligible for promotion to output IOFF.\n", cell->name.c_str()); - // check that q_sig has no other consumers - pool portbits; - modwalker.get_consumers(portbits, q); - if (GetSize(portbits) > 0) { - log_debug("not promoting: Q has other consumers\n"); - continue; + for (SigBit bit : output_bit_aliases[modwalker.sigmap(q)]) { + log_assert(bit.is_wire()); + output_ffs[bit.wire][bit.offset] = cell; } - cells_to_replace.insert(cell); + } } } - for (auto cell : cells_to_replace) { - log("Promoting register %s to IOFF.\n", log_signal(cell->getPort(ID::Q))); + for (auto cell : input_ffs) { + log("Promoting register %s to input IOFF.\n", log_signal(cell->getPort(ID::Q))); cell->type = ID(dff); cell->unsetPort(ID::E); cell->unsetPort(ID::R); cell->unsetPort(ID::S); } + for (auto & [old_port_output, ioff_cells] : output_ffs) { + if (std::any_of(ioff_cells.begin(), ioff_cells.end(), [](Cell * c) { return c != nullptr; })) + { + // create replacement output wire + RTLIL::Wire* new_port_output = module->addWire(NEW_ID, old_port_output->width); + new_port_output->start_offset = old_port_output->start_offset; + module->swap_names(old_port_output, new_port_output); + std::swap(old_port_output->port_id, new_port_output->port_id); + std::swap(old_port_output->port_input, new_port_output->port_input); + std::swap(old_port_output->port_output, new_port_output->port_output); + std::swap(old_port_output->upto, new_port_output->upto); + std::swap(old_port_output->is_signed, new_port_output->is_signed); + std::swap(old_port_output->attributes, new_port_output->attributes); + + // create new output FFs + SigSpec sig_o(old_port_output); + SigSpec sig_n(new_port_output); + for (int i = 0; i < new_port_output->width; i++) { + if (ioff_cells[i]) { + log("Promoting %s to output IOFF.\n", log_signal(sig_n[i])); + + RTLIL::Cell *new_cell = module->addCell(NEW_ID, ID(dff)); + new_cell->setPort(ID::C, ioff_cells[i]->getPort(ID::C)); + new_cell->setPort(ID::D, ioff_cells[i]->getPort(ID::D)); + new_cell->setPort(ID::Q, sig_n[i]); + new_cell->set_bool_attribute(ID::keep); + } else { + module->connect(sig_n[i], sig_o[i]); + } + } + } + } } } QlIoffPass; diff --git a/techlibs/quicklogic/synth_quicklogic.cc b/techlibs/quicklogic/synth_quicklogic.cc index 16f660943..07ec769b5 100644 --- a/techlibs/quicklogic/synth_quicklogic.cc +++ b/techlibs/quicklogic/synth_quicklogic.cc @@ -334,9 +334,10 @@ struct SynthQuickLogicPass : public ScriptPass { run("opt_lut"); } - if (check_label("iomap", "(for qlf_k6n10f)") && (family == "qlf_k6n10f" || help_mode)) { + if (check_label("iomap", "(for qlf_k6n10f, skip if -noioff)") && (family == "qlf_k6n10f" || help_mode)) { if (ioff || help_mode) { - run("ql_ioff", "(unless -noioff)"); + run("ql_ioff"); + run("opt_clean"); } } diff --git a/tests/arch/quicklogic/qlf_k6n10f/ioff.ys b/tests/arch/quicklogic/qlf_k6n10f/ioff.ys index 3144eda13..da1fb2946 100644 --- a/tests/arch/quicklogic/qlf_k6n10f/ioff.ys +++ b/tests/arch/quicklogic/qlf_k6n10f/ioff.ys @@ -21,6 +21,21 @@ EOF synth_quicklogic -family qlf_k6n10f -top top select -assert-count 4 t:dff +design -reset +# test: acceptable for output IOFF promotion; duplicate output FF +read_verilog < Date: Mon, 17 Feb 2025 17:36:51 +0100 Subject: [PATCH 08/11] liberty: fix clear and preset latches --- frontends/liberty/liberty.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index b29984ecd..cda13ff8b 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -348,7 +348,7 @@ static bool create_latch(RTLIL::Module *module, const LibertyAst *node, bool fla RTLIL::Cell *enable_gate = module->addCell(NEW_ID, enable_polarity ? ID($_OR_) : ID($_AND_)); enable_gate->setPort(ID::A, enable_sig); enable_gate->setPort(ID::B, clear_enable); - enable_gate->setPort(ID::Y, data_sig = module->addWire(NEW_ID)); + enable_gate->setPort(ID::Y, enable_sig = module->addWire(NEW_ID)); } if (preset_sig.size() == 1) @@ -376,7 +376,7 @@ static bool create_latch(RTLIL::Module *module, const LibertyAst *node, bool fla RTLIL::Cell *enable_gate = module->addCell(NEW_ID, enable_polarity ? ID($_OR_) : ID($_AND_)); enable_gate->setPort(ID::A, enable_sig); enable_gate->setPort(ID::B, preset_enable); - enable_gate->setPort(ID::Y, data_sig = module->addWire(NEW_ID)); + enable_gate->setPort(ID::Y, enable_sig = module->addWire(NEW_ID)); } cell = module->addCell(NEW_ID, stringf("$_DLATCH_%c_", enable_polarity ? 'P' : 'N')); From 1eaf1847b2724b796f081dd34a208d553a8c95d8 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Thu, 20 Feb 2025 14:15:34 +1300 Subject: [PATCH 09/11] CONTRIBUTING.md: Initial version --- CONTRIBUTING.md | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..86df13777 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,71 @@ +# Introduction + +Thanks for thinking about contributing to the Yosys project. If this is your +first time contributing to an open source project, please take a look at the +following guide: +https://opensource.guide/how-to-contribute/#orienting-yourself-to-a-new-project. + + +# Using the issue tracker + +The [issue tracker](https://github.com/YosysHQ/yosys/issues) is used for +tracking bugs or other problems with Yosys or its documentation. It is also the +place to go for requesting new features. +When [creating a new issue](https://github.com/YosysHQ/yosys/issues/new/choose), +we have a few templates available. Please make use of these! It will make it +much easier for someone to respond and help. + +### Bug reports + +Before you submit an issue, please have a search of the existing issues in case +one already exists. Making sure that you have a minimal, complete and +verifiable example (MVCE) is a great way to quickly check an existing issue +against a new one. Stack overflow has a guide on [how to create an +MVCE](https://stackoverflow.com/help/minimal-reproducible-example). The +[`bugpoint` +command](https://yosyshq.readthedocs.io/projects/yosys/en/latest/cmd/bugpoint.html) +in Yosys can be helpful for this process. + + +# Using pull requests + +If you are working on something to add to Yosys, or fix something that isn't +working quite right, make a PR! An open PR, even as a draft, tells everyone +that you're working on it and they don't have to. It can also be a useful way +to solicit feedback on in-progress changes. See below to find the best way to +[ask us questions](#asking-questions). + +In general, all changes to the code are done as a +[PR](https://github.com/YosysHQ/yosys/pulls), with [Continuous Integration +(CI)](https://github.com/YosysHQ/yosys/actions) tools that automatically run the +full suite of tests compiling and running Yosys. Please make use of this! If +you're adding a feature: add a test! Not only does it verify that your feature +is working as expected, but it can also be a handy way for people to see how the +feature is used. If you're fixing a bug: add a test! If you can, do this +first; it's okay if the test starts off failing - you already know there is a +bug. CI also helps to make sure that your changes still work under a range of +compilers, settings, and targets. + + +### Labels + +We use [labels](https://github.com/YosysHQ/yosys/labels) to help categorise +issues and PRs. If a label seems relevant to your work, please do add it; this +also includes the labels beggining with 'status-'. The 'merge-' labels are used +by maintainers for tracking and communicating which PRs are ready and pending +merge; please do not use these labels if you are not a maintainer. + + +# Asking questions + +If you have a question about how to use Yosys, please ask on our [discussions +page](https://github.com/YosysHQ/yosys/discussions) or in our [community +slack](https://join.slack.com/t/yosyshq/shared_invite/zt-1aopkns2q-EiQ97BeQDt_pwvE41sGSuA). +The slack is also a great place to ask questions about developing or +contributing to Yosys. + +We have open dev 'jour fixe' (JF) meetings where developers from YosysHQ and the +community come together to discuss open issues and PRs. This is also a good +place to talk to us about how to implement larger PRs. Please join the +community slack if you would like to join the next meeting, the link is +available in the description of the #devel-discuss channel. From 9c9b3ebf9e0ab3e74ce8694090f49de34fa7f4aa Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Thu, 20 Feb 2025 14:15:38 +1300 Subject: [PATCH 10/11] CONTRIBUTING.md: Move PR link --- CONTRIBUTING.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 86df13777..36940ae1b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,21 +30,21 @@ in Yosys can be helpful for this process. # Using pull requests If you are working on something to add to Yosys, or fix something that isn't -working quite right, make a PR! An open PR, even as a draft, tells everyone -that you're working on it and they don't have to. It can also be a useful way -to solicit feedback on in-progress changes. See below to find the best way to -[ask us questions](#asking-questions). +working quite right, make a [PR](https://github.com/YosysHQ/yosys/pulls)! An +open PR, even as a draft, tells everyone that you're working on it and they +don't have to. It can also be a useful way to solicit feedback on in-progress +changes. See below to find the best way to [ask us +questions](#asking-questions). -In general, all changes to the code are done as a -[PR](https://github.com/YosysHQ/yosys/pulls), with [Continuous Integration -(CI)](https://github.com/YosysHQ/yosys/actions) tools that automatically run the -full suite of tests compiling and running Yosys. Please make use of this! If -you're adding a feature: add a test! Not only does it verify that your feature -is working as expected, but it can also be a handy way for people to see how the -feature is used. If you're fixing a bug: add a test! If you can, do this -first; it's okay if the test starts off failing - you already know there is a -bug. CI also helps to make sure that your changes still work under a range of -compilers, settings, and targets. +In general, all changes to the code are done as a PR, with [Continuous +Integration (CI)](https://github.com/YosysHQ/yosys/actions) tools that +automatically run the full suite of tests compiling and running Yosys. Please +make use of this! If you're adding a feature: add a test! Not only does it +verify that your feature is working as expected, but it can also be a handy way +for people to see how the feature is used. If you're fixing a bug: add a test! +If you can, do this first; it's okay if the test starts off failing - you +already know there is a bug. CI also helps to make sure that your changes still +work under a range of compilers, settings, and targets. ### Labels From 38746ea5fad7018f00d2143c491ebd637552e7e0 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Thu, 20 Feb 2025 14:15:39 +1300 Subject: [PATCH 11/11] docs: Cross reference contributing .md points to .html on latest .rst points to .md on main (not that it will work before this is merged) --- CONTRIBUTING.md | 2 ++ .../yosys_internals/extending_yosys/contributing.rst | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 36940ae1b..6c4376cc4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,6 +5,8 @@ first time contributing to an open source project, please take a look at the following guide: https://opensource.guide/how-to-contribute/#orienting-yourself-to-a-new-project. +Information about the Yosys coding style is available on our Read the Docs: +https://yosys.readthedocs.io/en/latest/yosys_internals/extending_yosys/contributing.html. # Using the issue tracker diff --git a/docs/source/yosys_internals/extending_yosys/contributing.rst b/docs/source/yosys_internals/extending_yosys/contributing.rst index e06de61b1..69258aa5f 100644 --- a/docs/source/yosys_internals/extending_yosys/contributing.rst +++ b/docs/source/yosys_internals/extending_yosys/contributing.rst @@ -1,6 +1,14 @@ Contributing to Yosys ===================== +.. note:: + + For information on making a pull request on github, refer to our + |CONTRIBUTING|_ file. + +.. |CONTRIBUTING| replace:: :file:`CONTRIBUTING.md` +.. _CONTRIBUTING: https://github.com/YosysHQ/yosys/CONTRIBUTING.md + Coding Style ------------