ecp5: Add support for mapping PRLD FFs
authorDavid Shah <dave@ds0.me>
Sat, 7 Dec 2019 13:04:36 +0000 (13:04 +0000)
committerDavid Shah <dave@ds0.me>
Sat, 7 Dec 2019 13:04:36 +0000 (13:04 +0000)
Signed-off-by: David Shah <dave@ds0.me>
techlibs/ecp5/cells_map.v
techlibs/ecp5/synth_ecp5.cc

index 71ae9237be3bdb29595cef44f9a33bd7d4d74b0f..10e89a3e0c1a5aa425b65e4bdf9deac68a8704cc 100644 (file)
@@ -47,6 +47,21 @@ module  \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .
 module  \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE"))  _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
 module  \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE"))  _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
 
+`ifdef ASYNC_PRLD
+module  \$_DLATCH_N_ (input E, input D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))  _TECHMAP_REPLACE_ (.LSR(!E), .DI(1'b0), .M(D), .Q(Q)); endmodule
+module  \$_DLATCH_P_ (input E, input D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))  _TECHMAP_REPLACE_ (.LSR(E), .DI(1'b0), .M(D), .Q(Q)); endmodule
+
+module \$_DFFSR_NNN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))  _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || !R), .DI(D), .M(R), .Q(Q)); endmodule
+module \$_DFFSR_NNP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))  _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || R), .DI(D), .M(!R), .Q(Q)); endmodule
+module \$_DFFSR_NPN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))  _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || !R), .DI(D), .M(R), .Q(Q)); endmodule
+module \$_DFFSR_NPP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))  _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || R), .DI(D), .M(!R), .Q(Q)); endmodule
+
+module \$_DFFSR_PNN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))  _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || !R), .DI(D), .M(R), .Q(Q)); endmodule
+module \$_DFFSR_PNP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))  _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || R), .DI(D), .M(!R), .Q(Q)); endmodule
+module \$_DFFSR_PPN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))  _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || !R), .DI(D), .M(R), .Q(Q)); endmodule
+module \$_DFFSR_PPP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))  _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || R), .DI(D), .M(!R), .Q(Q)); endmodule
+`endif
+
 `include "cells_ff.vh"
 `include "cells_io.vh"
 
index 4cbb56ea16cf224772f129703e768782938f06b1..b71bb2395c82ffab565963f9ed6790fc1e352ae0 100644 (file)
@@ -79,6 +79,9 @@ struct SynthEcp5Pass : public ScriptPass
                log("    -nowidelut\n");
                log("        do not use PFU muxes to implement LUTs larger than LUT4s\n");
                log("\n");
+               log("    -asyncprld\n");
+               log("        use async PRLD mode to implement DLATCH and DFFSR (EXPERIMENTAL)\n");
+               log("\n");
                log("    -abc2\n");
                log("        run two passes of 'abc' for slightly improved logic density\n");
                log("\n");
@@ -99,7 +102,7 @@ struct SynthEcp5Pass : public ScriptPass
        }
 
        string top_opt, blif_file, edif_file, json_file;
-       bool noccu2, nodffe, nobram, nolutram, nowidelut, flatten, retime, abc2, abc9, nodsp, vpr;
+       bool noccu2, nodffe, nobram, nolutram, nowidelut, asyncprld, flatten, retime, abc2, abc9, nodsp, vpr;
 
        void clear_flags() YS_OVERRIDE
        {
@@ -112,6 +115,7 @@ struct SynthEcp5Pass : public ScriptPass
                nobram = false;
                nolutram = false;
                nowidelut = false;
+               asyncprld = false;
                flatten = true;
                retime = false;
                abc2 = false;
@@ -176,6 +180,10 @@ struct SynthEcp5Pass : public ScriptPass
                                nobram = true;
                                continue;
                        }
+                       if (args[argidx] == "-asyncprld") {
+                               asyncprld = true;
+                               continue;
+                       }
                        if (args[argidx] == "-nolutram" || /*deprecated alias*/ args[argidx] == "-nodram") {
                                nolutram = true;
                                continue;
@@ -292,7 +300,7 @@ struct SynthEcp5Pass : public ScriptPass
                        run("opt_clean");
                        if (!nodffe)
                                run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*");
-                       run("techmap -D NO_LUT -map +/ecp5/cells_map.v");
+                       run(stringf("techmap -D NO_LUT %s -map +/ecp5/cells_map.v", help_mode ? "[-D ASYNC_PRLD]" : (asyncprld ? "-D ASYNC_PRLD" : "")));
                        run("opt_expr -undriven -mux_undef");
                        run("simplemap");
                        run("ecp5_ffinit");
@@ -306,10 +314,11 @@ struct SynthEcp5Pass : public ScriptPass
                        if (abc2 || help_mode) {
                                run("abc", "      (only if -abc2)");
                        }
-                       std::string techmap_args = "-map +/ecp5/latches_map.v";
+                       std::string techmap_args = asyncprld ? "" : "-map +/ecp5/latches_map.v";
                        if (abc9)
                                techmap_args += " -map +/ecp5/abc9_map.v -max_iter 1";
-                       run("techmap " + techmap_args);
+                       if (!asyncprld || abc9)
+                               run("techmap " + techmap_args);
 
                        if (abc9) {
                                run("read_verilog -icells -lib +/ecp5/abc9_model.v");