Refactor SF2 iobuf insertion, Add clkint insertion
authorClifford Wolf <clifford@clifford.at>
Wed, 6 Mar 2019 08:41:02 +0000 (00:41 -0800)
committerClifford Wolf <clifford@clifford.at>
Wed, 6 Mar 2019 08:41:02 +0000 (00:41 -0800)
Signed-off-by: Clifford Wolf <clifford@clifford.at>
examples/igloo2/runme.sh
techlibs/sf2/cells_sim.v
techlibs/sf2/sf2_iobs.cc
techlibs/sf2/synth_sf2.cc

index 838f027db34c91f93490d1a542ccd6580c0501ee..a08894e0aedd33dcad589320256f3da7fad2135e 100644 (file)
@@ -1,6 +1,6 @@
 #!/bin/bash
 set -ex
-yosys -p 'synth_sf2 -noclkbuf -top example -edif netlist.edn -vlog netlist.vm' example.v
+yosys -p 'synth_sf2 -top example -edif netlist.edn -vlog netlist.vm' example.v
 export LM_LICENSE_FILE=${LM_LICENSE_FILE:-1702@localhost}
 /opt/microsemi/Libero_SoC_v12.0/Libero/bin/libero SCRIPT:libero.tcl
 cp proj/designer/example/export/example.stp .
index f967068af1175d4c103da6116daff888ee906b0e..b49101616f32bdf0afb4611409522baab8737558 100644 (file)
@@ -74,6 +74,13 @@ module CFG4 (
        assign Y = INIT >> {D, C, B, A};
 endmodule
 
+module CLKINT (
+       input A,
+       output Y
+);
+       assign Y = A;
+endmodule
+
 module CLKBUF (
        input PAD,
        output Y
index a85552575a3c8301c14b0098b42147777bc80994..dea8e353b5434ad03bd86c169155a59ffca9a32c 100644 (file)
 USING_YOSYS_NAMESPACE
 PRIVATE_NAMESPACE_BEGIN
 
+static void handle_iobufs(Module *module, bool clkbuf_mode)
+{
+       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 (clkbuf_mode && cell->type == "\\SLE") {
+                       for (auto bit : sigmap(cell->getPort("\\CLK")))
+                               clk_bits.insert(bit);
+               }
+               if (cell->type.in("\\INBUF", "\\OUTBUF", "\\TRIBUF", "\\BIBUF", "\\CLKBUF", "\\CLKBIBUF",
+                               "\\INBUF_DIFF", "\\OUTBUF_DIFF", "\\BIBUFF_DIFF", "\\TRIBUF_DIFF", "\\CLKBUF_DIFF",
+                               "\\GCLKBUF", "\\GCLKBUF_DIFF", "\\GCLKBIBUF")) {
+                       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 (clkbuf_mode && 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);
+}
+
+static void handle_clkint(Module *module)
+{
+       SigMap sigmap(module);
+
+       pool<SigBit> clk_bits;
+       vector<SigBit> handled_clk_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("\\CLKBUF", "\\CLKBIBUF", "\\CLKBUF_DIFF", "\\GCLKBUF", "\\GCLKBUF_DIFF", "\\GCLKBIBUF",
+                               "\\CLKINT", "\\CLKINT_PRESERVE", "\\GCLKINT", "\\RCLKINT", "\\RGCLKINT")) {
+                       for (auto bit : sigmap(cell->getPort("\\Y")))
+                               handled_clk_bits.push_back(bit);
+               }
+       }
+
+       for (auto bit : handled_clk_bits)
+               clk_bits.erase(bit);
+
+       for (auto cell : vector<Cell*>(module->cells()))
+       for (auto &conn : cell->connections())
+       {
+               if (!cell->output(conn.first))
+                       continue;
+
+               SigSpec sig = conn.second;
+               bool did_something = false;
+
+               for (auto &bit : sig) {
+                       SigBit canonical_bit = sigmap(bit);
+                       if (clk_bits.count(canonical_bit)) {
+                               Cell *c = module->addCell(NEW_ID, "\\CLKINT");
+                               SigBit new_bit = module->addWire(NEW_ID);
+                               c->setPort("\\A", new_bit);
+                               c->setPort("\\Y", bit);
+                               log("Added %s cell %s for clock signal %s.\n", log_id(c->type), log_id(c), log_signal(bit));
+                               clk_bits.erase(canonical_bit);
+                               did_something = true;
+                               bit = new_bit;
+                       }
+               }
+
+               if (did_something)
+                       cell->setPort(conn.first, sig);
+       }
+
+       for (auto bit : clk_bits)
+               log_error("Failed to insert CLKINT for clock signal %s.\n", log_signal(bit));
+}
+
 struct Sf2IobsPass : public Pass {
        Sf2IobsPass() : Pass("sf2_iobs", "SF2: insert IO buffers") { }
        void help() YS_OVERRIDE
@@ -31,23 +161,23 @@ struct Sf2IobsPass : public Pass {
                log("\n");
                log("    sf2_iobs [options] [selection]\n");
                log("\n");
-               log("Add SF2 I/O buffers to top module IOs as needed.\n");
+               log("Add SF2 I/O buffers and global buffers to top module as needed.\n");
                log("\n");
-               log("    -noclkbuf\n");
-               log("        Do not insert clock buffers\n");
+               log("    -clkbuf\n");
+               log("        Insert PAD->global_net clock buffers\n");
                log("\n");
        }
        void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
        {
-               bool noclkbuf_mode = false;
+               bool clkbuf_mode = false;
 
                log_header(design, "Executing sf2_iobs pass (insert IO buffers).\n");
 
                size_t argidx;
                for (argidx = 1; argidx < args.size(); argidx++)
                {
-                       if (args[argidx] == "-noclkbuf") {
-                               noclkbuf_mode = true;
+                       if (args[argidx] == "-clkbuf") {
+                               clkbuf_mode = true;
                                continue;
                        }
                        break;
@@ -59,76 +189,8 @@ struct Sf2IobsPass : public Pass {
                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) && !noclkbuf_mode) {
-                                       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);
+               handle_iobufs(module, clkbuf_mode);
+               handle_clkint(module);
        }
 } Sf2IobsPass;
 
index b834af07d7214f9f3b85785702b7f094db8ee907..0924df7a67780d78f1d96ec50319302a43df78c9 100644 (file)
@@ -63,8 +63,8 @@ struct SynthSf2Pass : public ScriptPass
                log("    -noiobs\n");
                log("        run synthesis in \"block mode\", i.e. do not insert IO buffers\n");
                log("\n");
-               log("    -noclkbuf\n");
-               log("        do not inser clock buffers, only simpe IO buffers\n");
+               log("    -clkbuf\n");
+               log("        insert direct PAD->global_net buffers\n");
                log("\n");
                log("    -retime\n");
                log("        run 'abc' with -dff option\n");
@@ -87,7 +87,7 @@ struct SynthSf2Pass : public ScriptPass
                flatten = true;
                retime = false;
                iobs = true;
-               clkbuf = true;
+               clkbuf = false;
        }
 
        void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@@ -134,8 +134,8 @@ struct SynthSf2Pass : public ScriptPass
                                iobs = false;
                                continue;
                        }
-                       if (args[argidx] == "-noclkbuf") {
-                               clkbuf = false;
+                       if (args[argidx] == "-clkbuf") {
+                               clkbuf = true;
                                continue;
                        }
                        break;
@@ -210,9 +210,9 @@ struct SynthSf2Pass : public ScriptPass
                if (check_label("map_iobs"))
                {
                        if (help_mode)
-                               run("sf2_iobs [-noclkbuf]", "(unless -noiobs)");
+                               run("sf2_iobs [-clkbuf]", "(unless -noiobs)");
                        else if (iobs)
-                               run(clkbuf ? "sf2_iobs" : "sf2_iobs -noclkbuf");
+                               run(clkbuf ? "sf2_iobs -clkbuf" : "sf2_iobs");
                        run("clean");
                }