quicklogic: ABC9 synthesis
authorLofty <dan.ravensloft@gmail.com>
Mon, 12 Apr 2021 09:33:40 +0000 (10:33 +0100)
committerMarcelina Koƛcielnicka <mwk@0x04.net>
Sat, 17 Apr 2021 18:54:58 +0000 (20:54 +0200)
12 files changed:
techlibs/quicklogic/Makefile.inc
techlibs/quicklogic/abc9_map.v [new file with mode: 0644]
techlibs/quicklogic/abc9_model.v [new file with mode: 0644]
techlibs/quicklogic/abc9_unmap.v [new file with mode: 0644]
techlibs/quicklogic/pp3_cells_sim.v
techlibs/quicklogic/synth_quicklogic.cc
tests/arch/quicklogic/add_sub.ys
tests/arch/quicklogic/counter.ys
tests/arch/quicklogic/fsm.ys
tests/arch/quicklogic/latches.ys
tests/arch/quicklogic/logic.ys
tests/arch/quicklogic/mux.ys

index 9a07c2eed209613a3666bd7cd0e71ea3e534862b..51eb28d44bd0896492562021f072c57ae87db60b 100644 (file)
@@ -7,3 +7,7 @@ $(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/pp3_cells_map.
 $(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/cells_sim.v))
 $(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/lut_sim.v))
 $(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/pp3_cells_sim.v))
+
+$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/abc9_model.v))
+$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/abc9_map.v))
+$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/abc9_unmap.v))
diff --git a/techlibs/quicklogic/abc9_map.v b/techlibs/quicklogic/abc9_map.v
new file mode 100644 (file)
index 0000000..46c11d6
--- /dev/null
@@ -0,0 +1,26 @@
+// This file exists to map purely-synchronous flops to ABC9 flops, while 
+// mapping flops with asynchronous-set/clear as boxes, this is because ABC9 
+// doesn't support asynchronous-set/clear flops in sequential synthesis.
+
+module dffepc (
+  output Q,
+  input D,
+  input CLK,
+  input EN,
+  input CLR,
+  input PRE
+);
+
+parameter INIT = 1'b0;
+
+parameter _TECHMAP_CONSTMSK_CLR_ = 1'b0;
+parameter _TECHMAP_CONSTMSK_PRE_ = 1'b0;
+parameter _TECHMAP_CONSTVAL_CLR_ = 1'b0;
+parameter _TECHMAP_CONSTVAL_PRE_ = 1'b0;
+
+if (_TECHMAP_CONSTMSK_CLR_ != 1'b0 && _TECHMAP_CONSTMSK_PRE_ != 1'b0 && _TECHMAP_CONSTVAL_CLR_ == 1'b0 && _TECHMAP_CONSTVAL_PRE_ == 1'b0)
+    $__PP3_DFFEPC_SYNCONLY _TECHMAP_REPLACE_ (.Q(Q), .D(D), .CLK(CLK), .EN(EN));
+else
+    wire _TECHMAP_FAIL_ = 1;
+
+endmodule
diff --git a/techlibs/quicklogic/abc9_model.v b/techlibs/quicklogic/abc9_model.v
new file mode 100644 (file)
index 0000000..06d4a2a
--- /dev/null
@@ -0,0 +1,11 @@
+(* abc9_flop, lib_whitebox *)
+module $__PP3_DFFEPC_SYNCONLY (
+  output Q,
+  input D,
+  input CLK,
+  input EN,
+);
+
+  dffepc ff (.Q(Q), .D(D), .CLK(CLK), .EN(EN), .PRE(1'b0), .CLR(1'b0));
+
+endmodule
diff --git a/techlibs/quicklogic/abc9_unmap.v b/techlibs/quicklogic/abc9_unmap.v
new file mode 100644 (file)
index 0000000..1681e01
--- /dev/null
@@ -0,0 +1,14 @@
+module $__PP3_DFFEPC_SYNCONLY (
+  output Q,
+  input D,
+  input CLK,
+  input EN,
+);
+
+// For some reason ABC9 adds init attributes to wires even though they were removed before mapping.
+// As a workaround, remove any init attributes that get reintroduced.
+wire _TECHMAP_REMOVEINIT_Q_ = 1;
+
+dffepc _TECHMAP_REPLACE_ (.Q(Q), .D(D), .CLK(CLK), .EN(EN), .PRE(1'b0), .CLR(1'b0));
+
+endmodule
index 61d1ee314f847b50e5799d1891fffce83b7cd6c9..5820d7a9ec0094597b81d5f60b41f54acf9300d2 100644 (file)
@@ -147,11 +147,10 @@ module dffepc (
 );
   parameter [0:0] INIT = 1'b0;
 
-  // The CLR => Q and PRE => Q paths are commented out due to YosysHQ/yosys#2530.
   specify
     if (EN) (posedge CLK => (Q : D)) = 1701; // QCK -> QZ
-    // if (CLR) (CLR => Q) = 967; // QRT -> QZ
-    // if (PRE) (PRE => Q) = 1252; // QST -> QZ
+    if (CLR) (CLR => Q) = 967; // QRT -> QZ
+    if (PRE) (PRE => Q) = 1252; // QST -> QZ
     $setup(D, posedge CLK, 216); // QCK -> QDS
     $setup(EN, posedge CLK, 590); // QCK -> QEN
   endspecify
index 90eb0f78b871708f625b75c6c3dec186df150694..a67b167b843c1e7913a64c3e80e55b660b0305d0 100644 (file)
@@ -51,12 +51,17 @@ struct SynthQuickLogicPass : public ScriptPass {
                log("        write the design to the specified verilog file. writing of an output file\n");
                log("        is omitted if this parameter is not specified.\n");
                log("\n");
+               log("    -abc\n");
+               log("        use old ABC flow, which has generally worse mapping results but is less\n");
+               log("        likely to have bugs.\n");
+               log("\n");
                log("The following commands are executed by this synthesis command:\n");
                help_script();
                log("\n");
        }
 
        string top_opt, blif_file, family, currmodule, verilog_file;
+       bool abc9;
 
        void clear_flags() override
        {
@@ -65,6 +70,7 @@ struct SynthQuickLogicPass : public ScriptPass {
                verilog_file = "";
                currmodule = "";
                family = "pp3";
+               abc9 = true;
        }
 
        void execute(std::vector<std::string> args, RTLIL::Design *design) override
@@ -91,6 +97,10 @@ struct SynthQuickLogicPass : public ScriptPass {
                                verilog_file = args[++argidx];
                                continue;
                        }
+                       if (args[argidx] == "-abc") {
+                               abc9 = false;
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
@@ -101,6 +111,11 @@ struct SynthQuickLogicPass : public ScriptPass {
                if (family != "pp3")
                        log_cmd_error("Invalid family specified: '%s'\n", family.c_str());
 
+               if (abc9 && design->scratchpad_get_int("abc9.D", 0) == 0) {
+                       log_warning("delay target has not been set via SDC or scratchpad; assuming 12 MHz clock.\n");
+                       design->scratchpad_set_int("abc9.D", 41667); // 12MHz = 83.33.. ns; divided by two to allow for interconnect delay.
+               }
+
                log_header(design, "Executing SYNTH_QUICKLOGIC pass.\n");
                log_push();
 
@@ -167,8 +182,14 @@ struct SynthQuickLogicPass : public ScriptPass {
 
                if (check_label("map_luts")) {
                        run(stringf("techmap -map +/quicklogic/%s_latches_map.v", family.c_str()));
-                       run("abc -luts 1,2,2,4 -dress");
-
+                       if (abc9) {
+                               run("read_verilog -lib -specify -icells +/quicklogic/abc9_model.v");
+                               run("techmap -map +/quicklogic/abc9_map.v");
+                               run("abc9 -maxlut 4 -dff");
+                               run("techmap -map +/quicklogic/abc9_unmap.v");
+                       } else {
+                               run("abc -luts 1,2,2,4 -dress");
+                       }
                        run("clean");
                }
 
index 168b3f8b33f0f87f8235c10242ed0fda2c0f6d43..73ee5cb44133eae312fd35de80b4fc7970cdc679 100644 (file)
@@ -3,9 +3,9 @@ hierarchy -top top
 equiv_opt -assert -map +/quicklogic/lut_sim.v -map +/quicklogic/pp3_cells_sim.v synth_quicklogic -family pp3 # equivalency check
 design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
 cd top # Constrain all select calls below inside the top module
-select -assert-count 3 t:LUT2
-select -assert-count 4 t:LUT3
-select -assert-count 4 t:LUT4
+select -assert-count 2 t:LUT2
+select -assert-count 8 t:LUT3
+select -assert-count 2 t:LUT4
 select -assert-count 8 t:inpad
 select -assert-count 8 t:outpad
 select -assert-none t:LUT2 t:LUT3 t:LUT4 t:inpad t:outpad %% t:* %D
index 0c04b5742ede0853f0f5f0b73f49c4ba27c2e661..2e266417caf33713a8c4d96e3e2f9ede8ee53c21 100644 (file)
@@ -6,9 +6,9 @@ equiv_opt -assert -multiclock -map +/quicklogic/pp3_cells_sim.v -map +/quicklogi
 design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
 cd top # Constrain all select calls below inside the top module
 select -assert-count 1 t:LUT1
-select -assert-count 5 t:LUT2
-select -assert-count 2 t:LUT3
-select -assert-count 3 t:LUT4
+select -assert-count 3 t:LUT2
+select -assert-count 5 t:LUT3
+select -assert-count 1 t:LUT4
 select -assert-count 8 t:dffepc
 select -assert-count 1 t:logic_0
 select -assert-count 1 t:logic_1
index 7ed36b9e4cdaba9b438d17e69ca6a104442ef570..130dacf42a9b8439818ca10d686abb7f3006f9e5 100644 (file)
@@ -11,14 +11,13 @@ sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip
 design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
 cd fsm # Constrain all select calls below inside the top module
 
-select -assert-count 3 t:LUT2
-select -assert-count 6 t:LUT3
-select -assert-count 7 t:LUT4
-select -assert-count 6 t:dffepc
+select -assert-count 1 t:LUT2
+select -assert-count 9 t:LUT3
+select -assert-count 4 t:dffepc
 select -assert-count 1 t:logic_0
 select -assert-count 1 t:logic_1
 select -assert-count 3 t:inpad
 select -assert-count 2 t:outpad
 select -assert-count 1 t:ckpad
 
-select -assert-none t:LUT2 t:LUT3 t:LUT4 t:dffepc t:logic_0 t:logic_1 t:inpad t:outpad t:ckpad %% t:* %D
+select -assert-none t:LUT2 t:LUT3 t:dffepc t:logic_0 t:logic_1 t:inpad t:outpad t:ckpad %% t:* %D
index d7652f749ad5c001c8b5592ddee7375099422390..bcef429904bfab36236b0f616236d8aa92e6355a 100644 (file)
@@ -32,8 +32,9 @@ proc
 # Can't run any sort of equivalence check because latches are blown to LUTs
 synth_quicklogic
 cd latchsr # Constrain all select calls below inside the top module
-select -assert-count 2 t:LUT3
+select -assert-count 1 t:LUT2
+select -assert-count 1 t:LUT4
 select -assert-count 5 t:inpad
 select -assert-count 1 t:outpad
 
-select -assert-none t:LUT3 t:inpad t:outpad %% t:* %D
+select -assert-none t:LUT2 t:LUT4 t:inpad t:outpad %% t:* %D
index 65f48a42b618bf1917205f6fa632b72a41e8eeb8..4b327c00af73207c54656e762e2dbe0529c43c8c 100644 (file)
@@ -7,8 +7,8 @@ cd top # Constrain all select calls below inside the top module
 
 select -assert-count 1 t:LUT1
 select -assert-count 6 t:LUT2
-select -assert-count 2 t:LUT4
+select -assert-count 2 t:LUT3
 select -assert-count 8 t:inpad
 select -assert-count 10 t:outpad
 
-select -assert-none t:LUT1 t:LUT2 t:LUT4 t:inpad t:outpad %% t:* %D
+select -assert-none t:LUT1 t:LUT2 t:LUT3 t:inpad t:outpad %% t:* %D
index 632d1468759f50b6f388cb5258d944c9f175ef67..ea17fa99b3d740badffc8d50c782b05ed09cb769 100644 (file)
@@ -30,13 +30,13 @@ proc
 equiv_opt -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check
 design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
 cd mux8 # Constrain all select calls below inside the top module
-select -assert-count 4 t:LUT2
+select -assert-count 1 t:LUT1
 select -assert-count 1 t:LUT3
 select -assert-count 2 t:mux4x0
 select -assert-count 11 t:inpad
 select -assert-count 1 t:outpad
 
-select -assert-none t:LUT2 t:LUT3 t:mux4x0 t:inpad t:outpad %% t:* %D
+select -assert-none t:LUT1 t:LUT3 t:mux4x0 t:inpad t:outpad %% t:* %D
 
 design -load read
 hierarchy -top mux16