From 947ca842f96a163446852cb64a270c7c72070deb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Mon, 10 Mar 2025 16:28:16 +0100 Subject: [PATCH] ql_dsp: Add promotion on cascading --- techlibs/quicklogic/ql_dsp.cc | 44 ++++++++++++++++++++++++++++++++++ techlibs/quicklogic/ql_dsp.pmg | 10 +++++--- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/techlibs/quicklogic/ql_dsp.cc b/techlibs/quicklogic/ql_dsp.cc index aa8ed6631..e84bd8905 100644 --- a/techlibs/quicklogic/ql_dsp.cc +++ b/techlibs/quicklogic/ql_dsp.cc @@ -22,6 +22,50 @@ PRIVATE_NAMESPACE_BEGIN USING_YOSYS_NAMESPACE +// promote dspv2_16x9x32_cfg_ports to dspv2_32x18x64_cfg_ports if need be +bool promote(Module *m, Cell *cell) { + if (cell->type == ID(dspv2_32x18x64_cfg_ports)) { + return false; + } else { + log_assert(cell->type == ID(dspv2_16x9x32_cfg_ports)); + } + + auto widen_output = [&](IdString port_name, int new_width) { + if (!cell->hasPort(port_name)) + return; + SigSpec port = cell->getPort(port_name); + if (port.size() < new_width) { + port = {m->addWire(NEW_ID, new_width - port.size()), port}; + cell->setPort(port_name, port); + } + }; + + auto widen_input = [&](IdString port_name, int new_width) { + if (!cell->hasPort(port_name)) + return; + SigSpec port = cell->getPort(port_name); + if (port.size() < new_width) { + port.extend_u0(new_width, /* is_signed= */ true); + cell->setPort(port_name, port); + } + }; + + widen_output(ID(z_o), 50); + widen_output(ID(a_cout_o), 32); + widen_output(ID(b_cout_o), 18); + widen_output(ID(z_cout_o), 50); + + if (cell->hasPort(ID(a_cin_i)) || cell->hasPort(ID(b_cin_i)) || cell->hasPort(ID(z_cin_i))) { + log_error("Cannot promote %s (type %s) with cascading paths\n", log_id(cell), log_id(cell->type)); + } + + widen_input(ID(a_i), 32); + widen_input(ID(b_i), 18); + widen_input(ID(c_i), 18); + cell->type = ID(dspv2_32x18x64_cfg_ports); + return true; +} + #include "ql_dsp_pm.h" struct QlDspPass : Pass { diff --git a/techlibs/quicklogic/ql_dsp.pmg b/techlibs/quicklogic/ql_dsp.pmg index a7e772f62..44c2377d0 100644 --- a/techlibs/quicklogic/ql_dsp.pmg +++ b/techlibs/quicklogic/ql_dsp.pmg @@ -11,7 +11,7 @@ udata dffclock dffreset udata dff match dsp - select dsp->type == \dspv2_32x18x64_cfg_ports + select dsp->type.in(\dspv2_32x18x64_cfg_ports, \dspv2_16x9x32_cfg_ports) endmatch code clock_inferred clock reset @@ -209,12 +209,12 @@ endcode pattern ql_dsp_cascade match dsp1 - select dsp1->type == \dspv2_32x18x64_cfg_ports + select dsp1->type.in(\dspv2_32x18x64_cfg_ports, \dspv2_16x9x32_cfg_ports) filter !dsp1->hasPort(\z_cout_o) || nusers(port(dsp1, \z_cout_o)) == 1 endmatch match dsp2 - select dsp2->type == \dspv2_32x18x64_cfg_ports + select dsp2->type.in(\dspv2_32x18x64_cfg_ports, \dspv2_16x9x32_cfg_ports) filter port(dsp2, \output_select_i).is_fully_const() define output_sel port(dsp2, \output_select_i).as_int() filter output_sel == 3 || (output_sel == 4 && !param(dsp2, \M_REG).as_bool()) @@ -243,6 +243,10 @@ code const int z_width = 50; log("%s: inferring post-adder from %s (type %s)\n", log_id(dsp2), log_id(add), log_id(add->type)); + if (promote(module, dsp1)) + log(" - promoting %s to non-fractured DSP block\n", log_id(dsp1)); + if (promote(module, dsp2)) + log(" - promoting %s to non-fractured DSP block\n", log_id(dsp2)); // link up z_cout_o of dsp1 to z_cin_i of dsp2 Wire *link = module->addWire(NEW_ID, z_width);