Add ice40_wrapcarry pass, rename $__ICE40_FULL_ADDER -> CARRY_WRAPPER
authorEddie Hung <eddie@fpgeh.com>
Wed, 7 Aug 2019 23:27:24 +0000 (16:27 -0700)
committerEddie Hung <eddie@fpgeh.com>
Wed, 7 Aug 2019 23:29:38 +0000 (16:29 -0700)
passes/pmgen/Makefile.inc
passes/pmgen/ice40_wrapcarry.cc [new file with mode: 0644]
passes/pmgen/ice40_wrapcarry.pmg [new file with mode: 0644]
techlibs/ice40/arith_map.v
techlibs/ice40/cells_map.v
techlibs/ice40/synth_ice40.cc

index 7911132db44d6c5f94d7b105a9b1740b2623c61f..c036061524af565c4a0873a396984951662f933e 100644 (file)
@@ -1,4 +1,5 @@
 OBJS += passes/pmgen/ice40_dsp.o
+OBJS += passes/pmgen/ice40_wrapcarry.o
 OBJS += passes/pmgen/peepopt.o
 
 # --------------------------------------
@@ -12,6 +13,15 @@ passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg
 
 # --------------------------------------
 
+passes/pmgen/ice40_wrapcarry.o: passes/pmgen/ice40_wrapcarry_pm.h
+EXTRA_OBJS += passes/pmgen/ice40_wrapcarry_pm.h
+.SECONDARY: passes/pmgen/ice40_wrapcarry_pm.h
+
+passes/pmgen/ice40_wrapcarry_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_wrapcarry.pmg
+       $(P) mkdir -p passes/pmgen && python3 $< -o $@ -p ice40_wrapcarry $(filter-out $<,$^)
+
+# --------------------------------------
+
 passes/pmgen/peepopt.o: passes/pmgen/peepopt_pm.h
 EXTRA_OBJS += passes/pmgen/peepopt_pm.h
 .SECONDARY: passes/pmgen/peepopt_pm.h
diff --git a/passes/pmgen/ice40_wrapcarry.cc b/passes/pmgen/ice40_wrapcarry.cc
new file mode 100644 (file)
index 0000000..69ef3cd
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *  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
+
+#include "passes/pmgen/ice40_wrapcarry_pm.h"
+
+void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm)
+{
+       auto &st = pm.st_ice40_wrapcarry;
+
+#if 0
+       log("\n");
+       log("carry: %s\n", log_id(st.carry, "--"));
+       log("lut:   %s\n", log_id(st.lut, "--"));
+#endif
+
+       log("  replacing SB_LUT + SB_CARRY with $__ICE40_CARRY_WRAPPER cell.\n");
+
+       Cell *cell = pm.module->addCell(NEW_ID, "$__ICE40_CARRY_WRAPPER");
+       pm.module->swap_names(cell, st.carry);
+
+       cell->setPort("\\A", st.carry->getPort("\\I0"));
+       cell->setPort("\\B", st.carry->getPort("\\I1"));
+       cell->setPort("\\CI", st.carry->getPort("\\CI"));
+       cell->setPort("\\CO", st.carry->getPort("\\CO"));
+
+       cell->setPort("\\I0", st.lut->getPort("\\I0"));
+       cell->setPort("\\I3", st.lut->getPort("\\I3"));
+       cell->setPort("\\O", st.lut->getPort("\\O"));
+       cell->setParam("\\LUT", st.lut->getParam("\\LUT_INIT"));
+
+       pm.autoremove(st.carry);
+       pm.autoremove(st.lut);
+}
+
+struct Ice40WrapCarryPass : public Pass {
+       Ice40WrapCarryPass() : Pass("ice40_wrapcarry", "iCE40: wrap carries") { }
+       void help() YS_OVERRIDE
+       {
+               //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+               log("\n");
+               log("    ice40_wrapcarry [selection]\n");
+               log("\n");
+               log("Wrap manually instantiated SB_CARRY cells, along with their associated SB_LUTs,\n");
+               log("into an internal $__ICE40_CARRY_WRAPPER cell for preservation across technology\n");
+               log("mapping.");
+               log("\n");
+       }
+       void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+       {
+               log_header(design, "Executing ICE40_WRAPCARRY pass (wrap carries).\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);
+
+               for (auto module : design->selected_modules())
+                       ice40_wrapcarry_pm(module, module->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry);
+       }
+} Ice40WrapCarryPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/pmgen/ice40_wrapcarry.pmg b/passes/pmgen/ice40_wrapcarry.pmg
new file mode 100644 (file)
index 0000000..9e64c74
--- /dev/null
@@ -0,0 +1,11 @@
+pattern ice40_wrapcarry
+
+match carry
+       select carry->type.in(\SB_CARRY)
+endmatch
+
+match lut
+       select lut->type.in(\SB_LUT4)
+       index <SigSpec> port(lut, \I1) === port(carry, \I0)
+       index <SigSpec> port(lut, \I2) === port(carry, \I1)
+endmatch
index 65f28c585e126bac8c38a6c5660391e090a874ee..26b24db9e3c62e7624646a8b44ec76f6f14b1743 100644 (file)
@@ -44,10 +44,18 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO);
 
        genvar i;
        generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
-               \$__ICE40_FULL_ADDER carry (
+               \$__ICE40_CARRY_WRAPPER #(
+                       //    A[0]: 1010 1010 1010 1010
+                       //    A[1]: 1100 1100 1100 1100
+                       //    A[2]: 1111 0000 1111 0000
+                       //    A[3]: 1111 1111 0000 0000
+                       .LUT(16'b 0110_1001_1001_0110)
+               ) fadd (
                        .A(AA[i]),
                        .B(BB[i]),
                        .CI(C[i]),
+                       .I0(1'b0),
+                       .I3(C[i]),
                        .CO(CO[i]),
                        .O(Y[i])
                );
index 511b7f6c6d62461fc62bd5f4820a5b91d6756fc0..0c10c9ac4cf6a1e12b3d49e7e4818b5f9152067e 100644 (file)
@@ -63,7 +63,8 @@ endmodule
 `endif
 
 `ifndef NO_ADDER
-module \$__ICE40_FULL_ADDER (output CO, O, input A, B, CI);
+module \$__ICE40_CARRY_WRAPPER (output CO, O, input A, B, CI, I0, I3);
+  parameter LUT = 0;
   SB_CARRY carry (
     .I0(A),
     .I1(B),
@@ -72,13 +73,9 @@ module \$__ICE40_FULL_ADDER (output CO, O, input A, B, CI);
   );
   \$lut #(
     .WIDTH(4),
-    //    A[0]: 1010 1010 1010 1010
-    //    A[1]: 1100 1100 1100 1100
-    //    A[2]: 1111 0000 1111 0000
-    //    A[3]: 1111 1111 0000 0000
-    .LUT(16'b 0110_1001_1001_0110)
-  ) adder (
-    .A({CI,B,A,1'b0}),
+    .LUT(LUT)
+  ) lut (
+    .A({I3,B,A,I0}),
     .Y(O)
   );
 endmodule
index 93d5dcbd418eed35a914b5eaa964e6cf7412d6ac..8f4a0f3770c046f6c885b522ed2d3ec14fde2304 100644 (file)
@@ -293,8 +293,10 @@ struct SynthIce40Pass : public ScriptPass
                {
                        if (nocarry)
                                run("techmap");
-                       else
+                       else {
+                               run("ice40_wrapcarry");
                                run("techmap -map +/techmap.v -map +/ice40/arith_map.v");
+                       }
                        if (retime || help_mode)
                                run(abc + " -dff", "(only if -retime)");
                        run("ice40_opt");