Added ice40 bram support
authorClifford Wolf <clifford@clifford.at>
Thu, 23 Apr 2015 22:06:50 +0000 (00:06 +0200)
committerClifford Wolf <clifford@clifford.at>
Thu, 23 Apr 2015 22:06:50 +0000 (00:06 +0200)
techlibs/ice40/Makefile.inc
techlibs/ice40/brams.txt [new file with mode: 0644]
techlibs/ice40/brams_map.v [new file with mode: 0644]
techlibs/ice40/synth_ice40.cc

index cd178d66450f0dc20d936c7b701328bfd9a897db..14ef4e7dcee0dacef344e396e40567074b36aecf 100644 (file)
@@ -5,4 +5,6 @@ OBJS += techlibs/ice40/ice40_ffssr.o
 $(eval $(call add_share_file,share/ice40,techlibs/ice40/arith_map.v))
 $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_map.v))
 $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_sim.v))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams_map.v))
 
diff --git a/techlibs/ice40/brams.txt b/techlibs/ice40/brams.txt
new file mode 100644 (file)
index 0000000..5d23ad1
--- /dev/null
@@ -0,0 +1,40 @@
+bram $__ICE40_RAM4K_M0
+  init 0
+  abits 8
+  dbits 16
+  groups 2
+  ports  1  1
+  wrmode 0  1
+  enable 0 16
+  transp 0  0
+  clocks 2  3
+  clkpol 2  3
+endbram
+
+bram $__ICE40_RAM4K_M123
+  init 0
+  abits  9 @M1
+  dbits  8 @M1
+  abits 10 @M2
+  dbits  4 @M2
+  abits 11 @M3
+  dbits  2 @M3
+  groups 2
+  ports  1 1
+  wrmode 0 1
+  enable 0 1
+  transp 0 0
+  clocks 2 3
+  clkpol 2 3
+endbram
+
+match $__ICE40_RAM4K_M0
+  min efficiency 10
+  make_transp
+  or_next_if_better
+endmatch
+
+match $__ICE40_RAM4K_M123
+  min efficiency 10
+  make_transp
+endmatch
diff --git a/techlibs/ice40/brams_map.v b/techlibs/ice40/brams_map.v
new file mode 100644 (file)
index 0000000..9dbc81e
--- /dev/null
@@ -0,0 +1,99 @@
+
+module \$__ICE40_RAM4K_M0 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
+       parameter [0:0] CLKPOL2 = 1;
+       parameter [0:0] CLKPOL3 = 1;
+
+       input CLK2;
+       input CLK3;
+
+       input [7:0] A1ADDR;
+       output [15:0] A1DATA;
+
+       input [7:0] B1ADDR;
+       input [15:0] B1DATA;
+       input [15:0] B1EN;
+
+       wire [10:0] A1ADDR_11 = A1ADDR;
+       wire [10:0] B1ADDR_11 = B1ADDR;
+
+       generate
+               case ({CLKPOL2, CLKPOL3})
+                       2'b00:
+                               SB_RAM40_4KNRNW #(.WRITE_MODE(0), .READ_MODE(0)) _TECHMAP_REPLACE_ (
+                                       .RDATA(A1DATA), .RADDR(A1ADDR_11),               .RCLK(CLK2), .RCLKE(1'b1), .RE(1'b1),
+                                       .WDATA(B1DATA), .WADDR(B1ADDR_11), .WMASK(B1EN), .WCLK(CLK3), .WCLKE(1'b1), .WE(|B1EN)
+                               );
+                       2'b01:
+                               SB_RAM40_4KNR #(.WRITE_MODE(0), .READ_MODE(0)) _TECHMAP_REPLACE_ (
+                                       .RDATA(A1DATA), .RADDR(A1ADDR_11),               .RCLK(CLK2), .RCLKE(1'b1), .RE(1'b1),
+                                       .WDATA(B1DATA), .WADDR(B1ADDR_11), .WMASK(B1EN), .WCLK(CLK3), .WCLKE(1'b1), .WE(|B1EN)
+                               );
+                       2'b10:
+                               SB_RAM40_4KNW #(.WRITE_MODE(0), .READ_MODE(0)) _TECHMAP_REPLACE_ (
+                                       .RDATA(A1DATA), .RADDR(A1ADDR_11),               .RCLK(CLK2), .RCLKE(1'b1), .RE(1'b1),
+                                       .WDATA(B1DATA), .WADDR(B1ADDR_11), .WMASK(B1EN), .WCLK(CLK3), .WCLKE(1'b1), .WE(|B1EN)
+                               );
+                       2'b11:
+                               SB_RAM40_4K #(.WRITE_MODE(0), .READ_MODE(0)) _TECHMAP_REPLACE_ (
+                                       .RDATA(A1DATA), .RADDR(A1ADDR_11),               .RCLK(CLK2), .RCLKE(1'b1), .RE(1'b1),
+                                       .WDATA(B1DATA), .WADDR(B1ADDR_11), .WMASK(B1EN), .WCLK(CLK3), .WCLKE(1'b1), .WE(|B1EN)
+                               );
+               endcase
+       endgenerate
+endmodule
+
+module \$__ICE40_RAM4K_M123 (CLK2, CLK3, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
+       parameter CFG_ABITS = 9;
+       parameter CFG_DBITS = 8;
+
+       parameter [0:0] CLKPOL2 = 1;
+       parameter [0:0] CLKPOL3 = 1;
+
+       localparam MODE =
+               CFG_ABITS ==  9 ? 1 :
+               CFG_ABITS == 10 ? 2 :
+               CFG_ABITS == 11 ? 3 : 'bx;
+
+       input CLK2;
+       input CLK3;
+
+       input [CFG_ABITS-1:0] A1ADDR;
+       output [CFG_DBITS-1:0] A1DATA;
+
+       input [CFG_ABITS-1:0] B1ADDR;
+       input [CFG_DBITS-1:0] B1DATA;
+       input B1EN;
+
+       wire [10:0] A1ADDR_11 = A1ADDR;
+       wire [10:0] B1ADDR_11 = B1ADDR;
+
+       wire [15:0] A1DATA_16;
+       wire [15:0] B1DATA_16 = B1DATA;
+       assign A1DATA = A1DATA_16;
+
+       generate
+               case ({CLKPOL2, CLKPOL3})
+                       2'b00:
+                               SB_RAM40_4KNRNW #(.WRITE_MODE(MODE), .READ_MODE(MODE)) _TECHMAP_REPLACE_ (
+                                       .RDATA(A1DATA_16), .RADDR(A1ADDR_11), .RCLK(CLK2), .RCLKE(1'b1), .RE(1'b1),
+                                       .WDATA(B1DATA_16), .WADDR(B1ADDR_11), .WCLK(CLK3), .WCLKE(1'b1), .WE(B1EN)
+                               );
+                       2'b01:
+                               SB_RAM40_4KNR #(.WRITE_MODE(MODE), .READ_MODE(MODE)) _TECHMAP_REPLACE_ (
+                                       .RDATA(A1DATA_16), .RADDR(A1ADDR_11), .RCLK(CLK2), .RCLKE(1'b1), .RE(1'b1),
+                                       .WDATA(B1DATA_16), .WADDR(B1ADDR_11), .WCLK(CLK3), .WCLKE(1'b1), .WE(B1EN)
+                               );
+                       2'b10:
+                               SB_RAM40_4RNW #(.WRITE_MODE(MODE), .READ_MODE(MODE)) _TECHMAP_REPLACE_ (
+                                       .RDATA(A1DATA_16), .RADDR(A1ADDR_11), .RCLK(CLK2), .RCLKE(1'b1), .RE(1'b1),
+                                       .WDATA(B1DATA_16), .WADDR(B1ADDR_11), .WCLK(CLK3), .WCLKE(1'b1), .WE(B1EN)
+                               );
+                       2'b11:
+                               SB_RAM40_4K #(.WRITE_MODE(MODE), .READ_MODE(MODE)) _TECHMAP_REPLACE_ (
+                                       .RDATA(A1DATA_16), .RADDR(A1ADDR_11), .RCLK(CLK2), .RCLKE(1'b1), .RE(1'b1),
+                                       .WDATA(B1DATA_16), .WADDR(B1ADDR_11), .WCLK(CLK3), .WCLKE(1'b1), .WE(B1EN)
+                               );
+               endcase
+       endgenerate
+endmodule
+
index dff12f8a9fbda978dc8d8a3be83c823883b533ec..bb0e5d4ad0846828751622ec97e163c30f301618 100644 (file)
@@ -52,6 +52,18 @@ struct SynthIce40Pass : public Pass {
                log("        from label is synonymous to 'begin', and empty to label is\n");
                log("        synonymous to the end of the command list.\n");
                log("\n");
+               log("    -flatten\n");
+               log("        flatten design before synthesis\n");
+               log("\n");
+               log("    -retime\n");
+               log("        run 'abc' with -dff option\n");
+               log("\n");
+               log("    -nocarry\n");
+               log("        do not use SB_CARRY cells in output netlist\n");
+               log("\n");
+               log("    -nobram\n");
+               log("        do not use SB_RAM40_4K* cells in output netlist\n");
+               log("\n");
                log("\n");
                log("The following commands are executed by this synthesis command:\n");
                log("\n");
@@ -59,14 +71,23 @@ struct SynthIce40Pass : public Pass {
                log("        read_verilog -lib +/ice40/cells_sim.v\n");
                log("        hierarchy -check -top <top>\n");
                log("\n");
+               log("    flatten:         (only if -flatten)\n");
+               log("        proc\n");
+               log("        flatten\n");
+               log("\n");
                log("    coarse:\n");
                log("        synth -run coarse\n");
                log("\n");
+               log("    bram:            (skip if -nobram)\n");
+               log("        memory_bram -rules +/ice40/brams.txt\n");
+               log("        techmap -map +/ice40/brams_map.v\n");
+               log("\n");
                log("    fine:\n");
                log("        opt -fast -mux_undef -undriven -fine\n");
                log("        memory_map\n");
                log("        opt -undriven -fine\n");
-               log("        techmap -map +/techmap.v -map +/ice40/arith_map.v\n");
+               log("        techmap -map +/techmap.v [-map +/ice40/arith_map.v]\n");
+               log("        abc -dff     (only if -retime)\n");
                log("        opt -fast\n");
                log("\n");
                log("    map_ffs:\n");
@@ -96,6 +117,9 @@ struct SynthIce40Pass : public Pass {
                std::string top_opt = "-auto-top";
                std::string run_from, run_to;
                bool nocarry = false;
+               bool nobram = false;
+               bool flatten = false;
+               bool retime = false;
 
                size_t argidx;
                for (argidx = 1; argidx < args.size(); argidx++)
@@ -112,10 +136,22 @@ struct SynthIce40Pass : public Pass {
                                run_to = args[argidx].substr(pos+1);
                                continue;
                        }
+                       if (args[argidx] == "-flatten") {
+                               flatten = true;
+                               continue;
+                       }
+                       if (args[argidx] == "-retime") {
+                               retime = true;
+                               continue;
+                       }
                        if (args[argidx] == "-nocarry") {
                                nocarry = true;
                                continue;
                        }
+                       if (args[argidx] == "-nobram") {
+                               nobram = true;
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
@@ -134,11 +170,23 @@ struct SynthIce40Pass : public Pass {
                        Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str()));
                }
 
+               if (flatten && check_label(active, run_from, run_to, "flatten"))
+               {
+                       Pass::call(design, "proc");
+                       Pass::call(design, "flatten");
+               }
+
                if (check_label(active, run_from, run_to, "coarse"))
                {
                        Pass::call(design, "synth -run coarse");
                }
 
+               if (!nobram && check_label(active, run_from, run_to, "bram"))
+               {
+                       Pass::call(design, "memory_bram -rules +/ice40/brams.txt");
+                       Pass::call(design, "techmap -map +/ice40/brams_map.v");
+               }
+
                if (check_label(active, run_from, run_to, "fine"))
                {
                        Pass::call(design, "opt -fast -mux_undef -undriven -fine");
@@ -148,6 +196,8 @@ struct SynthIce40Pass : public Pass {
                                Pass::call(design, "techmap");
                        else
                                Pass::call(design, "techmap -map +/techmap.v -map +/ice40/arith_map.v");
+                       if (retime)
+                               Pass::call(design, "abc -dff");
                        Pass::call(design, "opt -fast");
                }