Merge pull request #556 from YosysHQ/dave/cleanup

General opportunistic cleanup
This commit is contained in:
David Shah 2021-01-28 16:10:22 +00:00 committed by GitHub
commit 15b2852b91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 38 additions and 204 deletions

View File

@ -406,7 +406,7 @@ class SAPlacer
auto saplace_end = std::chrono::high_resolution_clock::now();
log_info("SA placement time %.02fs\n", std::chrono::duration<float>(saplace_end - saplace_start).count());
// Final post-pacement validitiy check
// Final post-placement validity check
ctx->yield();
for (auto bel : ctx->getBels()) {
CellInfo *cell = ctx->getBoundBelCell(bel);
@ -548,7 +548,7 @@ class SAPlacer
goto swap_fail;
}
// Recalculate metrics for all nets touched by the peturbation
// Recalculate metrics for all nets touched by the perturbation
compute_cost_changes(moveChange);
new_dist = get_constraints_distance(ctx, cell);
@ -560,7 +560,7 @@ class SAPlacer
if (cfg.netShareWeight > 0)
delta += -cfg.netShareWeight * (net_delta_score / std::max<double>(total_net_share, epsilon));
n_move++;
// SA acceptance criterea
// SA acceptance criteria
if (delta < 0 || (temp > 1e-8 && (ctx->rng() / float(0x3fffffff)) <= std::exp(-delta / temp))) {
n_accept++;
} else {
@ -691,7 +691,7 @@ class SAPlacer
cfg.netShareWeight * (orig_share_cost - total_net_share) / std::max<double>(total_net_share, 1e-20);
}
n_move++;
// SA acceptance criterea
// SA acceptance criteria
if (delta < 0 || (temp > 1e-9 && (ctx->rng() / float(0x3fffffff)) <= std::exp(-delta / temp))) {
n_accept++;
#if 0

View File

@ -195,8 +195,8 @@ class HeAPPlacer
}
if (cfg.placeAllAtOnce) {
// Never want to deal with LUTs, FFs, MUXFxs seperately,
// for now disable all single-cell-type runs and only have heteregenous
// Never want to deal with LUTs, FFs, MUXFxs separately,
// for now disable all single-cell-type runs and only have heterogeneous
// runs
heap_runs.clear();
}
@ -205,7 +205,7 @@ class HeAPPlacer
// The main HeAP placer loop
log_info("Running main analytical placer.\n");
while (stalled < 5 && (solved_hpwl <= legal_hpwl * 0.8)) {
// Alternate between particular Bel types and all bels
// Alternate between particular bel types and all bels
for (auto &run : heap_runs) {
auto run_startt = std::chrono::high_resolution_clock::now();
@ -321,7 +321,7 @@ class HeAPPlacer
std::vector<std::vector<std::vector<std::vector<BelId>>>> fast_bels;
std::unordered_map<IdString, std::tuple<int, int>> bel_types;
// For fast handling of heterogeneosity during initial placement without full legalisation,
// For fast handling of heterogeneity during initial placement without full legalisation,
// for each Bel type this goes from x or y to the nearest x or y where a Bel of a given type exists
// This is particularly important for the iCE40 architecture, where multipliers and BRAM only exist at the
// edges and corners respectively
@ -1123,7 +1123,6 @@ class HeAPPlacer
#endif
workqueue.emplace(r.id, false);
// cut_region(r, false);
}
while (!workqueue.empty()) {
auto front = workqueue.front();
@ -1139,7 +1138,6 @@ class HeAPPlacer
// Try the other dir, in case stuck in one direction only
auto res2 = cut_region(r, !front.second);
if (res2) {
// log_info("RETRY SUCCESS\n");
workqueue.emplace(res2->first, front.second);
workqueue.emplace(res2->second, front.second);
}
@ -1356,8 +1354,6 @@ class HeAPPlacer
for (int y1 = reg.y0; y1 <= reg.y1; y1++) {
for (size_t t = 0; t < beltype.size(); t++) {
if (occ_at(reg.x1 + 1, y1, t) > bels_at(reg.x1 + 1, y1, t)) {
// log_info("(%d, %d) occ %d bels %d\n", reg.x1+ 1, y1, occ_at(reg.x1 + 1, y1),
// bels_at(reg.x1 + 1, y1));
over_occ_x = true;
break;
}
@ -1374,8 +1370,6 @@ class HeAPPlacer
for (int x1 = reg.x0; x1 <= reg.x1; x1++) {
for (size_t t = 0; t < beltype.size(); t++) {
if (occ_at(x1, reg.y1 + 1, t) > bels_at(x1, reg.y1 + 1, t)) {
// log_info("(%d, %d) occ %d bels %d\n", x1, reg.y1 + 1, occ_at(x1, reg.y1 + 1),
// bels_at(x1, reg.y1 + 1));
over_occ_y = true;
break;
}
@ -1600,13 +1594,8 @@ class HeAPPlacer
if (std::accumulate(left_bels_v.begin(), left_bels_v.end(), 0) == 0 ||
std::accumulate(right_bels_v.begin(), right_bels_v.end(), 0) == 0)
return {};
// log_info("pivot %d target cut %d lc %d lb %d rc %d rb %d\n", pivot, best_tgt_cut,
// std::accumulate(left_cells_v.begin(), left_cells_v.end(), 0), std::accumulate(left_bels_v.begin(),
// left_bels_v.end(), 0),
// std::accumulate(right_cells_v.begin(), right_cells_v.end(), 0),
// std::accumulate(right_bels_v.begin(), right_bels_v.end(), 0));
// Peturb the source cut to eliminate overutilisation
// Perturb the source cut to eliminate overutilisation
auto is_part_overutil = [&](bool r) {
double delta = 0;
for (size_t t = 0; t < left_cells_v.size(); t++) {
@ -1629,8 +1618,7 @@ class HeAPPlacer
right_cells_v.at(type_index.at(cut_cells.at(pivot)->type)) -= size;
pivot++;
}
// log_info("peturbed pivot %d lc %d lb %d rc %d rb %d\n", pivot, left_cells, left_bels, right_cells,
// right_bels);
// Split regions into bins, and then spread cells by linear interpolation within those bins
auto spread_binlerp = [&](int cells_start, int cells_end, double area_l, double area_r) {
int N = cells_end - cells_start;
@ -1673,8 +1661,6 @@ class HeAPPlacer
NPNR_ASSERT(pos >= orig_left && pos <= orig_right);
pos = bl.second + m * (pos - orig_left);
}
// log("[%f, %f] -> [%f, %f]: %f -> %f\n", orig_left, orig_right, bl.second, br.second,
// orig_pos, pos);
}
}
};
@ -1690,7 +1676,6 @@ class HeAPPlacer
cl.x = std::min(r.x1, std::max(r.x0, int(cl.rawx)));
cl.y = std::min(r.y1, std::max(r.y0, int(cl.rawy)));
cells_at_location.at(cl.x).at(cl.y).push_back(cell);
// log_info("spread pos %d %d\n", cl.x, cl.y);
}
SpreaderRegion rl, rr;
rl.id = int(regions.size());

View File

@ -396,7 +396,8 @@ struct Router2
if (ctx->getBelPinType(bp.bel, bp.pin) != PORT_IN)
return false;
for (auto p : ctx->getPipsUphill(wire))
return false;
if (ctx->checkPipAvail(p))
return false;
return true;
}
@ -411,7 +412,7 @@ struct Router2
WireId cursor = sink;
bool done = false;
if (ctx->debug)
log("resevering wires for arc %d of net %s\n", int(i), ctx->nameOf(net));
log("reserving wires for arc %d of net %s\n", int(i), ctx->nameOf(net));
while (!done) {
auto &wd = wire_data(cursor);
if (ctx->debug)

View File

@ -1,69 +0,0 @@
#include <assert.h>
#include <string>
#include "log.h"
#include "nextpnr.h"
NEXTPNR_NAMESPACE_BEGIN
bool check_all_nets_driven(Context *ctx)
{
const bool debug = false;
log_info("Rule checker, verifying imported design\n");
for (auto &cell_entry : ctx->cells) {
CellInfo *cell = cell_entry.second.get();
if (debug)
log_info(" Examining cell \'%s\', of type \'%s\'\n", cell->name.c_str(ctx), cell->type.c_str(ctx));
for (auto port_entry : cell->ports) {
PortInfo &port = port_entry.second;
if (debug)
log_info(" Checking name of port \'%s\' "
"against \'%s\'\n",
port_entry.first.c_str(ctx), port.name.c_str(ctx));
NPNR_ASSERT(port.name == port_entry.first);
NPNR_ASSERT(!port.name.empty());
if (port.net == NULL) {
if (debug)
log_warning(" Port \'%s\' in cell \'%s\' is unconnected\n", port.name.c_str(ctx),
cell->name.c_str(ctx));
} else {
NPNR_ASSERT(port.net);
if (debug)
log_info(" Checking for a net named \'%s\'\n", port.net->name.c_str(ctx));
NPNR_ASSERT(ctx->nets.count(port.net->name) > 0);
}
}
}
for (auto &net_entry : ctx->nets) {
NetInfo *net = net_entry.second.get();
NPNR_ASSERT(net->name == net_entry.first);
if ((net->driver.cell != NULL) && (net->driver.cell->type != ctx->id("GND")) &&
(net->driver.cell->type != ctx->id("VCC"))) {
if (debug)
log_info(" Checking for a driver cell named \'%s\'\n", net->driver.cell->name.c_str(ctx));
NPNR_ASSERT(ctx->cells.count(net->driver.cell->name) > 0);
}
for (auto user : net->users) {
if ((user.cell != NULL) && (user.cell->type != ctx->id("GND")) && (user.cell->type != ctx->id("VCC"))) {
if (debug)
log_info(" Checking for a user cell named \'%s\'\n", user.cell->name.c_str(ctx));
NPNR_ASSERT(ctx->cells.count(user.cell->name) > 0);
}
}
}
if (debug)
log_info(" Verified!\n");
return true;
}
NEXTPNR_NAMESPACE_END

View File

@ -317,7 +317,8 @@ struct Timing
auto &data = net_data[port.second.net][start_clk];
auto &arrival = data.max_arrival;
arrival = std::max(arrival, usr_arrival + comb_delay.maxDelay());
if (!budget_override) { // Do not increment path length if budget overriden since it doesn't
if (!budget_override) { // Do not increment path length if budget overridden since it
// doesn't
// require a share of the slack
auto &path_length = data.max_path_length;
path_length = std::max(path_length, net_length_plus_one);
@ -602,20 +603,11 @@ struct Timing
auto &nc = (*net_crit)[net->name];
if (nc.slack.empty())
nc.slack.resize(net->users.size(), std::numeric_limits<delay_t>::max());
#if 0
if (ctx->debug)
log_info("Net %s cd %s\n", net->name.c_str(ctx), startdomain.first.clock.c_str(ctx));
#endif
for (size_t i = 0; i < net->users.size(); i++) {
delay_t slack = nd.min_required.at(i) -
(nd.max_arrival + ctx->getNetinfoRouteDelay(net, net->users.at(i)));
#if 0
if (ctx->debug)
log_info(" user %s.%s required %.02fns arrival %.02f route %.02f slack %.02f\n",
net->users.at(i).cell->name.c_str(ctx), net->users.at(i).port.c_str(ctx),
ctx->getDelayNS(nd.min_required.at(i)), ctx->getDelayNS(nd.max_arrival),
ctx->getDelayNS(ctx->getNetinfoRouteDelay(net, net->users.at(i))), ctx->getDelayNS(slack));
#endif
if (worst_slack.count(startdomain.first))
worst_slack.at(startdomain.first) = std::min(worst_slack.at(startdomain.first), slack);
else
@ -653,23 +645,6 @@ struct Timing
nc.cd_worst_slack = worst_slack.at(startdomain.first);
}
}
#if 0
if (ctx->debug) {
for (auto &nc : *net_crit) {
NetInfo *net = ctx->nets.at(nc.first).get();
log_info("Net %s maxlen %d worst_slack %.02fns: \n", nc.first.c_str(ctx), nc.second.max_path_length,
ctx->getDelayNS(nc.second.cd_worst_slack));
if (!nc.second.criticality.empty() && !nc.second.slack.empty()) {
for (size_t i = 0; i < net->users.size(); i++) {
log_info(" user %s.%s slack %.02fns crit %.03f\n", net->users.at(i).cell->name.c_str(ctx),
net->users.at(i).port.c_str(ctx), ctx->getDelayNS(nc.second.slack.at(i)),
nc.second.criticality.at(i));
}
}
log_break();
}
}
#endif
}
return min_slack;
}

View File

@ -320,8 +320,8 @@ Get the source wire for a pip.
Get the destination wire for a pip.
Bi-directional switches (transfer gates) are modelled using two
antiparallel pips.
Bi-directional switches (transfer gates) are modeled using two
anti-parallel pips.
### DelayInfo getPipDelay(PipId pip) const
@ -378,8 +378,8 @@ This should return a low upper bound for the fastest route from `src` to `dst`.
Or in other words it should assume an otherwise unused chip (thus "fastest route").
But it only produces an estimate for that fastest route, not an exact
result, and for that estimate it is considered more accaptable to return a
slightly too high result and it is considered less accaptable to return a
result, and for that estimate it is considered more acceptable to return a
slightly too high result and it is considered less acceptable to return a
too low result (thus "low upper bound").
### delay\_t predictDelay(const NetInfo \*net\_info, const PortRef &sink) const

View File

@ -32,7 +32,7 @@ Additionally to this; architectures provide functions for checking the availabil
To avoid the high cost of using strings as identifiers directly; almost all "string" identifiers in nextpnr (such as cell names and types) use an indexed string pool type named `IdString`. Unlike Yosys, which has a global garbage collected pool, nextpnr has a per-Context pool without any garbage collection.
`IdString`s can be created in two ways. Architectures can add `IdString`s with constant indicies - allowing `IdString` constants to be provided too - using `initialize_add` at startup. See how `constids.inc` is used in iCE40 for an example of this. The main way to create `IdString`s, however, is at runtime using the `id` member function of `BaseCtx` given the string to create from (if an `IdString` of that string already exists, the existing `IdString` will be returned).
`IdString`s can be created in two ways. Architectures can add `IdString`s with constant indices - allowing `IdString` constants to be provided too - using `initialize_add` at startup. See how `constids.inc` is used in iCE40 for an example of this. The main way to create `IdString`s, however, is at runtime using the `id` member function of `BaseCtx` given the string to create from (if an `IdString` of that string already exists, the existing `IdString` will be returned).
Note that `IdString`s need a `Context` (or `BaseCtx`) pointer to convert them back to regular strings, due to the pool being per-context as described above.

View File

@ -57,7 +57,7 @@ for your architecture once implementing small designs work.
The `getConflictingWireWire()`, `getConflictingWireNet()`, `getConflictingPipWire()`, and `getConflictingPipNet()` methods are used by the router
to determine which resources to rip up in order to make a given routing resource (wire or pip) available.
The architecture must guanrantee that the following invariants hold.
The architecture must guarantee that the following invariants hold.
**Invariant 1:**
@ -223,4 +223,4 @@ for these parts.
As the open source community now has support for multiple different FPGA parts,
in the nextpnr documentation we generally use Project IceStorm to mean the database and
tools that fulfil the same role as Project Trellis or Project X-Ray.
tools that fulfill the same role as Project Trellis or Project X-Ray.

View File

@ -615,31 +615,6 @@ bool Arch::route()
log_error("ECP5 architecture does not support router '%s'\n", router.c_str());
}
#if 0
std::vector<std::pair<WireId, int>> fanout_vector;
std::copy(wire_fanout.begin(), wire_fanout.end(), std::back_inserter(fanout_vector));
std::sort(fanout_vector.begin(), fanout_vector.end(), [](const std::pair<WireId, int> &a, const std::pair<WireId, int> &b) {
return a.second > b.second;
});
for (size_t i = 0; i < std::min(size_t(20), fanout_vector.size()); i++)
log_info(" fanout %s = %d\n", getWireName(fanout_vector[i].first).c_str(this), fanout_vector[i].second);
log_break();
PipId slowest_pip;
delay_t slowest_pipdelay = 0;
for (auto pip : pip_to_net) {
if (pip.second) {
delay_t dly = getPipDelay(pip.first).maxDelay();
if (dly > slowest_pipdelay) {
slowest_pip = pip.first;
slowest_pipdelay = dly;
}
}
}
log_info(" slowest pip %s = %.02f ns\n", getPipName(slowest_pip).c_str(this), getDelayNS(slowest_pipdelay));
log_info(" fanout %d\n", wire_fanout[getPipSrcWire(slowest_pip)]);
log_info(" base %d adder %d\n", speed_grade->pip_classes[locInfo(slowest_pip)->pip_data[slowest_pip.index].timing_class].max_base_delay,
speed_grade->pip_classes[locInfo(slowest_pip)->pip_data[slowest_pip.index].timing_class].max_fanout_adder);
#endif
getCtx()->settings[getCtx()->id("route")] = 1;
archInfoToAttributes();
return result;

View File

@ -527,7 +527,7 @@ static std::vector<bool> parse_config_str(const Property &p, int length)
std::vector<bool> word;
if (p.is_string) {
std::string str = p.as_string();
// For DCU config which might be bin, hex or dec using prefices accordingly
// For DCU config which might be bin, hex or dec using prefixes accordingly
std::string base = str.substr(0, 2);
word.resize(length, false);
if (base == "0b") {

View File

@ -1126,7 +1126,7 @@ class Ecp5Packer
flush_cells();
}
// Find a cell that meets some criterea near an origin cell
// Find a cell that meets some criteria near an origin cell
// Used for packing an FF into a nearby SLICE
template <typename TFunc> CellInfo *find_nearby_cell(CellInfo *origin, TFunc Func)
{

View File

@ -158,7 +158,7 @@ float FPGAViewWidget::PickedElement::distance(Context *ctx, float wx, float wy)
return std::abs(dw - dab) / dab;
}
default:
// Not close to antyhing.
// Not close to anything.
return -1;
}
});
@ -819,7 +819,7 @@ QVector4D FPGAViewWidget::mouseToWorldCoordinates(int x, int y)
vec = projection.inverted() * QVector4D(vec.x(), vec.y(), -1, 1);
// Hic sunt dracones.
// TODO(q3k): grab a book, remind yourselfl linear algebra and undo this
// TODO(q3k): grab a book, remind yourself linear algebra and undo this
// operation properly.
QVector3D ray = vec.toVector3DAffine();
ray.normalize();

View File

@ -26,7 +26,7 @@ void PolyLine::buildPoint(LineShaderData *building, const QVector2D *prev, const
const QVector2D *next) const
{
// buildPoint emits two vertices per line point, along with normals to move
// them the right directio when rendering and miter to compensate for
// them the right direction when rendering and miter to compensate for
// bends.
if (cur == nullptr) {
@ -104,7 +104,7 @@ void PolyLine::build(LineShaderData &target) const
// For every point on the line, call buildPoint with (prev, point, next).
// If we're building a closed line, prev/next wrap around. Otherwise
// they are passed as nullptr and buildPoint interprets that accordinglu.
// they are passed as nullptr and buildPoint interprets that accordingly.
const QVector2D *prev = nullptr;
// Loop iterator used to ensure next is valid.

View File

@ -20,7 +20,7 @@
#ifndef QUADTREE_H
#define QUADTREE_H
// This file implements a quad tree used for comitting 2D axis aligned
// This file implements a quad tree used for committing 2D axis aligned
// bounding boxes and then retrieving them by 2D point.
NEXTPNR_NAMESPACE_BEGIN
@ -382,17 +382,17 @@ template <typename CoordinateT, typename ElementT> class QuadTree
// Standard constructor.
//
// @param b Bounding box of the entire tree - all comitted elements must
// @param b Bounding box of the entire tree - all committed elements must
// fit within in.
QuadTree(BoundingBox b) : root_(b, 0) {}
// Inserts a new value at a given bounding box.e
// BoundingBoxes are not deduplicated - if two are pushed with the same
// coordinates, the first one will take precendence.
// coordinates, the first one will take precedence.
//
// @param k Bounding box at which to store value.
// @param v Value at a given bounding box.
// @returns Whether the insert was succesful.
// @returns Whether the insert was successful.
bool insert(BoundingBox k, ElementT v)
{
k.fixup();

View File

@ -145,7 +145,7 @@ class IdStringList : public Item
ElementType child_type_;
public:
// Create an IdStringList at given partent that will contain elements of
// Create an IdStringList at given parent that will contain elements of
// the given type.
IdStringList(ElementType type) : Item("root", nullptr), child_type_(type) {}

View File

@ -409,14 +409,6 @@ std::vector<std::pair<IdString, std::string>> Arch::getWireAttrs(WireId wire) co
ret.push_back(std::make_pair(id("GRID_Y"), stringf("%d", wi.y)));
ret.push_back(std::make_pair(id("GRID_Z"), stringf("%d", wi.z)));
#if 0
for (int i = 0; i < wi.num_segments; i++) {
auto &si = wi.segments[i];
ret.push_back(std::make_pair(id(stringf("segment[%d]", i)),
stringf("X%d/Y%d/%s", si.x, si.y, chip_info->tile_wire_names[si.index].get())));
}
#endif
return ret;
}
@ -830,28 +822,12 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
for (int i = 0; i < n; i++)
gfxTileWire(ret, p[i].x, p[i].y, chip_info->width, chip_info->height, GfxTileWireId(p[i].index), style);
#if 0
if (ret.empty()) {
WireId wire;
wire.index = decal.index;
log_warning("No gfx decal for wire %s (%d).\n", getWireName(wire).c_str(getCtx()), decal.index);
}
#endif
}
if (decal.type == DecalId::TYPE_PIP) {
const PipInfoPOD &p = chip_info->pip_data[decal.index];
GraphicElement::style_t style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_HIDDEN;
gfxTilePip(ret, p.x, p.y, GfxTileWireId(p.src_seg), GfxTileWireId(p.dst_seg), style);
#if 0
if (ret.empty()) {
PipId pip;
pip.index = decal.index;
log_warning("No gfx decal for pip %s (%d).\n", getPipName(pip).c_str(getCtx()), decal.index);
}
#endif
}
if (decal.type == DecalId::TYPE_BEL) {
@ -920,14 +896,6 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
el.y2 = chip_info->bel_data[bel.index].y + main_swbox_y2 + 0.05;
ret.push_back(el);
}
#if 0
if (ret.empty()) {
BelId bel;
bel.index = decal.index;
log_warning("No gfx decal for bel %s (%d).\n", getBelName(bel).c_str(getCtx()), decal.index);
}
#endif
}
return ret;

View File

@ -833,7 +833,7 @@ struct Arch : BaseCtx
bool logicCellsCompatible(const CellInfo **it, const size_t size) const;
// -------------------------------------------------
// Assign architecure-specific arguments to nets and cells, which must be
// Assign architecture-specific arguments to nets and cells, which must be
// called between packing or further
// netlist modifications, and validity checks
void assignArchInfo();

View File

@ -1354,7 +1354,7 @@ struct Arch : BaseCtx
void post_place_opt();
// -------------------------------------------------
// Assign architecure-specific arguments to nets and cells, which must be
// Assign architecture-specific arguments to nets and cells, which must be
// called between packing or further
// netlist modifications, and validity checks
void assignArchInfo();

View File

@ -1700,9 +1700,8 @@ struct NexusPacker
: std::string("USED_AS_LOWER_BIT_GENERATION");
}
// Create final mult36 if needed
CellInfo *mult36 = nullptr;
if (mult36_used) {
mult36 = create_dsp_cell(ci->name, id_MULT36_CORE, preadd9[0], 6, 6);
create_dsp_cell(ci->name, id_MULT36_CORE, preadd9[0], 6, 6);
}
// Configure output registers