diff options
Diffstat (limited to 'techlibs')
-rw-r--r-- | techlibs/coolrunner2/Makefile.inc | 1 | ||||
-rw-r--r-- | techlibs/coolrunner2/coolrunner2_fixup.cc | 161 | ||||
-rw-r--r-- | techlibs/coolrunner2/coolrunner2_sop.cc | 54 | ||||
-rw-r--r-- | techlibs/coolrunner2/synth_coolrunner2.cc | 1 |
4 files changed, 163 insertions, 54 deletions
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 <rqou@robertou.com> + * + * 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<std::string> 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<SigBit> 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<SigBit> 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<SigBit> 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<SigBit> 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"); } |