diff --git a/techlibs/quicklogic/Makefile.inc b/techlibs/quicklogic/Makefile.inc index d83a941ca..738a808b5 100644 --- a/techlibs/quicklogic/Makefile.inc +++ b/techlibs/quicklogic/Makefile.inc @@ -39,6 +39,7 @@ $(eval $(call add_gen_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic $(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/dspv1_sim.v)) +$(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dspv1_sim_extra.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/dspv1_final_map.v)) $(eval $(call add_share_file,share/quicklogic/qlf_k6n10f,techlibs/quicklogic/qlf_k6n10f/dspv2_sim.v)) diff --git a/techlibs/quicklogic/ql_dsp_macc.cc b/techlibs/quicklogic/ql_dsp_macc.cc index 69ed93c4a..de52156ef 100644 --- a/techlibs/quicklogic/ql_dsp_macc.cc +++ b/techlibs/quicklogic/ql_dsp_macc.cc @@ -61,7 +61,6 @@ static void create_ql_macc_dsp(ql_dsp_macc_pm &pm, int dsp_version) cell_base_name = "dspv2"; std::function set_fractured = nullptr; - auto set_fractured_dspv1 = [](Cell* cell) -> void {cell->setPort(ID(f_mode_i), State::S0);}; auto set_fractured_dspv2 = [](Cell* cell) -> void {cell->setParam(ID(FRAC_MODE), State::S0);}; if (min_width <= 2 && max_width <= 2 && z_width <= 4) { @@ -81,7 +80,6 @@ static void create_ql_macc_dsp(ql_dsp_macc_pm &pm, int dsp_version) tgt_a_width = 20; tgt_b_width = 18; tgt_z_width = 38; - set_fractured = set_fractured_dspv1; } else { reject = true; } diff --git a/techlibs/quicklogic/ql_dsp_simd.cc b/techlibs/quicklogic/ql_dsp_simd.cc index b77464cb3..9c2e340db 100644 --- a/techlibs/quicklogic/ql_dsp_simd.cc +++ b/techlibs/quicklogic/ql_dsp_simd.cc @@ -87,7 +87,7 @@ struct QlDspSimdPass : public Pass { log_header(a_Design, "Executing QL_DSP_SIMD pass.\n"); // The following lists have to match simulation model interfaces. - + // DSP control and config ports that must be equal between // merged half-blocks // In addition to functional differences, @@ -156,13 +156,13 @@ struct QlDspSimdPass : public Pass { ID(c_i), ID(z_o), }; - + // Source DSP cell type (half-block) static const IdString m_Dspv1SisdType = ID(dsp_t1_10x9x32_cfg_ports); static const IdString m_Dspv2SisdType = ID(dspv2_16x9x32_cfg_ports); // Target DSP cell types (full-block) - static const IdString m_Dspv1SimdType = ID(dsp_t1_20x18x64_cfg_ports); + static const IdString m_Dspv1SimdType = ID(dsp_t1_20x18x64_cfg_ports_fracturable); static const IdString m_Dspv2SimdType = ID(dspv2_32x18x64_cfg_ports); // Parse args @@ -241,7 +241,7 @@ struct QlDspSimdPass : public Pass { // Check if the target cell is known (important to know // its port widths) if (!simd->known()) - log_error(" The target cell type '%s' is not known!", log_id(simd)); + log_error(" The target cell type '%s' is not known!", log_id(simd->type)); // Connect common ports for (auto port : cfg_ports) { diff --git a/techlibs/quicklogic/qlf_k6n10f/dspv1_final_map.v b/techlibs/quicklogic/qlf_k6n10f/dspv1_final_map.v index 118fe1b5a..cdbc8056b 100644 --- a/techlibs/quicklogic/qlf_k6n10f/dspv1_final_map.v +++ b/techlibs/quicklogic/qlf_k6n10f/dspv1_final_map.v @@ -14,7 +14,7 @@ // // SPDX-License-Identifier: Apache-2.0 -module dsp_t1_20x18x64_cfg_ports ( +module dsp_t1_20x18x64_cfg_ports_fracturable ( input [19:0] a_i, input [17:0] b_i, input [ 5:0] acc_fir_i, @@ -60,7 +60,7 @@ module dsp_t1_20x18x64_cfg_ports ( .unsigned_a (unsigned_a_i), .unsigned_b (unsigned_b_i), - .f_mode (f_mode_i), // No fracturation + .f_mode (f_mode_i), .output_select (output_select_i), .saturate_enable (saturate_enable_i), .shift_right (shift_right_i), @@ -71,6 +71,62 @@ module dsp_t1_20x18x64_cfg_ports ( endmodule +module dsp_t1_20x18x64_cfg_ports ( + input [19:0] a_i, + input [17:0] b_i, + input [ 5:0] acc_fir_i, + output [37:0] z_o, + output [17:0] dly_b_o, + + input clock_i, + input reset_i, + + input [2:0] feedback_i, + input load_acc_i, + input unsigned_a_i, + input unsigned_b_i, + + input [2:0] output_select_i, + input saturate_enable_i, + input [5:0] shift_right_i, + input round_i, + input subtract_i, + input register_inputs_i +); + + parameter [19:0] COEFF_0 = 20'd0; + parameter [19:0] COEFF_1 = 20'd0; + parameter [19:0] COEFF_2 = 20'd0; + parameter [19:0] COEFF_3 = 20'd0; + + dsp_t1_20x18x64_cfg_ports_fracturable # ( + .COEFF_0 (COEFF_0), + .COEFF_1 (COEFF_1), + .COEFF_2 (COEFF_2), + .COEFF_3 (COEFF_3) + ) _TECHMAP_REPLACE_ ( + .a_i (a_i), + .b_i (b_i), + .acc_fir_i (acc_fir_i), + .z_o (z_o), + .dly_b_o (dly_b_o), + .clock_i (clock_i), + .reset_i (reset_i), + .feedback_i (feedback_i), + .load_acc_i (load_acc_i), + .unsigned_a_i (unsigned_a_i), + .unsigned_b_i (unsigned_b_i), + .output_select_i (output_select_i), + .saturate_enable_i (saturate_enable_i), + .shift_right_i (shift_right_i), + .round_i (round_i), + .subtract_i (subtract_i), + .register_inputs_i (register_inputs_i), + .f_mode_i (1'b0) + ); + +endmodule + module dsp_t1_10x9x32_cfg_ports ( input [ 9:0] a_i, input [ 8:0] b_i, @@ -123,7 +179,7 @@ module dsp_t1_10x9x32_cfg_ports ( .unsigned_a (unsigned_a_i), .unsigned_b (unsigned_b_i), - .f_mode (1'b1), // Enable fractuation, Use the lower half + .f_mode (1'b0), .output_select (output_select_i), .saturate_enable (saturate_enable_i), .shift_right (shift_right_i), diff --git a/techlibs/quicklogic/qlf_k6n10f/dspv1_sim.v b/techlibs/quicklogic/qlf_k6n10f/dspv1_sim.v index 474e3d647..5f43b3229 100644 --- a/techlibs/quicklogic/qlf_k6n10f/dspv1_sim.v +++ b/techlibs/quicklogic/qlf_k6n10f/dspv1_sim.v @@ -4195,8 +4195,7 @@ module dsp_t1_20x18x64_cfg_ports ( input wire [ 5:0] shift_right_i, input wire round_i, input wire subtract_i, - input wire register_inputs_i, - input wire f_mode_i + input wire register_inputs_i ); parameter [19:0] COEFF_0 = 20'd0; @@ -4212,7 +4211,7 @@ module dsp_t1_20x18x64_cfg_ports ( .z(z_o), .dly_b(dly_b_o), - .f_mode(f_mode_i), // 20x18x64 DSP + .f_mode(1'b0), // 20x18x64 DSP .acc_fir(acc_fir_i), .feedback(feedback_i), diff --git a/techlibs/quicklogic/qlf_k6n10f/dspv1_sim_extra.v b/techlibs/quicklogic/qlf_k6n10f/dspv1_sim_extra.v new file mode 100644 index 000000000..d888ac08a --- /dev/null +++ b/techlibs/quicklogic/qlf_k6n10f/dspv1_sim_extra.v @@ -0,0 +1,80 @@ +// 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 + +`timescale 1ps/1ps + +`default_nettype none + +// dsp_t1_20x18x64_cfg_ports but with input wire f_mode_i +// This is a yosys-specific extension beyond the vendor-provided model +module dsp_t1_20x18x64_cfg_ports_fracturable ( + input wire [19:0] a_i, + input wire [17:0] b_i, + input wire [ 5:0] acc_fir_i, + output wire [37:0] z_o, + output wire [17:0] dly_b_o, + + (* clkbuf_sink *) + input wire clock_i, + input wire reset_i, + + input wire [ 2:0] feedback_i, + input wire load_acc_i, + input wire unsigned_a_i, + input wire unsigned_b_i, + + input wire [ 2:0] output_select_i, + input wire saturate_enable_i, + input wire [ 5:0] shift_right_i, + input wire round_i, + input wire subtract_i, + input wire register_inputs_i, + input wire f_mode_i +); + + parameter [19:0] COEFF_0 = 20'd0; + parameter [19:0] COEFF_1 = 20'd0; + parameter [19:0] COEFF_2 = 20'd0; + parameter [19:0] COEFF_3 = 20'd0; + + QL_DSP2 #( + .MODE_BITS({COEFF_3, COEFF_2, COEFF_1, COEFF_0}) + ) dsp ( + .a(a_i), + .b(b_i), + .z(z_o), + .dly_b(dly_b_o), + + .f_mode(f_mode_i), // 20x18x64 DSP + + .acc_fir(acc_fir_i), + .feedback(feedback_i), + .load_acc(load_acc_i), + + .unsigned_a(unsigned_a_i), + .unsigned_b(unsigned_b_i), + + .clk(clock_i), + .reset(reset_i), + + .saturate_enable(saturate_enable_i), + .output_select(output_select_i), + .round(round_i), + .shift_right(shift_right_i), + .subtract(subtract_i), + .register_inputs(register_inputs_i) + ); +endmodule diff --git a/techlibs/quicklogic/synth_quicklogic.cc b/techlibs/quicklogic/synth_quicklogic.cc index 8089b294e..cfc71c891 100644 --- a/techlibs/quicklogic/synth_quicklogic.cc +++ b/techlibs/quicklogic/synth_quicklogic.cc @@ -208,9 +208,10 @@ struct SynthQuickLogicPass : public ScriptPass { read_simlibs += stringf(" %sqlf_k6n10f/brams_sim.v", lib_path.c_str()); if (bramTypes) read_simlibs += stringf(" %sqlf_k6n10f/bram_types_sim.v", lib_path.c_str()); - if (dsp == V1) + if (dsp == V1) { read_simlibs += stringf(" %sqlf_k6n10f/dspv1_sim.v", lib_path.c_str()); - else if (dsp == V2) + read_simlibs += stringf(" %sqlf_k6n10f/dspv1_sim_extra.v", lib_path.c_str()); + } else if (dsp == V2) read_simlibs += stringf(" %sqlf_k6n10f/dspv2_sim.v", lib_path.c_str()); } run(read_simlibs); diff --git a/tests/arch/quicklogic/qlf_k6n10f/dspv1_simd.ys b/tests/arch/quicklogic/qlf_k6n10f/dspv1_simd.ys index d6088bf26..26f0ca16b 100644 --- a/tests/arch/quicklogic/qlf_k6n10f/dspv1_simd.ys +++ b/tests/arch/quicklogic/qlf_k6n10f/dspv1_simd.ys @@ -21,13 +21,14 @@ chtype -set $mul t:$__soft_mul 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 techmap -map +/quicklogic/qlf_k6n10f/dspv1_map.v -D USE_DSP_CFG_PARAMS=0 read_verilog -lib +/quicklogic/qlf_k6n10f/dspv1_sim.v +read_verilog -lib +/quicklogic/qlf_k6n10f/dspv1_sim_extra.v select -assert-count 2 t:dsp_t1_10x9x32_cfg_ports -select -assert-count 0 t:dsp_t1_20x18x64_cfg_ports -equiv_opt -assert -async2sync -map +/quicklogic/qlf_k6n10f/dspv1_sim.v ql_dsp_simd +select -assert-count 0 t:dsp_t1_20x18x64_cfg_ports_fracturable +equiv_opt -assert -async2sync -map +/quicklogic/qlf_k6n10f/dspv1_sim.v -map +/quicklogic/qlf_k6n10f/dspv1_sim_extra.v ql_dsp_simd design -load postopt select -assert-count 0 t:dsp_t1_10x9x32_cfg_ports -select -assert-count 1 t:dsp_t1_20x18x64_cfg_ports +select -assert-count 1 t:dsp_t1_20x18x64_cfg_ports_fracturable design -reset @@ -54,10 +55,11 @@ chtype -set $mul t:$__soft_mul 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 techmap -map +/quicklogic/qlf_k6n10f/dspv1_map.v -D USE_DSP_CFG_PARAMS=0 read_verilog -lib +/quicklogic/qlf_k6n10f/dspv1_sim.v +read_verilog -lib +/quicklogic/qlf_k6n10f/dspv1_sim_extra.v select -assert-count 2 t:dsp_t1_10x9x32_cfg_ports -select -assert-count 0 t:dsp_t1_20x18x64_cfg_ports -equiv_opt -assert -async2sync -map +/quicklogic/qlf_k6n10f/dspv1_sim.v ql_dsp_simd +select -assert-count 0 t:dsp_t1_20x18x64_cfg_ports_fracturable +equiv_opt -assert -async2sync -map +/quicklogic/qlf_k6n10f/dspv1_sim.v -map +/quicklogic/qlf_k6n10f/dspv1_sim_extra.v ql_dsp_simd design -load postopt select -assert-count 0 t:dsp_t1_10x9x32_cfg_ports -select -assert-count 1 t:dsp_t1_20x18x64_cfg_ports +select -assert-count 1 t:dsp_t1_20x18x64_cfg_ports_fracturable