|
24 | 24 | #include "License_manager.hpp"
|
25 | 25 | #endif
|
26 | 26 |
|
| 27 | +int Count_ADD; |
27 | 28 | int DSP_COUNTER;
|
28 | 29 | USING_YOSYS_NAMESPACE
|
29 | 30 | PRIVATE_NAMESPACE_BEGIN
|
@@ -402,6 +403,8 @@ struct SynthRapidSiliconPass : public ScriptPass {
|
402 | 403 | Encoding fsm_encoding;
|
403 | 404 | EffortLevel effort;
|
404 | 405 | string abc_script;
|
| 406 | + bool dsp_limit_exhausted = false; |
| 407 | + string dsp_limit_message = ""; |
405 | 408 | bool cec;
|
406 | 409 | bool sec;
|
407 | 410 | int post_cleanup;
|
@@ -8242,6 +8245,127 @@ void collect_clocks (RTLIL::Module* module,
|
8242 | 8245 | }
|
8243 | 8246 | }
|
8244 | 8247 |
|
| 8248 | + std::pair<int, std::unordered_map<RTLIL::Cell *, int>> best_sum_under_dsp_limit(const std::unordered_map<RTLIL::Cell *, int> &items, int dsp_limit) |
| 8249 | + { |
| 8250 | + // Early exit if the items map is empty |
| 8251 | + if (items.empty()) |
| 8252 | + { |
| 8253 | + return {0, {}}; // Return a sum of 0 and an empty map |
| 8254 | + } |
| 8255 | + |
| 8256 | + std::vector<int> dp(dsp_limit + 1, 0); |
| 8257 | + std::vector<std::vector<RTLIL::Cell *>> dp_items(dsp_limit + 1); |
| 8258 | + |
| 8259 | + for (const auto &item : items) |
| 8260 | + { |
| 8261 | + RTLIL::Cell *cell = item.first; |
| 8262 | + int value = item.second; |
| 8263 | + |
| 8264 | + for (int j = dsp_limit; j >= value; --j) |
| 8265 | + { |
| 8266 | + if (dp[j - value] + value > dp[j]) |
| 8267 | + { |
| 8268 | + dp[j] = dp[j - value] + value; |
| 8269 | + dp_items[j] = dp_items[j - value]; |
| 8270 | + dp_items[j].push_back(cell); |
| 8271 | + } |
| 8272 | + } |
| 8273 | + } |
| 8274 | + |
| 8275 | + std::unordered_map<RTLIL::Cell *, int> best_items; |
| 8276 | + for (const auto &cell : dp_items[dsp_limit]) |
| 8277 | + { |
| 8278 | + best_items[cell] = items.at(cell); |
| 8279 | + } |
| 8280 | + |
| 8281 | + return {dp[dsp_limit], best_items}; |
| 8282 | + } |
| 8283 | + |
| 8284 | + void check_dsp_device_limit() |
| 8285 | + { |
| 8286 | + std::unordered_map<RTLIL::Cell *, int> dsp_control; |
| 8287 | + |
| 8288 | + for (auto cell : _design->top_module()->cells()) |
| 8289 | + { |
| 8290 | + if (cell->type == RTLIL::escape_id("$mul")) |
| 8291 | + { |
| 8292 | + int _a_width_ = cell->getParam(ID::A_WIDTH).as_int(); |
| 8293 | + int _b_width_ = cell->getParam(ID::B_WIDTH).as_int(); |
| 8294 | + int a_signed = cell->getParam(ID::A_SIGNED).as_int(); |
| 8295 | + int b_signed = cell->getParam(ID::B_SIGNED).as_int(); |
| 8296 | + |
| 8297 | + if (_a_width_ >= 11 && _b_width_ >= 10) |
| 8298 | + { |
| 8299 | + double sliceA, sliceB; |
| 8300 | + if (a_signed && b_signed) |
| 8301 | + { |
| 8302 | + sliceA = static_cast<double>(_a_width_ - a_signed - 1) / (20 - a_signed); |
| 8303 | + sliceB = static_cast<double>(_b_width_ - b_signed - 1) / (18 - b_signed); |
| 8304 | + } |
| 8305 | + else |
| 8306 | + { |
| 8307 | + sliceA = static_cast<double>(_a_width_ - 1) / 20; |
| 8308 | + sliceB = static_cast<double>(_b_width_ - 1) / 18; |
| 8309 | + } |
| 8310 | + int nodsp = round(sliceA) * round(sliceB); |
| 8311 | + dsp_control[cell] = nodsp; |
| 8312 | + } |
| 8313 | + else |
| 8314 | + { |
| 8315 | + dsp_control[cell] = 1; |
| 8316 | + } |
| 8317 | + } |
| 8318 | + } |
| 8319 | + |
| 8320 | + auto result = best_sum_under_dsp_limit(dsp_control, max_dsp - DSP_COUNTER); |
| 8321 | + |
| 8322 | + int best_sum = result.first; |
| 8323 | + std::unordered_map<RTLIL::Cell *, int> best_items = result.second; |
| 8324 | + |
| 8325 | + DSP_COUNTER += best_sum; |
| 8326 | + |
| 8327 | + for (const auto &cell_info : best_items) |
| 8328 | + { |
| 8329 | + cell_info.first->set_bool_attribute(RTLIL::escape_id("valid_map")); |
| 8330 | + } |
| 8331 | + |
| 8332 | + int remaining_item_count = 0; |
| 8333 | + int remaining_sum = 0; |
| 8334 | + |
| 8335 | + for (auto cell : _design->top_module()->cells()) |
| 8336 | + { |
| 8337 | + if (cell->type == RTLIL::escape_id("$mul")) |
| 8338 | + { |
| 8339 | + if (!cell->get_bool_attribute(RTLIL::escape_id("valid_map"))) |
| 8340 | + { |
| 8341 | + remaining_item_count++; |
| 8342 | + remaining_sum += dsp_control[cell]; |
| 8343 | + } |
| 8344 | + } |
| 8345 | + } |
| 8346 | + |
| 8347 | + dsp_limit_exhausted = (remaining_item_count > 0); |
| 8348 | + if (dsp_limit_exhausted) |
| 8349 | + { |
| 8350 | + for (auto cell : _design->top_module()->cells()) |
| 8351 | + { |
| 8352 | + if (cell->type == RTLIL::escape_id("$mul")) |
| 8353 | + { |
| 8354 | + if (!cell->get_bool_attribute(RTLIL::escape_id("valid_map"))) |
| 8355 | + { |
| 8356 | + log_warning("Using soft logic for mult '%s'\n", log_id(cell->name)); |
| 8357 | + } |
| 8358 | + } |
| 8359 | + } |
| 8360 | + dsp_limit_message = "DSP exceeds the available DSP block limit (" + std::to_string(max_dsp) + |
| 8361 | + ") on the device; the excess " + std::to_string(remaining_sum) + |
| 8362 | + " DSP blocks is mapped to soft logic.\n"; |
| 8363 | + 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); |
| 8364 | + } |
| 8365 | + |
| 8366 | + |
| 8367 | + } |
| 8368 | + |
8245 | 8369 | void script() override
|
8246 | 8370 | {
|
8247 | 8371 | string readArgs;
|
@@ -8572,25 +8696,18 @@ void collect_clocks (RTLIL::Module* module,
|
8572 | 8696 | run("stat");
|
8573 | 8697 | #endif
|
8574 | 8698 | if (new_dsp19x2) // RUN based on DSP19x2 mapping
|
8575 |
| - run("rs-dsp-multadd -genesis3 -new_dsp19x2"); |
8576 |
| - else |
8577 |
| - run("rs-dsp-multadd -genesis3"); |
| 8699 | + run("rs-dsp-multadd -genesis3 -new_dsp19x2 -max_dsp " + std::to_string(max_dsp)); |
| 8700 | + else |
| 8701 | + run("rs-dsp-multadd -genesis3 -max_dsp " + std::to_string(max_dsp)); |
| 8702 | + |
| 8703 | + DSP_COUNTER = DSP_COUNTER + Count_ADD; |
8578 | 8704 | run("wreduce t:$mul");
|
8579 | 8705 | if (!new_dsp19x2)
|
8580 | 8706 | run("rs_dsp_macc" + use_dsp_cfg_params + genesis3 + " -max_dsp " + std::to_string(max_dsp));
|
8581 | 8707 | else // RUN based on DSP19x2 mapping
|
8582 | 8708 | run("rs_dsp_macc" + use_dsp_cfg_params + genesis3 + " -new_dsp19x2" + " -max_dsp " + std::to_string(max_dsp));
|
8583 |
| - if (max_dsp != -1) |
8584 |
| - for(auto& modules : _design->selected_modules()){ |
8585 |
| - for(auto& cells : modules->selected_cells()){ |
8586 |
| - if(cells->type == RTLIL::escape_id("$mul")){ |
8587 |
| - if(DSP_COUNTER < max_dsp){ |
8588 |
| - cells->set_bool_attribute(RTLIL::escape_id("valid_map")); |
8589 |
| - } |
8590 |
| - ++DSP_COUNTER; |
8591 |
| - } |
8592 |
| - } |
8593 |
| - } |
| 8709 | + |
| 8710 | + check_dsp_device_limit(); |
8594 | 8711 |
|
8595 | 8712 | // Check if mult output is connected with Registers output
|
8596 | 8713 | if (tech == Technologies::GENESIS_3)
|
@@ -9276,11 +9393,14 @@ void collect_clocks (RTLIL::Module* module,
|
9276 | 9393 | //
|
9277 | 9394 | run("write_verilog -noattr -nohex -noexpr core_synthesis.v");
|
9278 | 9395 |
|
| 9396 | + if (dsp_limit_exhausted){ |
| 9397 | + log("\n"); |
| 9398 | + log_warning("%s\n",dsp_limit_message.c_str()); |
| 9399 | + } |
9279 | 9400 | if ((max_lut != -1) && (nbLUTx > max_lut)) {
|
9280 | 9401 | log("\n");
|
9281 | 9402 | log_error("Final netlist LUTs number [%d] exceeds '-max_lut' specified value [%d].\n", nbLUTx, max_lut);
|
9282 | 9403 | }
|
9283 |
| - |
9284 | 9404 | if ((max_reg != -1) && (nbREGs > max_reg)) {
|
9285 | 9405 | log("\n");
|
9286 | 9406 | log_error("Final netlist DFFs number [%d] exceeds '-max_reg' specified value [%d].\n", nbREGs, max_reg);
|
|
0 commit comments