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
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
117 changes: 103 additions & 14 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 @@ -8202,6 +8203,101 @@ 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)
{
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)
{
if (a_signed && b_signed)
{
double sliceA = static_cast<double>(_a_width_ - a_signed - 1) / (20 - a_signed);
double sliceB = static_cast<double>(_b_width_ - b_signed - 1) / (18 - b_signed);
int nodsp = round(sliceA) * round(sliceB);
dsp_control[cell] = nodsp;
}
else
{
double sliceA = static_cast<double>(_a_width_ - 1) / (20);
double 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 = 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;
Expand Down Expand Up @@ -8532,25 +8628,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
Loading