From 6a0682f5a0148949beacad0eb93ec5b754bf29cd Mon Sep 17 00:00:00 2001 From: "R. Ou" Date: Sun, 16 Feb 2020 20:25:46 -0800 Subject: [PATCH] coolrunner2: Separate and improve buffer cell insertion pass The new pass will contain all of the logic for inserting "passthrough" product term and XOR cells as appropriate for the architecture. For example, this commit fixes connecting an input pin directly to another output pin with no logic in between. --- techlibs/coolrunner2/Makefile.inc | 1 + techlibs/coolrunner2/coolrunner2_fixup.cc | 161 ++++++++++++++++++++++ techlibs/coolrunner2/coolrunner2_sop.cc | 54 -------- techlibs/coolrunner2/synth_coolrunner2.cc | 1 + 4 files changed, 163 insertions(+), 54 deletions(-) create mode 100644 techlibs/coolrunner2/coolrunner2_fixup.cc diff --git a/techlibs/coolrunner2/Makefile.inc b/techlibs/coolrunner2/Makefile.inc index d62c9960c..d5c45322a 100644 --- a/techlibs/coolrunner2/Makefile.inc +++ b/techlibs/coolrunner2/Makefile.inc @@ -1,6 +1,7 @@ OBJS += techlibs/coolrunner2/synth_coolrunner2.o OBJS += techlibs/coolrunner2/coolrunner2_sop.o +OBJS += techlibs/coolrunner2/coolrunner2_fixup.o $(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/cells_latch.v)) $(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/cells_sim.v)) diff --git a/techlibs/coolrunner2/coolrunner2_fixup.cc b/techlibs/coolrunner2/coolrunner2_fixup.cc new file mode 100644 index 000000000..bc1e8ff1b --- /dev/null +++ b/techlibs/coolrunner2/coolrunner2_fixup.cc @@ -0,0 +1,161 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2020 R. Ou + * + * 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 + +struct Coolrunner2FixupPass : public Pass { + Coolrunner2FixupPass() : Pass("coolrunner2_fixup", "insert necessary buffer cells for CoolRunner-II architecture") { } + void help() YS_OVERRIDE + { + log("\n"); + log(" coolrunner2_fixup [options] [selection]\n"); + log("\n"); + log("Insert necessary buffer cells for CoolRunner-II architecture.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing COOLRUNNER2_FIXUP pass (insert necessary buffer cells for CoolRunner-II architecture).\n"); + extra_args(args, 1, design); + + for (auto module : design->selected_modules()) + { + SigMap sigmap(module); + + // Find all the FF outputs + pool sig_fed_by_ff; + for (auto cell : module->selected_cells()) + { + if (cell->type.in("\\FDCP", "\\FDCP_N", "\\FDDCP", "\\LDCP", "\\LDCP_N", + "\\FTCP", "\\FTCP_N", "\\FTDCP", "\\FDCPE", "\\FDCPE_N", "\\FDDCPE")) + { + auto output = sigmap(cell->getPort("\\Q")[0]); + sig_fed_by_ff.insert(output); + } + } + + // Find all the XOR outputs + pool sig_fed_by_xor; + for (auto cell : module->selected_cells()) + { + if (cell->type == "\\MACROCELL_XOR") + { + auto output = sigmap(cell->getPort("\\OUT")[0]); + sig_fed_by_xor.insert(output); + } + } + + // Find all the input/inout outputs + pool sig_fed_by_io; + for (auto cell : module->selected_cells()) + { + if (cell->type.in("\\IBUF", "\\IOBUFE")) + { + if (cell->hasPort("\\O")) { + auto output = sigmap(cell->getPort("\\O")[0]); + sig_fed_by_io.insert(output); + } + } + } + + // Start by buffering FF inputs. FF inputs can only come from either + // an IO pin or from an XOR. Otherwise AND/XOR cells need to be inserted. + for (auto cell : module->selected_cells()) + { + if (cell->type.in("\\FDCP", "\\FDCP_N", "\\FDDCP", "\\LDCP", "\\LDCP_N", + "\\FTCP", "\\FTCP_N", "\\FTDCP", "\\FDCPE", "\\FDCPE_N", "\\FDDCPE")) + { + SigBit input; + if (cell->type.in("\\FTCP", "\\FTCP_N", "\\FTDCP")) + input = sigmap(cell->getPort("\\T")[0]); + else + input = sigmap(cell->getPort("\\D")[0]); + + if (!sig_fed_by_xor[input] && !sig_fed_by_io[input]) + { + log("Buffering input to \"%s\"\n", cell->name.c_str()); + + auto and_to_xor_wire = module->addWire(NEW_ID); + auto xor_to_ff_wire = module->addWire(NEW_ID); + + auto and_cell = module->addCell(NEW_ID, "\\ANDTERM"); + and_cell->setParam("\\TRUE_INP", 1); + and_cell->setParam("\\COMP_INP", 0); + and_cell->setPort("\\OUT", and_to_xor_wire); + and_cell->setPort("\\IN", input); + and_cell->setPort("\\IN_B", SigSpec()); + + auto xor_cell = module->addCell(NEW_ID, "\\MACROCELL_XOR"); + xor_cell->setParam("\\INVERT_OUT", false); + xor_cell->setPort("\\IN_PTC", and_to_xor_wire); + xor_cell->setPort("\\OUT", xor_to_ff_wire); + + if (cell->type.in("\\FTCP", "\\FTCP_N", "\\FTDCP")) + cell->setPort("\\T", xor_to_ff_wire); + else + cell->setPort("\\D", xor_to_ff_wire); + } + } + } + + // Buffer IOBUFE inputs. This can only be fed from an XOR or FF. + for (auto cell : module->selected_cells()) + { + if (cell->type == "\\IOBUFE") + { + SigBit input = sigmap(cell->getPort("\\I")[0]); + + // Special case: constant 0 and 1 are handled by xc2par + if (input == SigBit(true) || input == SigBit(false)) { + log("Not buffering constant IO to \"%s\"\n", cell->name.c_str()); + continue; + } + + if (!sig_fed_by_xor[input] && !sig_fed_by_ff[input]) + { + log("Buffering input to \"%s\"\n", cell->name.c_str()); + + auto and_to_xor_wire = module->addWire(NEW_ID); + auto xor_to_io_wire = module->addWire(NEW_ID); + + auto and_cell = module->addCell(NEW_ID, "\\ANDTERM"); + and_cell->setParam("\\TRUE_INP", 1); + and_cell->setParam("\\COMP_INP", 0); + and_cell->setPort("\\OUT", and_to_xor_wire); + and_cell->setPort("\\IN", input); + and_cell->setPort("\\IN_B", SigSpec()); + + auto xor_cell = module->addCell(NEW_ID, "\\MACROCELL_XOR"); + xor_cell->setParam("\\INVERT_OUT", false); + xor_cell->setPort("\\IN_PTC", and_to_xor_wire); + xor_cell->setPort("\\OUT", xor_to_io_wire); + + cell->setPort("\\I", xor_to_io_wire); + } + } + } + } + } +} Coolrunner2FixupPass; + +PRIVATE_NAMESPACE_END diff --git a/techlibs/coolrunner2/coolrunner2_sop.cc b/techlibs/coolrunner2/coolrunner2_sop.cc index de0cbb29d..49ae8e21a 100644 --- a/techlibs/coolrunner2/coolrunner2_sop.cc +++ b/techlibs/coolrunner2/coolrunner2_sop.cc @@ -248,60 +248,6 @@ struct Coolrunner2SopPass : public Pass { } } - // In some cases we can get a FF feeding straight into an FF. This is not possible, so we need to insert - // some AND/XOR cells in the middle to make it actually work. - - // Find all the FF outputs - pool sig_fed_by_ff; - for (auto cell : module->selected_cells()) - { - if (cell->type.in("\\FDCP", "\\FDCP_N", "\\FDDCP", "\\LDCP", "\\LDCP_N", - "\\FTCP", "\\FTCP_N", "\\FTDCP", "\\FDCPE", "\\FDCPE_N", "\\FDDCPE")) - { - auto output = sigmap(cell->getPort("\\Q")[0]); - sig_fed_by_ff.insert(output); - } - } - - // Look at all the FF inputs - for (auto cell : module->selected_cells()) - { - if (cell->type.in("\\FDCP", "\\FDCP_N", "\\FDDCP", "\\LDCP", "\\LDCP_N", - "\\FTCP", "\\FTCP_N", "\\FTDCP", "\\FDCPE", "\\FDCPE_N", "\\FDDCPE")) - { - SigBit input; - if (cell->type.in("\\FTCP", "\\FTCP_N", "\\FTDCP")) - input = sigmap(cell->getPort("\\T")[0]); - else - input = sigmap(cell->getPort("\\D")[0]); - - if (sig_fed_by_ff[input]) - { - printf("Buffering input to \"%s\"\n", cell->name.c_str()); - - auto and_to_xor_wire = module->addWire(NEW_ID); - auto xor_to_ff_wire = module->addWire(NEW_ID); - - auto and_cell = module->addCell(NEW_ID, "\\ANDTERM"); - and_cell->setParam("\\TRUE_INP", 1); - and_cell->setParam("\\COMP_INP", 0); - and_cell->setPort("\\OUT", and_to_xor_wire); - and_cell->setPort("\\IN", input); - and_cell->setPort("\\IN_B", SigSpec()); - - auto xor_cell = module->addCell(NEW_ID, "\\MACROCELL_XOR"); - xor_cell->setParam("\\INVERT_OUT", false); - xor_cell->setPort("\\IN_PTC", and_to_xor_wire); - xor_cell->setPort("\\OUT", xor_to_ff_wire); - - if (cell->type.in("\\FTCP", "\\FTCP_N", "\\FTDCP")) - cell->setPort("\\T", xor_to_ff_wire); - else - cell->setPort("\\D", xor_to_ff_wire); - } - } - } - // Actually do the removal now that we aren't iterating for (auto cell : cells_to_remove) { diff --git a/techlibs/coolrunner2/synth_coolrunner2.cc b/techlibs/coolrunner2/synth_coolrunner2.cc index 3bac8623d..b30b3775b 100644 --- a/techlibs/coolrunner2/synth_coolrunner2.cc +++ b/techlibs/coolrunner2/synth_coolrunner2.cc @@ -178,6 +178,7 @@ struct SynthCoolrunner2Pass : public ScriptPass run("iopadmap -bits -inpad IBUF O:I -outpad IOBUFE I:IO -inoutpad IOBUFE O:IO -toutpad IOBUFE E:I:IO -tinoutpad IOBUFE E:O:I:IO"); run("attrmvcp -attr src -attr LOC t:IOBUFE n:*"); run("attrmvcp -attr src -attr LOC -driven t:IBUF n:*"); + run("coolrunner2_fixup"); run("splitnets"); run("clean"); }