synth_quicklogic: add -dspv2 to opt into v2 DSP blocks

This commit is contained in:
Emil J. Tywoniak 2025-02-25 11:29:45 +01:00
parent fa8fc08621
commit 23924902a7
10 changed files with 4680 additions and 24 deletions

View File

@ -38,9 +38,11 @@ $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf
$(eval $(call add_gen_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/bram_types_sim.v)) $(eval $(call add_gen_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/bram_types_sim.v))
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/cells_sim.v)) $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/cells_sim.v))
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/ffs_map.v)) $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/ffs_map.v))
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dsp_sim.v)) $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dspv1_sim.v))
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dsp_map.v)) $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dspv1_map.v))
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dsp_final_map.v)) $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dspv1_final_map.v))
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dspv2_sim.v))
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dspv2_map.v))
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/TDP18K_FIFO.v)) $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/TDP18K_FIFO.v))
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/ufifo_ctl.v)) $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/ufifo_ctl.v))
$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/sram1024x18_mem.v)) $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/sram1024x18_mem.v))

View File

@ -0,0 +1,102 @@
// Copyright 2020-2022 F4PGA Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
module \$__QL_MUL20X18 (input [19:0] A, input [17:0] B, output [37:0] Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 0;
parameter B_WIDTH = 0;
parameter Y_WIDTH = 0;
wire [19:0] a;
wire [17:0] b;
wire [37:0] z;
assign a = (A_WIDTH == 20) ? A :
(A_SIGNED) ? {{(20 - A_WIDTH){A[A_WIDTH-1]}}, A} :
{{(20 - A_WIDTH){1'b0}}, A};
assign b = (B_WIDTH == 18) ? B :
(B_SIGNED) ? {{(18 - B_WIDTH){B[B_WIDTH-1]}}, B} :
{{(18 - B_WIDTH){1'b0}}, B};
(* is_inferred=1 *)
dsp_t1_20x18x64_cfg_ports _TECHMAP_REPLACE_ (
.a_i (a),
.b_i (b),
.acc_fir_i (6'd0),
.z_o (z),
.feedback_i (3'd0),
.load_acc_i (1'b0),
.unsigned_a_i (!A_SIGNED),
.unsigned_b_i (!B_SIGNED),
.output_select_i (3'd0),
.saturate_enable_i (1'b0),
.shift_right_i (6'd0),
.round_i (1'b0),
.subtract_i (1'b0),
.register_inputs_i (1'b0)
);
assign Y = z;
endmodule
module \$__QL_MUL10X9 (input [9:0] A, input [8:0] B, output [18:0] Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 0;
parameter B_WIDTH = 0;
parameter Y_WIDTH = 0;
wire [ 9:0] a;
wire [ 8:0] b;
wire [18:0] z;
assign a = (A_WIDTH == 10) ? A :
(A_SIGNED) ? {{(10 - A_WIDTH){A[A_WIDTH-1]}}, A} :
{{(10 - A_WIDTH){1'b0}}, A};
assign b = (B_WIDTH == 9) ? B :
(B_SIGNED) ? {{( 9 - B_WIDTH){B[B_WIDTH-1]}}, B} :
{{( 9 - B_WIDTH){1'b0}}, B};
(* is_inferred=1 *)
dsp_t1_10x9x32_cfg_ports _TECHMAP_REPLACE_ (
.a_i (a),
.b_i (b),
.acc_fir_i (6'd0),
.z_o (z),
.feedback_i (3'd0),
.load_acc_i (1'b0),
.unsigned_a_i (!A_SIGNED),
.unsigned_b_i (!B_SIGNED),
.output_select_i (3'd0),
.saturate_enable_i (1'b0),
.shift_right_i (6'd0),
.round_i (1'b0),
.subtract_i (1'b0),
.register_inputs_i (1'b0)
);
assign Y = z;
endmodule

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,12 @@ PRIVATE_NAMESPACE_BEGIN
struct SynthQuickLogicPass : public ScriptPass { struct SynthQuickLogicPass : public ScriptPass {
enum DSPKind {
None,
V1,
V2,
};
SynthQuickLogicPass() : ScriptPass("synth_quicklogic", "Synthesis for QuickLogic FPGAs") {} SynthQuickLogicPass() : ScriptPass("synth_quicklogic", "Synthesis for QuickLogic FPGAs") {}
void help() override void help() override
@ -50,6 +56,10 @@ struct SynthQuickLogicPass : public ScriptPass {
log(" do not use dsp_t1_* to implement multipliers and associated logic\n"); log(" do not use dsp_t1_* to implement multipliers and associated logic\n");
log(" (qlf_k6n10f only).\n"); log(" (qlf_k6n10f only).\n");
log("\n"); log("\n");
log(" -dspv2\n");
log(" synthesize for the v2 DSP block model instead of v1\n");
log(" (qlf_k6n10f only).\n");
log("\n");
log(" -nocarry\n"); log(" -nocarry\n");
log(" do not use adder_carry cells in output netlist.\n"); log(" do not use adder_carry cells in output netlist.\n");
log("\n"); log("\n");
@ -78,7 +88,8 @@ struct SynthQuickLogicPass : public ScriptPass {
} }
string top_opt, blif_file, edif_file, family, currmodule, verilog_file, lib_path; string top_opt, blif_file, edif_file, family, currmodule, verilog_file, lib_path;
bool abc9, inferAdder, nobram, bramTypes, dsp; bool abc9, inferAdder, nobram, bramTypes;
DSPKind dsp;
void clear_flags() override void clear_flags() override
{ {
@ -93,7 +104,7 @@ struct SynthQuickLogicPass : public ScriptPass {
nobram = false; nobram = false;
bramTypes = false; bramTypes = false;
lib_path = "+/quicklogic/"; lib_path = "+/quicklogic/";
dsp = true; dsp = V1;
} }
void set_scratchpad_defaults(RTLIL::Design *design) { void set_scratchpad_defaults(RTLIL::Design *design) {
@ -155,7 +166,11 @@ struct SynthQuickLogicPass : public ScriptPass {
continue; continue;
} }
if (args[argidx] == "-nodsp" || args[argidx] == "-no_dsp") { if (args[argidx] == "-nodsp" || args[argidx] == "-no_dsp") {
dsp = false; dsp = None;
continue;
}
if (args[argidx] == "-dspv2") {
dsp = V2;
continue; continue;
} }
break; break;
@ -193,8 +208,10 @@ struct SynthQuickLogicPass : public ScriptPass {
read_simlibs += stringf(" %sqlf_k6n10f/brams_sim.v", lib_path.c_str()); read_simlibs += stringf(" %sqlf_k6n10f/brams_sim.v", lib_path.c_str());
if (bramTypes) if (bramTypes)
read_simlibs += stringf(" %sqlf_k6n10f/bram_types_sim.v", lib_path.c_str()); read_simlibs += stringf(" %sqlf_k6n10f/bram_types_sim.v", lib_path.c_str());
if (dsp) if (dsp == V1)
read_simlibs += stringf(" %sqlf_k6n10f/dsp_sim.v", lib_path.c_str()); read_simlibs += stringf(" %sqlf_k6n10f/dspv1_sim.v", lib_path.c_str());
else if (dsp == V2)
read_simlibs += stringf(" %sqlf_k6n10f/dspv2_sim.v", lib_path.c_str());
} }
run(read_simlibs); run(read_simlibs);
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str())); run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
@ -220,23 +237,31 @@ struct SynthQuickLogicPass : public ScriptPass {
} }
if (check_label("map_dsp", "(for qlf_k6n10f, skip if -nodsp)") if (check_label("map_dsp", "(for qlf_k6n10f, skip if -nodsp)")
&& ((dsp && family == "qlf_k6n10f") || help_mode)) { && (((dsp != None) && family == "qlf_k6n10f") || help_mode)) {
run("wreduce t:$mul"); run("wreduce t:$mul");
//run("ql_dsp_macc");
if (dsp == V1) {
run("ql_dsp_macc");
run("techmap -map +/mul2dsp.v -map " + lib_path + family + "/dsp_map.v -D USE_DSP_CFG_PARAMS=0 -D DSP_SIGNEDONLY " run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=20 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=11 -D DSP_B_MINWIDTH=10 -D DSP_NAME=$__QL_MUL20X18");
run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=10 -D DSP_B_MAXWIDTH=9 -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=4 -D DSP_NAME=$__QL_MUL10X9");
run("chtype -set $mul t:$__soft_mul");
run("techmap -map " + lib_path + family + "/dspv1_map.v -D USE_DSP_CFG_PARAMS=0");
run("ql_dsp_simd");
run("techmap -map " + lib_path + family + "/dspv1_final_map.v");
run("ql_dsp_io_regs");
} else if (dsp == V2) {
run("techmap -map +/mul2dsp.v -map " + lib_path + family + "/dspv2_map.v -D USE_DSP_CFG_PARAMS=0 -D DSP_SIGNEDONLY "
"-D DSP_A_MAXWIDTH=32 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=10 -D DSP_B_MINWIDTH=10 -D DSP_NAME=$__MUL32X18"); "-D DSP_A_MAXWIDTH=32 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=10 -D DSP_B_MINWIDTH=10 -D DSP_NAME=$__MUL32X18");
run("chtype -set $mul t:$__soft_mul"); run("chtype -set $mul t:$__soft_mul");
run("techmap -map +/mul2dsp.v -map " + lib_path + family + "/dsp_map.v -D USE_DSP_CFG_PARAMS=0 -D DSP_SIGNEDONLY " run("techmap -map +/mul2dsp.v -map " + lib_path + family + "/dspv2_map.v -D USE_DSP_CFG_PARAMS=0 -D DSP_SIGNEDONLY "
"-D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=9 -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=4 -D DSP_NAME=$__MUL16X9"); "-D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=9 -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=4 -D DSP_NAME=$__MUL16X9");
run("chtype -set $mul t:$__soft_mul"); run("chtype -set $mul t:$__soft_mul");
run("ql_dspv2");
run("ql_dsp"); } else {
log_assert(false);
//run("ql_dsp_simd"); }
//run("techmap -map " + lib_path + family + "/dsp_final_map.v");
//run("ql_dsp_io_regs");
} }
if (check_label("coarse")) { if (check_label("coarse")) {

View File

@ -12,7 +12,7 @@ module top(input signed [16:0] ar, input signed [16:0] ai, input signed [16:0] b
endmodule endmodule
EOF EOF
synth_quicklogic -family qlf_k6n10f -run :coarse synth_quicklogic -family qlf_k6n10f -dspv2 -run :coarse
check -assert check -assert
read_verilog +/quicklogic/qlf_k6n10f/dsp_sim.v read_verilog +/quicklogic/qlf_k6n10f/dsp_sim.v
prep -top top -flatten prep -top top -flatten

View File

@ -11,7 +11,7 @@ module top(input [16:0] a, input [16:0] b, output reg [33:0] o, input clk, input
endmodule endmodule
EOF EOF
synth_quicklogic -family qlf_k6n10f -run :coarse synth_quicklogic -family qlf_k6n10f -dspv2 -run :coarse
check check
opt_clean opt_clean
dump dump

View File

@ -5,7 +5,7 @@ module top(input [16:0] a, input [16:0] b, input [16:0] c, input [16:0] d, outpu
endmodule endmodule
EOF EOF
synth_quicklogic -family qlf_k6n10f -run :coarse synth_quicklogic -family qlf_k6n10f -dspv2 -run :coarse
read_verilog +/quicklogic/qlf_k6n10f/dsp_sim.v read_verilog +/quicklogic/qlf_k6n10f/dsp_sim.v
prep -top top -flatten prep -top top -flatten
opt_clean -purge opt_clean -purge