Merge branch 'redist_slack' into 'redist_slack'

Redist slack

See merge request eddiehung/nextpnr!5
This commit is contained in:
Eddie Hung 2018-07-21 19:03:35 +00:00
commit f176ee48cd
13 changed files with 816 additions and 572 deletions

View File

@ -27,6 +27,8 @@
#include <unordered_set> #include <unordered_set>
#include <vector> #include <vector>
#include <boost/functional/hash.hpp>
#ifndef NEXTPNR_H #ifndef NEXTPNR_H
#define NEXTPNR_H #define NEXTPNR_H
@ -158,8 +160,30 @@ struct GraphicElement
std::string text; std::string text;
}; };
struct Loc
{
int x = -1, y = -1, z = -1;
bool operator==(const Loc &other) const { return (x == other.x) && (y == other.y) && (z == other.z); }
bool operator!=(const Loc &other) const { return (x != other.x) || (y != other.y) || (z == other.z); }
};
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END
namespace std {
template <> struct hash<NEXTPNR_NAMESPACE_PREFIX Loc>
{
std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX Loc &obj) const noexcept
{
std::size_t seed = 0;
boost::hash_combine(seed, hash<int>()(obj.x));
boost::hash_combine(seed, hash<int>()(obj.y));
boost::hash_combine(seed, hash<int>()(obj.z));
return seed;
}
};
} // namespace std
#include "archdefs.h" #include "archdefs.h"
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN

View File

@ -402,6 +402,21 @@ struct Router
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
static void prioritise_nets(Context *ctx, std::vector<IdString> &netsArray)
{
std::unordered_map<IdString, delay_t> netScores;
for (auto net_name : netsArray) {
delay_t score = std::numeric_limits<delay_t>::max();
for (const auto &sink : ctx->nets.at(net_name)->users) {
if (sink.budget < score)
score = sink.budget;
}
netScores[net_name] = score;
}
std::sort(netsArray.begin(), netsArray.end(),
[&netScores](IdString a, IdString b) { return netScores[a] < netScores[b]; });
}
bool router1(Context *ctx) bool router1(Context *ctx)
{ {
try { try {
@ -508,7 +523,7 @@ bool router1(Context *ctx)
bool printNets = ctx->verbose && (netsQueue.size() < 10); bool printNets = ctx->verbose && (netsQueue.size() < 10);
std::vector<IdString> netsArray(netsQueue.begin(), netsQueue.end()); std::vector<IdString> netsArray(netsQueue.begin(), netsQueue.end());
ctx->sorted_shuffle(netsArray); prioritise_nets(ctx, netsArray);
netsQueue.clear(); netsQueue.clear();
for (auto net_name : netsArray) { for (auto net_name : netsArray) {
@ -560,7 +575,7 @@ bool router1(Context *ctx)
int ripCnt = 0; int ripCnt = 0;
std::vector<IdString> ripupArray(ripupQueue.begin(), ripupQueue.end()); std::vector<IdString> ripupArray(ripupQueue.begin(), ripupQueue.end());
ctx->sorted_shuffle(ripupArray); prioritise_nets(ctx, ripupArray);
for (auto net_name : ripupArray) { for (auto net_name : ripupArray) {
if (printNets) if (printNets)

View File

@ -217,6 +217,11 @@ void update_budget(Context *ctx)
if (it == updates.end()) continue; if (it == updates.end()) continue;
user.budget = delays.at(pi) + it->second; user.budget = delays.at(pi) + it->second;
// HACK HACK HACK
if (net.second->driver.port == ctx->id("COUT"))
user.budget = 0;
// HACK HACK HACK
// Post-update check // Post-update check
// if (user.budget < 0) // if (user.budget < 0)
// log_warning("port %s.%s, connected to net '%s', has negative " // log_warning("port %s.%s, connected to net '%s', has negative "

View File

@ -29,8 +29,8 @@ void Arch::addWire(IdString name, int x, int y)
NPNR_ASSERT(wires.count(name) == 0); NPNR_ASSERT(wires.count(name) == 0);
WireInfo &wi = wires[name]; WireInfo &wi = wires[name];
wi.name = name; wi.name = name;
wi.grid_x = x; wi.x = x;
wi.grid_y = y; wi.y = y;
wire_ids.push_back(name); wire_ids.push_back(name);
} }
@ -62,18 +62,28 @@ void Arch::addAlias(IdString name, IdString srcWire, IdString dstWire, DelayInfo
pip_ids.push_back(name); pip_ids.push_back(name);
} }
void Arch::addBel(IdString name, IdString type, int x, int y, bool gb) void Arch::addBel(IdString name, IdString type, int x, int y, int z, bool gb)
{ {
Loc loc;
loc.x = x;
loc.y = y;
loc.z = z;
NPNR_ASSERT(bels.count(name) == 0); NPNR_ASSERT(bels.count(name) == 0);
NPNR_ASSERT(bel_by_loc.count(loc) == 0);
BelInfo &bi = bels[name]; BelInfo &bi = bels[name];
bi.name = name; bi.name = name;
bi.type = type; bi.type = type;
bi.grid_x = x; bi.x = x;
bi.grid_y = y; bi.y = y;
bi.z = z;
bi.gb = gb; bi.gb = gb;
bel_ids.push_back(name); bel_ids.push_back(name);
bel_ids_by_type[type].push_back(name); bel_ids_by_type[type].push_back(name);
bel_by_loc[loc] = name;
bels_by_tile[x][y].push_back(name);
} }
void Arch::addBelInput(IdString bel, IdString name, IdString wire) void Arch::addBelInput(IdString bel, IdString name, IdString wire)
@ -348,8 +358,8 @@ const std::vector<GroupId> &Arch::getGroupGroups(GroupId group) const { return g
void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const
{ {
x = bels.at(bel).grid_x; x = bels.at(bel).x;
y = bels.at(bel).grid_y; y = bels.at(bel).y;
gb = bels.at(bel).gb; gb = bels.at(bel).gb;
} }
@ -357,8 +367,8 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const
{ {
const WireInfo &s = wires.at(src); const WireInfo &s = wires.at(src);
const WireInfo &d = wires.at(dst); const WireInfo &d = wires.at(dst);
int dx = abs(s.grid_x - d.grid_x); int dx = abs(s.x - d.x);
int dy = abs(s.grid_y - d.grid_y); int dy = abs(s.y - d.y);
return (dx + dy) * grid_distance_to_delay; return (dx + dy) * grid_distance_to_delay;
} }

View File

@ -44,7 +44,7 @@ struct WireInfo
BelPin uphill_bel_pin; BelPin uphill_bel_pin;
std::vector<BelPin> downhill_bel_pins; std::vector<BelPin> downhill_bel_pins;
DecalXY decalxy; DecalXY decalxy;
int grid_x, grid_y; int x, y;
}; };
struct PinInfo struct PinInfo
@ -59,7 +59,7 @@ struct BelInfo
IdString name, type, bound_cell; IdString name, type, bound_cell;
std::unordered_map<IdString, PinInfo> pins; std::unordered_map<IdString, PinInfo> pins;
DecalXY decalxy; DecalXY decalxy;
int grid_x, grid_y; int x, y, z;
bool gb; bool gb;
}; };
@ -85,6 +85,9 @@ struct Arch : BaseCtx
std::vector<IdString> bel_ids, wire_ids, pip_ids; std::vector<IdString> bel_ids, wire_ids, pip_ids;
std::unordered_map<IdString, std::vector<IdString>> bel_ids_by_type; std::unordered_map<IdString, std::vector<IdString>> bel_ids_by_type;
std::unordered_map<Loc, BelId> bel_by_loc;
std::unordered_map<int, std::unordered_map<int, std::vector<BelId>>> bels_by_tile;
std::unordered_map<DecalId, std::vector<GraphicElement>> decal_graphics; std::unordered_map<DecalId, std::vector<GraphicElement>> decal_graphics;
DecalXY frame_decalxy; DecalXY frame_decalxy;
@ -94,7 +97,7 @@ struct Arch : BaseCtx
void addPip(IdString name, IdString srcWire, IdString dstWire, DelayInfo delay); void addPip(IdString name, IdString srcWire, IdString dstWire, DelayInfo delay);
void addAlias(IdString name, IdString srcWire, IdString dstWire, DelayInfo delay); void addAlias(IdString name, IdString srcWire, IdString dstWire, DelayInfo delay);
void addBel(IdString name, IdString type, int x, int y, bool gb); void addBel(IdString name, IdString type, int x, int y, int z, bool gb);
void addBelInput(IdString bel, IdString name, IdString wire); void addBelInput(IdString bel, IdString name, IdString wire);
void addBelOutput(IdString bel, IdString name, IdString wire); void addBelOutput(IdString bel, IdString name, IdString wire);
void addBelInout(IdString bel, IdString name, IdString wire); void addBelInout(IdString bel, IdString name, IdString wire);
@ -129,6 +132,10 @@ struct Arch : BaseCtx
BelId getBelByName(IdString name) const; BelId getBelByName(IdString name) const;
IdString getBelName(BelId bel) const; IdString getBelName(BelId bel) const;
Loc getBelLocation(BelId bel) const;
BelId getBelByLocation(Loc loc) const;
std::vector<BelId> getBelsByTile(int x, int y) const;
bool getBelGlobalBuf(BelId bel) const;
uint32_t getBelChecksum(BelId bel) const; uint32_t getBelChecksum(BelId bel) const;
void bindBel(BelId bel, IdString cell, PlaceStrength strength); void bindBel(BelId bel, IdString cell, PlaceStrength strength);
void unbindBel(BelId bel); void unbindBel(BelId bel);

View File

@ -230,6 +230,9 @@ void DesignWidget::addToHistory(QTreeWidgetItem *item)
void DesignWidget::newContext(Context *ctx) void DesignWidget::newContext(Context *ctx)
{ {
treeWidget->clear(); treeWidget->clear();
// reset pointers since they are not valid after clear
nets_root = nullptr;
cells_root = nullptr;
history_ignore = false; history_ignore = false;
history_index = -1; history_index = -1;
history.clear(); history.clear();
@ -334,16 +337,7 @@ void DesignWidget::newContext(Context *ctx)
for (auto pip : nameToItem[2].toStdMap()) { for (auto pip : nameToItem[2].toStdMap()) {
pip_root->addChild(pip.second); pip_root->addChild(pip.second);
} }
updateTree();
// Add nets to tree
nets_root = new QTreeWidgetItem(treeWidget);
nets_root->setText(0, "Nets");
treeWidget->insertTopLevelItem(0, nets_root);
// Add cells to tree
cells_root = new QTreeWidgetItem(treeWidget);
cells_root->setText(0, "Cells");
treeWidget->insertTopLevelItem(0, cells_root);
} }
void DesignWidget::updateTree() void DesignWidget::updateTree()

View File

@ -25,7 +25,7 @@
#include "placer1.h" #include "placer1.h"
#include "router1.h" #include "router1.h"
#include "util.h" #include "util.h"
#include "cells.h"
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@ -255,11 +255,52 @@ BelId Arch::getBelByName(IdString name) const
return ret; return ret;
} }
BelId Arch::getBelByLocation(Loc loc) const
{
BelId bel;
if (bel_by_loc.empty()) {
for (int i = 0; i < chip_info->num_bels; i++) {
BelId b;
b.index = i;
bel_by_loc[getBelLocation(b)] = i;
}
}
auto it = bel_by_loc.find(loc);
if (it != bel_by_loc.end())
bel.index = it->second;
return bel;
}
BelRange Arch::getBelsByTile(int x, int y) const
{
// In iCE40 chipdb bels at the same tile are consecutive and dense z ordinates are used
BelRange br;
Loc loc;
loc.x = x;
loc.y = y;
loc.z = 0;
br.b.cursor = Arch::getBelByLocation(loc).index;
br.e.cursor = br.b.cursor;
if (br.e.cursor != -1) {
while (br.e.cursor < chip_info->num_bels &&
chip_info->bel_data[br.e.cursor].x == x &&
chip_info->bel_data[br.e.cursor].y == y)
br.e.cursor++;
}
return br;
}
BelRange Arch::getBelsAtSameTile(BelId bel) const BelRange Arch::getBelsAtSameTile(BelId bel) const
{ {
BelRange br; BelRange br;
NPNR_ASSERT(bel != BelId()); NPNR_ASSERT(bel != BelId());
// This requires Bels at the same tile are consecutive
int x = chip_info->bel_data[bel.index].x; int x = chip_info->bel_data[bel.index].x;
int y = chip_info->bel_data[bel.index].y; int y = chip_info->bel_data[bel.index].y;
int start = bel.index, end = bel.index; int start = bel.index, end = bel.index;
@ -704,6 +745,14 @@ void Arch::assignArchInfo()
NetInfo *ni = net.second.get(); NetInfo *ni = net.second.get();
if (isGlobalNet(ni)) if (isGlobalNet(ni))
ni->is_global = true; ni->is_global = true;
ni->is_enable = false;
ni->is_reset = false;
for (auto usr : ni->users) {
if (is_enable_port(this, usr))
ni->is_enable = true;
if (is_reset_port(this, usr))
ni->is_reset = true;
}
} }
for (auto &cell : getCtx()->cells) { for (auto &cell : getCtx()->cells) {
CellInfo *ci = cell.second.get(); CellInfo *ci = cell.second.get();

View File

@ -350,6 +350,7 @@ struct Arch : BaseCtx
mutable std::unordered_map<IdString, int> bel_by_name; mutable std::unordered_map<IdString, int> bel_by_name;
mutable std::unordered_map<IdString, int> wire_by_name; mutable std::unordered_map<IdString, int> wire_by_name;
mutable std::unordered_map<IdString, int> pip_by_name; mutable std::unordered_map<IdString, int> pip_by_name;
mutable std::unordered_map<Loc, int> bel_by_loc;
std::vector<IdString> bel_to_cell; std::vector<IdString> bel_to_cell;
std::vector<IdString> wire_to_net; std::vector<IdString> wire_to_net;
@ -440,7 +441,24 @@ struct Arch : BaseCtx
return range; return range;
} }
BelRange getBelsAtSameTile(BelId bel) const; Loc getBelLocation(BelId bel) const
{
Loc loc;
loc.x = chip_info->bel_data[bel.index].x;
loc.y = chip_info->bel_data[bel.index].y;
loc.z = chip_info->bel_data[bel.index].z;
return loc;
}
BelId getBelByLocation(Loc loc) const;
BelRange getBelsByTile(int x, int y) const;
bool getBelGlobalBuf(BelId bel) const
{
return chip_info->bel_data[bel.index].type == TYPE_SB_GB;
}
BelRange getBelsAtSameTile(BelId bel) const NPNR_DEPRECATED;
BelType getBelType(BelId bel) const BelType getBelType(BelId bel) const
{ {
@ -671,7 +689,7 @@ struct Arch : BaseCtx
// ------------------------------------------------- // -------------------------------------------------
void estimatePosition(BelId bel, int &x, int &y, bool &gb) const; void estimatePosition(BelId bel, int &x, int &y, bool &gb) const NPNR_DEPRECATED;
delay_t estimateDelay(WireId src, WireId dst) const; delay_t estimateDelay(WireId src, WireId dst) const;
delay_t getDelayEpsilon() const { return 20; } delay_t getDelayEpsilon() const { return 20; }
delay_t getRipupDelayPenalty() const { return 200; } delay_t getRipupDelayPenalty() const { return 200; }

View File

@ -108,21 +108,15 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
} else if (cell->type == id_sb_io) { } else if (cell->type == id_sb_io) {
return getBelPackagePin(bel) != ""; return getBelPackagePin(bel) != "";
} else if (cell->type == id_sb_gb) { } else if (cell->type == id_sb_gb) {
bool is_reset = false, is_cen = false;
NPNR_ASSERT(cell->ports.at(id_glb_buf_out).net != nullptr); NPNR_ASSERT(cell->ports.at(id_glb_buf_out).net != nullptr);
for (auto user : cell->ports.at(id_glb_buf_out).net->users) { const NetInfo *net = cell->ports.at(id_glb_buf_out).net;
if (is_reset_port(this, user))
is_reset = true;
if (is_enable_port(this, user))
is_cen = true;
}
IdString glb_net = getWireName(getWireBelPin(bel, PIN_GLOBAL_BUFFER_OUTPUT)); IdString glb_net = getWireName(getWireBelPin(bel, PIN_GLOBAL_BUFFER_OUTPUT));
int glb_id = std::stoi(std::string("") + glb_net.str(this).back()); int glb_id = std::stoi(std::string("") + glb_net.str(this).back());
if (is_reset && is_cen) if (net->is_reset && net->is_enable)
return false; return false;
else if (is_reset) else if (net->is_reset)
return (glb_id % 2) == 0; return (glb_id % 2) == 0;
else if (is_cen) else if (net->is_enable)
return (glb_id % 2) == 1; return (glb_id % 2) == 1;
else else
return true; return true;

View File

@ -21,8 +21,6 @@
#error Include "archdefs.h" via "nextpnr.h" only. #error Include "archdefs.h" via "nextpnr.h" only.
#endif #endif
#include <boost/functional/hash.hpp>
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
typedef int delay_t; typedef int delay_t;
@ -153,6 +151,7 @@ struct DecalId
struct ArchNetInfo struct ArchNetInfo
{ {
bool is_global = false; bool is_global = false;
bool is_reset = false, is_enable = false;
}; };
struct NetInfo; struct NetInfo;

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,7 @@
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
void write_asc(const Context *ctx, std::ostream &out); void write_asc(const Context *ctx, std::ostream &out);
bool read_asc(Context *ctx, std::istream &in);
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END

View File

@ -66,6 +66,12 @@ void svg_dump_decal(const Context *ctx, const DecalXY &decal)
} }
} }
void conflicting_options(const boost::program_options::variables_map &vm, const char *opt1, const char *opt2)
{
if (vm.count(opt1) && !vm[opt1].defaulted() && vm.count(opt2) && !vm[opt2].defaulted())
log_error((std::string("Conflicting options '") + opt1 + "' and '" + opt2 + "'.").c_str());
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
try { try {
@ -95,6 +101,7 @@ int main(int argc, char *argv[])
options.add_options()("json", po::value<std::string>(), "JSON design file to ingest"); options.add_options()("json", po::value<std::string>(), "JSON design file to ingest");
options.add_options()("pcf", po::value<std::string>(), "PCF constraints file to ingest"); options.add_options()("pcf", po::value<std::string>(), "PCF constraints file to ingest");
options.add_options()("asc", po::value<std::string>(), "asc bitstream file to write"); options.add_options()("asc", po::value<std::string>(), "asc bitstream file to write");
options.add_options()("read", po::value<std::string>(), "asc bitstream file to read");
options.add_options()("seed", po::value<int>(), "seed value for random number generator"); options.add_options()("seed", po::value<int>(), "seed value for random number generator");
options.add_options()("version,V", "show version"); options.add_options()("version,V", "show version");
options.add_options()("tmfuzz", "run path delay estimate fuzzer"); options.add_options()("tmfuzz", "run path delay estimate fuzzer");
@ -121,13 +128,17 @@ int main(int argc, char *argv[])
po::store(parsed, vm); po::store(parsed, vm);
po::notify(vm); po::notify(vm);
} } catch (std::exception &e) {
catch (std::exception &e) {
std::cout << e.what() << "\n"; std::cout << e.what() << "\n";
return 1; return 1;
} }
conflicting_options(vm, "read", "json");
#ifndef ICE40_HX1K_ONLY
if ((vm.count("lp384") + vm.count("lp1k") + vm.count("lp8k") + vm.count("hx1k") + vm.count("hx8k") +
vm.count("up5k")) > 1)
log_error("Only one device type can be set\n");
#endif
if (vm.count("help") || argc == 1) { if (vm.count("help") || argc == 1) {
help: help:
std::cout << boost::filesystem::basename(argv[0]) std::cout << boost::filesystem::basename(argv[0])
@ -353,6 +364,13 @@ int main(int argc, char *argv[])
if (vm.count("no-tmdriv")) if (vm.count("no-tmdriv"))
ctx->timing_driven = false; ctx->timing_driven = false;
if (vm.count("read")) {
std::string filename = vm["read"].as<std::string>();
std::ifstream f(filename);
if (!read_asc(ctx.get(), f))
log_error("Loading ASC failed.\n");
}
#ifndef NO_GUI #ifndef NO_GUI
if (vm.count("gui")) { if (vm.count("gui")) {
Application a(argc, argv); Application a(argc, argv);