--- /dev/null
+
+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
+
 
                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");
                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");
                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++)
                                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);
                        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");
                                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");
                }