coolrunner2: Separate and improve buffer cell insertion pass
authorR. Ou <rqou@robertou.com>
Mon, 17 Feb 2020 04:25:46 +0000 (20:25 -0800)
committerR. Ou <rqou@robertou.com>
Mon, 17 Feb 2020 04:25:46 +0000 (20:25 -0800)
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
techlibs/coolrunner2/coolrunner2_fixup.cc [new file with mode: 0644]
techlibs/coolrunner2/coolrunner2_sop.cc
techlibs/coolrunner2/synth_coolrunner2.cc

index d62c9960c7039d150b51902b655ff94e2954ca11..d5c45322a8149b8ce653e91f21e2be5ece72c62c 100644 (file)
@@ -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 (file)
index 0000000..bc1e8ff
--- /dev/null
@@ -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
index de0cbb29db004c12b93a6fc93453406cc7a5c37b..49ae8e21a3847a61fded0a16d23df6b807c81be7 100644 (file)
@@ -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)
                        {
index 3bac8623d184e8dbf6f394c5c91991a5235cfb8d..b30b3775bdb7e1cd6a4b4387e7381015d0e2217d 100644 (file)
@@ -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");
                }