From dce037a62c5bda9a8256d271d39b06be366120e8 Mon Sep 17 00:00:00 2001 From: Lofty Date: Mon, 12 Apr 2021 10:33:40 +0100 Subject: [PATCH] quicklogic: ABC9 synthesis --- techlibs/quicklogic/Makefile.inc | 4 ++++ techlibs/quicklogic/abc9_map.v | 26 +++++++++++++++++++++++++ techlibs/quicklogic/abc9_model.v | 11 +++++++++++ techlibs/quicklogic/abc9_unmap.v | 14 +++++++++++++ techlibs/quicklogic/pp3_cells_sim.v | 5 ++--- techlibs/quicklogic/synth_quicklogic.cc | 25 ++++++++++++++++++++++-- tests/arch/quicklogic/add_sub.ys | 6 +++--- tests/arch/quicklogic/counter.ys | 6 +++--- tests/arch/quicklogic/fsm.ys | 9 ++++----- tests/arch/quicklogic/latches.ys | 5 +++-- tests/arch/quicklogic/logic.ys | 4 ++-- tests/arch/quicklogic/mux.ys | 4 ++-- 12 files changed, 97 insertions(+), 22 deletions(-) create mode 100644 techlibs/quicklogic/abc9_map.v create mode 100644 techlibs/quicklogic/abc9_model.v create mode 100644 techlibs/quicklogic/abc9_unmap.v diff --git a/techlibs/quicklogic/Makefile.inc b/techlibs/quicklogic/Makefile.inc index 9a07c2eed..51eb28d44 100644 --- a/techlibs/quicklogic/Makefile.inc +++ b/techlibs/quicklogic/Makefile.inc @@ -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 index 000000000..46c11d675 --- /dev/null +++ b/techlibs/quicklogic/abc9_map.v @@ -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 index 000000000..06d4a2a56 --- /dev/null +++ b/techlibs/quicklogic/abc9_model.v @@ -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 index 000000000..1681e01bb --- /dev/null +++ b/techlibs/quicklogic/abc9_unmap.v @@ -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 diff --git a/techlibs/quicklogic/pp3_cells_sim.v b/techlibs/quicklogic/pp3_cells_sim.v index 61d1ee314..5820d7a9e 100644 --- a/techlibs/quicklogic/pp3_cells_sim.v +++ b/techlibs/quicklogic/pp3_cells_sim.v @@ -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 diff --git a/techlibs/quicklogic/synth_quicklogic.cc b/techlibs/quicklogic/synth_quicklogic.cc index 90eb0f78b..a67b167b8 100644 --- a/techlibs/quicklogic/synth_quicklogic.cc +++ b/techlibs/quicklogic/synth_quicklogic.cc @@ -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 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"); } diff --git a/tests/arch/quicklogic/add_sub.ys b/tests/arch/quicklogic/add_sub.ys index 168b3f8b3..73ee5cb44 100644 --- a/tests/arch/quicklogic/add_sub.ys +++ b/tests/arch/quicklogic/add_sub.ys @@ -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 diff --git a/tests/arch/quicklogic/counter.ys b/tests/arch/quicklogic/counter.ys index 0c04b5742..2e266417c 100644 --- a/tests/arch/quicklogic/counter.ys +++ b/tests/arch/quicklogic/counter.ys @@ -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 diff --git a/tests/arch/quicklogic/fsm.ys b/tests/arch/quicklogic/fsm.ys index 7ed36b9e4..130dacf42 100644 --- a/tests/arch/quicklogic/fsm.ys +++ b/tests/arch/quicklogic/fsm.ys @@ -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 diff --git a/tests/arch/quicklogic/latches.ys b/tests/arch/quicklogic/latches.ys index d7652f749..bcef42990 100644 --- a/tests/arch/quicklogic/latches.ys +++ b/tests/arch/quicklogic/latches.ys @@ -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 diff --git a/tests/arch/quicklogic/logic.ys b/tests/arch/quicklogic/logic.ys index 65f48a42b..4b327c00a 100644 --- a/tests/arch/quicklogic/logic.ys +++ b/tests/arch/quicklogic/logic.ys @@ -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 diff --git a/tests/arch/quicklogic/mux.ys b/tests/arch/quicklogic/mux.ys index 632d14687..ea17fa99b 100644 --- a/tests/arch/quicklogic/mux.ys +++ b/tests/arch/quicklogic/mux.ys @@ -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 -- 2.30.2