Skip to content

DSP device limit implemented in synthesis #408

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Sep 20, 2024
11 changes: 11 additions & 0 deletions src/rs-dsp-multadd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "kernel/ffinit.h"
#include "kernel/ff.h"

extern int Count_ADD;
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
150 changes: 135 additions & 15 deletions src/synth_rapidsilicon.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "License_manager.hpp"
#endif

int Count_ADD;
int DSP_COUNTER;
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
Expand Down Expand Up @@ -402,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;
Expand Down Expand Up @@ -8242,6 +8245,127 @@ void collect_clocks (RTLIL::Module* module,
}
}

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)
{
// Early exit if the items map is empty
if (items.empty())
{
return {0, {}}; // Return a sum of 0 and an empty map
}

std::vector<int> dp(dsp_limit + 1, 0);
std::vector<std::vector<RTLIL::Cell *>> 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<RTLIL::Cell *, int> 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<RTLIL::Cell *, int> 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)
{
double sliceA, sliceB;
if (a_signed && b_signed)
{
sliceA = static_cast<double>(_a_width_ - a_signed - 1) / (20 - a_signed);
sliceB = static_cast<double>(_b_width_ - b_signed - 1) / (18 - b_signed);
}
else
{
sliceA = static_cast<double>(_a_width_ - 1) / 20;
sliceB = static_cast<double>(_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<RTLIL::Cell *, int> best_items = result.second;

DSP_COUNTER += best_sum;

for (const auto &cell_info : best_items)
{
cell_info.first->set_bool_attribute(RTLIL::escape_id("valid_map"));
}

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())
{
if (cell->type == RTLIL::escape_id("$mul"))
{
if (!cell->get_bool_attribute(RTLIL::escape_id("valid_map")))
{
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);
}


}

void script() override
{
string readArgs;
Expand Down Expand Up @@ -8572,25 +8696,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)
Expand Down Expand Up @@ -9276,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);
Expand Down