From 0485e4294734588f4f49227294a87622ab4327c9 Mon Sep 17 00:00:00 2001 From: awaisabbas006 Date: Thu, 12 Sep 2024 18:47:30 +0500 Subject: [PATCH 1/2] Refined DSP device limit --- src/rs-dsp-multadd.cc | 11 ++++ src/synth_rapidsilicon.cc | 117 +++++++++++++++++++++++++++++++++----- 2 files changed, 114 insertions(+), 14 deletions(-) diff --git a/src/rs-dsp-multadd.cc b/src/rs-dsp-multadd.cc index ffe6205d..19449218 100644 --- a/src/rs-dsp-multadd.cc +++ b/src/rs-dsp-multadd.cc @@ -6,6 +6,7 @@ #include "kernel/ffinit.h" #include "kernel/ff.h" +extern int Count_ADD; USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -23,6 +24,7 @@ bool is_genesis; bool is_genesis2; bool is_genesis3; bool new_dsp19x2; +int max_dsp; struct RsDspMultAddWorker { RTLIL::Module *m_module; @@ -191,6 +193,11 @@ struct RsDspMultAddWorker // Too wide continue; } + if (max_dsp != -1 && Count_ADD > max_dsp) + { + return; + } + ++Count_ADD; log("Inferring MULTADD %zux%zu->%zu as %s from:\n", a_width, b_width, z_width, RTLIL::unescape_id(type).c_str()); for (auto cell : {mult_coeff, mult_add_cell, shift_left_cell}) { //Awais: unescape $neg which is being handled in MACC if (cell != nullptr) { @@ -420,6 +427,10 @@ struct RSDspMultAddPass : public Pass { is_genesis = true; if (a_Args[argidx] == "-new_dsp19x2") new_dsp19x2 = true; + if (a_Args[argidx] == "-max_dsp" && argidx + 1 < a_Args.size()) { + max_dsp = std::stoi(a_Args[++argidx]); + continue; + } } extra_args(a_Args, argidx, design); diff --git a/src/synth_rapidsilicon.cc b/src/synth_rapidsilicon.cc index c14e1776..616d3bfb 100644 --- a/src/synth_rapidsilicon.cc +++ b/src/synth_rapidsilicon.cc @@ -24,6 +24,7 @@ #include "License_manager.hpp" #endif +int Count_ADD; int DSP_COUNTER; USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -8212,6 +8213,101 @@ void collect_clocks (RTLIL::Module* module, } } + std::pair> best_sum_under_dsp_limit(const std::unordered_map &items, int dsp_limit) + { + std::vector dp(dsp_limit + 1, 0); + std::vector> dp_items(dsp_limit + 1); + + for (const auto &item : items) + { + RTLIL::Cell *cell = item.first; + int value = item.second; + + for (int j = dsp_limit; j >= value; --j) + { + if (dp[j - value] + value > dp[j]) + { + dp[j] = dp[j - value] + value; + dp_items[j] = dp_items[j - value]; + dp_items[j].push_back(cell); + } + } + } + + std::unordered_map best_items; + for (const auto &cell : dp_items[dsp_limit]) + { + best_items[cell] = items.at(cell); + } + + return {dp[dsp_limit], best_items}; + } + + void check_dsp_device_limit() + { + std::unordered_map dsp_control; + + for (auto cell : _design->top_module()->cells()) + { + if (cell->type == RTLIL::escape_id("$mul")) + { + int _a_width_ = cell->getParam(ID::A_WIDTH).as_int(); + int _b_width_ = cell->getParam(ID::B_WIDTH).as_int(); + int a_signed = cell->getParam(ID::A_SIGNED).as_int(); + int b_signed = cell->getParam(ID::B_SIGNED).as_int(); + if (_a_width_ >= 11 && _b_width_ >= 10) + { + if (a_signed && b_signed) + { + double sliceA = static_cast(_a_width_ - a_signed - 1) / (20 - a_signed); + double sliceB = static_cast(_b_width_ - b_signed - 1) / (18 - b_signed); + int nodsp = round(sliceA) * round(sliceB); + dsp_control[cell] = nodsp; + } + else + { + double sliceA = static_cast(_a_width_ - 1) / (20); + double sliceB = static_cast(_b_width_ - 1) / (18); + int nodsp = round(sliceA) * round(sliceB); + dsp_control[cell] = nodsp; + } + } + else + { + dsp_control[cell] = 1; + } + } + } + auto result = best_sum_under_dsp_limit(dsp_control, max_dsp - DSP_COUNTER); + + int best_sum = result.first; + std::unordered_map best_items = result.second; + DSP_COUNTER = DSP_COUNTER + best_sum; + for (const auto &cell_info : best_items) + { + cell_info.first->set_bool_attribute(RTLIL::escape_id("valid_map")); + } + bool dsp_limit_exhausted = false; + if (DSP_COUNTER >= max_dsp) + { + for (auto cell : _design->top_module()->cells()) + { + if (cell->type == RTLIL::escape_id("$mul")) + { + if (!cell->get_bool_attribute(RTLIL::escape_id("valid_map"))) + { + dsp_limit_exhausted = true; + log_warning("Using soft logic for mult '%s'\n", log_id(cell->name)); + } + } + } + } + if (dsp_limit_exhausted) + { + log_warning("DSP exceeds the available DSP block limit on the device; the excess will be mapped to LUTs.\n"); + } + } + void script() override { string readArgs; @@ -8542,25 +8638,18 @@ void collect_clocks (RTLIL::Module* module, run("stat"); #endif if (new_dsp19x2) // RUN based on DSP19x2 mapping - run("rs-dsp-multadd -genesis3 -new_dsp19x2"); - else - run("rs-dsp-multadd -genesis3"); + run("rs-dsp-multadd -genesis3 -new_dsp19x2 -max_dsp " + std::to_string(max_dsp)); + else + run("rs-dsp-multadd -genesis3 -max_dsp " + std::to_string(max_dsp)); + + DSP_COUNTER = DSP_COUNTER + Count_ADD; run("wreduce t:$mul"); if (!new_dsp19x2) run("rs_dsp_macc" + use_dsp_cfg_params + genesis3 + " -max_dsp " + std::to_string(max_dsp)); else // RUN based on DSP19x2 mapping run("rs_dsp_macc" + use_dsp_cfg_params + genesis3 + " -new_dsp19x2" + " -max_dsp " + std::to_string(max_dsp)); - if (max_dsp != -1) - for(auto& modules : _design->selected_modules()){ - for(auto& cells : modules->selected_cells()){ - if(cells->type == RTLIL::escape_id("$mul")){ - if(DSP_COUNTER < max_dsp){ - cells->set_bool_attribute(RTLIL::escape_id("valid_map")); - } - ++DSP_COUNTER; - } - } - } + + check_dsp_device_limit(); // Check if mult output is connected with Registers output if (tech == Technologies::GENESIS_3) From 4292033d245966f4bfffe5541bd896d923301ed3 Mon Sep 17 00:00:00 2001 From: awaisabbas006 Date: Fri, 20 Sep 2024 16:01:28 +0500 Subject: [PATCH 2/2] DSP limit warning added the end of synthesis --- src/synth_rapidsilicon.cc | 75 +++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/src/synth_rapidsilicon.cc b/src/synth_rapidsilicon.cc index 57d494f2..0de75f0b 100644 --- a/src/synth_rapidsilicon.cc +++ b/src/synth_rapidsilicon.cc @@ -403,6 +403,8 @@ struct SynthRapidSiliconPass : public ScriptPass { Encoding fsm_encoding; EffortLevel effort; string abc_script; + bool dsp_limit_exhausted = false; + string dsp_limit_message = ""; bool cec; bool sec; int post_cleanup; @@ -8245,6 +8247,12 @@ void collect_clocks (RTLIL::Module* module, std::pair> best_sum_under_dsp_limit(const std::unordered_map &items, int dsp_limit) { + // Early exit if the items map is empty + if (items.empty()) + { + return {0, {}}; // Return a sum of 0 and an empty map + } + std::vector dp(dsp_limit + 1, 0); std::vector> dp_items(dsp_limit + 1); @@ -8258,8 +8266,8 @@ void collect_clocks (RTLIL::Module* module, if (dp[j - value] + value > dp[j]) { dp[j] = dp[j - value] + value; - dp_items[j] = dp_items[j - value]; - dp_items[j].push_back(cell); + dp_items[j] = dp_items[j - value]; + dp_items[j].push_back(cell); } } } @@ -8267,7 +8275,7 @@ void collect_clocks (RTLIL::Module* module, std::unordered_map best_items; for (const auto &cell : dp_items[dsp_limit]) { - best_items[cell] = items.at(cell); + best_items[cell] = items.at(cell); } return {dp[dsp_limit], best_items}; @@ -8285,40 +8293,59 @@ void collect_clocks (RTLIL::Module* module, int _b_width_ = cell->getParam(ID::B_WIDTH).as_int(); int a_signed = cell->getParam(ID::A_SIGNED).as_int(); int b_signed = cell->getParam(ID::B_SIGNED).as_int(); + if (_a_width_ >= 11 && _b_width_ >= 10) { + double sliceA, sliceB; if (a_signed && b_signed) { - double sliceA = static_cast(_a_width_ - a_signed - 1) / (20 - a_signed); - double sliceB = static_cast(_b_width_ - b_signed - 1) / (18 - b_signed); - int nodsp = round(sliceA) * round(sliceB); - dsp_control[cell] = nodsp; + sliceA = static_cast(_a_width_ - a_signed - 1) / (20 - a_signed); + sliceB = static_cast(_b_width_ - b_signed - 1) / (18 - b_signed); } else { - double sliceA = static_cast(_a_width_ - 1) / (20); - double sliceB = static_cast(_b_width_ - 1) / (18); - int nodsp = round(sliceA) * round(sliceB); - dsp_control[cell] = nodsp; + sliceA = static_cast(_a_width_ - 1) / 20; + sliceB = static_cast(_b_width_ - 1) / 18; } + int nodsp = round(sliceA) * round(sliceB); + dsp_control[cell] = nodsp; } else { - dsp_control[cell] = 1; + dsp_control[cell] = 1; } } } + auto result = best_sum_under_dsp_limit(dsp_control, max_dsp - DSP_COUNTER); - int best_sum = result.first; + int best_sum = result.first; std::unordered_map best_items = result.second; - DSP_COUNTER = DSP_COUNTER + best_sum; + + DSP_COUNTER += best_sum; + for (const auto &cell_info : best_items) { cell_info.first->set_bool_attribute(RTLIL::escape_id("valid_map")); } - bool dsp_limit_exhausted = false; - if (DSP_COUNTER >= max_dsp) + + int remaining_item_count = 0; + int remaining_sum = 0; + + for (auto cell : _design->top_module()->cells()) + { + if (cell->type == RTLIL::escape_id("$mul")) + { + if (!cell->get_bool_attribute(RTLIL::escape_id("valid_map"))) + { + remaining_item_count++; + remaining_sum += dsp_control[cell]; + } + } + } + + dsp_limit_exhausted = (remaining_item_count > 0); + if (dsp_limit_exhausted) { for (auto cell : _design->top_module()->cells()) { @@ -8326,16 +8353,17 @@ void collect_clocks (RTLIL::Module* module, { if (!cell->get_bool_attribute(RTLIL::escape_id("valid_map"))) { - dsp_limit_exhausted = true; log_warning("Using soft logic for mult '%s'\n", log_id(cell->name)); } } } + dsp_limit_message = "DSP exceeds the available DSP block limit (" + std::to_string(max_dsp) + + ") on the device; the excess " + std::to_string(remaining_sum) + + " DSP blocks is mapped to soft logic.\n"; + log_warning("DSP exceeds the available DSP block limit (%d) on the device; the excess %d DSP blocks will be mapped to LUTs.\n",max_dsp, remaining_sum); } - if (dsp_limit_exhausted) - { - log_warning("DSP exceeds the available DSP block limit on the device; the excess will be mapped to LUTs.\n"); - } + + } void script() override @@ -9365,11 +9393,14 @@ void collect_clocks (RTLIL::Module* module, // run("write_verilog -noattr -nohex -noexpr core_synthesis.v"); + if (dsp_limit_exhausted){ + log("\n"); + log_warning("%s\n",dsp_limit_message.c_str()); + } if ((max_lut != -1) && (nbLUTx > max_lut)) { log("\n"); log_error("Final netlist LUTs number [%d] exceeds '-max_lut' specified value [%d].\n", nbLUTx, max_lut); } - if ((max_reg != -1) && (nbREGs > max_reg)) { log("\n"); log_error("Final netlist DFFs number [%d] exceeds '-max_reg' specified value [%d].\n", nbREGs, max_reg);