Skip to content

Commit 90eac86

Browse files
Merge pull request #408 from awaisabbas006/main
DSP device limit implemented in synthesis
2 parents afbcf0b + 13191fe commit 90eac86

File tree

2 files changed

+146
-15
lines changed

2 files changed

+146
-15
lines changed

src/rs-dsp-multadd.cc

+11
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "kernel/ffinit.h"
77
#include "kernel/ff.h"
88

9+
extern int Count_ADD;
910
USING_YOSYS_NAMESPACE
1011
PRIVATE_NAMESPACE_BEGIN
1112

@@ -23,6 +24,7 @@ bool is_genesis;
2324
bool is_genesis2;
2425
bool is_genesis3;
2526
bool new_dsp19x2;
27+
int max_dsp;
2628
struct RsDspMultAddWorker
2729
{
2830
RTLIL::Module *m_module;
@@ -191,6 +193,11 @@ struct RsDspMultAddWorker
191193
// Too wide
192194
continue;
193195
}
196+
if (max_dsp != -1 && Count_ADD > max_dsp)
197+
{
198+
return;
199+
}
200+
++Count_ADD;
194201
log("Inferring MULTADD %zux%zu->%zu as %s from:\n", a_width, b_width, z_width, RTLIL::unescape_id(type).c_str());
195202
for (auto cell : {mult_coeff, mult_add_cell, shift_left_cell}) { //Awais: unescape $neg which is being handled in MACC
196203
if (cell != nullptr) {
@@ -420,6 +427,10 @@ struct RSDspMultAddPass : public Pass {
420427
is_genesis = true;
421428
if (a_Args[argidx] == "-new_dsp19x2")
422429
new_dsp19x2 = true;
430+
if (a_Args[argidx] == "-max_dsp" && argidx + 1 < a_Args.size()) {
431+
max_dsp = std::stoi(a_Args[++argidx]);
432+
continue;
433+
}
423434
}
424435

425436
extra_args(a_Args, argidx, design);

src/synth_rapidsilicon.cc

+135-15
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "License_manager.hpp"
2525
#endif
2626

27+
int Count_ADD;
2728
int DSP_COUNTER;
2829
USING_YOSYS_NAMESPACE
2930
PRIVATE_NAMESPACE_BEGIN
@@ -402,6 +403,8 @@ struct SynthRapidSiliconPass : public ScriptPass {
402403
Encoding fsm_encoding;
403404
EffortLevel effort;
404405
string abc_script;
406+
bool dsp_limit_exhausted = false;
407+
string dsp_limit_message = "";
405408
bool cec;
406409
bool sec;
407410
int post_cleanup;
@@ -8242,6 +8245,127 @@ void collect_clocks (RTLIL::Module* module,
82428245
}
82438246
}
82448247

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+
82458369
void script() override
82468370
{
82478371
string readArgs;
@@ -8572,25 +8696,18 @@ void collect_clocks (RTLIL::Module* module,
85728696
run("stat");
85738697
#endif
85748698
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;
85788704
run("wreduce t:$mul");
85798705
if (!new_dsp19x2)
85808706
run("rs_dsp_macc" + use_dsp_cfg_params + genesis3 + " -max_dsp " + std::to_string(max_dsp));
85818707
else // RUN based on DSP19x2 mapping
85828708
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();
85948711

85958712
// Check if mult output is connected with Registers output
85968713
if (tech == Technologies::GENESIS_3)
@@ -9276,11 +9393,14 @@ void collect_clocks (RTLIL::Module* module,
92769393
//
92779394
run("write_verilog -noattr -nohex -noexpr core_synthesis.v");
92789395

9396+
if (dsp_limit_exhausted){
9397+
log("\n");
9398+
log_warning("%s\n",dsp_limit_message.c_str());
9399+
}
92799400
if ((max_lut != -1) && (nbLUTx > max_lut)) {
92809401
log("\n");
92819402
log_error("Final netlist LUTs number [%d] exceeds '-max_lut' specified value [%d].\n", nbLUTx, max_lut);
92829403
}
9283-
92849404
if ((max_reg != -1) && (nbREGs > max_reg)) {
92859405
log("\n");
92869406
log_error("Final netlist DFFs number [%d] exceeds '-max_reg' specified value [%d].\n", nbREGs, max_reg);

0 commit comments

Comments
 (0)