From 8ee149f4fcb66cb61aa729263448c0935fb4d2ad Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 18 Jun 2018 14:06:37 +0200 Subject: [PATCH] Rename Design to Context, derive from Arch instead of instantiating Signed-off-by: Clifford Wolf --- common/design.h | 10 ++-- common/design_utils.cc | 8 +-- common/design_utils.h | 2 +- common/place_sa.cc | 95 ++++++++++++++++---------------- common/place_sa.h | 2 +- common/pybindings.cc | 17 +++--- common/route.cc | 107 ++++++++++++++++++------------------- common/route.h | 2 +- common/rulecheck.cc | 12 ++--- dummy/arch_place.cc | 4 +- dummy/arch_place.h | 4 +- dummy/main.cc | 4 +- frontend/json/jsonparse.cc | 60 ++++++++++----------- frontend/json/jsonparse.h | 2 +- gui/designwidget.cc | 16 +++--- gui/designwidget.h | 6 +-- gui/fpgaviewwidget.cc | 8 +-- gui/fpgaviewwidget.h | 2 +- gui/mainwindow.cc | 8 +-- gui/mainwindow.h | 6 +-- ice40/arch_place.cc | 32 ++++++----- ice40/arch_place.h | 4 +- ice40/bitstream.cc | 69 ++++++++++++------------ ice40/bitstream.h | 2 +- ice40/cells.cc | 2 +- ice40/cells.h | 2 +- ice40/main.cc | 29 +++++----- ice40/pack.cc | 102 +++++++++++++++++------------------ ice40/pack.h | 2 +- ice40/pcf.cc | 10 ++-- ice40/pcf.h | 2 +- 31 files changed, 309 insertions(+), 322 deletions(-) diff --git a/common/design.h b/common/design.h index 13c66d4e..cae50904 100644 --- a/common/design.h +++ b/common/design.h @@ -70,17 +70,15 @@ struct CellInfo std::unordered_map pins; }; -struct Design +struct Context : Arch { - struct Arch chip; + std::unordered_map nets; + std::unordered_map cells; - Design(ArchArgs args) : chip(args) + Context(ArchArgs args) : Arch(args) { // ... } - - std::unordered_map nets; - std::unordered_map cells; }; NEXTPNR_NAMESPACE_END diff --git a/common/design_utils.cc b/common/design_utils.cc index ae6e21ed..f2ce2285 100644 --- a/common/design_utils.cc +++ b/common/design_utils.cc @@ -53,16 +53,16 @@ void replace_port(CellInfo *old_cell, IdString old_name, CellInfo *rep_cell, } // Print utilisation of a design -void print_utilisation(const Design *design) +void print_utilisation(const Context *ctx) { // Sort by Bel type std::map used_types; - for (auto cell : design->cells) { + for (auto cell : ctx->cells) { used_types[belTypeFromId(cell.second->type)]++; } std::map available_types; - for (auto bel : design->chip.getBels()) { - available_types[design->chip.getBelType(bel)]++; + for (auto bel : ctx->getBels()) { + available_types[ctx->getBelType(bel)]++; } log("\nDesign utilisation:\n"); for (auto type : available_types) { diff --git a/common/design_utils.h b/common/design_utils.h index d640bf68..2177c0e5 100644 --- a/common/design_utils.h +++ b/common/design_utils.h @@ -84,7 +84,7 @@ CellInfo *net_driven_by(const NetInfo *net, F1 cell_pred, IdString port) } } -void print_utilisation(const Design *design); +void print_utilisation(const Context *ctx); NEXTPNR_NAMESPACE_END diff --git a/common/place_sa.cc b/common/place_sa.cc index f1c3dea2..19588d27 100644 --- a/common/place_sa.cc +++ b/common/place_sa.cc @@ -70,7 +70,7 @@ static int random_int_between(rnd_state &rnd, int a, int b) } // Initial random placement -static void place_initial(Design *design, CellInfo *cell, rnd_state &rnd) +static void place_initial(Context *ctx, CellInfo *cell, rnd_state &rnd) { bool all_placed = false; int iters = 25; @@ -78,18 +78,17 @@ static void place_initial(Design *design, CellInfo *cell, rnd_state &rnd) BelId best_bel = BelId(); float best_score = std::numeric_limits::infinity(), best_ripup_score = std::numeric_limits::infinity(); - Arch &chip = design->chip; CellInfo *ripup_target = nullptr; BelId ripup_bel = BelId(); if (cell->bel != BelId()) { - chip.unbindBel(cell->bel); + ctx->unbindBel(cell->bel); cell->bel = BelId(); } BelType targetType = belTypeFromId(cell->type); - for (auto bel : chip.getBels()) { - if (chip.getBelType(bel) == targetType && - isValidBelForCell(design, cell, bel)) { - if (chip.checkBelAvail(bel)) { + for (auto bel : ctx->getBels()) { + if (ctx->getBelType(bel) == targetType && + isValidBelForCell(ctx, cell, bel)) { + if (ctx->checkBelAvail(bel)) { float score = random_float_upto(rnd, 1.0); if (score <= best_score) { best_score = score; @@ -100,7 +99,7 @@ static void place_initial(Design *design, CellInfo *cell, rnd_state &rnd) if (score <= best_ripup_score) { best_ripup_score = score; ripup_target = - design->cells.at(chip.getBelCell(bel, true)); + ctx->cells.at(ctx->getBelCell(bel, true)); ripup_bel = bel; } } @@ -111,17 +110,17 @@ static void place_initial(Design *design, CellInfo *cell, rnd_state &rnd) log_error("failed to place cell '%s' of type '%s'\n", cell->name.c_str(), cell->type.c_str()); --iters; - chip.unbindBel(ripup_target->bel); + ctx->unbindBel(ripup_target->bel); ripup_target->bel = BelId(); best_bel = ripup_bel; } else { all_placed = true; } cell->bel = best_bel; - chip.bindBel(cell->bel, cell->name); + ctx->bindBel(cell->bel, cell->name); // Back annotate location - cell->attrs["BEL"] = chip.getBelName(cell->bel).str(); + cell->attrs["BEL"] = ctx->getBelName(cell->bel).str(); cell = ripup_target; } } @@ -174,22 +173,21 @@ static float get_wirelength(Arch *chip, NetInfo *net) } // Attempt a SA position swap, return true on success or false on failure -static bool try_swap_position(Design *design, CellInfo *cell, BelId newBel, +static bool try_swap_position(Context *ctx, CellInfo *cell, BelId newBel, rnd_state &rnd, SAState &state) { static std::unordered_set update; static std::vector> new_lengths; new_lengths.clear(); update.clear(); - Arch &chip = design->chip; BelId oldBel = cell->bel; - IdString other = chip.getBelCell(newBel, true); + IdString other = ctx->getBelCell(newBel, true); CellInfo *other_cell = nullptr; float new_wirelength = 0, delta; - chip.unbindBel(oldBel); + ctx->unbindBel(oldBel); if (other != IdString()) { - other_cell = design->cells[other]; - chip.unbindBel(newBel); + other_cell = ctx->cells[other]; + ctx->unbindBel(newBel); } for (const auto &port : cell->ports) @@ -202,17 +200,17 @@ static bool try_swap_position(Design *design, CellInfo *cell, BelId newBel, update.insert(port.second.net); } - chip.bindBel(newBel, cell->name); + ctx->bindBel(newBel, cell->name); if (other != IdString()) { - chip.bindBel(oldBel, other_cell->name); + ctx->bindBel(oldBel, other_cell->name); } - if (!isBelLocationValid(design, newBel) || - ((other != IdString() && !isBelLocationValid(design, oldBel)))) { - chip.unbindBel(newBel); + if (!isBelLocationValid(ctx, newBel) || + ((other != IdString() && !isBelLocationValid(ctx, oldBel)))) { + ctx->unbindBel(newBel); if (other != IdString()) - chip.unbindBel(oldBel); + ctx->unbindBel(oldBel); goto swap_fail; } @@ -225,7 +223,7 @@ static bool try_swap_position(Design *design, CellInfo *cell, BelId newBel, // Recalculate wirelengths for all nets touched by the peturbation for (auto net : update) { new_wirelength -= state.wirelengths.at(net); - float net_new_wl = get_wirelength(&chip, net); + float net_new_wl = get_wirelength(ctx, net); new_wirelength += net_new_wl; new_lengths.push_back(std::make_pair(net, net_new_wl)); } @@ -240,8 +238,8 @@ static bool try_swap_position(Design *design, CellInfo *cell, BelId newBel, state.improved = true; } else { if (other != IdString()) - chip.unbindBel(oldBel); - chip.unbindBel(newBel); + ctx->unbindBel(oldBel); + ctx->unbindBel(newBel); goto swap_fail; } state.curr_wirelength = new_wirelength; @@ -250,10 +248,10 @@ static bool try_swap_position(Design *design, CellInfo *cell, BelId newBel, return true; swap_fail: - chip.bindBel(oldBel, cell->name); + ctx->bindBel(oldBel, cell->name); cell->bel = oldBel; if (other != IdString()) { - chip.bindBel(newBel, other); + ctx->bindBel(newBel, other); other_cell->bel = newBel; } return false; @@ -261,13 +259,12 @@ swap_fail: // Find a random Bel of the correct type for a cell, within the specified // diameter -BelId random_bel_for_cell(Design *design, CellInfo *cell, SAState &state, +BelId random_bel_for_cell(Context *ctx, CellInfo *cell, SAState &state, rnd_state &rnd) { - Arch &chip = design->chip; BelType targetType = belTypeFromId(cell->type); int x = 0, y = 0; - chip.estimatePosition(cell->bel, x, y); + ctx->estimatePosition(cell->bel, x, y); while (true) { int nx = random_int_between(rnd, std::max(int(x) - state.diameter, 0), int(x) + state.diameter + 1); @@ -288,26 +285,26 @@ BelId random_bel_for_cell(Design *design, CellInfo *cell, SAState &state, } } -void place_design_sa(Design *design, int seed) +void place_design_sa(Context *ctx, int seed) { SAState state; size_t placed_cells = 0; std::queue visit_cells; // Initial constraints placer - for (auto cell_entry : design->cells) { + for (auto cell_entry : ctx->cells) { CellInfo *cell = cell_entry.second; auto loc = cell->attrs.find("BEL"); if (loc != cell->attrs.end()) { std::string loc_name = loc->second; - BelId bel = design->chip.getBelByName(IdString(loc_name)); + BelId bel = ctx->getBelByName(IdString(loc_name)); if (bel == BelId()) { log_error("No Bel named \'%s\' located for " "this chip (processing BEL attribute on \'%s\')\n", loc_name.c_str(), cell->name.c_str()); } - BelType bel_type = design->chip.getBelType(bel); + BelType bel_type = ctx->getBelType(bel); if (bel_type != belTypeFromId(cell->type)) { log_error("Bel \'%s\' of type \'%s\' does not match cell " "\'%s\' of type \'%s\'", @@ -316,7 +313,7 @@ void place_design_sa(Design *design, int seed) } cell->bel = bel; - design->chip.bindBel(bel, cell->name); + ctx->bindBel(bel, cell->name); state.locked_bels.insert(bel); placed_cells++; visit_cells.push(cell); @@ -327,7 +324,7 @@ void place_design_sa(Design *design, int seed) rnd.state = seed; std::vector autoplaced; // Sort to-place cells for deterministic initial placement - for (auto cell : design->cells) { + for (auto cell : ctx->cells) { CellInfo *ci = cell.second; if (ci->bel == BelId()) { autoplaced.push_back(cell.second); @@ -337,16 +334,16 @@ void place_design_sa(Design *design, int seed) [](CellInfo *a, CellInfo *b) { return a->name < b->name; }); // Place cells randomly initially for (auto cell : autoplaced) { - place_initial(design, cell, rnd); + place_initial(ctx, cell, rnd); placed_cells++; } // Build up a fast position/type to Bel lookup table int max_x = 0, max_y = 0; int bel_types = 0; - for (auto bel : design->chip.getBels()) { + for (auto bel : ctx->getBels()) { int x, y; - design->chip.estimatePosition(bel, x, y); - BelType type = design->chip.getBelType(bel); + ctx->estimatePosition(bel, x, y); + BelType type = ctx->getBelType(bel); int type_idx; if (state.bel_types.find(type) == state.bel_types.end()) { type_idx = bel_types++; @@ -367,8 +364,8 @@ void place_design_sa(Design *design, int seed) state.diameter = std::max(max_x, max_y) + 1; // Calculate wirelength after initial placement state.curr_wirelength = 0; - for (auto net : design->nets) { - float wl = get_wirelength(&design->chip, net.second); + for (auto net : ctx->nets) { + float wl = get_wirelength(ctx, net.second); state.wirelengths[net.second] = wl; state.curr_wirelength += wl; } @@ -390,11 +387,11 @@ void place_design_sa(Design *design, int seed) // Loop through all automatically placed cells for (auto cell : autoplaced) { // Find another random Bel for this cell - BelId try_bel = random_bel_for_cell(design, cell, state, rnd); + BelId try_bel = random_bel_for_cell(ctx, cell, state, rnd); // If valid, try and swap to a new position and see if // the new position is valid/worthwhile if (try_bel != BelId() && try_bel != cell->bel) - try_swap_position(design, cell, try_bel, rnd, state); + try_swap_position(ctx, cell, try_bel, rnd, state); } } // Heuristic to improve placement on the 8k @@ -434,14 +431,14 @@ void place_design_sa(Design *design, int seed) } } } - for (auto bel : design->chip.getBels()) { - if (!isBelLocationValid(design, bel)) { + for (auto bel : ctx->getBels()) { + if (!isBelLocationValid(ctx, bel)) { std::string cell_text = "no cell"; - IdString cell = design->chip.getBelCell(bel, false); + IdString cell = ctx->getBelCell(bel, false); if (cell != IdString()) cell_text = std::string("cell '") + cell.str() + "'"; log_error("post-placement validity check failed for Bel '%s' (%s)", - design->chip.getBelName(bel).c_str(), cell_text.c_str()); + ctx->getBelName(bel).c_str(), cell_text.c_str()); } } } diff --git a/common/place_sa.h b/common/place_sa.h index 944cb97e..8ac9e8f6 100644 --- a/common/place_sa.h +++ b/common/place_sa.h @@ -23,7 +23,7 @@ NEXTPNR_NAMESPACE_BEGIN -extern void place_design_sa(Design *design, int seed); +extern void place_design_sa(Context *ctx, int seed); NEXTPNR_NAMESPACE_END diff --git a/common/pybindings.cc b/common/pybindings.cc index 3621d27a..4c10939a 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -47,7 +47,7 @@ bool operator==(const PortRef &a, const PortRef &b) } // Load a JSON file into a design -void parse_json_shim(std::string filename, Design &d) +void parse_json_shim(std::string filename, Context &d) { std::ifstream inf(filename); if (!inf) @@ -57,9 +57,9 @@ void parse_json_shim(std::string filename, Design &d) } // Create a new Chip and load design from json file -Design load_design_shim(std::string filename, ArchArgs args) +Context load_design_shim(std::string filename, ArchArgs args) { - Design d(args); + Context d(args); parse_json_shim(filename, d); return d; } @@ -113,13 +113,12 @@ BOOST_PYTHON_MODULE(MODULE_NAME) WRAP_MAP(decltype(CellInfo::ports), "IdPortMap"); // WRAP_MAP(decltype(CellInfo::pins), "IdIdMap"); - class_("Design", no_init) - .def_readwrite("chip", &Design::chip) - .def_readwrite("nets", &Design::nets) - .def_readwrite("cells", &Design::cells); + class_("Context", no_init) + .def_readwrite("nets", &Context::nets) + .def_readwrite("cells", &Context::cells); - WRAP_MAP(decltype(Design::nets), "IdNetMap"); - WRAP_MAP(decltype(Design::cells), "IdCellMap"); + WRAP_MAP(decltype(Context::nets), "IdNetMap"); + WRAP_MAP(decltype(Context::cells), "IdCellMap"); def("parse_json", parse_json_shim); def("load_design", load_design_shim); diff --git a/common/route.cc b/common/route.cc index a4127532..080440d6 100644 --- a/common/route.cc +++ b/common/route.cc @@ -44,15 +44,14 @@ struct QueuedWire }; }; -void ripup_net(Design *design, IdString net_name) +void ripup_net(Context *ctx, IdString net_name) { - auto &chip = design->chip; - auto net_info = design->nets.at(net_name); + auto net_info = ctx->nets.at(net_name); for (auto &it : net_info->wires) { if (it.second != PipId()) - chip.unbindPip(it.second); - chip.unbindWire(it.first); + ctx->unbindPip(it.second); + ctx->unbindWire(it.first); } net_info->wires.clear(); @@ -66,11 +65,10 @@ struct Router delay_t maxDelay = 0.0; WireId failedDest; - Router(Design *design, IdString net_name, bool verbose, bool ripup = false, + Router(Context *ctx, IdString net_name, bool verbose, bool ripup = false, delay_t ripup_penalty = 0) { - auto &chip = design->chip; - auto net_info = design->nets.at(net_name); + auto net_info = ctx->nets.at(net_name); if (verbose) log("Routing net %s.\n", net_name.c_str()); @@ -87,7 +85,7 @@ struct Router net_info->driver.cell->type.c_str()); if (verbose) - log(" Source bel: %s\n", chip.getBelName(src_bel).c_str()); + log(" Source bel: %s\n", ctx->getBelName(src_bel).c_str()); IdString driver_port = net_info->driver.port; @@ -95,22 +93,22 @@ struct Router if (driver_port_it != net_info->driver.cell->pins.end()) driver_port = driver_port_it->second; - auto src_wire = chip.getWireBelPin(src_bel, portPinFromId(driver_port)); + auto src_wire = ctx->getWireBelPin(src_bel, portPinFromId(driver_port)); if (src_wire == WireId()) log_error("No wire found for port %s (pin %s) on source cell %s " "(bel %s).\n", net_info->driver.port.c_str(), driver_port.c_str(), net_info->driver.cell->name.c_str(), - chip.getBelName(src_bel).c_str()); + ctx->getBelName(src_bel).c_str()); if (verbose) - log(" Source wire: %s\n", chip.getWireName(src_wire).c_str()); + log(" Source wire: %s\n", ctx->getWireName(src_wire).c_str()); std::unordered_map src_wires; src_wires[src_wire] = DelayInfo(); net_info->wires[src_wire] = PipId(); - chip.bindWire(src_wire, net_name); + ctx->bindWire(src_wire, net_name); for (auto &user_it : net_info->users) { if (verbose) @@ -126,7 +124,7 @@ struct Router if (verbose) log(" Destination bel: %s\n", - chip.getBelName(dst_bel).c_str()); + ctx->getBelName(dst_bel).c_str()); IdString user_port = user_it.port; @@ -136,20 +134,20 @@ struct Router user_port = user_port_it->second; auto dst_wire = - chip.getWireBelPin(dst_bel, portPinFromId(user_port)); + ctx->getWireBelPin(dst_bel, portPinFromId(user_port)); if (dst_wire == WireId()) log_error("No wire found for port %s (pin %s) on destination " "cell %s (bel %s).\n", user_it.port.c_str(), user_port.c_str(), user_it.cell->name.c_str(), - chip.getBelName(dst_bel).c_str()); + ctx->getBelName(dst_bel).c_str()); if (verbose) { log(" Destination wire: %s\n", - chip.getWireName(dst_wire).c_str()); + ctx->getWireName(dst_wire).c_str()); log(" Path delay estimate: %.2f\n", - float(chip.estimateDelay(src_wire, dst_wire))); + float(ctx->estimateDelay(src_wire, dst_wire))); } std::unordered_map visited; @@ -162,7 +160,7 @@ struct Router qw.wire = it.first; qw.pip = PipId(); qw.delay = it.second.avgDelay(); - qw.togo = chip.estimateDelay(qw.wire, dst_wire); + qw.togo = ctx->estimateDelay(qw.wire, dst_wire); queue.push(qw); visited[qw.wire] = qw; @@ -172,26 +170,26 @@ struct Router QueuedWire qw = queue.top(); queue.pop(); - for (auto pip : chip.getPipsDownhill(qw.wire)) { + for (auto pip : ctx->getPipsDownhill(qw.wire)) { delay_t next_delay = qw.delay; IdString ripupNet = net_name; visitCnt++; - if (!chip.checkPipAvail(pip)) { + if (!ctx->checkPipAvail(pip)) { if (!ripup) continue; - ripupNet = chip.getPipNet(pip, true); + ripupNet = ctx->getPipNet(pip, true); if (ripupNet == net_name) continue; } - WireId next_wire = chip.getPipDstWire(pip); - next_delay += chip.getPipDelay(pip).avgDelay(); + WireId next_wire = ctx->getPipDstWire(pip); + next_delay += ctx->getPipDelay(pip).avgDelay(); - if (!chip.checkWireAvail(next_wire)) { + if (!ctx->checkWireAvail(next_wire)) { if (!ripup) continue; - ripupNet = chip.getWireNet(next_wire, true); + ripupNet = ctx->getWireNet(next_wire, true); if (ripupNet == net_name) continue; } @@ -207,7 +205,7 @@ struct Router if (verbose) log("Found better route to %s. Old vs new delay " "estimate: %.2f %.2f\n", - chip.getWireName(next_wire).c_str(), + ctx->getWireName(next_wire).c_str(), float(visited.at(next_wire).delay), float(next_delay)); #endif @@ -218,7 +216,7 @@ struct Router next_qw.wire = next_wire; next_qw.pip = pip; next_qw.delay = next_delay; - next_qw.togo = chip.estimateDelay(next_wire, dst_wire); + next_qw.togo = ctx->estimateDelay(next_wire, dst_wire); visited[next_qw.wire] = next_qw; queue.push(next_qw); } @@ -227,13 +225,13 @@ struct Router if (visited.count(dst_wire) == 0) { if (verbose) log("Failed to route %s -> %s.\n", - chip.getWireName(src_wire).c_str(), - chip.getWireName(dst_wire).c_str()); + ctx->getWireName(src_wire).c_str(), + ctx->getWireName(dst_wire).c_str()); else if (ripup) log_info("Failed to route %s -> %s.\n", - chip.getWireName(src_wire).c_str(), - chip.getWireName(dst_wire).c_str()); - ripup_net(design, net_name); + ctx->getWireName(src_wire).c_str(), + ctx->getWireName(dst_wire).c_str()); + ripup_net(ctx, net_name); failedDest = dst_wire; return; } @@ -251,35 +249,35 @@ struct Router while (1) { if (verbose) log(" %8.2f %s\n", float(visited[cursor].delay), - chip.getWireName(cursor).c_str()); + ctx->getWireName(cursor).c_str()); if (src_wires.count(cursor)) break; - IdString conflicting_net = chip.getWireNet(cursor, true); + IdString conflicting_net = ctx->getWireNet(cursor, true); if (conflicting_net != IdString()) { assert(ripup); assert(conflicting_net != net_name); - ripup_net(design, conflicting_net); + ripup_net(ctx, conflicting_net); rippedNets.insert(conflicting_net); } - conflicting_net = chip.getPipNet(visited[cursor].pip, true); + conflicting_net = ctx->getPipNet(visited[cursor].pip, true); if (conflicting_net != IdString()) { assert(ripup); assert(conflicting_net != net_name); - ripup_net(design, conflicting_net); + ripup_net(ctx, conflicting_net); rippedNets.insert(conflicting_net); } net_info->wires[cursor] = visited[cursor].pip; - chip.bindWire(cursor, net_name); - chip.bindPip(visited[cursor].pip, net_name); + ctx->bindWire(cursor, net_name); + ctx->bindPip(visited[cursor].pip, net_name); - src_wires[cursor] = chip.getPipDelay(visited[cursor].pip); - cursor = chip.getPipSrcWire(visited[cursor].pip); + src_wires[cursor] = ctx->getPipDelay(visited[cursor].pip); + cursor = ctx->getPipSrcWire(visited[cursor].pip); } } @@ -291,16 +289,15 @@ struct Router NEXTPNR_NAMESPACE_BEGIN -bool route_design(Design *design, bool verbose) +bool route_design(Context *ctx, bool verbose) { - auto &chip = design->chip; delay_t ripup_penalty = 5; log_info("Routing..\n"); std::unordered_set netsQueue; - for (auto &net_it : design->nets) { + for (auto &net_it : ctx->nets) { auto net_name = net_it.first; auto net_info = net_it.second; @@ -325,7 +322,7 @@ bool route_design(Design *design, bool verbose) int estimatedTotalDelayCnt = 0; for (auto net_name : netsQueue) { - auto net_info = design->nets.at(net_name); + auto net_info = ctx->nets.at(net_name); auto src_bel = net_info->driver.cell->bel; @@ -338,7 +335,7 @@ bool route_design(Design *design, bool verbose) if (driver_port_it != net_info->driver.cell->pins.end()) driver_port = driver_port_it->second; - auto src_wire = chip.getWireBelPin(src_bel, portPinFromId(driver_port)); + auto src_wire = ctx->getWireBelPin(src_bel, portPinFromId(driver_port)); if (src_wire == WireId()) continue; @@ -357,12 +354,12 @@ bool route_design(Design *design, bool verbose) user_port = user_port_it->second; auto dst_wire = - chip.getWireBelPin(dst_bel, portPinFromId(user_port)); + ctx->getWireBelPin(dst_bel, portPinFromId(user_port)); if (dst_wire == WireId()) continue; - estimatedTotalDelay += chip.estimateDelay(src_wire, dst_wire); + estimatedTotalDelay += ctx->estimateDelay(src_wire, dst_wire); estimatedTotalDelayCnt++; } } @@ -390,9 +387,9 @@ bool route_design(Design *design, bool verbose) for (auto net_name : netsQueue) { if (printNets) log_info(" routing net %s. (%d users)\n", net_name.c_str(), - int(design->nets.at(net_name)->users.size())); + int(ctx->nets.at(net_name)->users.size())); - Router router(design, net_name, verbose, false); + Router router(ctx, net_name, verbose, false); netCnt++; visitCnt += router.visitCnt; @@ -401,7 +398,7 @@ bool route_design(Design *design, bool verbose) if (!router.routedOkay) { if (printNets) log_info(" failed to route to %s.\n", - chip.getWireName(router.failedDest).c_str()); + ctx->getWireName(router.failedDest).c_str()); ripupQueue.insert(net_name); } @@ -433,9 +430,9 @@ bool route_design(Design *design, bool verbose) for (auto net_name : ripupQueue) { if (printNets) log_info(" routing net %s. (%d users)\n", net_name.c_str(), - int(design->nets.at(net_name)->users.size())); + int(ctx->nets.at(net_name)->users.size())); - Router router(design, net_name, verbose, true, + Router router(ctx, net_name, verbose, true, ripup_penalty * (iterCnt - 1)); netCnt++; @@ -455,7 +452,7 @@ bool route_design(Design *design, bool verbose) int(router.rippedNets.size())); for (auto n : router.rippedNets) log_info(" %s (%d users)\n", n.c_str(), - int(design->nets.at(n)->users.size())); + int(ctx->nets.at(n)->users.size())); } else { log_info(" ripped up %d other nets.\n", int(router.rippedNets.size())); diff --git a/common/route.h b/common/route.h index fd4368bf..8475957b 100644 --- a/common/route.h +++ b/common/route.h @@ -24,7 +24,7 @@ NEXTPNR_NAMESPACE_BEGIN -extern bool route_design(Design *design, bool verbose = false); +extern bool route_design(Context *ctx, bool verbose = false); NEXTPNR_NAMESPACE_END diff --git a/common/rulecheck.cc b/common/rulecheck.cc index 987eb602..2f70498f 100644 --- a/common/rulecheck.cc +++ b/common/rulecheck.cc @@ -5,13 +5,13 @@ NEXTPNR_NAMESPACE_BEGIN -bool check_all_nets_driven(Design *design) +bool check_all_nets_driven(Context *ctx) { const bool debug = false; log_info("Rule checker, Verifying pre-placed design\n"); - for (auto cell_entry : design->cells) { + for (auto cell_entry : ctx->cells) { CellInfo *cell = cell_entry.second; if (debug) @@ -37,12 +37,12 @@ bool check_all_nets_driven(Design *design) if (debug) log_info(" Checking for a net named \'%s\'\n", port.net->name.c_str()); - assert(design->nets.count(port.net->name) > 0); + assert(ctx->nets.count(port.net->name) > 0); } } } - for (auto net_entry : design->nets) { + for (auto net_entry : ctx->nets) { NetInfo *net = net_entry.second; assert(net->name == net_entry.first); @@ -52,7 +52,7 @@ bool check_all_nets_driven(Design *design) if (debug) log_info(" Checking for a driver cell named \'%s\'\n", net->driver.cell->name.c_str()); - assert(design->cells.count(net->driver.cell->name) > 0); + assert(ctx->cells.count(net->driver.cell->name) > 0); } for (auto user : net->users) { @@ -62,7 +62,7 @@ bool check_all_nets_driven(Design *design) if (debug) log_info(" Checking for a user cell named \'%s\'\n", user.cell->name.c_str()); - assert(design->cells.count(user.cell->name) > 0); + assert(ctx->cells.count(user.cell->name) > 0); } } } diff --git a/dummy/arch_place.cc b/dummy/arch_place.cc index 07ff53ae..4f3e2509 100644 --- a/dummy/arch_place.cc +++ b/dummy/arch_place.cc @@ -21,12 +21,12 @@ NEXTPNR_NAMESPACE_BEGIN -bool isValidBelForCell(Design *design, CellInfo *cell, BelId bel) +bool isValidBelForCell(Context *ctx, CellInfo *cell, BelId bel) { return true; } -bool isBelLocationValid(Design *design, BelId bel) +bool isBelLocationValid(Context *ctx, BelId bel) { return true; } diff --git a/dummy/arch_place.h b/dummy/arch_place.h index 1e14ec68..3abd80c5 100644 --- a/dummy/arch_place.h +++ b/dummy/arch_place.h @@ -29,10 +29,10 @@ NEXTPNR_NAMESPACE_BEGIN // Whether or not a given cell can be placed at a given Bel // This is not intended for Bel type checks, but finer-grained constraints // such as conflicting set/reset signals, etc -bool isValidBelForCell(Design *design, CellInfo *cell, BelId bel); +bool isValidBelForCell(Context *ctx, CellInfo *cell, BelId bel); // Return true whether all Bels at a given location are valid -bool isBelLocationValid(Design *design, BelId bel); +bool isBelLocationValid(Context *ctx, BelId bel); NEXTPNR_NAMESPACE_END diff --git a/dummy/main.cc b/dummy/main.cc index 9ac4db26..6375eef9 100644 --- a/dummy/main.cc +++ b/dummy/main.cc @@ -27,10 +27,10 @@ USING_NEXTPNR_NAMESPACE int main(int argc, char *argv[]) { - Design design(ArchArgs{}); + Context ctx(ArchArgs{}); QApplication a(argc, argv); - MainWindow w(&design); + MainWindow w(&ctx); w.show(); return a.exec(); diff --git a/frontend/json/jsonparse.cc b/frontend/json/jsonparse.cc index 3c060fd7..26919d24 100644 --- a/frontend/json/jsonparse.cc +++ b/frontend/json/jsonparse.cc @@ -31,7 +31,7 @@ NEXTPNR_NAMESPACE_BEGIN -extern bool check_all_nets_driven(Design *design); +extern bool check_all_nets_driven(Context *ctx); namespace JsonParser { @@ -313,7 +313,7 @@ bool is_blackbox(JsonNode *node) return true; } -void json_import_cell_params(Design *design, string &modname, CellInfo *cell, +void json_import_cell_params(Context *ctx, string &modname, CellInfo *cell, JsonNode *param_node, std::unordered_map *dest, int param_id) @@ -344,7 +344,7 @@ void json_import_cell_params(Design *design, string &modname, CellInfo *cell, static int const_net_idx = 0; template -void json_import_ports(Design *design, const string &modname, +void json_import_ports(Context *ctx, const string &modname, const std::vector &netnames, const string &obj_name, const string &port_name, JsonNode *dir_node, JsonNode *wire_group_node, F visitor) @@ -437,7 +437,7 @@ void json_import_ports(Design *design, const string &modname, net_id = netnames.at(net_num); else net_id = std::to_string(net_num); - if (design->nets.count(net_id) == 0) { + if (ctx->nets.count(net_id) == 0) { // The net doesn't exist in the design (yet) // Create in now @@ -449,13 +449,13 @@ void json_import_ports(Design *design, const string &modname, this_net->name = net_id; this_net->driver.cell = NULL; this_net->driver.port = ""; - design->nets[net_id] = this_net; + ctx->nets[net_id] = this_net; } else { // // The net already exists within the design. // We'll connect to it // - this_net = design->nets[net_id]; + this_net = ctx->nets[net_id]; if (json_debug) log_info(" Reusing net \'%s\', id \'%s\', " "with driver \'%s\'\n", @@ -510,12 +510,12 @@ void json_import_ports(Design *design, const string &modname, this_port.name.c_str(), obj_name.c_str()); visitor(this_port.type, this_port.name, this_net); - if (design->nets.count(this_net->name) == 0) - design->nets[this_net->name] = this_net; + if (ctx->nets.count(this_net->name) == 0) + ctx->nets[this_net->name] = this_net; } } -void json_import_cell(Design *design, string modname, +void json_import_cell(Context *ctx, string modname, const std::vector &netnames, JsonNode *cell_node, string cell_name) { @@ -547,7 +547,7 @@ void json_import_cell(Design *design, string modname, for (int paramid = 0; paramid < GetSize(param_node->data_dict_keys); paramid++) { - json_import_cell_params(design, modname, cell, param_node, + json_import_cell_params(ctx, modname, cell, param_node, &cell->params, paramid); } @@ -563,7 +563,7 @@ void json_import_cell(Design *design, string modname, for (int attrid = 0; attrid < GetSize(attr_node->data_dict_keys); attrid++) { - json_import_cell_params(design, modname, cell, attr_node, &cell->attrs, + json_import_cell_params(ctx, modname, cell, attr_node, &cell->attrs, attrid); } @@ -621,7 +621,7 @@ void json_import_cell(Design *design, string modname, wire_group_node = connections->data_dict.at(port_name); json_import_ports( - design, modname, netnames, cell->name, port_name, dir_node, + ctx, modname, netnames, cell->name, port_name, dir_node, wire_group_node, [cell](PortType type, const std::string &name, NetInfo *net) { cell->ports[name] = PortInfo{name, net, type}; @@ -639,11 +639,11 @@ void json_import_cell(Design *design, string modname, }); } - design->cells[cell->name] = cell; - // check_all_nets_driven(design); + ctx->cells[cell->name] = cell; + // check_all_nets_driven(ctx); } -static void insert_iobuf(Design *design, NetInfo *net, PortType type, +static void insert_iobuf(Context *ctx, NetInfo *net, PortType type, const string &name) { // Instantiate a architecture-independent IO buffer connected to a given @@ -683,7 +683,7 @@ static void insert_iobuf(Design *design, NetInfo *net, PortType type, net2->driver = net->driver; net2->driver.cell->ports[net2->driver.port].net = net2; net->driver.cell = nullptr; - design->nets[net2->name] = net2; + ctx->nets[net2->name] = net2; iobuf->ports["I"].net = net2; PortRef ref; ref.cell = iobuf; @@ -697,24 +697,24 @@ static void insert_iobuf(Design *design, NetInfo *net, PortType type, } else { assert(false); } - design->cells[iobuf->name] = iobuf; + ctx->cells[iobuf->name] = iobuf; } -void json_import_toplevel_port(Design *design, const string &modname, +void json_import_toplevel_port(Context *ctx, const string &modname, const std::vector &netnames, const string &portname, JsonNode *node) { JsonNode *dir_node = node->data_dict.at("direction"); JsonNode *nets_node = node->data_dict.at("bits"); json_import_ports( - design, modname, netnames, "Top Level IO", portname, dir_node, + ctx, modname, netnames, "Top Level IO", portname, dir_node, nets_node, - [design](PortType type, const std::string &name, NetInfo *net) { - insert_iobuf(design, net, type, name); + [ctx](PortType type, const std::string &name, NetInfo *net) { + insert_iobuf(ctx, net, type, name); }); } -void json_import(Design *design, string modname, JsonNode *node) +void json_import(Context *ctx, string modname, JsonNode *node) { if (is_blackbox(node)) return; @@ -763,7 +763,7 @@ void json_import(Design *design, string modname, JsonNode *node) here = cell_parent->data_dict.at( cell_parent->data_dict_keys[cellid]); - json_import_cell(design, modname, netnames, here, + json_import_cell(ctx, modname, netnames, here, cell_parent->data_dict_keys[cellid]); } } @@ -780,12 +780,12 @@ void json_import(Design *design, string modname, JsonNode *node) here = ports_parent->data_dict.at( ports_parent->data_dict_keys[portid]); - json_import_toplevel_port(design, modname, netnames, + json_import_toplevel_port(ctx, modname, netnames, ports_parent->data_dict_keys[portid], here); } } - check_all_nets_driven(design); + check_all_nets_driven(ctx); } struct JsonFrontend @@ -794,9 +794,9 @@ struct JsonFrontend JsonFrontend(void) {} virtual void help() {} virtual void execute(std::istream *&f, std::string &filename, - Design *design) + Context *ctx) { - // log_header(design, "Executing JSON frontend.\n"); + // log_header(ctx, "Executing JSON frontend.\n"); JsonNode root(*f); @@ -810,17 +810,17 @@ struct JsonFrontend log_error("JSON modules node is not a dictionary.\n"); for (auto &it : modules->data_dict) - json_import(design, it.first, it.second); + json_import(ctx, it.first, it.second); } } }; // JsonFrontend; }; // End Namespace JsonParser -void parse_json_file(std::istream *&f, std::string &filename, Design *design) +void parse_json_file(std::istream *&f, std::string &filename, Context *ctx) { auto *parser = new JsonParser::JsonFrontend(); - parser->execute(f, filename, design); + parser->execute(f, filename, ctx); } NEXTPNR_NAMESPACE_END diff --git a/frontend/json/jsonparse.h b/frontend/json/jsonparse.h index ca0844e7..ee3d19ca 100644 --- a/frontend/json/jsonparse.h +++ b/frontend/json/jsonparse.h @@ -26,7 +26,7 @@ NEXTPNR_NAMESPACE_BEGIN -extern void parse_json_file(std::istream *&, std::string &, Design *); +extern void parse_json_file(std::istream *&, std::string &, Context *); NEXTPNR_NAMESPACE_END diff --git a/gui/designwidget.cc b/gui/designwidget.cc index ac367e4e..9bb25992 100644 --- a/gui/designwidget.cc +++ b/gui/designwidget.cc @@ -77,8 +77,8 @@ class PipTreeItem : public ElementTreeItem IdString data; }; -DesignWidget::DesignWidget(Design *_design, QWidget *parent) - : QWidget(parent), design(_design) +DesignWidget::DesignWidget(Context *_ctx, QWidget *parent) + : QWidget(parent), ctx(_ctx) { treeWidget = new QTreeWidget(); @@ -93,8 +93,8 @@ DesignWidget::DesignWidget(Design *_design, QWidget *parent) bel_root->setText(0, QString("Bels")); treeWidget->insertTopLevelItem(0, bel_root); QList bel_items; - for (auto bel : design->chip.getBels()) { - auto name = design->chip.getBelName(bel); + for (auto bel : ctx->getBels()) { + auto name = ctx->getBelName(bel); bel_items.append( new BelTreeItem(name, ElementType::BEL, QString(name.c_str()))); } @@ -105,8 +105,8 @@ DesignWidget::DesignWidget(Design *_design, QWidget *parent) QList wire_items; wire_root->setText(0, QString("Wires")); treeWidget->insertTopLevelItem(0, wire_root); - for (auto wire : design->chip.getWires()) { - auto name = design->chip.getWireName(wire); + for (auto wire : ctx->getWires()) { + auto name = ctx->getWireName(wire); wire_items.append(new WireTreeItem(name, ElementType::WIRE, QString(name.c_str()))); } @@ -117,8 +117,8 @@ DesignWidget::DesignWidget(Design *_design, QWidget *parent) QList pip_items; pip_root->setText(0, QString("Pips")); treeWidget->insertTopLevelItem(0, pip_root); - for (auto pip : design->chip.getPips()) { - auto name = design->chip.getPipName(pip); + for (auto pip : ctx->getPips()) { + auto name = ctx->getPipName(pip); pip_items.append( new PipTreeItem(name, ElementType::PIP, QString(name.c_str()))); } diff --git a/gui/designwidget.h b/gui/designwidget.h index e3f7e622..9682726c 100644 --- a/gui/designwidget.h +++ b/gui/designwidget.h @@ -15,9 +15,9 @@ class DesignWidget : public QWidget Q_OBJECT public: - explicit DesignWidget(Design *design, QWidget *parent = 0); + explicit DesignWidget(Context *ctx, QWidget *parent = 0); ~DesignWidget(); - Design *getDesign() { return design; } + Context *getContext() { return ctx; } private: void addProperty(QtVariantProperty *property, const QString &id); @@ -32,7 +32,7 @@ class DesignWidget : public QWidget void selectObject(); private: - Design *design; + Context *ctx; QTreeWidget *treeWidget; diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc index 58df0586..000b4cf0 100644 --- a/gui/fpgaviewwidget.cc +++ b/gui/fpgaviewwidget.cc @@ -9,7 +9,7 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent) : QOpenGLWidget(parent), m_xMove(0), m_yMove(0), m_zDistance(1.0) { - design = qobject_cast(getMainWindow())->getDesign(); + ctx = qobject_cast(getMainWindow())->getContext(); } QMainWindow *FPGAViewWidget::getMainWindow() @@ -118,12 +118,12 @@ void FPGAViewWidget::paintGL() glColor3f(0.1, 0.1, 0.1); glLineWidth(0.1); // Draw Bels - for (auto bel : design->chip.getBels()) { - for (auto &el : design->chip.getBelGraphics(bel)) + for (auto bel : ctx->getBels()) { + for (auto &el : ctx->getBelGraphics(bel)) drawElement(el); } // Draw Frame Graphics - for (auto &el : design->chip.getFrameGraphics()) + for (auto &el : ctx->getFrameGraphics()) drawElement(el); } diff --git a/gui/fpgaviewwidget.h b/gui/fpgaviewwidget.h index 1d05afb7..2407f757 100644 --- a/gui/fpgaviewwidget.h +++ b/gui/fpgaviewwidget.h @@ -46,7 +46,7 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions float m_yMove; float m_zDistance; QPoint m_lastPos; - Design *design; + Context *ctx; }; #endif diff --git a/gui/mainwindow.cc b/gui/mainwindow.cc index 76addbba..b9b86663 100644 --- a/gui/mainwindow.cc +++ b/gui/mainwindow.cc @@ -11,10 +11,10 @@ #include "fpgaviewwidget.h" #include "pythontab.h" -MainWindow::MainWindow(Design *_design, QWidget *parent) - : QMainWindow(parent), design(_design) +MainWindow::MainWindow(Context *_ctx, QWidget *parent) + : QMainWindow(parent), ctx(_ctx) { - std::string title = "nextpnr-ice40 - " + design->chip.getChipName(); + std::string title = "nextpnr-ice40 - " + ctx->getChipName(); setWindowTitle(title.c_str()); setObjectName(QStringLiteral("MainWindow")); resize(1024, 768); @@ -35,7 +35,7 @@ MainWindow::MainWindow(Design *_design, QWidget *parent) setCentralWidget(centralWidget); - DesignWidget *designview = new DesignWidget(design); + DesignWidget *designview = new DesignWidget(ctx); designview->setMinimumWidth(300); designview->setMaximumWidth(300); splitter_h->addWidget(designview); diff --git a/gui/mainwindow.h b/gui/mainwindow.h index 6516a986..149c4aa5 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -15,9 +15,9 @@ class MainWindow : public QMainWindow Q_OBJECT public: - explicit MainWindow(Design *design, QWidget *parent = 0); + explicit MainWindow(Context *ctx, QWidget *parent = 0); ~MainWindow(); - Design *getDesign() { return design; } + Context *getContext() { return ctx; } private: void createMenusAndBars(); @@ -26,7 +26,7 @@ class MainWindow : public QMainWindow void writeInfo(std::string text); private: - Design *design; + Context *ctx; InfoTab *info; }; diff --git a/ice40/arch_place.cc b/ice40/arch_place.cc index d9210378..faa6b187 100644 --- a/ice40/arch_place.cc +++ b/ice40/arch_place.cc @@ -88,40 +88,38 @@ static bool logicCellsCompatible(const std::vector &cells) return locals.size() <= 32; } -bool isBelLocationValid(Design *design, BelId bel) +bool isBelLocationValid(Context *ctx, BelId bel) { - const Arch &chip = design->chip; - if (chip.getBelType(bel) == TYPE_ICESTORM_LC) { + if (ctx->getBelType(bel) == TYPE_ICESTORM_LC) { std::vector cells; - for (auto bel_other : chip.getBelsAtSameTile(bel)) { - IdString cell_other = chip.getBelCell(bel_other, false); + for (auto bel_other : ctx->getBelsAtSameTile(bel)) { + IdString cell_other = ctx->getBelCell(bel_other, false); if (cell_other != IdString()) { - const CellInfo *ci_other = design->cells[cell_other]; + const CellInfo *ci_other = ctx->cells[cell_other]; cells.push_back(ci_other); } } return logicCellsCompatible(cells); } else { - IdString cellId = chip.getBelCell(bel, false); + IdString cellId = ctx->getBelCell(bel, false); if (cellId == IdString()) return true; else - return isValidBelForCell(design, design->cells.at(cellId), bel); + return isValidBelForCell(ctx, ctx->cells.at(cellId), bel); } } -bool isValidBelForCell(Design *design, CellInfo *cell, BelId bel) +bool isValidBelForCell(Context *ctx, CellInfo *cell, BelId bel) { - const Arch &chip = design->chip; if (cell->type == "ICESTORM_LC") { - assert(chip.getBelType(bel) == TYPE_ICESTORM_LC); + assert(ctx->getBelType(bel) == TYPE_ICESTORM_LC); std::vector cells; - for (auto bel_other : chip.getBelsAtSameTile(bel)) { - IdString cell_other = chip.getBelCell(bel_other, false); + for (auto bel_other : ctx->getBelsAtSameTile(bel)) { + IdString cell_other = ctx->getBelCell(bel_other, false); if (cell_other != IdString()) { - const CellInfo *ci_other = design->cells[cell_other]; + const CellInfo *ci_other = ctx->cells[cell_other]; cells.push_back(ci_other); } } @@ -129,7 +127,7 @@ bool isValidBelForCell(Design *design, CellInfo *cell, BelId bel) cells.push_back(cell); return logicCellsCompatible(cells); } else if (cell->type == "SB_IO") { - return design->chip.getBelPackagePin(bel) != ""; + return ctx->getBelPackagePin(bel) != ""; } else if (cell->type == "SB_GB") { bool is_reset = false, is_cen = false; assert(cell->ports.at("GLOBAL_BUFFER_OUTPUT").net != nullptr); @@ -139,8 +137,8 @@ bool isValidBelForCell(Design *design, CellInfo *cell, BelId bel) if (is_enable_port(user)) is_cen = true; } - IdString glb_net = chip.getWireName( - chip.getWireBelPin(bel, PIN_GLOBAL_BUFFER_OUTPUT)); + IdString glb_net = ctx->getWireName( + ctx->getWireBelPin(bel, PIN_GLOBAL_BUFFER_OUTPUT)); int glb_id = std::stoi(std::string("") + glb_net.str().back()); if (is_reset && is_cen) return false; diff --git a/ice40/arch_place.h b/ice40/arch_place.h index 5cd14809..3d05ed7a 100644 --- a/ice40/arch_place.h +++ b/ice40/arch_place.h @@ -29,10 +29,10 @@ NEXTPNR_NAMESPACE_BEGIN // Whether or not a given cell can be placed at a given Bel // This is not intended for Bel type checks, but finer-grained constraints // such as conflicting set/reset signals, etc -bool isValidBelForCell(Design *design, CellInfo *cell, BelId bel); +bool isValidBelForCell(Context *ctx, CellInfo *cell, BelId bel); // Return true whether all Bels at a given location are valid -bool isBelLocationValid(Design *design, BelId bel); +bool isBelLocationValid(Context *ctx, BelId bel); NEXTPNR_NAMESPACE_END diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index ff839ba1..8b28842c 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -23,9 +23,9 @@ NEXTPNR_NAMESPACE_BEGIN -inline TileType tile_at(const Arch &chip, int x, int y) +inline TileType tile_at(const Context *ctx, int x, int y) { - return chip.chip_info->tile_grid[y * chip.chip_info->width + x]; + return ctx->chip_info->tile_grid[y * ctx->chip_info->width + x]; } const ConfigEntryPOD &find_config(const TileInfoPOD &tile, @@ -95,18 +95,17 @@ std::string get_param_str_or_def(const CellInfo *cell, const std::string ¶m, char get_hexdigit(int i) { return std::string("0123456789ABCDEF").at(i); } -void write_asc(const Design &design, std::ostream &out) +void write_asc(const Context *ctx, std::ostream &out) { - const Arch &chip = design.chip; // [y][x][row][col] - const ChipInfoPOD &ci = *chip.chip_info; + const ChipInfoPOD &ci = *ctx->chip_info; const BitstreamInfoPOD &bi = *ci.bits_info; std::vector>>> config; config.resize(ci.height); for (int y = 0; y < ci.height; y++) { config.at(y).resize(ci.width); for (int x = 0; x < ci.width; x++) { - TileType tile = tile_at(chip, x, y); + TileType tile = tile_at(ctx, x, y); int rows = bi.tiles_nonrouting[tile].rows; int cols = bi.tiles_nonrouting[tile].cols; config.at(y).at(x).resize(rows, std::vector(cols)); @@ -114,7 +113,7 @@ void write_asc(const Design &design, std::ostream &out) } out << ".comment from next-pnr" << std::endl; - switch (chip.args.type) { + switch (ctx->args.type) { case ArchArgs::LP384: out << ".device 384" << std::endl; break; @@ -133,8 +132,8 @@ void write_asc(const Design &design, std::ostream &out) assert(false); } // Set pips - for (auto pip : chip.getPips()) { - if (chip.pip_to_net[pip.index] != IdString()) { + for (auto pip : ctx->getPips()) { + if (ctx->pip_to_net[pip.index] != IdString()) { const PipInfoPOD &pi = ci.pip_data[pip.index]; const SwitchInfoPOD &swi = bi.switches[pi.switch_index]; for (int i = 0; i < swi.num_bits; i++) { @@ -151,7 +150,7 @@ void write_asc(const Design &design, std::ostream &out) } } // Set logic cell config - for (auto cell : design.cells) { + for (auto cell : ctx->cells) { BelId bel = cell.second->bel; if (bel == BelId()) { std::cout << "Found unplaced cell " << cell.first @@ -206,15 +205,15 @@ void write_asc(const Design &design, std::ostream &out) assert(iez != -1); bool input_en = false; - if ((chip.wire_to_net[chip.getWireBelPin(bel, PIN_D_IN_0).index] != + if ((ctx->wire_to_net[ctx->getWireBelPin(bel, PIN_D_IN_0).index] != IdString()) || - (chip.wire_to_net[chip.getWireBelPin(bel, PIN_D_IN_1).index] != + (ctx->wire_to_net[ctx->getWireBelPin(bel, PIN_D_IN_1).index] != IdString())) { input_en = true; } - if (chip.args.type == ArchArgs::LP1K || - chip.args.type == ArchArgs::HX1K) { + if (ctx->args.type == ArchArgs::LP1K || + ctx->args.type == ArchArgs::HX1K) { set_config(ti, config.at(iey).at(iex), "IoCtrl.IE_" + std::to_string(iez), !input_en); set_config(ti, config.at(iey).at(iex), @@ -232,8 +231,8 @@ void write_asc(const Design &design, std::ostream &out) int x = beli.x, y = beli.y; const TileInfoPOD &ti_ramt = bi.tiles_nonrouting[TILE_RAMT]; const TileInfoPOD &ti_ramb = bi.tiles_nonrouting[TILE_RAMB]; - if (!(chip.args.type == ArchArgs::LP1K || - chip.args.type == ArchArgs::HX1K)) { + if (!(ctx->args.type == ArchArgs::LP1K || + ctx->args.type == ArchArgs::HX1K)) { set_config(ti_ramb, config.at(y).at(x), "RamConfig.PowerUp", true); } @@ -258,9 +257,9 @@ void write_asc(const Design &design, std::ostream &out) } } // Set config bits in unused IO and RAM - for (auto bel : chip.getBels()) { - if (chip.bel_to_cell[bel.index] == IdString() && - chip.getBelType(bel) == TYPE_SB_IO) { + for (auto bel : ctx->getBels()) { + if (ctx->bel_to_cell[bel.index] == IdString() && + ctx->getBelType(bel) == TYPE_SB_IO) { const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO]; const BelInfoPOD &beli = ci.bel_data[bel.index]; int x = beli.x, y = beli.y, z = beli.z; @@ -268,21 +267,21 @@ void write_asc(const Design &design, std::ostream &out) int iex, iey, iez; std::tie(iex, iey, iez) = ieren; if (iez != -1) { - if (chip.args.type == ArchArgs::LP1K || - chip.args.type == ArchArgs::HX1K) { + if (ctx->args.type == ArchArgs::LP1K || + ctx->args.type == ArchArgs::HX1K) { set_config(ti, config.at(iey).at(iex), "IoCtrl.IE_" + std::to_string(iez), true); set_config(ti, config.at(iey).at(iex), "IoCtrl.REN_" + std::to_string(iez), false); } } - } else if (chip.bel_to_cell[bel.index] == IdString() && - chip.getBelType(bel) == TYPE_ICESTORM_RAM) { + } else if (ctx->bel_to_cell[bel.index] == IdString() && + ctx->getBelType(bel) == TYPE_ICESTORM_RAM) { const BelInfoPOD &beli = ci.bel_data[bel.index]; int x = beli.x, y = beli.y; const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_RAMB]; - if ((chip.args.type == ArchArgs::LP1K || - chip.args.type == ArchArgs::HX1K)) { + if ((ctx->args.type == ArchArgs::LP1K || + ctx->args.type == ArchArgs::HX1K)) { set_config(ti, config.at(y).at(x), "RamConfig.PowerUp", true); } } @@ -291,22 +290,22 @@ void write_asc(const Design &design, std::ostream &out) // Set other config bits for (int y = 0; y < ci.height; y++) { for (int x = 0; x < ci.width; x++) { - TileType tile = tile_at(chip, x, y); + TileType tile = tile_at(ctx, x, y); const TileInfoPOD &ti = bi.tiles_nonrouting[tile]; // set all ColBufCtrl bits (FIXME) bool setColBufCtrl = true; - if (chip.args.type == ArchArgs::LP1K || - chip.args.type == ArchArgs::HX1K) { + if (ctx->args.type == ArchArgs::LP1K || + ctx->args.type == ArchArgs::HX1K) { if (tile == TILE_RAMB || tile == TILE_RAMT) { setColBufCtrl = (y == 3 || y == 5 || y == 11 || y == 13); } else { setColBufCtrl = (y == 4 || y == 5 || y == 12 || y == 13); } - } else if (chip.args.type == ArchArgs::LP8K || - chip.args.type == ArchArgs::HX8K) { + } else if (ctx->args.type == ArchArgs::LP8K || + ctx->args.type == ArchArgs::HX8K) { setColBufCtrl = (y == 8 || y == 9 || y == 24 || y == 25); - } else if (chip.args.type == ArchArgs::UP5K) { + } else if (ctx->args.type == ArchArgs::UP5K) { if (tile == TILE_LOGIC) { setColBufCtrl = (y == 4 || y == 5 || y == 14 || y == 15 || y == 26 || y == 27); @@ -338,7 +337,7 @@ void write_asc(const Design &design, std::ostream &out) // Write config out for (int y = 0; y < ci.height; y++) { for (int x = 0; x < ci.width; x++) { - TileType tile = tile_at(chip, x, y); + TileType tile = tile_at(ctx, x, y); if (tile == TILE_NONE) continue; switch (tile) { @@ -372,7 +371,7 @@ void write_asc(const Design &design, std::ostream &out) } // Write RAM init data - for (auto cell : design.cells) { + for (auto cell : ctx->cells) { if (cell.second->bel != BelId()) { if (cell.second->type == "ICESTORM_RAM") { const BelInfoPOD &beli = ci.bel_data[cell.second->bel.index]; @@ -402,8 +401,8 @@ void write_asc(const Design &design, std::ostream &out) // Write symbols const bool write_symbols = 1; - for (auto wire : chip.getWires()) { - IdString net = chip.getWireNet(wire, false); + for (auto wire : ctx->getWires()) { + IdString net = ctx->getWireNet(wire, false); if (net != IdString()) out << ".sym " << wire.index << " " << net << std::endl; } diff --git a/ice40/bitstream.h b/ice40/bitstream.h index 0e2a4aa9..4dcb79bc 100644 --- a/ice40/bitstream.h +++ b/ice40/bitstream.h @@ -26,7 +26,7 @@ NEXTPNR_NAMESPACE_BEGIN -void write_asc(const Design &design, std::ostream &out); +void write_asc(const Context *ctx, std::ostream &out); NEXTPNR_NAMESPACE_END diff --git a/ice40/cells.cc b/ice40/cells.cc index fb264051..16cbd68d 100644 --- a/ice40/cells.cc +++ b/ice40/cells.cc @@ -29,7 +29,7 @@ static void add_port(CellInfo *cell, IdString name, PortType dir) cell->ports[name] = PortInfo{name, nullptr, dir}; } -CellInfo *create_ice_cell(Design *design, IdString type, IdString name) +CellInfo *create_ice_cell(Context *ctx, IdString type, IdString name) { static int auto_idx = 0; CellInfo *new_cell = new CellInfo(); diff --git a/ice40/cells.h b/ice40/cells.h index 45e81fd1..5bea420d 100644 --- a/ice40/cells.h +++ b/ice40/cells.h @@ -27,7 +27,7 @@ NEXTPNR_NAMESPACE_BEGIN // Create a standard iCE40 cell and return it // Name will be automatically assigned if not specified -CellInfo *create_ice_cell(Design *design, IdString type, +CellInfo *create_ice_cell(Context *ctx, IdString type, IdString name = IdString()); // Return true if a cell is a LUT diff --git a/ice40/main.cc b/ice40/main.cc index ed660069..02dfe038 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -193,21 +193,20 @@ int main(int argc, char *argv[]) if (vm.count("package")) chipArgs.package = vm["package"].as(); - Design design(chipArgs); + Context ctx(chipArgs); init_python(argv[0]); - python_export_global("design", design); - python_export_global("chip", design.chip); + python_export_global("ctx", ctx); if (vm.count("svg")) { std::cout << "\n"; - for (auto bel : design.chip.getBels()) { - std::cout << "\n"; - for (auto &el : design.chip.getBelGraphics(bel)) + for (auto bel : ctx.getBels()) { + std::cout << "\n"; + for (auto &el : ctx.getBelGraphics(bel)) svg_dump_el(el); } std::cout << "\n"; - for (auto &el : design.chip.getFrameGraphics()) + for (auto &el : ctx.getFrameGraphics()) svg_dump_el(el); std::cout << "\n"; } @@ -216,15 +215,15 @@ int main(int argc, char *argv[]) std::string filename = vm["json"].as(); std::istream *f = new std::ifstream(filename); - parse_json_file(f, filename, &design); + parse_json_file(f, filename, &ctx); if (vm.count("pcf")) { std::ifstream pcf(vm["pcf"].as()); - apply_pcf(&design, pcf); + apply_pcf(&ctx, pcf); } - pack_design(&design); - print_utilisation(&design); + pack_design(&ctx); + print_utilisation(&ctx); int seed = 1; if (vm.count("seed")) { @@ -234,15 +233,15 @@ int main(int argc, char *argv[]) } if (!vm.count("pack-only")) { - place_design_sa(&design, seed); - route_design(&design, verbose); + place_design_sa(&ctx, seed); + route_design(&ctx, verbose); } } if (vm.count("asc")) { std::string filename = vm["asc"].as(); std::ofstream f(filename); - write_asc(design, f); + write_asc(&ctx, f); } if (vm.count("run")) { @@ -254,7 +253,7 @@ int main(int argc, char *argv[]) if (vm.count("gui")) { QApplication a(argc, argv); - MainWindow w(&design); + MainWindow w(&ctx); w.show(); rc = a.exec(); diff --git a/ice40/pack.cc b/ice40/pack.cc index 3e852a91..b8e2cb8f 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -28,18 +28,18 @@ NEXTPNR_NAMESPACE_BEGIN // Pack LUTs and LUT-FF pairs -static void pack_lut_lutffs(Design *design) +static void pack_lut_lutffs(Context *ctx) { log_info("Packing LUT-FFs..\n"); std::unordered_set packed_cells; std::vector new_cells; - for (auto cell : design->cells) { + for (auto cell : ctx->cells) { CellInfo *ci = cell.second; log_info("cell '%s' is of type '%s'\n", ci->name.c_str(), ci->type.c_str()); if (is_lut(ci)) { - CellInfo *packed = create_ice_cell(design, "ICESTORM_LC", + CellInfo *packed = create_ice_cell(ctx, "ICESTORM_LC", ci->name.str() + "_LC"); std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin())); @@ -62,7 +62,7 @@ static void pack_lut_lutffs(Design *design) } else { lut_to_lc(ci, packed, false); dff_to_lc(dff, packed, false); - design->nets.erase(o->name); + ctx->nets.erase(o->name); if (dff_bel != dff->attrs.end()) packed->attrs["BEL"] = dff_bel->second; packed_cells.insert(dff->name); @@ -77,25 +77,25 @@ static void pack_lut_lutffs(Design *design) } } for (auto pcell : packed_cells) { - design->cells.erase(pcell); + ctx->cells.erase(pcell); } for (auto ncell : new_cells) { - design->cells[ncell->name] = ncell; + ctx->cells[ncell->name] = ncell; } } // Pack FFs not packed as LUTFFs -static void pack_nonlut_ffs(Design *design) +static void pack_nonlut_ffs(Context *ctx) { log_info("Packing non-LUT FFs..\n"); std::unordered_set packed_cells; std::vector new_cells; - for (auto cell : design->cells) { + for (auto cell : ctx->cells) { CellInfo *ci = cell.second; if (is_ff(ci)) { - CellInfo *packed = create_ice_cell(design, "ICESTORM_LC", + CellInfo *packed = create_ice_cell(ctx, "ICESTORM_LC", ci->name.str() + "_DFFLC"); std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin())); @@ -107,25 +107,25 @@ static void pack_nonlut_ffs(Design *design) } } for (auto pcell : packed_cells) { - design->cells.erase(pcell); + ctx->cells.erase(pcell); } for (auto ncell : new_cells) { - design->cells[ncell->name] = ncell; + ctx->cells[ncell->name] = ncell; } } // "Pack" RAMs -static void pack_ram(Design *design) +static void pack_ram(Context *ctx) { log_info("Packing RAMs..\n"); std::unordered_set packed_cells; std::vector new_cells; - for (auto cell : design->cells) { + for (auto cell : ctx->cells) { CellInfo *ci = cell.second; if (is_ram(ci)) { - CellInfo *packed = create_ice_cell(design, "ICESTORM_RAM", + CellInfo *packed = create_ice_cell(ctx, "ICESTORM_RAM", ci->name.str() + "_RAM"); packed_cells.insert(ci->name); new_cells.push_back(packed); @@ -153,10 +153,10 @@ static void pack_ram(Design *design) } for (auto pcell : packed_cells) { - design->cells.erase(pcell); + ctx->cells.erase(pcell); } for (auto ncell : new_cells) { - design->cells[ncell->name] = ncell; + ctx->cells[ncell->name] = ncell; } } @@ -180,18 +180,18 @@ static void set_net_constant(NetInfo *orig, NetInfo *constnet, bool constval) } // Pack constants (simple implementation) -static void pack_constants(Design *design) +static void pack_constants(Context *ctx) { log_info("Packing constants..\n"); - CellInfo *gnd_cell = create_ice_cell(design, "ICESTORM_LC", "$PACKER_GND"); + CellInfo *gnd_cell = create_ice_cell(ctx, "ICESTORM_LC", "$PACKER_GND"); gnd_cell->params["LUT_INIT"] = "0"; NetInfo *gnd_net = new NetInfo; gnd_net->name = "$PACKER_GND_NET"; gnd_net->driver.cell = gnd_cell; gnd_net->driver.port = "O"; - CellInfo *vcc_cell = create_ice_cell(design, "ICESTORM_LC", "$PACKER_VCC"); + CellInfo *vcc_cell = create_ice_cell(ctx, "ICESTORM_LC", "$PACKER_VCC"); vcc_cell->params["LUT_INIT"] = "1"; NetInfo *vcc_net = new NetInfo; vcc_net->name = "$PACKER_VCC_NET"; @@ -200,24 +200,24 @@ static void pack_constants(Design *design) std::vector dead_nets; - for (auto net : design->nets) { + for (auto net : ctx->nets) { NetInfo *ni = net.second; if (ni->driver.cell != nullptr && ni->driver.cell->type == "GND") { set_net_constant(ni, gnd_net, false); - design->cells[gnd_cell->name] = gnd_cell; - design->nets[gnd_net->name] = gnd_net; + ctx->cells[gnd_cell->name] = gnd_cell; + ctx->nets[gnd_net->name] = gnd_net; dead_nets.push_back(net.first); } else if (ni->driver.cell != nullptr && ni->driver.cell->type == "VCC") { set_net_constant(ni, vcc_net, true); - design->cells[vcc_cell->name] = vcc_cell; - design->nets[vcc_net->name] = vcc_net; + ctx->cells[vcc_cell->name] = vcc_cell; + ctx->nets[vcc_net->name] = vcc_net; dead_nets.push_back(net.first); } } for (auto dn : dead_nets) - design->nets.erase(dn); + ctx->nets.erase(dn); } static bool is_nextpnr_iob(CellInfo *cell) @@ -227,14 +227,14 @@ static bool is_nextpnr_iob(CellInfo *cell) } // Pack IO buffers -static void pack_io(Design *design) +static void pack_io(Context *ctx) { std::unordered_set packed_cells; std::vector new_cells; log_info("Packing IOs..\n"); - for (auto cell : design->cells) { + for (auto cell : ctx->cells) { CellInfo *ci = cell.second; if (is_nextpnr_iob(ci)) { CellInfo *sb = nullptr; @@ -254,12 +254,12 @@ static void pack_io(Design *design) ci->name.c_str()); NetInfo *net = sb->ports.at("PACKAGE_PIN").net; if (net != nullptr) { - design->nets.erase(net->name); + ctx->nets.erase(net->name); sb->ports.at("PACKAGE_PIN").net = nullptr; } } else { // Create a SB_IO buffer - sb = create_ice_cell(design, "SB_IO"); + sb = create_ice_cell(ctx, "SB_IO"); nxio_to_sb(ci, sb); new_cells.push_back(sb); } @@ -269,19 +269,19 @@ static void pack_io(Design *design) } } for (auto pcell : packed_cells) { - design->cells.erase(pcell); + ctx->cells.erase(pcell); } for (auto ncell : new_cells) { - design->cells[ncell->name] = ncell; + ctx->cells[ncell->name] = ncell; } } -static void insert_global(Design *design, NetInfo *net, bool is_reset, +static void insert_global(Context *ctx, NetInfo *net, bool is_reset, bool is_cen) { std::string glb_name = net->name.str() + std::string("_$glb_") + (is_reset ? "sr" : (is_cen ? "ce" : "clk")); - CellInfo *gb = create_ice_cell(design, "SB_GB", "$gbuf_" + glb_name); + CellInfo *gb = create_ice_cell(ctx, "SB_GB", "$gbuf_" + glb_name); gb->ports["USER_SIGNAL_TO_GLOBAL_BUFFER"].net = net; PortRef pr; pr.cell = gb; @@ -293,7 +293,7 @@ static void insert_global(Design *design, NetInfo *net, bool is_reset, NetInfo *glbnet = new NetInfo(); glbnet->name = glb_name; glbnet->driver = pr; - design->nets[glbnet->name] = glbnet; + ctx->nets[glbnet->name] = glbnet; gb->ports["GLOBAL_BUFFER_OUTPUT"].net = glbnet; std::vector keep_users; for (auto user : net->users) { @@ -306,16 +306,16 @@ static void insert_global(Design *design, NetInfo *net, bool is_reset, } } net->users = keep_users; - design->cells[gb->name] = gb; + ctx->cells[gb->name] = gb; } // Simple global promoter (clock only) -static void promote_globals(Design *design) +static void promote_globals(Context *ctx) { log_info("Promoting globals..\n"); std::unordered_map clock_count, reset_count, cen_count; - for (auto net : design->nets) { + for (auto net : ctx->nets) { NetInfo *ni = net.second; if (ni->driver.cell != nullptr && !is_global_net(ni)) { clock_count[net.first] = 0; @@ -334,7 +334,7 @@ static void promote_globals(Design *design) } int prom_globals = 0, prom_resets = 0, prom_cens = 0; int gbs_available = 8; - for (auto cell : design->cells) + for (auto cell : ctx->cells) if (is_gbuf(cell.second)) --gbs_available; while (prom_globals < gbs_available) { @@ -358,24 +358,24 @@ static void promote_globals(Design *design) return a.second < b.second; }); if (global_reset->second > global_clock->second && prom_resets < 4) { - NetInfo *rstnet = design->nets[global_reset->first]; - insert_global(design, rstnet, true, false); + NetInfo *rstnet = ctx->nets[global_reset->first]; + insert_global(ctx, rstnet, true, false); ++prom_globals; ++prom_resets; clock_count.erase(rstnet->name); reset_count.erase(rstnet->name); cen_count.erase(rstnet->name); } else if (global_cen->second > global_clock->second && prom_cens < 4) { - NetInfo *cennet = design->nets[global_cen->first]; - insert_global(design, cennet, false, true); + NetInfo *cennet = ctx->nets[global_cen->first]; + insert_global(ctx, cennet, false, true); ++prom_globals; ++prom_cens; clock_count.erase(cennet->name); reset_count.erase(cennet->name); cen_count.erase(cennet->name); } else if (global_clock->second != 0) { - NetInfo *clknet = design->nets[global_clock->first]; - insert_global(design, clknet, false, false); + NetInfo *clknet = ctx->nets[global_clock->first]; + insert_global(ctx, clknet, false, false); ++prom_globals; clock_count.erase(clknet->name); reset_count.erase(clknet->name); @@ -387,14 +387,14 @@ static void promote_globals(Design *design) } // Main pack function -void pack_design(Design *design) +void pack_design(Context *ctx) { - pack_constants(design); - promote_globals(design); - pack_io(design); - pack_lut_lutffs(design); - pack_nonlut_ffs(design); - pack_ram(design); + pack_constants(ctx); + promote_globals(ctx); + pack_io(ctx); + pack_lut_lutffs(ctx); + pack_nonlut_ffs(ctx); + pack_ram(ctx); } NEXTPNR_NAMESPACE_END diff --git a/ice40/pack.h b/ice40/pack.h index 60f22ef3..5495c986 100644 --- a/ice40/pack.h +++ b/ice40/pack.h @@ -25,7 +25,7 @@ NEXTPNR_NAMESPACE_BEGIN -void pack_design(Design *design); +void pack_design(Context *ctx); NEXTPNR_NAMESPACE_END diff --git a/ice40/pcf.cc b/ice40/pcf.cc index 3bef962f..6fc90118 100644 --- a/ice40/pcf.cc +++ b/ice40/pcf.cc @@ -27,7 +27,7 @@ NEXTPNR_NAMESPACE_BEGIN // Read a w // Apply PCF constraints to a pre-packing design -void apply_pcf(Design *design, std::istream &in) +void apply_pcf(Context *ctx, std::istream &in) { if (!in) log_error("failed to open PCF file"); @@ -50,16 +50,16 @@ void apply_pcf(Design *design, std::istream &in) args_end++; std::string cell = words.at(args_end); std::string pin = words.at(args_end + 1); - auto fnd_cell = design->cells.find(cell); - if (fnd_cell == design->cells.end()) { + auto fnd_cell = ctx->cells.find(cell); + if (fnd_cell == ctx->cells.end()) { log_warning("unmatched pcf constraint %s\n", cell.c_str()); } else { - BelId pin_bel = design->chip.getPackagePinBel(pin); + BelId pin_bel = ctx->getPackagePinBel(pin); if (pin_bel == BelId()) log_error("package does not have a pin named %s\n", pin.c_str()); fnd_cell->second->attrs["BEL"] = - design->chip.getBelName(pin_bel).str(); + ctx->getBelName(pin_bel).str(); log_info("constrained '%s' to bel '%s'\n", cell.c_str(), fnd_cell->second->attrs["BEL"].c_str()); } diff --git a/ice40/pcf.h b/ice40/pcf.h index ec2f4923..e0816075 100644 --- a/ice40/pcf.h +++ b/ice40/pcf.h @@ -27,7 +27,7 @@ NEXTPNR_NAMESPACE_BEGIN // Apply PCF constraints to a pre-packing design -void apply_pcf(Design *design, std::istream &in); +void apply_pcf(Context *ctx, std::istream &in); NEXTPNR_NAMESPACE_END