aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/coolrunner2
diff options
context:
space:
mode:
authorR. Ou <rqou@robertou.com>2020-02-16 20:25:46 -0800
committerR. Ou <rqou@robertou.com>2020-02-16 20:25:46 -0800
commit6a0682f5a0148949beacad0eb93ec5b754bf29cd (patch)
treedecc145a7bc6e32f684dfcbcb700cb06c93137c0 /techlibs/coolrunner2
parentcd60f079d6c96e1d8a00c3c081fab1148d432b44 (diff)
downloadyosys-6a0682f5a0148949beacad0eb93ec5b754bf29cd.tar.gz
yosys-6a0682f5a0148949beacad0eb93ec5b754bf29cd.tar.bz2
yosys-6a0682f5a0148949beacad0eb93ec5b754bf29cd.zip
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.
Diffstat (limited to 'techlibs/coolrunner2')
-rw-r--r--techlibs/coolrunner2/Makefile.inc1
-rw-r--r--techlibs/coolrunner2/coolrunner2_fixup.cc161
-rw-r--r--techlibs/coolrunner2/coolrunner2_sop.cc54
-rw-r--r--techlibs/coolrunner2/synth_coolrunner2.cc1
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");
}