ecp5: Add criticality-based LUT permutation
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
f363dd2d3c
commit
a0fa164399
12
ecp5/arch.cc
12
ecp5/arch.cc
@ -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()
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "design_utils.h"
|
||||
#include "globals.h"
|
||||
#include "log.h"
|
||||
#include "timing.h"
|
||||
#include "util.h"
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user