ecp5: Add criticality-based LUT permutation

Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
David Shah 2019-02-25 11:06:33 +00:00
parent f363dd2d3c
commit a0fa164399
4 changed files with 88 additions and 1 deletions

View File

@ -486,7 +486,7 @@ delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const
int dx = abs(driver_loc.x - sink_loc.x), dy = abs(driver_loc.y - sink_loc.y);
return (130 - 25 * args.speed) *
(4 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5)));
(6 + std::max(dx - 5, 0) + std::max(dy - 5, 0) + 2 * (std::min(dx, 5) + std::min(dy, 5)));
}
bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const
@ -504,7 +504,17 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay
// -----------------------------------------------------------------------
<<<<<<< HEAD
bool Arch::place() { return placer1(getCtx(), Placer1Cfg(getCtx())); }
=======
bool Arch::place()
{
bool result = placer_heap(getCtx());
if (result)
permute_luts();
return result;
}
>>>>>>> 136e030... lut permutation
bool Arch::route()
{

View File

@ -971,6 +971,8 @@ struct Arch : BaseCtx
void assignArchInfo();
void permute_luts();
std::vector<std::pair<std::string, std::string>> getTilesAtLocation(int row, int col);
std::string getTileByTypeAndLocation(int row, int col, std::string type) const
{

View File

@ -18,8 +18,10 @@
*/
#include "cells.h"
#include "design_utils.h"
#include "log.h"
#include "nextpnr.h"
#include "timing.h"
#include "util.h"
NEXTPNR_NAMESPACE_BEGIN
@ -115,4 +117,76 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
}
}
void Arch::permute_luts()
{
NetCriticalityMap nc;
get_criticalities(getCtx(), &nc);
std::unordered_map<PortInfo *, size_t> port_to_user;
for (auto net : sorted(nets)) {
NetInfo *ni = net.second;
for (size_t i = 0; i < ni->users.size(); i++) {
auto &usr = ni->users.at(i);
port_to_user[&(usr.cell->ports.at(usr.port))] = i;
}
}
auto proc_lut = [&](CellInfo *ci, int lut) {
std::vector<IdString> port_names;
for (int i = 0; i < 4; i++)
port_names.push_back(id(std::string("ABCD").substr(i, 1) + std::to_string(lut)));
std::vector<std::pair<float, int>> inputs;
std::vector<NetInfo *> orig_nets;
for (int i = 0; i < 4; i++) {
auto &port = ci->ports.at(port_names.at(i));
float crit = 0;
if (port.net != nullptr && nc.count(port.net->name)) {
auto &n = nc.at(port.net->name);
size_t usr = port_to_user.at(&port);
if (usr < n.criticality.size())
crit = n.criticality.at(usr);
}
orig_nets.push_back(port.net);
inputs.emplace_back(crit, i);
}
// Least critical first (A input is slowest)
std::sort(inputs.begin(), inputs.end());
for (int i = 0; i < 4; i++) {
IdString p = port_names.at(i);
// log_info("%s %s %f\n", p.c_str(ctx), port_names.at(inputs.at(i).second).c_str(ctx), inputs.at(i).first);
disconnect_port(getCtx(), ci, p);
ci->ports.at(p).net = nullptr;
if (orig_nets.at(inputs.at(i).second) != nullptr) {
connect_port(getCtx(), orig_nets.at(inputs.at(i).second), ci, p);
ci->params[id(p.str(this) + "MUX")] = p.str(this);
} else {
ci->params[id(p.str(this) + "MUX")] = "1";
}
}
// Rewrite function
int old_init = int_or_default(ci->params, id("LUT" + std::to_string(lut) + "_INITVAL"), 0);
int new_init = 0;
for (int i = 0; i < 16; i++) {
int old_index = 0;
for (int k = 0; k < 4; k++) {
if (i & (1 << k))
old_index |= (1 << inputs.at(k).second);
}
if (old_init & (1 << old_index))
new_init |= (1 << i);
}
ci->params[id("LUT" + std::to_string(lut) + "_INITVAL")] = std::to_string(new_init);
};
for (auto cell : sorted(cells)) {
CellInfo *ci = cell.second;
if (ci->type == id_TRELLIS_SLICE && str_or_default(ci->params, id("MODE"), "LOGIC") == "LOGIC") {
proc_lut(ci, 0);
proc_lut(ci, 1);
}
}
}
NEXTPNR_NAMESPACE_END

View File

@ -27,6 +27,7 @@
#include "design_utils.h"
#include "globals.h"
#include "log.h"
#include "timing.h"
#include "util.h"
NEXTPNR_NAMESPACE_BEGIN