Use hashlib for core netlist structures
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
ff72454f83
commit
579b98c596
@ -59,29 +59,29 @@ struct BaseCtx
|
||||
mutable StrRingBuffer log_strs;
|
||||
|
||||
// Project settings and config switches
|
||||
std::unordered_map<IdString, Property> settings;
|
||||
dict<IdString, Property> settings;
|
||||
|
||||
// Placed nets and cells.
|
||||
std::unordered_map<IdString, std::unique_ptr<NetInfo>> nets;
|
||||
std::unordered_map<IdString, std::unique_ptr<CellInfo>> cells;
|
||||
dict<IdString, std::unique_ptr<NetInfo>> nets;
|
||||
dict<IdString, std::unique_ptr<CellInfo>> cells;
|
||||
|
||||
// Hierarchical (non-leaf) cells by full path
|
||||
std::unordered_map<IdString, HierarchicalCell> hierarchy;
|
||||
dict<IdString, HierarchicalCell> hierarchy;
|
||||
// This is the root of the above structure
|
||||
IdString top_module;
|
||||
|
||||
// Aliases for nets, which may have more than one name due to assignments and hierarchy
|
||||
std::unordered_map<IdString, IdString> net_aliases;
|
||||
dict<IdString, IdString> net_aliases;
|
||||
|
||||
// Top-level ports
|
||||
std::unordered_map<IdString, PortInfo> ports;
|
||||
std::unordered_map<IdString, CellInfo *> port_cells;
|
||||
dict<IdString, PortInfo> ports;
|
||||
dict<IdString, CellInfo *> port_cells;
|
||||
|
||||
// Floorplanning regions
|
||||
std::unordered_map<IdString, std::unique_ptr<Region>> region;
|
||||
dict<IdString, std::unique_ptr<Region>> region;
|
||||
|
||||
// Context meta data
|
||||
std::unordered_map<IdString, Property> attrs;
|
||||
dict<IdString, Property> attrs;
|
||||
|
||||
Context *as_ctx = nullptr;
|
||||
|
||||
@ -186,10 +186,10 @@ struct BaseCtx
|
||||
|
||||
bool allUiReload = true;
|
||||
bool frameUiReload = false;
|
||||
std::unordered_set<BelId> belUiReload;
|
||||
std::unordered_set<WireId> wireUiReload;
|
||||
std::unordered_set<PipId> pipUiReload;
|
||||
std::unordered_set<GroupId> groupUiReload;
|
||||
pool<BelId> belUiReload;
|
||||
pool<WireId> wireUiReload;
|
||||
pool<PipId> pipUiReload;
|
||||
pool<GroupId> groupUiReload;
|
||||
|
||||
void refreshUi() { allUiReload = true; }
|
||||
|
||||
|
@ -37,10 +37,10 @@ std::vector<CellChain> find_chains(const Context *ctx, F1 cell_type_predicate, F
|
||||
{
|
||||
std::set<IdString> chained;
|
||||
std::vector<CellChain> chains;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
for (auto &cell : ctx->cells) {
|
||||
if (chained.find(cell.first) != chained.end())
|
||||
continue;
|
||||
CellInfo *ci = cell.second;
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (cell_type_predicate(ctx, ci)) {
|
||||
CellInfo *start = ci;
|
||||
CellInfo *prev_start = ci;
|
||||
|
@ -389,8 +389,8 @@ struct FixupHierarchyWorker
|
||||
// Update hierarchy structure for nets and cells that have hiercell set
|
||||
void rebuild_hierarchy()
|
||||
{
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->hierpath == IdString())
|
||||
ci->hierpath = ctx->top_module;
|
||||
auto &hc = ctx->hierarchy.at(ci->hierpath);
|
||||
|
@ -339,6 +339,10 @@ template <typename K, typename T, typename OPS> class dict
|
||||
}
|
||||
|
||||
public:
|
||||
using key_type = K;
|
||||
using mapped_type = T;
|
||||
using value_type = std::pair<K, T>;
|
||||
|
||||
class const_iterator : public std::iterator<std::forward_iterator_tag, std::pair<K, T>>
|
||||
{
|
||||
friend class dict;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <unordered_set>
|
||||
|
||||
#include "archdefs.h"
|
||||
#include "hashlib.h"
|
||||
#include "nextpnr_base_types.h"
|
||||
#include "nextpnr_namespaces.h"
|
||||
#include "property.h"
|
||||
@ -56,9 +57,9 @@ struct Region
|
||||
bool constr_wires = false;
|
||||
bool constr_pips = false;
|
||||
|
||||
std::unordered_set<BelId> bels;
|
||||
std::unordered_set<WireId> wires;
|
||||
std::unordered_set<Loc> piplocs;
|
||||
pool<BelId> bels;
|
||||
pool<WireId> wires;
|
||||
pool<Loc> piplocs;
|
||||
};
|
||||
|
||||
struct PipMap
|
||||
@ -128,10 +129,10 @@ struct NetInfo : ArchNetInfo
|
||||
|
||||
PortRef driver;
|
||||
std::vector<PortRef> users;
|
||||
std::unordered_map<IdString, Property> attrs;
|
||||
dict<IdString, Property> attrs;
|
||||
|
||||
// wire -> uphill_pip
|
||||
std::unordered_map<WireId, PipMap> wires;
|
||||
dict<WireId, PipMap> wires;
|
||||
|
||||
std::vector<IdString> aliases; // entries in net_aliases that point to this net
|
||||
|
||||
@ -159,8 +160,8 @@ struct CellInfo : ArchCellInfo
|
||||
IdString name, type, hierpath;
|
||||
int32_t udata;
|
||||
|
||||
std::unordered_map<IdString, PortInfo> ports;
|
||||
std::unordered_map<IdString, Property> attrs, params;
|
||||
dict<IdString, PortInfo> ports;
|
||||
dict<IdString, Property> attrs, params;
|
||||
|
||||
BelId bel;
|
||||
PlaceStrength belStrength = STRENGTH_NONE;
|
||||
@ -232,13 +233,13 @@ struct HierarchicalCell
|
||||
{
|
||||
IdString name, type, parent, fullpath;
|
||||
// Name inside cell instance -> global name
|
||||
std::unordered_map<IdString, IdString> leaf_cells, nets;
|
||||
dict<IdString, IdString> leaf_cells, nets;
|
||||
// Global name -> name inside cell instance
|
||||
std::unordered_map<IdString, IdString> leaf_cells_by_gname, nets_by_gname;
|
||||
dict<IdString, IdString> leaf_cells_by_gname, nets_by_gname;
|
||||
// Cell port to net
|
||||
std::unordered_map<IdString, HierarchicalPort> ports;
|
||||
dict<IdString, HierarchicalPort> ports;
|
||||
// Name inside cell instance -> global name
|
||||
std::unordered_map<IdString, IdString> hier_cells;
|
||||
dict<IdString, IdString> hier_cells;
|
||||
};
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
@ -377,9 +377,9 @@ class ConstraintLegaliseWorker
|
||||
public:
|
||||
ConstraintLegaliseWorker(Context *ctx) : ctx(ctx)
|
||||
{
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
for (auto &cell : ctx->cells) {
|
||||
if (cell.second->cluster != ClusterId())
|
||||
cluster2cells[cell.second->cluster].push_back(cell.second);
|
||||
cluster2cells[cell.second->cluster].push_back(cell.second.get());
|
||||
}
|
||||
};
|
||||
|
||||
@ -414,11 +414,11 @@ class ConstraintLegaliseWorker
|
||||
int legalise_constraints()
|
||||
{
|
||||
log_info("Legalising relative constraints...\n");
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
for (auto &cell : ctx->cells) {
|
||||
oldLocations[cell.first] = ctx->getBelLocation(cell.second->bel);
|
||||
}
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
bool res = legalise_cell(cell.second);
|
||||
for (auto &cell : ctx->cells) {
|
||||
bool res = legalise_cell(cell.second.get());
|
||||
if (!res) {
|
||||
log_error("failed to place chain starting at cell '%s'\n", cell.first.c_str(ctx));
|
||||
return -1;
|
||||
@ -434,8 +434,8 @@ class ConstraintLegaliseWorker
|
||||
}
|
||||
}
|
||||
auto score = print_stats("replacing ripped up cells");
|
||||
for (auto cell : sorted(ctx->cells))
|
||||
if (get_constraints_distance(ctx, cell.second) != 0)
|
||||
for (auto &cell : ctx->cells)
|
||||
if (get_constraints_distance(ctx, cell.second.get()) != 0)
|
||||
log_error("constraint satisfaction check failed for cell '%s' at Bel '%s'\n", cell.first.c_str(ctx),
|
||||
ctx->nameOfBel(cell.second->bel));
|
||||
return score;
|
||||
|
@ -88,7 +88,7 @@ class SAPlacer
|
||||
diameter = std::max(max_x, max_y) + 1;
|
||||
|
||||
std::unordered_set<IdString> cell_types_in_use;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
for (auto &cell : ctx->cells) {
|
||||
IdString cell_type = cell.second->type;
|
||||
cell_types_in_use.insert(cell_type);
|
||||
}
|
||||
@ -108,8 +108,8 @@ class SAPlacer
|
||||
net.second->udata = n++;
|
||||
net_by_udata.push_back(net.second.get());
|
||||
}
|
||||
for (auto ®ion : sorted(ctx->region)) {
|
||||
Region *r = region.second;
|
||||
for (auto ®ion : ctx->region) {
|
||||
Region *r = region.second.get();
|
||||
BoundingBox bb;
|
||||
if (r->constr_bels) {
|
||||
bb.x0 = std::numeric_limits<int>::max();
|
||||
@ -360,12 +360,12 @@ class SAPlacer
|
||||
// Only increase temperature if something was moved
|
||||
autoplaced.clear();
|
||||
chain_basis.clear();
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
for (auto &cell : ctx->cells) {
|
||||
if (cell.second->belStrength <= STRENGTH_STRONG && cell.second->cluster != ClusterId() &&
|
||||
ctx->getClusterRootCell(cell.second->cluster) == cell.second)
|
||||
chain_basis.push_back(cell.second);
|
||||
ctx->getClusterRootCell(cell.second->cluster) == cell.second.get())
|
||||
chain_basis.push_back(cell.second.get());
|
||||
else if (cell.second->belStrength < STRENGTH_STRONG)
|
||||
autoplaced.push_back(cell.second);
|
||||
autoplaced.push_back(cell.second.get());
|
||||
}
|
||||
// temp = post_legalise_temp;
|
||||
// diameter = std::min<int>(M, diameter * post_legalise_dia_scale);
|
||||
@ -421,8 +421,8 @@ class SAPlacer
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto cell : sorted(ctx->cells))
|
||||
if (get_constraints_distance(ctx, cell.second) != 0)
|
||||
for (auto &cell : ctx->cells)
|
||||
if (get_constraints_distance(ctx, cell.second.get()) != 0)
|
||||
log_error("constraint satisfaction check failed for cell '%s' at Bel '%s'\n", cell.first.c_str(ctx),
|
||||
ctx->nameOfBel(cell.second->bel));
|
||||
timing_analysis(ctx);
|
||||
@ -831,8 +831,8 @@ class SAPlacer
|
||||
// Set up the cost maps
|
||||
void setup_costs()
|
||||
{
|
||||
for (auto net : sorted(ctx->nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
if (ignore_net(ni))
|
||||
continue;
|
||||
net_bounds[ni->udata] = get_net_bounds(ni);
|
||||
@ -1118,8 +1118,8 @@ class SAPlacer
|
||||
// Build the cell port -> user index
|
||||
void build_port_index()
|
||||
{
|
||||
for (auto net : sorted(ctx->nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
for (size_t i = 0; i < ni->users.size(); i++) {
|
||||
auto &usr = ni->users.at(i);
|
||||
fast_port_to_user[&(usr.cell->ports.at(usr.port))] = i;
|
||||
@ -1135,8 +1135,8 @@ class SAPlacer
|
||||
{
|
||||
total_net_share = 0;
|
||||
nets_by_tile.resize(max_x + 1, std::vector<std::unordered_map<IdString, int>>(max_y + 1));
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (int(ci->ports.size()) > large_cell_thresh)
|
||||
continue;
|
||||
Loc loc = ctx->getBelLocation(ci->bel);
|
||||
|
@ -146,9 +146,9 @@ class HeAPPlacer
|
||||
tmg.setup_only = true;
|
||||
tmg.setup();
|
||||
|
||||
for (auto cell : sorted(ctx->cells))
|
||||
for (auto &cell : ctx->cells)
|
||||
if (cell.second->cluster != ClusterId())
|
||||
cluster2cells[cell.second->cluster].push_back(cell.second);
|
||||
cluster2cells[cell.second->cluster].push_back(cell.second.get());
|
||||
}
|
||||
|
||||
bool place()
|
||||
@ -283,8 +283,8 @@ class HeAPPlacer
|
||||
stalled = 0;
|
||||
// Save solution
|
||||
solution.clear();
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
solution.emplace_back(cell.second, cell.second->bel, cell.second->belStrength);
|
||||
for (auto &cell : ctx->cells) {
|
||||
solution.emplace_back(cell.second.get(), cell.second->bel, cell.second->belStrength);
|
||||
}
|
||||
} else {
|
||||
++stalled;
|
||||
@ -311,10 +311,10 @@ class HeAPPlacer
|
||||
ctx->bindBel(bel, cell, strength);
|
||||
}
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
for (auto &cell : ctx->cells) {
|
||||
if (cell.second->bel == BelId())
|
||||
log_error("Found unbound cell %s\n", cell.first.c_str(ctx));
|
||||
if (ctx->getBoundBelCell(cell.second->bel) != cell.second)
|
||||
if (ctx->getBoundBelCell(cell.second->bel) != cell.second.get())
|
||||
log_error("Found cell %s with mismatched binding\n", cell.first.c_str(ctx));
|
||||
if (ctx->debug)
|
||||
log_info("AP soln: %s -> %s\n", cell.first.c_str(ctx), ctx->nameOfBel(cell.second->bel));
|
||||
@ -450,7 +450,7 @@ class HeAPPlacer
|
||||
|
||||
std::unordered_set<IdString> cell_types_in_use;
|
||||
std::unordered_set<BelBucketId> buckets_in_use;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
for (auto &cell : ctx->cells) {
|
||||
IdString cell_type = cell.second->type;
|
||||
cell_types_in_use.insert(cell_type);
|
||||
BelBucketId bucket = ctx->getBelBucketForCellType(cell_type);
|
||||
@ -465,8 +465,8 @@ class HeAPPlacer
|
||||
}
|
||||
|
||||
// Determine bounding boxes of region constraints
|
||||
for (auto ®ion : sorted(ctx->region)) {
|
||||
Region *r = region.second;
|
||||
for (auto ®ion : ctx->region) {
|
||||
Region *r = region.second.get();
|
||||
BoundingBox bb;
|
||||
if (r->constr_bels) {
|
||||
bb.x0 = std::numeric_limits<int>::max();
|
||||
@ -539,8 +539,8 @@ class HeAPPlacer
|
||||
ctx->shuffle(t.second.begin(), t.second.end());
|
||||
}
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->bel != BelId()) {
|
||||
Loc loc = ctx->getBelLocation(ci->bel);
|
||||
cell_locs[cell.first].x = loc.x;
|
||||
@ -591,7 +591,7 @@ class HeAPPlacer
|
||||
cell_locs[cell.first].global = ctx->getBelGlobalBuf(bel);
|
||||
|
||||
// FIXME
|
||||
if (has_connectivity(cell.second) && !cfg.ioBufTypes.count(ci->type)) {
|
||||
if (has_connectivity(cell.second.get()) && !cfg.ioBufTypes.count(ci->type)) {
|
||||
bels_used.insert(bel);
|
||||
place_cells.push_back(ci);
|
||||
placed = true;
|
||||
@ -617,7 +617,7 @@ class HeAPPlacer
|
||||
int row = 0;
|
||||
solve_cells.clear();
|
||||
// First clear the udata of all cells
|
||||
for (auto cell : sorted(ctx->cells))
|
||||
for (auto &cell : ctx->cells)
|
||||
cell.second->udata = dont_solve;
|
||||
// Then update cells to be placed, which excludes cell children
|
||||
for (auto cell : place_cells) {
|
||||
@ -671,8 +671,8 @@ class HeAPPlacer
|
||||
|
||||
es.reset();
|
||||
|
||||
for (auto net : sorted(ctx->nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
if (ni->driver.cell == nullptr)
|
||||
continue;
|
||||
if (ni->users.empty())
|
||||
@ -783,8 +783,8 @@ class HeAPPlacer
|
||||
wirelen_t total_hpwl()
|
||||
{
|
||||
wirelen_t hpwl = 0;
|
||||
for (auto net : sorted(ctx->nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
if (ni->driver.cell == nullptr)
|
||||
continue;
|
||||
CellLocation &drvloc = cell_locs.at(ni->driver.cell->name);
|
||||
@ -809,8 +809,8 @@ class HeAPPlacer
|
||||
auto startt = std::chrono::high_resolution_clock::now();
|
||||
|
||||
// Unbind all cells placed in this solution
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->bel != BelId() &&
|
||||
(ci->udata != dont_solve ||
|
||||
(ci->cluster != ClusterId() && ctx->getClusterRootCell(ci->cluster)->udata != dont_solve)))
|
||||
|
@ -164,10 +164,10 @@ PYBIND11_EMBEDDED_MODULE(MODULE_NAME, m)
|
||||
.def("maxFallDelay", &DelayQuad::maxFallDelay)
|
||||
.def("delayPair", &DelayQuad::delayPair);
|
||||
|
||||
typedef std::unordered_map<IdString, Property> AttrMap;
|
||||
typedef std::unordered_map<IdString, PortInfo> PortMap;
|
||||
typedef std::unordered_map<IdString, IdString> IdIdMap;
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<Region>> RegionMap;
|
||||
typedef dict<IdString, Property> AttrMap;
|
||||
typedef dict<IdString, PortInfo> PortMap;
|
||||
typedef dict<IdString, IdString> IdIdMap;
|
||||
typedef dict<IdString, std::unique_ptr<Region>> RegionMap;
|
||||
|
||||
py::class_<BaseCtx>(m, "BaseCtx");
|
||||
|
||||
@ -218,9 +218,9 @@ PYBIND11_EMBEDDED_MODULE(MODULE_NAME, m)
|
||||
pass_through<PortType>>::def_wrap(pi_cls, "type");
|
||||
|
||||
typedef std::vector<PortRef> PortRefVector;
|
||||
typedef std::unordered_map<WireId, PipMap> WireMap;
|
||||
typedef std::unordered_set<BelId> BelSet;
|
||||
typedef std::unordered_set<WireId> WireSet;
|
||||
typedef dict<WireId, PipMap> WireMap;
|
||||
typedef pool<BelId> BelSet;
|
||||
typedef pool<WireId> WireSet;
|
||||
|
||||
auto ni_cls = py::class_<ContextualWrapper<NetInfo &>>(m, "NetInfo");
|
||||
readwrite_wrapper<NetInfo &, decltype(&NetInfo::name), &NetInfo::name, conv_to_str<IdString>,
|
||||
|
@ -131,8 +131,8 @@ struct Router2
|
||||
nets.resize(ctx->nets.size());
|
||||
nets_by_udata.resize(ctx->nets.size());
|
||||
size_t i = 0;
|
||||
for (auto net : sorted(ctx->nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
ni->udata = i;
|
||||
nets_by_udata.at(i) = ni;
|
||||
nets.at(i).arcs.resize(ni->users.size());
|
||||
@ -231,8 +231,8 @@ struct Router2
|
||||
flat_wires.push_back(pwd);
|
||||
}
|
||||
|
||||
for (auto net_pair : sorted(ctx->nets)) {
|
||||
auto *net = net_pair.second;
|
||||
for (auto &net_pair : ctx->nets) {
|
||||
auto *net = net_pair.second.get();
|
||||
auto &nd = nets.at(net->udata);
|
||||
for (size_t usr = 0; usr < net->users.size(); usr++) {
|
||||
auto &ad = nd.arcs.at(usr);
|
||||
|
@ -254,9 +254,9 @@ void Context::writeSDF(std::ostream &out, bool cvc_mode) const
|
||||
return rf;
|
||||
};
|
||||
|
||||
for (auto cell : sorted(cells)) {
|
||||
for (const auto &cell : cells) {
|
||||
Cell sc;
|
||||
const CellInfo *ci = cell.second;
|
||||
const CellInfo *ci = cell.second.get();
|
||||
sc.instance = ci->name.str(this);
|
||||
sc.celltype = ci->type.str(this);
|
||||
for (auto port : ci->ports) {
|
||||
@ -313,8 +313,8 @@ void Context::writeSDF(std::ostream &out, bool cvc_mode) const
|
||||
wr.cells.push_back(sc);
|
||||
}
|
||||
|
||||
for (auto net : sorted(nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
if (ni->driver.cell == nullptr)
|
||||
continue;
|
||||
for (auto &usr : ni->users) {
|
||||
|
@ -52,17 +52,17 @@ void TimingAnalyser::run()
|
||||
void TimingAnalyser::init_ports()
|
||||
{
|
||||
// Per cell port structures
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto port : sorted_ref(ci->ports)) {
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
for (auto &port : ci->ports) {
|
||||
auto &data = ports[CellPortKey(ci->name, port.first)];
|
||||
data.type = port.second.type;
|
||||
data.cell_port = CellPortKey(ci->name, port.first);
|
||||
}
|
||||
}
|
||||
// Cell port to net port mapping
|
||||
for (auto net : sorted(ctx->nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
if (ni->driver.cell != nullptr)
|
||||
ports[CellPortKey(ni->driver)].net_port = NetPortKey(ni->name);
|
||||
for (size_t i = 0; i < ni->users.size(); i++)
|
||||
@ -138,8 +138,8 @@ void TimingAnalyser::get_cell_delays()
|
||||
|
||||
void TimingAnalyser::get_route_delays()
|
||||
{
|
||||
for (auto net : sorted(ctx->nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
if (ni->driver.cell == nullptr || ni->driver.cell->bel == BelId())
|
||||
continue;
|
||||
for (auto &usr : ni->users) {
|
||||
|
@ -68,8 +68,8 @@ class TimingOptimiser
|
||||
void setup_delay_limits()
|
||||
{
|
||||
max_net_delay.clear();
|
||||
for (auto net : sorted(ctx->nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
if (ni->driver.cell == nullptr)
|
||||
continue;
|
||||
for (auto usr : ni->users) {
|
||||
@ -239,7 +239,7 @@ class TimingOptimiser
|
||||
std::vector<std::pair<NetInfo *, int>> crit_nets;
|
||||
std::vector<IdString> netnames;
|
||||
std::transform(ctx->nets.begin(), ctx->nets.end(), std::back_inserter(netnames),
|
||||
[](const std::pair<const IdString, std::unique_ptr<NetInfo>> &kv) { return kv.first; });
|
||||
[](const std::pair<IdString, std::unique_ptr<NetInfo>> &kv) { return kv.first; });
|
||||
ctx->sorted_shuffle(netnames);
|
||||
for (auto net : netnames) {
|
||||
if (crit_nets.size() >= max_count)
|
||||
|
@ -55,7 +55,7 @@ std::string str_or_default(const Container &ct, const KeyType &key, std::string
|
||||
};
|
||||
|
||||
template <typename KeyType>
|
||||
std::string str_or_default(const std::unordered_map<KeyType, Property> &ct, const KeyType &key, std::string def = "")
|
||||
std::string str_or_default(const dict<KeyType, Property> &ct, const KeyType &key, std::string def = "")
|
||||
{
|
||||
auto found = ct.find(key);
|
||||
if (found == ct.end())
|
||||
@ -78,8 +78,7 @@ template <typename Container, typename KeyType> int int_or_default(const Contain
|
||||
return std::stoi(found->second);
|
||||
};
|
||||
|
||||
template <typename KeyType>
|
||||
int int_or_default(const std::unordered_map<KeyType, Property> &ct, const KeyType &key, int def = 0)
|
||||
template <typename KeyType> int int_or_default(const dict<KeyType, Property> &ct, const KeyType &key, int def = 0)
|
||||
{
|
||||
auto found = ct.find(key);
|
||||
if (found == ct.end())
|
||||
|
@ -99,8 +99,8 @@ void Arch::permute_luts()
|
||||
tmg.setup();
|
||||
|
||||
std::unordered_map<PortInfo *, size_t> port_to_user;
|
||||
for (auto net : sorted(nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
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;
|
||||
@ -157,8 +157,8 @@ void Arch::permute_luts()
|
||||
ci->params[id("LUT" + std::to_string(lut) + "_INITVAL")] = Property(new_init, 16);
|
||||
};
|
||||
|
||||
for (auto cell : sorted(cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_TRELLIS_SLICE && str_or_default(ci->params, id("MODE"), "LOGIC") == "LOGIC") {
|
||||
proc_lut(ci, 0);
|
||||
proc_lut(ci, 1);
|
||||
@ -169,8 +169,8 @@ void Arch::permute_luts()
|
||||
void Arch::setup_wire_locations()
|
||||
{
|
||||
wire_loc_overrides.clear();
|
||||
for (auto cell : sorted(cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->bel == BelId())
|
||||
continue;
|
||||
if (ci->type == id_MULT18X18D || ci->type == id_DCUA || ci->type == id_DDRDLL || ci->type == id_DQSBUFM ||
|
||||
|
@ -44,10 +44,10 @@ void arch_wrap_python(py::module &m)
|
||||
.def("place", &Context::place)
|
||||
.def("route", &Context::route);
|
||||
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap;
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap;
|
||||
typedef std::unordered_map<IdString, IdString> AliasMap;
|
||||
typedef std::unordered_map<IdString, HierarchicalCell> HierarchyMap;
|
||||
typedef dict<IdString, std::unique_ptr<CellInfo>> CellMap;
|
||||
typedef dict<IdString, std::unique_ptr<NetInfo>> NetMap;
|
||||
typedef dict<IdString, IdString> AliasMap;
|
||||
typedef dict<IdString, HierarchicalCell> HierarchyMap;
|
||||
|
||||
auto belpin_cls = py::class_<ContextualWrapper<BelPin>>(m, "BelPin");
|
||||
readonly_wrapper<BelPin, decltype(&BelPin::bel), &BelPin::bel, conv_to_str<BelId>>::def_wrap(belpin_cls, "bel");
|
||||
|
@ -569,8 +569,7 @@ static std::vector<bool> parse_config_str(const Property &p, int length)
|
||||
return word;
|
||||
}
|
||||
|
||||
std::string intstr_or_default(const std::unordered_map<IdString, Property> &ct, const IdString &key,
|
||||
std::string def = "0")
|
||||
std::string intstr_or_default(const dict<IdString, Property> &ct, const IdString &key, std::string def = "0")
|
||||
{
|
||||
auto found = ct.find(key);
|
||||
if (found == ct.end())
|
||||
|
@ -91,8 +91,8 @@ class Ecp5GlobalRouter
|
||||
}
|
||||
// DCCAs must always drive globals
|
||||
std::vector<NetInfo *> clocks;
|
||||
for (auto &cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_DCCA) {
|
||||
NetInfo *glb = ci->ports.at(id_CLKO).net;
|
||||
if (glb != nullptr) {
|
||||
@ -536,8 +536,8 @@ class Ecp5GlobalRouter
|
||||
}
|
||||
std::vector<std::pair<PortRef *, int>> toroute;
|
||||
std::unordered_map<int, NetInfo *> clocks;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_DCCA) {
|
||||
NetInfo *clock = ci->ports.at(id_CLKO).net;
|
||||
NPNR_ASSERT(clock != nullptr);
|
||||
@ -577,8 +577,8 @@ class Ecp5GlobalRouter
|
||||
void route_eclk_sources()
|
||||
{
|
||||
// Try and use dedicated paths if possible
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_ECLKSYNCB || ci->type == id_TRELLIS_ECLKBUF || ci->type == id_ECLKBRIDGECS) {
|
||||
std::vector<IdString> pins;
|
||||
if (ci->type == id_ECLKSYNCB || ci->type == id_TRELLIS_ECLKBUF) {
|
||||
|
@ -270,8 +270,8 @@ void ECP5CommandHandler::customAfterLoad(Context *ctx)
|
||||
log_error("failed to parse LPF file '%s'\n", filename.c_str());
|
||||
}
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_obuf") ||
|
||||
ci->type == ctx->id("$nextpnr_iobuf")) {
|
||||
if (!ci->attrs.count(ctx->id("LOC"))) {
|
||||
|
122
ecp5/pack.cc
122
ecp5/pack.cc
@ -106,8 +106,8 @@ class Ecp5Packer
|
||||
void find_lutff_pairs()
|
||||
{
|
||||
log_info("Finding LUTFF pairs...\n");
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_lut(ctx, ci) || is_pfumx(ctx, ci) || is_l6mux(ctx, ci)) {
|
||||
NetInfo *znet = ci->ports.at(ctx->id("Z")).net;
|
||||
if (znet != nullptr) {
|
||||
@ -262,8 +262,8 @@ class Ecp5Packer
|
||||
{
|
||||
log_info("Finding LUT-LUT pairs...\n");
|
||||
std::unordered_set<IdString> procdLuts;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_lut(ctx, ci) && procdLuts.find(cell.first) == procdLuts.end()) {
|
||||
NetInfo *znet = ci->ports.at(ctx->id("Z")).net;
|
||||
std::vector<NetInfo *> inpnets;
|
||||
@ -392,8 +392,8 @@ class Ecp5Packer
|
||||
}
|
||||
if (ctx->debug) {
|
||||
log_info("Singleton LUTs (packer QoR debug): \n");
|
||||
for (auto cell : sorted(ctx->cells))
|
||||
if (is_lut(ctx, cell.second) && !procdLuts.count(cell.first))
|
||||
for (auto &cell : ctx->cells)
|
||||
if (is_lut(ctx, cell.second.get()) && !procdLuts.count(cell.first))
|
||||
log_info(" %s\n", cell.first.c_str(ctx));
|
||||
}
|
||||
}
|
||||
@ -443,8 +443,8 @@ class Ecp5Packer
|
||||
{
|
||||
log_info("Packing IOs..\n");
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_nextpnr_iob(ctx, ci)) {
|
||||
CellInfo *trio = nullptr;
|
||||
NetInfo *ionet = nullptr;
|
||||
@ -536,8 +536,8 @@ class Ecp5Packer
|
||||
void pack_lut5xs()
|
||||
{
|
||||
log_info("Packing LUT5-7s...\n");
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_pfumx(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed =
|
||||
create_ecp5_cell(ctx, ctx->id("TRELLIS_SLICE"), ci->name.str(ctx) + "_SLICE");
|
||||
@ -593,8 +593,8 @@ class Ecp5Packer
|
||||
}
|
||||
flush_cells();
|
||||
// Pack LUT6s
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_l6mux(ctx, ci)) {
|
||||
NetInfo *ofx0_0 = ci->ports.at(ctx->id("D0")).net;
|
||||
if (ofx0_0 == nullptr)
|
||||
@ -651,8 +651,8 @@ class Ecp5Packer
|
||||
}
|
||||
flush_cells();
|
||||
// Pack LUT7s
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_l6mux(ctx, ci)) {
|
||||
NetInfo *ofx1_0 = ci->ports.at(ctx->id("D0")).net;
|
||||
if (ofx1_0 == nullptr)
|
||||
@ -975,8 +975,8 @@ class Ecp5Packer
|
||||
// Pack distributed RAM
|
||||
void pack_dram()
|
||||
{
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_dpram(ctx, ci)) {
|
||||
|
||||
// Create RAMW slice
|
||||
@ -1108,8 +1108,8 @@ class Ecp5Packer
|
||||
void pack_remaining_luts()
|
||||
{
|
||||
log_info("Packing unpaired LUTs into a SLICE...\n");
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_lut(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> slice =
|
||||
create_ecp5_cell(ctx, ctx->id("TRELLIS_SLICE"), ci->name.str(ctx) + "_SLICE");
|
||||
@ -1181,8 +1181,8 @@ class Ecp5Packer
|
||||
++used_slices;
|
||||
|
||||
log_info("Packing unpaired FFs into a SLICE...\n");
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_ff(ctx, ci)) {
|
||||
bool pack_dense = used_slices > (dense_pack_mode_thresh * available_slices);
|
||||
bool requires_m = get_net_or_empty(ci, ctx->id("M")) != nullptr;
|
||||
@ -1403,8 +1403,8 @@ class Ecp5Packer
|
||||
|
||||
bool gnd_used = false, vcc_used = false;
|
||||
|
||||
for (auto net : sorted(ctx->nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) {
|
||||
IdString drv_cell = ni->driver.cell->name;
|
||||
set_net_constant(ctx, ni, gnd_net.get(), false);
|
||||
@ -1461,8 +1461,8 @@ class Ecp5Packer
|
||||
c->params[n] = c->params[o];
|
||||
c->params.erase(o);
|
||||
};
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
// Convert 36-bit PDP RAMs to regular 18-bit DP ones that match the Bel
|
||||
if (ci->type == ctx->id("PDPW16KD")) {
|
||||
ci->params[ctx->id("DATA_WIDTH_A")] = 36; // force PDP mode
|
||||
@ -1503,8 +1503,8 @@ class Ecp5Packer
|
||||
ci->type = id_DP16KD;
|
||||
}
|
||||
}
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_DP16KD) {
|
||||
// Add ports, even if disconnected, to ensure correct tie-offs
|
||||
for (int i = 0; i < 14; i++) {
|
||||
@ -1544,8 +1544,8 @@ class Ecp5Packer
|
||||
// Pack DSPs
|
||||
void pack_dsps()
|
||||
{
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_MULT18X18D) {
|
||||
// Add ports, even if disconnected, to ensure correct tie-offs
|
||||
for (auto sig : {"CLK", "CE", "RST"})
|
||||
@ -1708,8 +1708,8 @@ class Ecp5Packer
|
||||
// "Pack" DCUs
|
||||
void pack_dcus()
|
||||
{
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_DCUA) {
|
||||
if (ci->attrs.count(ctx->id("LOC"))) {
|
||||
std::string loc = ci->attrs.at(ctx->id("LOC")).as_string();
|
||||
@ -1759,8 +1759,8 @@ class Ecp5Packer
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_EXTREFB) {
|
||||
const NetInfo *refo = net_or_nullptr(ci, id_REFCLKO);
|
||||
CellInfo *dcu = nullptr;
|
||||
@ -1800,8 +1800,8 @@ class Ecp5Packer
|
||||
// Miscellaneous packer tasks
|
||||
void pack_misc()
|
||||
{
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_USRMCLK) {
|
||||
rename_port(ctx, ci, ctx->id("USRMCLKI"), id_PADDO);
|
||||
rename_port(ctx, ci, ctx->id("USRMCLKTS"), id_PADDT);
|
||||
@ -1829,14 +1829,14 @@ class Ecp5Packer
|
||||
if (ctx->getBelType(bel) == id_EHXPLLL && ctx->checkBelAvail(bel))
|
||||
available_plls.insert(bel);
|
||||
}
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_EHXPLLL && ci->attrs.count(ctx->id("BEL")))
|
||||
available_plls.erase(ctx->getBelByNameStr(ci->attrs.at(ctx->id("BEL")).as_string()));
|
||||
}
|
||||
// Place PLL connected to fixed drivers such as IO close to their source
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_EHXPLLL && !ci->attrs.count(ctx->id("BEL"))) {
|
||||
const NetInfo *drivernet = net_or_nullptr(ci, id_CLKI);
|
||||
if (drivernet == nullptr || drivernet->driver.cell == nullptr)
|
||||
@ -1863,8 +1863,8 @@ class Ecp5Packer
|
||||
}
|
||||
}
|
||||
// Place PLLs driven by logic, etc, randomly
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_EHXPLLL && !ci->attrs.count(ctx->id("BEL"))) {
|
||||
if (available_plls.empty())
|
||||
log_error("failed to place PLL '%s'\n", ci->name.c_str(ctx));
|
||||
@ -2030,8 +2030,8 @@ class Ecp5Packer
|
||||
// Pack DQSBUFs
|
||||
void pack_dqsbuf()
|
||||
{
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_DQSBUFM) {
|
||||
CellInfo *pio = net_driven_by(ctx, ci->ports.at(ctx->id("DQSI")).net, is_trellis_io, id_O);
|
||||
if (pio == nullptr || ci->ports.at(ctx->id("DQSI")).net->users.size() > 1)
|
||||
@ -2265,8 +2265,8 @@ class Ecp5Packer
|
||||
}
|
||||
};
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == ctx->id("DELAYF") || ci->type == ctx->id("DELAYG")) {
|
||||
CellInfo *i_pio = net_driven_by(ctx, ci->ports.at(ctx->id("A")).net, is_trellis_io, id_O);
|
||||
CellInfo *o_pio = net_only_drives(ctx, ci->ports.at(ctx->id("Z")).net, is_trellis_io, id_I, true);
|
||||
@ -2349,8 +2349,8 @@ class Ecp5Packer
|
||||
}
|
||||
}
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == ctx->id("IDDRX1F")) {
|
||||
CellInfo *pio = net_driven_by(ctx, ci->ports.at(ctx->id("D")).net, is_trellis_io, id_O);
|
||||
if (pio == nullptr || ci->ports.at(ctx->id("D")).net->users.size() > 1)
|
||||
@ -2692,8 +2692,8 @@ class Ecp5Packer
|
||||
}
|
||||
flush_cells();
|
||||
// Constrain ECLK-related cells
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_ECLKBRIDGECS) {
|
||||
Loc loc;
|
||||
NetInfo *i0 = get_net_or_empty(ci, id_CLK0), *i1 = get_net_or_empty(ci, id_CLK1),
|
||||
@ -2760,8 +2760,8 @@ class Ecp5Packer
|
||||
}
|
||||
}
|
||||
// Promote/route edge clocks
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_IOLOGIC || ci->type == id_DQSBUFM) {
|
||||
if (!ci->ports.count(id_ECLK) || ci->ports.at(id_ECLK).net == nullptr)
|
||||
continue;
|
||||
@ -2780,8 +2780,8 @@ class Ecp5Packer
|
||||
}
|
||||
flush_cells();
|
||||
std::unordered_set<BelId> used_eclksyncb;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_CLKDIVF) {
|
||||
const NetInfo *clki = net_or_nullptr(ci, id_CLKI);
|
||||
for (auto &eclk : eclks) {
|
||||
@ -2896,8 +2896,8 @@ class Ecp5Packer
|
||||
}
|
||||
}
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_ECLKSYNCB) {
|
||||
// **All** ECLKSYNCBs must be constrained
|
||||
// Most will be dealt with above, but there might be some rogue cases
|
||||
@ -2921,8 +2921,8 @@ class Ecp5Packer
|
||||
}
|
||||
}
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_CLKDIVF) {
|
||||
if (ci->attrs.count(ctx->id("BEL")))
|
||||
continue;
|
||||
@ -3114,8 +3114,8 @@ class Ecp5Packer
|
||||
{
|
||||
// Check for legacy-style JSON (use CEMUX as a clue) and error out, avoiding a confusing assertion failure
|
||||
// later
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
if (is_ff(ctx, cell.second) && cell.second->params.count(ctx->id("CEMUX")) &&
|
||||
for (auto &cell : ctx->cells) {
|
||||
if (is_ff(ctx, cell.second.get()) && cell.second->params.count(ctx->id("CEMUX")) &&
|
||||
!cell.second->params[ctx->id("CEMUX")].is_string)
|
||||
log_error("Found netlist using legacy-style JSON parameter values, please update your Yosys.\n");
|
||||
}
|
||||
@ -3188,8 +3188,8 @@ bool Arch::pack()
|
||||
|
||||
void Arch::assignArchInfo()
|
||||
{
|
||||
for (auto cell : sorted(cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_TRELLIS_SLICE) {
|
||||
|
||||
ci->sliceInfo.using_dff = false;
|
||||
@ -3301,7 +3301,7 @@ void Arch::assignArchInfo()
|
||||
ci->multInfo.is_clocked = ci->multInfo.timing_id != id_MULT18X18D_REGS_NONE;
|
||||
}
|
||||
}
|
||||
for (auto net : sorted(nets)) {
|
||||
for (auto &net : nets) {
|
||||
net.second->is_global = bool_or_default(net.second->attrs, id("ECP5_IS_GLOBAL"));
|
||||
}
|
||||
}
|
||||
|
@ -2047,8 +2047,8 @@ void Arch::pack_default_conns()
|
||||
|
||||
std::vector<IdString> dead_nets;
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
const DefaultCellConnsPOD *conns = get_default_conns(ci->type);
|
||||
if (conns == nullptr)
|
||||
continue;
|
||||
|
@ -49,10 +49,10 @@ void arch_wrap_python(py::module &m)
|
||||
fn_wrapper_1a_v<Context, decltype(&Context::explain_bel_status), &Context::explain_bel_status,
|
||||
conv_from_str<BelId>>::def_wrap(ctx_cls, "explain_bel_status");
|
||||
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap;
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap;
|
||||
typedef std::unordered_map<IdString, IdString> AliasMap;
|
||||
typedef std::unordered_map<IdString, HierarchicalCell> HierarchyMap;
|
||||
typedef dict<IdString, std::unique_ptr<CellInfo>> CellMap;
|
||||
typedef dict<IdString, std::unique_ptr<NetInfo>> NetMap;
|
||||
typedef dict<IdString, IdString> AliasMap;
|
||||
typedef dict<IdString, HierarchicalCell> HierarchyMap;
|
||||
|
||||
auto belpin_cls = py::class_<ContextualWrapper<BelPin>>(m, "BelPin");
|
||||
readonly_wrapper<BelPin, decltype(&BelPin::bel), &BelPin::bel, conv_to_str<BelId>>::def_wrap(belpin_cls, "bel");
|
||||
|
@ -85,12 +85,14 @@ struct GroupId
|
||||
{
|
||||
bool operator==(const GroupId &other) const { return true; }
|
||||
bool operator!=(const GroupId &other) const { return false; }
|
||||
unsigned int hash() const { return 0; }
|
||||
};
|
||||
|
||||
struct DecalId
|
||||
{
|
||||
bool operator==(const DecalId &other) const { return true; }
|
||||
bool operator!=(const DecalId &other) const { return false; }
|
||||
unsigned int hash() const { return 0; }
|
||||
};
|
||||
|
||||
struct BelBucketId
|
||||
|
@ -160,8 +160,8 @@ void Arch::place_globals()
|
||||
|
||||
// TODO: for more complex PLL type setups, we might want a toposort or iterative loop as the PLL must be placed
|
||||
// before the GBs it drives
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
const GlobalCellPOD *glb_cell = global_cell_info(ci->type);
|
||||
if (glb_cell == nullptr)
|
||||
continue;
|
||||
@ -239,8 +239,8 @@ void Arch::route_globals()
|
||||
IdString gnd_net_name(chip_info->constants->gnd_net_name);
|
||||
IdString vcc_net_name(chip_info->constants->vcc_net_name);
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
const GlobalCellPOD *glb_cell = global_cell_info(ci->type);
|
||||
if (glb_cell == nullptr)
|
||||
continue;
|
||||
|
@ -53,8 +53,8 @@ void Arch::expand_macros()
|
||||
// Make up a list of cells, so we don't have modify-while-iterating issues
|
||||
Context *ctx = getCtx();
|
||||
std::vector<CellInfo *> cells;
|
||||
for (auto cell : sorted(ctx->cells))
|
||||
cells.push_back(cell.second);
|
||||
for (auto &cell : ctx->cells)
|
||||
cells.push_back(cell.second.get());
|
||||
|
||||
std::vector<CellInfo *> next_cells;
|
||||
|
||||
|
@ -553,8 +553,8 @@ bool Arch::place()
|
||||
std::string placer = str_or_default(settings, id("placer"), defaultPlacer);
|
||||
if (placer == "heap") {
|
||||
bool have_iobuf_or_constr = false;
|
||||
for (auto cell : sorted(cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id("GENERIC_IOB") || ci->bel != BelId() || ci->attrs.count(id("BEL"))) {
|
||||
have_iobuf_or_constr = true;
|
||||
break;
|
||||
|
@ -138,9 +138,9 @@ void arch_wrap_python(py::module &m)
|
||||
fn_wrapper_3a<Context, decltype(&Context::constructDecalXY), &Context::constructDecalXY, wrap_context<DecalXY>,
|
||||
conv_from_str<DecalId>, pass_through<float>, pass_through<float>>::def_wrap(ctx_cls, "DecalXY");
|
||||
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap;
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap;
|
||||
typedef std::unordered_map<IdString, HierarchicalCell> HierarchyMap;
|
||||
typedef dict<IdString, std::unique_ptr<CellInfo>> CellMap;
|
||||
typedef dict<IdString, std::unique_ptr<NetInfo>> NetMap;
|
||||
typedef dict<IdString, HierarchicalCell> HierarchyMap;
|
||||
|
||||
readonly_wrapper<Context, decltype(&Context::cells), &Context::cells, wrap_context<CellMap &>>::def_wrap(ctx_cls,
|
||||
"cells");
|
||||
|
@ -34,14 +34,15 @@ static void pack_lut_lutffs(Context *ctx)
|
||||
|
||||
std::unordered_set<IdString> packed_cells;
|
||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ctx->verbose)
|
||||
log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx));
|
||||
if (is_lut(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed =
|
||||
create_generic_cell(ctx, ctx->id("GENERIC_SLICE"), ci->name.str(ctx) + "_LC");
|
||||
std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin()));
|
||||
for (auto &attr : ci->attrs)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
packed_cells.insert(ci->name);
|
||||
if (ctx->verbose)
|
||||
log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx));
|
||||
@ -91,12 +92,13 @@ static void pack_nonlut_ffs(Context *ctx)
|
||||
std::unordered_set<IdString> packed_cells;
|
||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_ff(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed =
|
||||
create_generic_cell(ctx, ctx->id("GENERIC_SLICE"), ci->name.str(ctx) + "_DFFLC");
|
||||
std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin()));
|
||||
for (auto &attr : ci->attrs)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
if (ctx->verbose)
|
||||
log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx));
|
||||
packed_cells.insert(ci->name);
|
||||
@ -158,8 +160,8 @@ static void pack_constants(Context *ctx)
|
||||
|
||||
bool gnd_used = false, vcc_used = false;
|
||||
|
||||
for (auto net : sorted(ctx->nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) {
|
||||
IdString drv_cell = ni->driver.cell->name;
|
||||
set_net_constant(ctx, ni, gnd_net.get(), false);
|
||||
@ -207,8 +209,8 @@ static void pack_io(Context *ctx)
|
||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||
log_info("Packing IOs..\n");
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_nextpnr_iob(ctx, ci)) {
|
||||
CellInfo *iob = nullptr;
|
||||
if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_iobuf")) {
|
||||
@ -254,7 +256,8 @@ static void pack_io(Context *ctx)
|
||||
}
|
||||
packed_cells.insert(ci->name);
|
||||
if (iob != nullptr)
|
||||
std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(iob->attrs, iob->attrs.begin()));
|
||||
for (auto &attr : ci->attrs)
|
||||
iob->attrs[attr.first] = attr.second;
|
||||
}
|
||||
}
|
||||
for (auto pcell : packed_cells) {
|
||||
|
@ -1009,8 +1009,8 @@ bool Arch::place()
|
||||
std::string placer = str_or_default(settings, id("placer"), defaultPlacer);
|
||||
if (placer == "heap") {
|
||||
bool have_iobuf_or_constr = false;
|
||||
for (auto cell : sorted(cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id("IOB") || ci->bel != BelId() || ci->attrs.count(id("BEL"))) {
|
||||
have_iobuf_or_constr = true;
|
||||
break;
|
||||
|
@ -137,9 +137,9 @@ void arch_wrap_python(py::module &m)
|
||||
fn_wrapper_3a<Context, decltype(&Context::constructDecalXY), &Context::constructDecalXY, wrap_context<DecalXY>,
|
||||
conv_from_str<DecalId>, pass_through<float>, pass_through<float>>::def_wrap(ctx_cls, "DecalXY");
|
||||
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap;
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap;
|
||||
typedef std::unordered_map<IdString, HierarchicalCell> HierarchyMap;
|
||||
typedef dict<IdString, std::unique_ptr<CellInfo>> CellMap;
|
||||
typedef dict<IdString, std::unique_ptr<NetInfo>> NetMap;
|
||||
typedef dict<IdString, HierarchicalCell> HierarchyMap;
|
||||
|
||||
readonly_wrapper<Context, decltype(&Context::cells), &Context::cells, wrap_context<CellMap &>>::def_wrap(ctx_cls,
|
||||
"cells");
|
||||
|
@ -36,13 +36,14 @@ static void pack_lut_lutffs(Context *ctx)
|
||||
|
||||
std::unordered_set<IdString> packed_cells;
|
||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ctx->verbose)
|
||||
log_info("cell '%s' is of type '%s'\n", ctx->nameOf(ci), ci->type.c_str(ctx));
|
||||
if (is_lut(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed = create_generic_cell(ctx, ctx->id("SLICE"), ci->name.str(ctx) + "_LC");
|
||||
std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin()));
|
||||
for (auto &attr : ci->attrs)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
packed_cells.insert(ci->name);
|
||||
if (ctx->verbose)
|
||||
log_info("packed cell %s into %s\n", ctx->nameOf(ci), ctx->nameOf(packed.get()));
|
||||
@ -92,11 +93,12 @@ static void pack_nonlut_ffs(Context *ctx)
|
||||
std::unordered_set<IdString> packed_cells;
|
||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_ff(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed = create_generic_cell(ctx, ctx->id("SLICE"), ci->name.str(ctx) + "_DFFLC");
|
||||
std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin()));
|
||||
for (auto &attr : ci->attrs)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
if (ctx->verbose)
|
||||
log_info("packed cell %s into %s\n", ctx->nameOf(ci), ctx->nameOf(packed.get()));
|
||||
packed_cells.insert(ci->name);
|
||||
@ -158,8 +160,8 @@ static void pack_constants(Context *ctx)
|
||||
|
||||
bool gnd_used = false;
|
||||
|
||||
for (auto net : sorted(ctx->nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) {
|
||||
IdString drv_cell = ni->driver.cell->name;
|
||||
set_net_constant(ctx, ni, gnd_net.get(), false);
|
||||
@ -216,8 +218,8 @@ static void pack_io(Context *ctx)
|
||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||
log_info("Packing IOs..\n");
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_gowin_iob(ctx, ci)) {
|
||||
CellInfo *iob = nullptr;
|
||||
switch (ci->type.index) {
|
||||
@ -251,7 +253,8 @@ static void pack_io(Context *ctx)
|
||||
|
||||
packed_cells.insert(ci->name);
|
||||
if (iob != nullptr)
|
||||
std::copy(iob->attrs.begin(), iob->attrs.end(), std::inserter(gwiob->attrs, gwiob->attrs.begin()));
|
||||
for (auto &attr : iob->attrs)
|
||||
gwiob->attrs[attr.first] = attr.second;
|
||||
}
|
||||
}
|
||||
for (auto pcell : packed_cells) {
|
||||
|
@ -60,10 +60,10 @@ void arch_wrap_python(py::module &m)
|
||||
.def("place", &Context::place)
|
||||
.def("route", &Context::route);
|
||||
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap;
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap;
|
||||
typedef std::unordered_map<IdString, IdString> AliasMap;
|
||||
typedef std::unordered_map<IdString, HierarchicalCell> HierarchyMap;
|
||||
typedef dict<IdString, std::unique_ptr<CellInfo>> CellMap;
|
||||
typedef dict<IdString, std::unique_ptr<NetInfo>> NetMap;
|
||||
typedef dict<IdString, IdString> AliasMap;
|
||||
typedef dict<IdString, HierarchicalCell> HierarchyMap;
|
||||
|
||||
auto belpin_cls = py::class_<ContextualWrapper<BelPin>>(m, "BelPin");
|
||||
readonly_wrapper<BelPin, decltype(&BelPin::bel), &BelPin::bel, conv_to_str<BelId>>::def_wrap(belpin_cls, "bel");
|
||||
|
@ -260,8 +260,8 @@ class ChainConstrainer
|
||||
}
|
||||
// Any cells not in chains, but with carry enabled, must also be put in a single-carry chain
|
||||
// for correct processing
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (chained.find(cell.first) == chained.end() && is_lc(ctx, ci) &&
|
||||
bool_or_default(ci->params, ctx->id("CARRY_ENABLE"))) {
|
||||
CellChain sChain;
|
||||
|
@ -37,13 +37,14 @@ static void pack_lut_lutffs(Context *ctx)
|
||||
int lut_only = 0, lut_and_ff = 0;
|
||||
std::unordered_set<IdString> packed_cells;
|
||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ctx->verbose)
|
||||
log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx));
|
||||
if (is_lut(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), ci->name.str(ctx) + "_LC");
|
||||
std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin()));
|
||||
for (auto &attr : ci->attrs)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
packed_cells.insert(ci->name);
|
||||
if (ctx->verbose)
|
||||
log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx));
|
||||
@ -103,12 +104,13 @@ static void pack_nonlut_ffs(Context *ctx)
|
||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||
int ff_only = 0;
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_ff(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed =
|
||||
create_ice_cell(ctx, ctx->id("ICESTORM_LC"), ci->name.str(ctx) + "_DFFLC");
|
||||
std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin()));
|
||||
for (auto &attr : ci->attrs)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
if (ctx->verbose)
|
||||
log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx));
|
||||
packed_cells.insert(ci->name);
|
||||
@ -147,8 +149,8 @@ static void pack_carries(Context *ctx)
|
||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||
int carry_only = 0;
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_carry(ctx, ci)) {
|
||||
packed_cells.insert(cell.first);
|
||||
|
||||
@ -275,8 +277,8 @@ static void pack_ram(Context *ctx)
|
||||
std::unordered_set<IdString> packed_cells;
|
||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_ram(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed =
|
||||
create_ice_cell(ctx, ctx->id("ICESTORM_RAM"), ci->name.str(ctx) + "_RAM");
|
||||
@ -379,8 +381,8 @@ static void pack_constants(Context *ctx)
|
||||
|
||||
bool gnd_used = false;
|
||||
|
||||
for (auto net : sorted(ctx->nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) {
|
||||
IdString drv_cell = ni->driver.cell->name;
|
||||
set_net_constant(ctx, ni, gnd_net_info, false);
|
||||
@ -469,8 +471,8 @@ static void pack_io(Context *ctx)
|
||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||
log_info("Packing IOs..\n");
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_nextpnr_iob(ctx, ci)) {
|
||||
CellInfo *sb = nullptr, *rgb = nullptr;
|
||||
if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_iobuf")) {
|
||||
@ -531,7 +533,8 @@ static void pack_io(Context *ctx)
|
||||
for (auto port : ci->ports)
|
||||
disconnect_port(ctx, ci, port.first);
|
||||
packed_cells.insert(ci->name);
|
||||
std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(sb->attrs, sb->attrs.begin()));
|
||||
for (auto &attr : ci->attrs)
|
||||
sb->attrs[attr.first] = attr.second;
|
||||
} else if (is_sb_io(ctx, ci) || is_sb_gb_io(ctx, ci)) {
|
||||
NetInfo *net = ci->ports.at(ctx->id("PACKAGE_PIN")).net;
|
||||
if ((net != nullptr) && ((net->users.size() > 2) ||
|
||||
@ -541,8 +544,8 @@ static void pack_io(Context *ctx)
|
||||
ci->name.c_str(ctx));
|
||||
}
|
||||
}
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_sb_gb_io(ctx, ci)) {
|
||||
// If something is connecto the GLOBAL OUTPUT, create the fake 'matching' SB_GB
|
||||
std::unique_ptr<CellInfo> gb =
|
||||
@ -637,8 +640,8 @@ static void promote_globals(Context *ctx)
|
||||
const int enable_fanout_thresh = 15;
|
||||
const int reset_fanout_thresh = 15;
|
||||
std::map<IdString, int> clock_count, reset_count, cen_count, logic_count;
|
||||
for (auto net : sorted(ctx->nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
if (ni->driver.cell != nullptr && !ctx->is_global_net(ni)) {
|
||||
clock_count[net.first] = 0;
|
||||
reset_count[net.first] = 0;
|
||||
@ -778,8 +781,8 @@ static void place_plls(Context *ctx)
|
||||
}
|
||||
|
||||
// Find all the PLLs cells we need to place and do pre-checks
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (!is_sb_pll40(ctx, ci))
|
||||
continue;
|
||||
|
||||
@ -861,8 +864,8 @@ static void place_plls(Context *ctx)
|
||||
}
|
||||
|
||||
// Scan all SB_IOs to check for conflict with PLL BELs
|
||||
for (auto io_cell : sorted(ctx->cells)) {
|
||||
CellInfo *io_ci = io_cell.second;
|
||||
for (auto &io_cell : ctx->cells) {
|
||||
CellInfo *io_ci = io_cell.second.get();
|
||||
if (!is_sb_io(ctx, io_ci))
|
||||
continue;
|
||||
|
||||
@ -899,8 +902,8 @@ static void place_plls(Context *ctx)
|
||||
}
|
||||
|
||||
// Scan all SB_GBs to check for conflicts with PLL BELs
|
||||
for (auto gb_cell : sorted(ctx->cells)) {
|
||||
CellInfo *gb_ci = gb_cell.second;
|
||||
for (auto &gb_cell : ctx->cells) {
|
||||
CellInfo *gb_ci = gb_cell.second.get();
|
||||
if (!is_gbuf(ctx, gb_ci))
|
||||
continue;
|
||||
|
||||
@ -1120,8 +1123,8 @@ static void pack_special(Context *ctx)
|
||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||
|
||||
// Handle LED_DRV_CUR first to set the ledCurConnected flag before RGB_DRV is handled below.
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_sb_led_drv_cur(ctx, ci)) {
|
||||
/* Force placement (no choices anyway) */
|
||||
cell_place_unique(ctx, ci);
|
||||
@ -1139,8 +1142,8 @@ static void pack_special(Context *ctx)
|
||||
ctx->nets.erase(ledpu_net->name);
|
||||
}
|
||||
}
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_sb_lfosc(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed =
|
||||
create_ice_cell(ctx, ctx->id("ICESTORM_LFOSC"), ci->name.str(ctx) + "_OSC");
|
||||
@ -1298,8 +1301,8 @@ void pack_plls(Context *ctx)
|
||||
|
||||
std::unordered_set<IdString> packed_cells;
|
||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_sb_pll40(ctx, ci)) {
|
||||
bool is_pad = is_sb_pll40_pad(ctx, ci);
|
||||
bool is_core = !is_pad;
|
||||
|
@ -108,8 +108,8 @@ bool apply_pcf(Context *ctx, std::string filename, std::istream &in)
|
||||
log_error("unsupported PCF command '%s' (on line %d)\n", cmd.c_str(), lineno);
|
||||
}
|
||||
}
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_obuf") ||
|
||||
ci->type == ctx->id("$nextpnr_iobuf")) {
|
||||
if (!ci->attrs.count(ctx->id("BEL"))) {
|
||||
|
@ -45,7 +45,7 @@ std::string get_string(std::string str)
|
||||
|
||||
std::string get_name(IdString name, Context *ctx) { return get_string(name.c_str(ctx)); }
|
||||
|
||||
void write_parameters(std::ostream &f, Context *ctx, const std::unordered_map<IdString, Property> ¶meters,
|
||||
void write_parameters(std::ostream &f, Context *ctx, const dict<IdString, Property> ¶meters,
|
||||
bool for_module = false)
|
||||
{
|
||||
bool first = true;
|
||||
@ -64,8 +64,7 @@ struct PortGroup
|
||||
PortType dir;
|
||||
};
|
||||
|
||||
std::vector<PortGroup> group_ports(Context *ctx, const std::unordered_map<IdString, PortInfo> &ports,
|
||||
bool is_cell = false)
|
||||
std::vector<PortGroup> group_ports(Context *ctx, const dict<IdString, PortInfo> &ports, bool is_cell = false)
|
||||
{
|
||||
std::vector<PortGroup> groups;
|
||||
std::unordered_map<std::string, size_t> base_to_group;
|
||||
|
@ -45,10 +45,10 @@ void arch_wrap_python(py::module &m)
|
||||
.def("place", &Context::place)
|
||||
.def("route", &Context::route);
|
||||
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap;
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap;
|
||||
typedef std::unordered_map<IdString, IdString> AliasMap;
|
||||
typedef std::unordered_map<IdString, HierarchicalCell> HierarchyMap;
|
||||
typedef dict<IdString, std::unique_ptr<CellInfo>> CellMap;
|
||||
typedef dict<IdString, std::unique_ptr<NetInfo>> NetMap;
|
||||
typedef dict<IdString, IdString> AliasMap;
|
||||
typedef dict<IdString, HierarchicalCell> HierarchyMap;
|
||||
|
||||
auto belpin_cls = py::class_<ContextualWrapper<BelPin>>(m, "BelPin");
|
||||
readonly_wrapper<BelPin, decltype(&BelPin::bel), &BelPin::bel, conv_to_str<BelId>>::def_wrap(belpin_cls, "bel");
|
||||
|
@ -114,8 +114,7 @@ static std::vector<bool> int_to_bitvector(int val, int size)
|
||||
return bv;
|
||||
}
|
||||
|
||||
std::string intstr_or_default(const std::unordered_map<IdString, Property> &ct, const IdString &key,
|
||||
std::string def = "0")
|
||||
std::string intstr_or_default(const dict<IdString, Property> &ct, const IdString &key, std::string def = "0")
|
||||
{
|
||||
auto found = ct.find(key);
|
||||
if (found == ct.end())
|
||||
|
@ -35,13 +35,14 @@ static void pack_lut_lutffs(Context *ctx)
|
||||
|
||||
std::unordered_set<IdString> packed_cells;
|
||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ctx->verbose)
|
||||
log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx));
|
||||
if (is_lut(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed = create_machxo2_cell(ctx, id_FACADE_SLICE, ci->name.str(ctx) + "_LC");
|
||||
std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin()));
|
||||
for (auto &attr : ci->attrs)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
|
||||
packed_cells.insert(ci->name);
|
||||
if (ctx->verbose)
|
||||
@ -93,15 +94,16 @@ static void pack_remaining_ffs(Context *ctx)
|
||||
std::unordered_set<IdString> packed_cells;
|
||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
|
||||
if (is_ff(ctx, ci)) {
|
||||
if (ctx->verbose)
|
||||
log_info("cell '%s' of type '%s remains unpacked'\n", ci->name.c_str(ctx), ci->type.c_str(ctx));
|
||||
|
||||
std::unique_ptr<CellInfo> packed = create_machxo2_cell(ctx, id_FACADE_SLICE, ci->name.str(ctx) + "_LC");
|
||||
std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin()));
|
||||
for (auto &attr : ci->attrs)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
|
||||
auto dff_bel = ci->attrs.find(ctx->id("BEL"));
|
||||
dff_to_lc(ctx, ci, packed.get(), false);
|
||||
@ -142,7 +144,8 @@ static void set_net_constant(Context *ctx, NetInfo *orig, NetInfo *constnet, boo
|
||||
log_info("FACADE_FF %s is driven by a constant\n", uc->name.c_str(ctx));
|
||||
|
||||
std::unique_ptr<CellInfo> lc = create_machxo2_cell(ctx, id_FACADE_SLICE, uc->name.str(ctx) + "_CONST");
|
||||
std::copy(uc->attrs.begin(), uc->attrs.end(), std::inserter(lc->attrs, lc->attrs.begin()));
|
||||
for (auto &attr : uc->attrs)
|
||||
lc->attrs[attr.first] = attr.second;
|
||||
|
||||
dff_to_lc(ctx, uc, lc.get(), true);
|
||||
packed_cells.insert(uc->name);
|
||||
@ -193,8 +196,8 @@ static void pack_constants(Context *ctx)
|
||||
|
||||
std::vector<IdString> dead_nets;
|
||||
|
||||
for (auto net : sorted(ctx->nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) {
|
||||
IdString drv_cell = ni->driver.cell->name;
|
||||
set_net_constant(ctx, ni, gnd_net.get(), false);
|
||||
@ -234,8 +237,8 @@ static void pack_io(Context *ctx)
|
||||
|
||||
log_info("Packing IOs..\n");
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_nextpnr_iob(ctx, ci)) {
|
||||
for (auto &p : ci->ports)
|
||||
disconnect_port(ctx, ci, p.first);
|
||||
|
@ -375,8 +375,8 @@ void Arch::assign_default_pinmap(CellInfo *cell)
|
||||
|
||||
void Arch::assignArchInfo()
|
||||
{
|
||||
for (auto cell : sorted(cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_comb_cell(ci->type))
|
||||
assign_comb_info(ci);
|
||||
else if (ci->type == id_MISTRAL_FF)
|
||||
|
@ -50,10 +50,10 @@ void arch_wrap_python(py::module &m)
|
||||
fn_wrapper_2a<Context, decltype(&Context::compute_lut_mask), &Context::compute_lut_mask, pass_through<uint64_t>,
|
||||
pass_through<uint32_t>, pass_through<uint8_t>>::def_wrap(ctx_cls, "compute_lut_mask");
|
||||
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap;
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap;
|
||||
typedef std::unordered_map<IdString, IdString> AliasMap;
|
||||
typedef std::unordered_map<IdString, HierarchicalCell> HierarchyMap;
|
||||
typedef dict<IdString, std::unique_ptr<CellInfo>> CellMap;
|
||||
typedef dict<IdString, std::unique_ptr<NetInfo>> NetMap;
|
||||
typedef dict<IdString, IdString> AliasMap;
|
||||
typedef dict<IdString, HierarchicalCell> HierarchyMap;
|
||||
|
||||
auto belpin_cls = py::class_<ContextualWrapper<BelPin>>(m, "BelPin");
|
||||
readonly_wrapper<BelPin, decltype(&BelPin::bel), &BelPin::bel, conv_to_str<BelId>>::def_wrap(belpin_cls, "bel");
|
||||
|
@ -156,9 +156,9 @@ struct MistralBitgen
|
||||
|
||||
void write_routing()
|
||||
{
|
||||
for (auto net : sorted(ctx->nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto wire : sorted_ref(ni->wires)) {
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
for (auto &wire : ni->wires) {
|
||||
PipId pip = wire.second.pip;
|
||||
if (pip == PipId())
|
||||
continue;
|
||||
@ -200,8 +200,8 @@ struct MistralBitgen
|
||||
|
||||
void write_cells()
|
||||
{
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
Loc loc = ctx->getBelLocation(ci->bel);
|
||||
int bi = ctx->bel_data(ci->bel).block_index;
|
||||
if (ctx->is_io_cell(ci->type))
|
||||
|
@ -133,8 +133,8 @@ struct MistralPacker
|
||||
// Remove unused inverters and high/low drivers
|
||||
std::vector<IdString> trim_cells;
|
||||
std::vector<IdString> trim_nets;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type != id_MISTRAL_NOT && ci->type != id_GND && ci->type != id_VCC)
|
||||
continue;
|
||||
IdString port = (ci->type == id_MISTRAL_NOT) ? id_Q : id_Y;
|
||||
@ -161,15 +161,15 @@ struct MistralPacker
|
||||
void pack_constants()
|
||||
{
|
||||
// Iterate through cells
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
// Skip certain cells at this point
|
||||
if (ci->type != id_MISTRAL_NOT && ci->type != id_GND && ci->type != id_VCC)
|
||||
process_inv_constants(cell.second);
|
||||
process_inv_constants(ci);
|
||||
}
|
||||
// Special case - SDATA can only be trimmed if SLOAD is low
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type != id_MISTRAL_FF)
|
||||
continue;
|
||||
if (ci->get_pin_state(id_SLOAD) != PIN_0)
|
||||
@ -185,7 +185,7 @@ struct MistralPacker
|
||||
// Find the actual IO buffer corresponding to a port; and copy attributes across to it
|
||||
// Note that this relies on Yosys to do IO buffer inference, to avoid tristate issues once we get to synthesised
|
||||
// JSON. In all cases the nextpnr-inserted IO buffers are removed as redundant.
|
||||
for (auto &port : sorted_ref(ctx->ports)) {
|
||||
for (auto &port : ctx->ports) {
|
||||
if (!ctx->cells.count(port.first))
|
||||
log_error("Port '%s' doesn't seem to have a corresponding top level IO\n", ctx->nameOf(port.first));
|
||||
CellInfo *ci = ctx->cells.at(port.first).get();
|
||||
@ -256,8 +256,8 @@ struct MistralPacker
|
||||
// Step 0: deal with top level inserted IO buffers
|
||||
prepare_io();
|
||||
// Stage 1: apply constraints
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
// Iterate through all IO buffer primitives
|
||||
if (!ctx->is_io_cell(ci->type))
|
||||
continue;
|
||||
@ -286,8 +286,8 @@ struct MistralPacker
|
||||
|
||||
void constrain_carries()
|
||||
{
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type != id_MISTRAL_ALUT_ARITH)
|
||||
continue;
|
||||
const NetInfo *cin = get_net_or_empty(ci, id_CI);
|
||||
@ -332,8 +332,8 @@ struct MistralPacker
|
||||
}
|
||||
}
|
||||
// Check we reached all the cells in the above pass
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type != id_MISTRAL_ALUT_ARITH)
|
||||
continue;
|
||||
if (ci->cluster == ClusterId())
|
||||
|
@ -667,19 +667,19 @@ bool Arch::place()
|
||||
|
||||
void Arch::pre_routing()
|
||||
{
|
||||
for (auto cell : sorted(cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_MULT9_CORE || ci->type == id_PREADD9_CORE || ci->type == id_MULT18_CORE ||
|
||||
ci->type == id_MULT18X36_CORE || ci->type == id_MULT36_CORE || ci->type == id_REG18_CORE ||
|
||||
ci->type == id_ACC54_CORE) {
|
||||
for (auto port : sorted_ref(ci->ports)) {
|
||||
for (auto &port : ci->ports) {
|
||||
WireId wire = getBelPinWire(ci->bel, port.first);
|
||||
if (wire != WireId())
|
||||
dsp_wires.insert(wire);
|
||||
}
|
||||
}
|
||||
if (ci->type == id_LRAM_CORE) {
|
||||
for (auto port : sorted_ref(ci->ports)) {
|
||||
for (auto &port : ci->ports) {
|
||||
WireId wire = getBelPinWire(ci->bel, port.first);
|
||||
if (wire != WireId())
|
||||
lram_wires.insert(wire);
|
||||
|
@ -46,10 +46,10 @@ void arch_wrap_python(py::module &m)
|
||||
.def("place", &Context::place)
|
||||
.def("route", &Context::route);
|
||||
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<CellInfo>> CellMap;
|
||||
typedef std::unordered_map<IdString, std::unique_ptr<NetInfo>> NetMap;
|
||||
typedef std::unordered_map<IdString, HierarchicalCell> HierarchyMap;
|
||||
typedef std::unordered_map<IdString, IdString> AliasMap;
|
||||
typedef dict<IdString, std::unique_ptr<CellInfo>> CellMap;
|
||||
typedef dict<IdString, std::unique_ptr<NetInfo>> NetMap;
|
||||
typedef dict<IdString, HierarchicalCell> HierarchyMap;
|
||||
typedef dict<IdString, IdString> AliasMap;
|
||||
|
||||
typedef UpDownhillPipRange UphillPipRange;
|
||||
typedef UpDownhillPipRange DownhillPipRange;
|
||||
|
@ -248,7 +248,7 @@ struct NexusFasmWriter
|
||||
// Write out the mux config for a cell
|
||||
void write_cell_muxes(const CellInfo *cell)
|
||||
{
|
||||
for (auto port : sorted_cref(cell->ports)) {
|
||||
for (auto &port : cell->ports) {
|
||||
// Only relevant to inputs
|
||||
if (port.second.type != PORT_IN)
|
||||
continue;
|
||||
@ -539,7 +539,7 @@ struct NexusFasmWriter
|
||||
push_bel(bel);
|
||||
if (cell->type != id_MULT18_CORE && cell->type != id_MULT18X36_CORE && cell->type != id_MULT36_CORE)
|
||||
write_bit(stringf("MODE.%s", ctx->nameOf(cell->type)));
|
||||
for (auto param : sorted_cref(cell->params)) {
|
||||
for (auto ¶m : cell->params) {
|
||||
const std::string ¶m_name = param.first.str(ctx);
|
||||
if (is_mux_param(param_name))
|
||||
continue;
|
||||
@ -601,7 +601,7 @@ struct NexusFasmWriter
|
||||
write_cell_muxes(cell);
|
||||
pop();
|
||||
push(stringf("IP_%s", ctx->nameOf(IdString(ctx->bel_data(bel).name))));
|
||||
for (auto param : sorted_cref(cell->params)) {
|
||||
for (auto ¶m : cell->params) {
|
||||
const std::string &name = param.first.str(ctx);
|
||||
if (is_mux_param(name) || name == "CLKMUX_FB" || name == "SEL_FBK")
|
||||
continue;
|
||||
@ -622,7 +622,7 @@ struct NexusFasmWriter
|
||||
{
|
||||
BelId bel = cell->bel;
|
||||
push(stringf("IP_%s", ctx->nameOf(IdString(ctx->bel_data(bel).name))));
|
||||
for (auto param : sorted_cref(cell->params)) {
|
||||
for (auto ¶m : cell->params) {
|
||||
const std::string &name = param.first.str(ctx);
|
||||
if (is_mux_param(name) || name == "GSR")
|
||||
continue;
|
||||
@ -753,8 +753,8 @@ struct NexusFasmWriter
|
||||
// Write out placeholder bankref config
|
||||
void write_bankcfg()
|
||||
{
|
||||
for (auto c : sorted(ctx->cells)) {
|
||||
const CellInfo *ci = c.second;
|
||||
for (auto &c : ctx->cells) {
|
||||
const CellInfo *ci = c.second.get();
|
||||
if (ci->type != id_SEIO33_CORE)
|
||||
continue;
|
||||
if (!ci->attrs.count(id_IO_TYPE))
|
||||
@ -809,12 +809,12 @@ struct NexusFasmWriter
|
||||
write_attribute("oxide.device_variant", ctx->variant);
|
||||
blank();
|
||||
// Write routing
|
||||
for (auto n : sorted(ctx->nets)) {
|
||||
write_net(n.second);
|
||||
for (auto &n : ctx->nets) {
|
||||
write_net(n.second.get());
|
||||
}
|
||||
// Write cell config
|
||||
for (auto c : sorted(ctx->cells)) {
|
||||
const CellInfo *ci = c.second;
|
||||
for (auto &c : ctx->cells) {
|
||||
const CellInfo *ci = c.second.get();
|
||||
write_comment(stringf("# Cell %s", ctx->nameOf(ci)));
|
||||
if (ci->type == id_OXIDE_COMB)
|
||||
write_comb(ci);
|
||||
|
@ -155,8 +155,8 @@ struct NexusGlobalRouter
|
||||
void operator()()
|
||||
{
|
||||
log_info("Routing globals...\n");
|
||||
for (auto net : sorted(ctx->nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
CellInfo *drv = ni->driver.cell;
|
||||
if (drv == nullptr)
|
||||
continue;
|
||||
|
@ -182,8 +182,8 @@ struct NexusPacker
|
||||
{
|
||||
std::map<std::string, int> cell_count;
|
||||
std::map<std::string, int> new_types;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (rules.count(ci->type)) {
|
||||
cell_count[ci->type.str(ctx)]++;
|
||||
xform_cell(rules, ci);
|
||||
@ -303,8 +303,8 @@ struct NexusPacker
|
||||
{
|
||||
// Gets a constant net, given the driver type (VHI or VLO)
|
||||
// If one doesn't exist already; then create it
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type != type)
|
||||
continue;
|
||||
NetInfo *z = get_net_or_empty(ci, id_Z);
|
||||
@ -369,8 +369,8 @@ struct NexusPacker
|
||||
// Remove unused inverters and high/low drivers
|
||||
std::vector<IdString> trim_cells;
|
||||
std::vector<IdString> trim_nets;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type != id_INV && ci->type != id_VLO && ci->type != id_VHI && ci->type != id_VCC_DRV)
|
||||
continue;
|
||||
NetInfo *z = get_net_or_empty(ci, id_Z);
|
||||
@ -474,7 +474,7 @@ struct NexusPacker
|
||||
// Find the actual IO buffer corresponding to a port; and copy attributes across to it
|
||||
// Note that this relies on Yosys to do IO buffer inference, to match vendor tooling behaviour
|
||||
// In all cases the nextpnr-inserted IO buffers are removed as redundant.
|
||||
for (auto &port : sorted_ref(ctx->ports)) {
|
||||
for (auto &port : ctx->ports) {
|
||||
if (!ctx->cells.count(port.first))
|
||||
log_error("Port '%s' doesn't seem to have a corresponding top level IO\n", ctx->nameOf(port.first));
|
||||
CellInfo *ci = ctx->cells.at(port.first).get();
|
||||
@ -579,8 +579,8 @@ struct NexusPacker
|
||||
prepare_io();
|
||||
|
||||
// Stage 1: setup constraints
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
// Iterate through all IO buffer primitives
|
||||
if (!iob_types.count(ci->type))
|
||||
continue;
|
||||
@ -625,8 +625,8 @@ struct NexusPacker
|
||||
// Stage 2: apply rules for primitives that need them
|
||||
generic_xform(io_rules, false);
|
||||
// Stage 3: all other IO primitives become their bel type
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
// Iterate through all IO buffer primitives
|
||||
if (!iob_types.count(ci->type))
|
||||
continue;
|
||||
@ -660,12 +660,12 @@ struct NexusPacker
|
||||
gnd_net = get_const_net(id_VLO);
|
||||
dedi_vcc_net = get_const_net(id_VCC_DRV);
|
||||
// Iterate through cells
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
// Skip certain cells at this point
|
||||
if (ci->type != id_LUT4 && ci->type != id_INV && ci->type != id_VHI && ci->type != id_VLO &&
|
||||
ci->type != id_VCC_DRV)
|
||||
process_inv_constants(cell.second);
|
||||
process_inv_constants(ci);
|
||||
}
|
||||
// Remove superfluous inverters and constant drivers
|
||||
trim_design();
|
||||
@ -854,8 +854,8 @@ struct NexusPacker
|
||||
{
|
||||
std::vector<std::pair<int, IdString>> clk_fanout;
|
||||
int available_globals = 16;
|
||||
for (auto net : sorted(ctx->nets)) {
|
||||
NetInfo *ni = net.second;
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
// Skip undriven nets; and nets that are already global
|
||||
if (ni->driver.cell == nullptr)
|
||||
continue;
|
||||
@ -894,8 +894,8 @@ struct NexusPacker
|
||||
bool did_something = true;
|
||||
while (did_something) {
|
||||
did_something = false;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_OSC_CORE)
|
||||
did_something |= preplace_singleton(ci);
|
||||
else if (ci->type == id_DCC)
|
||||
@ -916,8 +916,8 @@ struct NexusPacker
|
||||
{
|
||||
// Do this so we don't have an iterate-and-modfiy situation
|
||||
std::vector<CellInfo *> lutrams;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type != id_DPR16X4)
|
||||
continue;
|
||||
lutrams.push_back(ci);
|
||||
@ -1031,8 +1031,8 @@ struct NexusPacker
|
||||
{id_PLL, id_PLL_CORE}, {id_DPHY, id_DPHY_CORE},
|
||||
};
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (!prim_map.count(ci->type))
|
||||
continue;
|
||||
prim_to_core(ci, prim_map.at(ci->type));
|
||||
@ -1084,8 +1084,8 @@ struct NexusPacker
|
||||
generic_xform(bram_rules, true);
|
||||
|
||||
int wid = 2;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type != id_OXIDE_EBR)
|
||||
continue;
|
||||
if (ci->params.count(id_WID))
|
||||
@ -1129,8 +1129,8 @@ struct NexusPacker
|
||||
log_info("Packing LRAM...\n");
|
||||
generic_xform(lram_rules, true);
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type != id_LRAM_CORE)
|
||||
continue;
|
||||
if (str_or_default(ci->params, ctx->id("ECC_BYTE_SEL"), "BYTE_EN") == "BYTE_EN")
|
||||
@ -1151,8 +1151,8 @@ struct NexusPacker
|
||||
void pack_widefn()
|
||||
{
|
||||
std::vector<CellInfo *> widefns;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type != id_WIDEFN9)
|
||||
continue;
|
||||
widefns.push_back(ci);
|
||||
@ -1200,8 +1200,8 @@ struct NexusPacker
|
||||
// Find root carry cells
|
||||
log_info("Packing carries...\n");
|
||||
std::vector<CellInfo *> roots;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type != id_CCU2)
|
||||
continue;
|
||||
if (get_net_or_empty(ci, id_CIN) != nullptr)
|
||||
@ -1306,7 +1306,7 @@ struct NexusPacker
|
||||
continue;
|
||||
cell->addOutput(bp);
|
||||
}
|
||||
for (auto port : sorted_ref(cell->ports)) {
|
||||
for (auto &port : cell->ports) {
|
||||
// Skip if not an output, or being used already for something else
|
||||
if (port.second.type != PORT_OUT || port.second.net != nullptr)
|
||||
continue;
|
||||
@ -1609,8 +1609,8 @@ struct NexusPacker
|
||||
log_info("Packing DSPs...\n");
|
||||
std::vector<CellInfo *> to_remove;
|
||||
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (!dsp_types.count(ci->type))
|
||||
continue;
|
||||
auto &mt = dsp_types.at(ci->type);
|
||||
@ -1792,7 +1792,7 @@ struct NexusPacker
|
||||
}
|
||||
|
||||
for (auto cell : to_remove) {
|
||||
for (auto port : sorted_ref(cell->ports))
|
||||
for (auto &port : cell->ports)
|
||||
disconnect_port(ctx, cell, port.first);
|
||||
ctx->cells.erase(cell->name);
|
||||
}
|
||||
@ -1949,8 +1949,8 @@ struct NexusPacker
|
||||
{id_FLOCK_CTRL, "2X"}, {id_FLOCK_EN, "ENABLED"}, {id_FLOCK_SRC_SEL, "REFCLK"},
|
||||
{id_DIV_DEL, "0b0000001"}, {id_FBK_PI_RC, "0b1100"}, {id_FBK_PR_IC, "0b1000"},
|
||||
};
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_PLL_CORE) {
|
||||
// Extra log to phys rules
|
||||
rename_port(ctx, ci, id_PLLPOWERDOWN_N, id_PLLPDN);
|
||||
@ -1975,8 +1975,8 @@ struct NexusPacker
|
||||
|
||||
void pack_ip()
|
||||
{
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_DPHY_CORE) {
|
||||
auto loc_attr = ci->attrs.find(id_LOC);
|
||||
if (loc_attr == ci->attrs.end())
|
||||
@ -2026,8 +2026,8 @@ bool Arch::pack()
|
||||
|
||||
void Arch::assignArchInfo()
|
||||
{
|
||||
for (auto cell : sorted(cells)) {
|
||||
assignCellInfo(cell.second);
|
||||
for (auto &cell : cells) {
|
||||
assignCellInfo(cell.second.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,9 +88,9 @@ struct NexusPostPlaceOpt
|
||||
void opt_lutffs()
|
||||
{
|
||||
int moves_made = 0;
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
for (auto &cell : ctx->cells) {
|
||||
// Search for FF cells
|
||||
CellInfo *ff = cell.second;
|
||||
CellInfo *ff = cell.second.get();
|
||||
if (ff->type != id_OXIDE_FF)
|
||||
continue;
|
||||
// Check M ('fabric') input net
|
||||
|
Loading…
Reference in New Issue
Block a user