Add SF2 IO buffer insertion
authorClifford Wolf <clifford@clifford.at>
Thu, 17 Jan 2019 13:38:37 +0000 (14:38 +0100)
committerClifford Wolf <clifford@clifford.at>
Thu, 17 Jan 2019 13:38:37 +0000 (14:38 +0100)
Signed-off-by: Clifford Wolf <clifford@clifford.at>
examples/igloo2/example.v
examples/igloo2/libero.tcl
techlibs/sf2/Makefile.inc
techlibs/sf2/cells_sim.v
techlibs/sf2/sf2_iobs.cc [new file with mode: 0644]
techlibs/sf2/synth_sf2.cc

index 0e336e557335c28d74ee38fee9a5db692d11385b..1a1967d5ae2e4292a2a833c648c52d32a496d257 100644 (file)
@@ -1,5 +1,6 @@
 module example (
        input  clk,
+       input  EN,
        output LED1,
        output LED2,
        output LED3,
@@ -14,7 +15,7 @@ module example (
        reg [BITS-1:0] outcnt;
 
        always @(posedge clk) begin
-               counter <= counter + 1;
+               counter <= counter + EN;
                outcnt <= counter >> LOG2DELAY;
        end
 
index b2090f40229328b1dd5345586b60a9615d19c4ef..952342a4c40bf09afaf51d95d8c79e30f71fed72 100644 (file)
@@ -5,7 +5,7 @@ file delete -force proj
 new_project \
     -name example \
     -location proj \
-    -block_mode 1 \
+    -block_mode 0 \
     -hdl "VERILOG" \
     -family IGLOO2 \
     -die PA4MGL500 \
index cade49f37dd26fcc99bc9deeb4a751a5718d0a50..cc3054aced8f055eaef0ffc8986760ba62e62d67 100644 (file)
@@ -1,5 +1,6 @@
 
 OBJS += techlibs/sf2/synth_sf2.o
+OBJS += techlibs/sf2/sf2_iobs.o
 
 $(eval $(call add_share_file,share/sf2,techlibs/sf2/arith_map.v))
 $(eval $(call add_share_file,share/sf2,techlibs/sf2/cells_map.v))
index b03b2c750bb5b7bc5c1b26db80d0bfdb60265376..f967068af1175d4c103da6116daff888ee906b0e 100644 (file)
@@ -73,3 +73,24 @@ module CFG4 (
        parameter [15:0] INIT = 16'h0;
        assign Y = INIT >> {D, C, B, A};
 endmodule
+
+module CLKBUF (
+       input PAD,
+       output Y
+);
+       assign Y = PAD;
+endmodule
+
+module INBUF (
+       input PAD,
+       output Y
+);
+       assign Y = PAD;
+endmodule
+
+module OUTBUF (
+       input D,
+       output PAD
+);
+       assign PAD = D;
+endmodule
diff --git a/techlibs/sf2/sf2_iobs.cc b/techlibs/sf2/sf2_iobs.cc
new file mode 100644 (file)
index 0000000..2714143
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ *  yosys -- Yosys Open SYnthesis Suite
+ *
+ *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
+ *
+ *  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 Sf2IobsPass : public Pass {
+       Sf2IobsPass() : Pass("sf2_iobs", "SF2: insert IO buffers") { }
+       void help() YS_OVERRIDE
+       {
+               //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+               log("\n");
+               log("    sf2_iobs [options] [selection]\n");
+               log("\n");
+               log("Add SF2 I/O buffers to top module IOs as needed.\n");
+               log("\n");
+       }
+       void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+       {
+               log_header(design, "Executing sf2_iobs pass (insert IO buffers).\n");
+
+               size_t argidx;
+               for (argidx = 1; argidx < args.size(); argidx++)
+               {
+                       // if (args[argidx] == "-singleton") {
+                       //      singleton_mode = true;
+                       //      continue;
+                       // }
+                       break;
+               }
+               extra_args(args, argidx, design);
+
+               Module *module = design->top_module();
+
+               if (module == nullptr)
+                       log_cmd_error("No top module found.\n");
+
+               SigMap sigmap(module);
+
+               pool<SigBit> clk_bits;
+               pool<SigBit> handled_io_bits;
+               dict<SigBit, SigBit> rewrite_bits;
+               vector<pair<Cell*, SigBit>> pad_bits;
+
+               for (auto cell : module->cells())
+               {
+                       if (cell->type == "\\SLE") {
+                               for (auto bit : sigmap(cell->getPort("\\CLK")))
+                                       clk_bits.insert(bit);
+                       }
+                       if (cell->type.in("\\INBUF", "\\OUTBUF", "\\CLKBUF")) {
+                               for (auto bit : sigmap(cell->getPort("\\PAD")))
+                                       handled_io_bits.insert(bit);
+                       }
+               }
+
+               for (auto wire : vector<Wire*>(module->wires()))
+               {
+                       if (!wire->port_input && !wire->port_output)
+                               continue;
+
+                       for (int index = 0; index < GetSize(wire); index++)
+                       {
+                               SigBit bit(wire, index);
+                               SigBit canonical_bit = sigmap(bit);
+
+                               if (handled_io_bits.count(canonical_bit))
+                                       continue;
+
+                               if (wire->port_input && wire->port_output)
+                                       log_error("Failed to add buffer for inout port bit %s.\n", log_signal(bit));
+
+                               IdString buf_type, buf_port;
+
+                               if (wire->port_output) {
+                                       buf_type = "\\OUTBUF";
+                                       buf_port = "\\D";
+                               } else if (clk_bits.count(canonical_bit)) {
+                                       buf_type = "\\CLKBUF";
+                                       buf_port = "\\Y";
+                               } else {
+                                       buf_type = "\\INBUF";
+                                       buf_port = "\\Y";
+                               }
+
+                               Cell *c = module->addCell(NEW_ID, buf_type);
+                               SigBit new_bit = module->addWire(NEW_ID);
+                               c->setPort(buf_port, new_bit);
+                               pad_bits.push_back(make_pair(c, bit));
+                               rewrite_bits[canonical_bit] = new_bit;
+
+                               log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit));
+                       }
+               }
+
+               auto rewrite_function = [&](SigSpec &s) {
+                       for (auto &bit : s) {
+                               SigBit canonical_bit = sigmap(bit);
+                               if (rewrite_bits.count(canonical_bit))
+                                       bit = rewrite_bits.at(canonical_bit);
+                       }
+               };
+
+               module->rewrite_sigspecs(rewrite_function);
+
+               for (auto &it : pad_bits)
+                       it.first->setPort("\\PAD", it.second);
+       }
+} Sf2IobsPass;
+
+PRIVATE_NAMESPACE_END
index 6828a429842e2a1310cdf558ca8d4915b0b2fac2..bdc20456d734b2cba6bd95afcbf42eb92217439d 100644 (file)
@@ -60,6 +60,9 @@ struct SynthSf2Pass : public ScriptPass
                log("    -noflatten\n");
                log("        do not flatten design before synthesis\n");
                log("\n");
+               log("    -noiobs\n");
+               log("        run synthesis in \"block mode\", i.e. do not insert IO buffers\n");
+               log("\n");
                log("    -retime\n");
                log("        run 'abc' with -dff option\n");
                log("\n");
@@ -70,7 +73,7 @@ struct SynthSf2Pass : public ScriptPass
        }
 
        string top_opt, edif_file, vlog_file, json_file;
-       bool flatten, retime;
+       bool flatten, retime, iobs;
 
        void clear_flags() YS_OVERRIDE
        {
@@ -80,6 +83,7 @@ struct SynthSf2Pass : public ScriptPass
                json_file = "";
                flatten = true;
                retime = false;
+               iobs = true;
        }
 
        void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@@ -122,6 +126,10 @@ struct SynthSf2Pass : public ScriptPass
                                retime = true;
                                continue;
                        }
+                       if (args[argidx] == "-noiobs") {
+                               iobs = false;
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
@@ -191,6 +199,13 @@ struct SynthSf2Pass : public ScriptPass
                        run("clean");
                }
 
+               if (check_label("map_iobs"))
+               {
+                       if (iobs || help_mode)
+                               run("sf2_iobs", "(unless -noiobs)");
+                       run("clean");
+               }
+
                if (check_label("check"))
                {
                        run("hierarchy -check");