From 0d484818a7ef3dad0621a97bfbfad19c4fe6becc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Tue, 11 Mar 2025 16:35:38 +0100 Subject: [PATCH] ql_dsp_io_regs: Add DSPv2 support, adjust sim model Add support for cell type dispatching of the new DSP block; adjust the definition of MULT and MULTACC variants to support those instances starting a cascading chain. --- techlibs/quicklogic/ql_dsp_io_regs.cc | 154 ++++++++++++++++++++- techlibs/quicklogic/qlf_k6n10f/dspv2_sim.v | 48 ++++--- 2 files changed, 185 insertions(+), 17 deletions(-) diff --git a/techlibs/quicklogic/ql_dsp_io_regs.cc b/techlibs/quicklogic/ql_dsp_io_regs.cc index d99623dcc..922feadd0 100644 --- a/techlibs/quicklogic/ql_dsp_io_regs.cc +++ b/techlibs/quicklogic/ql_dsp_io_regs.cc @@ -44,20 +44,32 @@ struct QlDspIORegs : public Pass { log("\n"); log("This pass looks for QL_DSP2 cells and changes their cell type depending on their\n"); log("configuration.\n"); + log("\n"); + log(" -dspv2\n"); + log(" target DSPv2.\n"); + log("\n"); } void execute(std::vector a_Args, RTLIL::Design *a_Design) override { log_header(a_Design, "Executing QL_DSP_IO_REGS pass.\n"); + bool target_dspv2 = false; size_t argidx; for (argidx = 1; argidx < a_Args.size(); argidx++) { + if (a_Args[argidx] == "-dspv2") { + target_dspv2 = true; + continue; + } break; } extra_args(a_Args, argidx, a_Design); for (auto module : a_Design->selected_modules()) { - ql_dsp_io_regs_pass(module); + if (target_dspv2) + ql_dsp_io_regs_pass_v2(module); + else + ql_dsp_io_regs_pass(module); } } @@ -153,6 +165,146 @@ struct QlDspIORegs : public Pass { } } } + + + void ql_dsp_io_regs_pass_v2(Module *module) + { + sigmap.set(module); + + for (auto cell : module->cells()) { + if (cell->type != ID(QL_DSPV2)) + continue; + + // If the cell does not have the "is_inferred" attribute set + // then don't touch it. + if (!cell->get_bool_attribute(ID(is_inferred))) + continue; + + if (!cell->hasPort(ID(output_select)) || + !sigmap(cell->getPort(ID(output_select))).is_fully_def() || + !cell->hasParam(ID(MODE_BITS)) || + cell->getParam(ID(MODE_BITS)).size() != 72) { + log_error("Missing configuration tie-offs or parameters on DSP cell %s\n", + log_id(cell)); + } + int out_sel_i = sigmap(cell->getPort(ID(output_select))).as_int(); + Const mode = cell->getParam(ID(MODE_BITS)); + + // Get the feedback port + if (!cell->hasPort(ID(feedback))) + log_error("Missing 'feedback' port on %s", log_id(cell)); + SigSpec feedback = sigmap(cell->getPort(ID(feedback))); + + bool a_reg = mode[61] != RTLIL::S0; + bool b_reg = mode[63] != RTLIL::S0; + + // Build new type name + std::string new_type = "\\QL_DSPV2_MULT"; + + // Decide if we should be deleting the clock port + bool del_clk = true; + + if (a_reg != b_reg) { + // no specialized type for mixed scenario + continue; + } + + enum { + MULT, + MULTADD, + MULTACC, + Unrecognized + } base_function = Unrecognized; + + switch (out_sel_i) { + case 0: + case 4: + base_function = MULT; + break; + case 1: + case 5: + case 2: + case 3: + case 6: + case 7: + if (feedback.is_fully_def() && (feedback.as_int() == 2 || feedback.as_int() == 3)) { + del_clk = false; + new_type += "ADD"; + base_function = MULTADD; + break; + } else if (feedback.extract(1, 2).is_fully_zero()) { + del_clk = false; + new_type += "ACC"; + base_function = MULTACC; + break; + } else { + base_function = Unrecognized; + } + break; + default: + break; + } + + if (base_function == Unrecognized) { + continue; + } + + if (a_reg && b_reg) { + del_clk = false; + new_type += "_REGIN"; + } + + if (out_sel_i > 3) { + del_clk = false; + new_type += "_REGOUT"; + } + + // Set new type name + log_debug("Converted %s to %s\n", log_id(cell->type), new_type.c_str()); + cell->type = RTLIL::IdString(new_type); + + std::vector ports2del; + + if (del_clk) { + cell->unsetPort(ID(clk)); + cell->unsetPort(ID(reset)); + } + + switch (base_function) { + case MULTACC: { + static const std::vector to_del = { + ID(c), ID(a_cin), ID(b_cin), ID(z_cin), + ID(a_cout), ID(b_cout) + }; + + for (auto port : to_del) + cell->unsetPort(port); + break; + } + case MULTADD: { + static const std::vector to_del = { + ID(c), ID(a_cin), ID(b_cin), ID(a_cout), ID(b_cout) + }; + + for (auto port : to_del) + cell->unsetPort(port); + break; + } + case MULT: { + static const std::vector to_del = { + ID(c), ID(load_acc), ID(acc_reset), + ID(a_cin), ID(b_cin), ID(z_cin), ID(a_cout), ID(b_cout) + }; + + for (auto port : to_del) + cell->unsetPort(port); + break; + } + default: + ; + } + } + } } QlDspIORegs; PRIVATE_NAMESPACE_END diff --git a/techlibs/quicklogic/qlf_k6n10f/dspv2_sim.v b/techlibs/quicklogic/qlf_k6n10f/dspv2_sim.v index c879e5c32..fd85c70ff 100644 --- a/techlibs/quicklogic/qlf_k6n10f/dspv2_sim.v +++ b/techlibs/quicklogic/qlf_k6n10f/dspv2_sim.v @@ -214,7 +214,9 @@ module QL_DSPV2_MULT ( output wire [49:0] z, input wire [2:0] feedback, - input wire [2:0] output_select + input wire [2:0] output_select, + + output wire [49:0] z_cout ); parameter [71:0] MODE_BITS = 72'h000000000000000000; @@ -257,7 +259,7 @@ module QL_DSPV2_MULT ( .b_cin(), .z_cin(), - .z_cout(), + .z_cout(z_cout), .a_cout(), .b_cout() ); @@ -274,7 +276,9 @@ module QL_DSPV2_MULT_REGIN ( input wire reset, input wire [2:0] feedback, - input wire [2:0] output_select + input wire [2:0] output_select, + + output wire [49:0] z_cout ); parameter [71:0] MODE_BITS = 72'h00A000000000000000; @@ -317,7 +321,7 @@ module QL_DSPV2_MULT_REGIN ( .b_cin(), .z_cin(), - .z_cout(), + .z_cout(z_cout), .a_cout(), .b_cout() ); @@ -334,7 +338,9 @@ module QL_DSPV2_MULT_REGOUT ( input wire reset, input wire [2:0] feedback, - input wire [2:0] output_select + input wire [2:0] output_select, + + output wire [49:0] z_cout ); parameter [71:0] MODE_BITS = 72'h000000000000000000; @@ -377,7 +383,7 @@ module QL_DSPV2_MULT_REGOUT ( .b_cin(), .z_cin(), - .z_cout(), + .z_cout(z_cout), .a_cout(), .b_cout() ); @@ -394,7 +400,9 @@ module QL_DSPV2_MULT_REGIN_REGOUT ( input wire reset, input wire [2:0] feedback, - input wire [2:0] output_select + input wire [2:0] output_select, + + output wire [49:0] z_cout ); parameter [71:0] MODE_BITS = 72'h00A000000000000000; @@ -437,7 +445,7 @@ module QL_DSPV2_MULT_REGIN_REGOUT ( .b_cin(), .z_cin(), - .z_cout(), + .z_cout(z_cout), .a_cout(), .b_cout() ); @@ -715,7 +723,9 @@ module QL_DSPV2_MULTACC ( input wire acc_reset, input wire load_acc, input wire [ 2:0] feedback, - input wire [ 2:0] output_select + input wire [ 2:0] output_select, + + output wire [49:0] z_cout ); parameter [71:0] MODE_BITS = 72'h000000000000000000; @@ -758,7 +768,7 @@ module QL_DSPV2_MULTACC ( .b_cin(), .z_cin(), - .z_cout(), + .z_cout(z_cout), .a_cout(), .b_cout() ); @@ -776,7 +786,9 @@ module QL_DSPV2_MULTACC_REGIN ( input wire acc_reset, input wire load_acc, input wire [ 2:0] feedback, - input wire [ 2:0] output_select + input wire [ 2:0] output_select, + + output wire [49:0] z_cout ); parameter [71:0] MODE_BITS = 72'h004000000000000000; @@ -819,7 +831,7 @@ module QL_DSPV2_MULTACC_REGIN ( .b_cin(), .z_cin(), - .z_cout(), + .z_cout(z_cout), .a_cout(), .b_cout() ); @@ -837,7 +849,9 @@ module QL_DSPV2_MULTACC_REGOUT ( input wire acc_reset, input wire load_acc, input wire [ 2:0] feedback, - input wire [ 2:0] output_select + input wire [ 2:0] output_select, + + output wire [49:0] z_cout ); parameter [71:0] MODE_BITS = 72'h000000000000000000; @@ -880,7 +894,7 @@ module QL_DSPV2_MULTACC_REGOUT ( .b_cin(), .z_cin(), - .z_cout(), + .z_cout(z_cout), .a_cout(), .b_cout() ); @@ -898,7 +912,9 @@ module QL_DSPV2_MULTACC_REGIN_REGOUT ( input wire acc_reset, input wire load_acc, input wire [ 2:0] feedback, - input wire [ 2:0] output_select + input wire [ 2:0] output_select, + + output wire [49:0] z_cout ); parameter [71:0] MODE_BITS = 72'h004000000000000000; @@ -941,7 +957,7 @@ module QL_DSPV2_MULTACC_REGIN_REGOUT ( .b_cin(), .z_cin(), - .z_cout(), + .z_cout(z_cout), .a_cout(), .b_cout() );