Rename Design to Context, derive from Arch instead of instantiating

Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
Clifford Wolf 2018-06-18 14:06:37 +02:00
parent ad18cdb087
commit 8ee149f4fc
31 changed files with 309 additions and 322 deletions

View File

@ -70,17 +70,15 @@ struct CellInfo
std::unordered_map<IdString, IdString> pins; std::unordered_map<IdString, IdString> pins;
}; };
struct Design struct Context : Arch
{ {
struct Arch chip; std::unordered_map<IdString, NetInfo *> nets;
std::unordered_map<IdString, CellInfo *> cells;
Design(ArchArgs args) : chip(args) Context(ArchArgs args) : Arch(args)
{ {
// ... // ...
} }
std::unordered_map<IdString, NetInfo *> nets;
std::unordered_map<IdString, CellInfo *> cells;
}; };
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END

View File

@ -53,16 +53,16 @@ void replace_port(CellInfo *old_cell, IdString old_name, CellInfo *rep_cell,
} }
// Print utilisation of a design // Print utilisation of a design
void print_utilisation(const Design *design) void print_utilisation(const Context *ctx)
{ {
// Sort by Bel type // Sort by Bel type
std::map<BelType, int> used_types; std::map<BelType, int> used_types;
for (auto cell : design->cells) { for (auto cell : ctx->cells) {
used_types[belTypeFromId(cell.second->type)]++; used_types[belTypeFromId(cell.second->type)]++;
} }
std::map<BelType, int> available_types; std::map<BelType, int> available_types;
for (auto bel : design->chip.getBels()) { for (auto bel : ctx->getBels()) {
available_types[design->chip.getBelType(bel)]++; available_types[ctx->getBelType(bel)]++;
} }
log("\nDesign utilisation:\n"); log("\nDesign utilisation:\n");
for (auto type : available_types) { for (auto type : available_types) {

View File

@ -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 NEXTPNR_NAMESPACE_END

View File

@ -70,7 +70,7 @@ static int random_int_between(rnd_state &rnd, int a, int b)
} }
// Initial random placement // 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; bool all_placed = false;
int iters = 25; int iters = 25;
@ -78,18 +78,17 @@ static void place_initial(Design *design, CellInfo *cell, rnd_state &rnd)
BelId best_bel = BelId(); BelId best_bel = BelId();
float best_score = std::numeric_limits<float>::infinity(), float best_score = std::numeric_limits<float>::infinity(),
best_ripup_score = std::numeric_limits<float>::infinity(); best_ripup_score = std::numeric_limits<float>::infinity();
Arch &chip = design->chip;
CellInfo *ripup_target = nullptr; CellInfo *ripup_target = nullptr;
BelId ripup_bel = BelId(); BelId ripup_bel = BelId();
if (cell->bel != BelId()) { if (cell->bel != BelId()) {
chip.unbindBel(cell->bel); ctx->unbindBel(cell->bel);
cell->bel = BelId(); cell->bel = BelId();
} }
BelType targetType = belTypeFromId(cell->type); BelType targetType = belTypeFromId(cell->type);
for (auto bel : chip.getBels()) { for (auto bel : ctx->getBels()) {
if (chip.getBelType(bel) == targetType && if (ctx->getBelType(bel) == targetType &&
isValidBelForCell(design, cell, bel)) { isValidBelForCell(ctx, cell, bel)) {
if (chip.checkBelAvail(bel)) { if (ctx->checkBelAvail(bel)) {
float score = random_float_upto(rnd, 1.0); float score = random_float_upto(rnd, 1.0);
if (score <= best_score) { if (score <= best_score) {
best_score = score; best_score = score;
@ -100,7 +99,7 @@ static void place_initial(Design *design, CellInfo *cell, rnd_state &rnd)
if (score <= best_ripup_score) { if (score <= best_ripup_score) {
best_ripup_score = score; best_ripup_score = score;
ripup_target = ripup_target =
design->cells.at(chip.getBelCell(bel, true)); ctx->cells.at(ctx->getBelCell(bel, true));
ripup_bel = bel; 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", log_error("failed to place cell '%s' of type '%s'\n",
cell->name.c_str(), cell->type.c_str()); cell->name.c_str(), cell->type.c_str());
--iters; --iters;
chip.unbindBel(ripup_target->bel); ctx->unbindBel(ripup_target->bel);
ripup_target->bel = BelId(); ripup_target->bel = BelId();
best_bel = ripup_bel; best_bel = ripup_bel;
} else { } else {
all_placed = true; all_placed = true;
} }
cell->bel = best_bel; cell->bel = best_bel;
chip.bindBel(cell->bel, cell->name); ctx->bindBel(cell->bel, cell->name);
// Back annotate location // Back annotate location
cell->attrs["BEL"] = chip.getBelName(cell->bel).str(); cell->attrs["BEL"] = ctx->getBelName(cell->bel).str();
cell = ripup_target; 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 // 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) rnd_state &rnd, SAState &state)
{ {
static std::unordered_set<NetInfo *> update; static std::unordered_set<NetInfo *> update;
static std::vector<std::pair<NetInfo *, float>> new_lengths; static std::vector<std::pair<NetInfo *, float>> new_lengths;
new_lengths.clear(); new_lengths.clear();
update.clear(); update.clear();
Arch &chip = design->chip;
BelId oldBel = cell->bel; BelId oldBel = cell->bel;
IdString other = chip.getBelCell(newBel, true); IdString other = ctx->getBelCell(newBel, true);
CellInfo *other_cell = nullptr; CellInfo *other_cell = nullptr;
float new_wirelength = 0, delta; float new_wirelength = 0, delta;
chip.unbindBel(oldBel); ctx->unbindBel(oldBel);
if (other != IdString()) { if (other != IdString()) {
other_cell = design->cells[other]; other_cell = ctx->cells[other];
chip.unbindBel(newBel); ctx->unbindBel(newBel);
} }
for (const auto &port : cell->ports) 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); update.insert(port.second.net);
} }
chip.bindBel(newBel, cell->name); ctx->bindBel(newBel, cell->name);
if (other != IdString()) { if (other != IdString()) {
chip.bindBel(oldBel, other_cell->name); ctx->bindBel(oldBel, other_cell->name);
} }
if (!isBelLocationValid(design, newBel) || if (!isBelLocationValid(ctx, newBel) ||
((other != IdString() && !isBelLocationValid(design, oldBel)))) { ((other != IdString() && !isBelLocationValid(ctx, oldBel)))) {
chip.unbindBel(newBel); ctx->unbindBel(newBel);
if (other != IdString()) if (other != IdString())
chip.unbindBel(oldBel); ctx->unbindBel(oldBel);
goto swap_fail; 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 // Recalculate wirelengths for all nets touched by the peturbation
for (auto net : update) { for (auto net : update) {
new_wirelength -= state.wirelengths.at(net); 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_wirelength += net_new_wl;
new_lengths.push_back(std::make_pair(net, 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; state.improved = true;
} else { } else {
if (other != IdString()) if (other != IdString())
chip.unbindBel(oldBel); ctx->unbindBel(oldBel);
chip.unbindBel(newBel); ctx->unbindBel(newBel);
goto swap_fail; goto swap_fail;
} }
state.curr_wirelength = new_wirelength; state.curr_wirelength = new_wirelength;
@ -250,10 +248,10 @@ static bool try_swap_position(Design *design, CellInfo *cell, BelId newBel,
return true; return true;
swap_fail: swap_fail:
chip.bindBel(oldBel, cell->name); ctx->bindBel(oldBel, cell->name);
cell->bel = oldBel; cell->bel = oldBel;
if (other != IdString()) { if (other != IdString()) {
chip.bindBel(newBel, other); ctx->bindBel(newBel, other);
other_cell->bel = newBel; other_cell->bel = newBel;
} }
return false; return false;
@ -261,13 +259,12 @@ swap_fail:
// Find a random Bel of the correct type for a cell, within the specified // Find a random Bel of the correct type for a cell, within the specified
// diameter // 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) rnd_state &rnd)
{ {
Arch &chip = design->chip;
BelType targetType = belTypeFromId(cell->type); BelType targetType = belTypeFromId(cell->type);
int x = 0, y = 0; int x = 0, y = 0;
chip.estimatePosition(cell->bel, x, y); ctx->estimatePosition(cell->bel, x, y);
while (true) { while (true) {
int nx = random_int_between(rnd, std::max(int(x) - state.diameter, 0), int nx = random_int_between(rnd, std::max(int(x) - state.diameter, 0),
int(x) + state.diameter + 1); 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; SAState state;
size_t placed_cells = 0; size_t placed_cells = 0;
std::queue<CellInfo *> visit_cells; std::queue<CellInfo *> visit_cells;
// Initial constraints placer // Initial constraints placer
for (auto cell_entry : design->cells) { for (auto cell_entry : ctx->cells) {
CellInfo *cell = cell_entry.second; CellInfo *cell = cell_entry.second;
auto loc = cell->attrs.find("BEL"); auto loc = cell->attrs.find("BEL");
if (loc != cell->attrs.end()) { if (loc != cell->attrs.end()) {
std::string loc_name = loc->second; std::string loc_name = loc->second;
BelId bel = design->chip.getBelByName(IdString(loc_name)); BelId bel = ctx->getBelByName(IdString(loc_name));
if (bel == BelId()) { if (bel == BelId()) {
log_error("No Bel named \'%s\' located for " log_error("No Bel named \'%s\' located for "
"this chip (processing BEL attribute on \'%s\')\n", "this chip (processing BEL attribute on \'%s\')\n",
loc_name.c_str(), cell->name.c_str()); 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)) { if (bel_type != belTypeFromId(cell->type)) {
log_error("Bel \'%s\' of type \'%s\' does not match cell " log_error("Bel \'%s\' of type \'%s\' does not match cell "
"\'%s\' of type \'%s\'", "\'%s\' of type \'%s\'",
@ -316,7 +313,7 @@ void place_design_sa(Design *design, int seed)
} }
cell->bel = bel; cell->bel = bel;
design->chip.bindBel(bel, cell->name); ctx->bindBel(bel, cell->name);
state.locked_bels.insert(bel); state.locked_bels.insert(bel);
placed_cells++; placed_cells++;
visit_cells.push(cell); visit_cells.push(cell);
@ -327,7 +324,7 @@ void place_design_sa(Design *design, int seed)
rnd.state = seed; rnd.state = seed;
std::vector<CellInfo *> autoplaced; std::vector<CellInfo *> autoplaced;
// Sort to-place cells for deterministic initial placement // Sort to-place cells for deterministic initial placement
for (auto cell : design->cells) { for (auto cell : ctx->cells) {
CellInfo *ci = cell.second; CellInfo *ci = cell.second;
if (ci->bel == BelId()) { if (ci->bel == BelId()) {
autoplaced.push_back(cell.second); 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; }); [](CellInfo *a, CellInfo *b) { return a->name < b->name; });
// Place cells randomly initially // Place cells randomly initially
for (auto cell : autoplaced) { for (auto cell : autoplaced) {
place_initial(design, cell, rnd); place_initial(ctx, cell, rnd);
placed_cells++; placed_cells++;
} }
// Build up a fast position/type to Bel lookup table // Build up a fast position/type to Bel lookup table
int max_x = 0, max_y = 0; int max_x = 0, max_y = 0;
int bel_types = 0; int bel_types = 0;
for (auto bel : design->chip.getBels()) { for (auto bel : ctx->getBels()) {
int x, y; int x, y;
design->chip.estimatePosition(bel, x, y); ctx->estimatePosition(bel, x, y);
BelType type = design->chip.getBelType(bel); BelType type = ctx->getBelType(bel);
int type_idx; int type_idx;
if (state.bel_types.find(type) == state.bel_types.end()) { if (state.bel_types.find(type) == state.bel_types.end()) {
type_idx = bel_types++; 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; state.diameter = std::max(max_x, max_y) + 1;
// Calculate wirelength after initial placement // Calculate wirelength after initial placement
state.curr_wirelength = 0; state.curr_wirelength = 0;
for (auto net : design->nets) { for (auto net : ctx->nets) {
float wl = get_wirelength(&design->chip, net.second); float wl = get_wirelength(ctx, net.second);
state.wirelengths[net.second] = wl; state.wirelengths[net.second] = wl;
state.curr_wirelength += wl; state.curr_wirelength += wl;
} }
@ -390,11 +387,11 @@ void place_design_sa(Design *design, int seed)
// Loop through all automatically placed cells // Loop through all automatically placed cells
for (auto cell : autoplaced) { for (auto cell : autoplaced) {
// Find another random Bel for this cell // 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 // If valid, try and swap to a new position and see if
// the new position is valid/worthwhile // the new position is valid/worthwhile
if (try_bel != BelId() && try_bel != cell->bel) 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 // 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()) { for (auto bel : ctx->getBels()) {
if (!isBelLocationValid(design, bel)) { if (!isBelLocationValid(ctx, bel)) {
std::string cell_text = "no cell"; std::string cell_text = "no cell";
IdString cell = design->chip.getBelCell(bel, false); IdString cell = ctx->getBelCell(bel, false);
if (cell != IdString()) if (cell != IdString())
cell_text = std::string("cell '") + cell.str() + "'"; cell_text = std::string("cell '") + cell.str() + "'";
log_error("post-placement validity check failed for Bel '%s' (%s)", 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());
} }
} }
} }

View File

@ -23,7 +23,7 @@
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
extern void place_design_sa(Design *design, int seed); extern void place_design_sa(Context *ctx, int seed);
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END

View File

@ -47,7 +47,7 @@ bool operator==(const PortRef &a, const PortRef &b)
} }
// Load a JSON file into a design // 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); std::ifstream inf(filename);
if (!inf) 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 // 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); parse_json_shim(filename, d);
return d; return d;
} }
@ -113,13 +113,12 @@ BOOST_PYTHON_MODULE(MODULE_NAME)
WRAP_MAP(decltype(CellInfo::ports), "IdPortMap"); WRAP_MAP(decltype(CellInfo::ports), "IdPortMap");
// WRAP_MAP(decltype(CellInfo::pins), "IdIdMap"); // WRAP_MAP(decltype(CellInfo::pins), "IdIdMap");
class_<Design, Design *>("Design", no_init) class_<Context, Context *>("Context", no_init)
.def_readwrite("chip", &Design::chip) .def_readwrite("nets", &Context::nets)
.def_readwrite("nets", &Design::nets) .def_readwrite("cells", &Context::cells);
.def_readwrite("cells", &Design::cells);
WRAP_MAP(decltype(Design::nets), "IdNetMap"); WRAP_MAP(decltype(Context::nets), "IdNetMap");
WRAP_MAP(decltype(Design::cells), "IdCellMap"); WRAP_MAP(decltype(Context::cells), "IdCellMap");
def("parse_json", parse_json_shim); def("parse_json", parse_json_shim);
def("load_design", load_design_shim); def("load_design", load_design_shim);

View File

@ -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 = ctx->nets.at(net_name);
auto net_info = design->nets.at(net_name);
for (auto &it : net_info->wires) { for (auto &it : net_info->wires) {
if (it.second != PipId()) if (it.second != PipId())
chip.unbindPip(it.second); ctx->unbindPip(it.second);
chip.unbindWire(it.first); ctx->unbindWire(it.first);
} }
net_info->wires.clear(); net_info->wires.clear();
@ -66,11 +65,10 @@ struct Router
delay_t maxDelay = 0.0; delay_t maxDelay = 0.0;
WireId failedDest; 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) delay_t ripup_penalty = 0)
{ {
auto &chip = design->chip; auto net_info = ctx->nets.at(net_name);
auto net_info = design->nets.at(net_name);
if (verbose) if (verbose)
log("Routing net %s.\n", net_name.c_str()); log("Routing net %s.\n", net_name.c_str());
@ -87,7 +85,7 @@ struct Router
net_info->driver.cell->type.c_str()); net_info->driver.cell->type.c_str());
if (verbose) 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; IdString driver_port = net_info->driver.port;
@ -95,22 +93,22 @@ struct Router
if (driver_port_it != net_info->driver.cell->pins.end()) if (driver_port_it != net_info->driver.cell->pins.end())
driver_port = driver_port_it->second; 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()) if (src_wire == WireId())
log_error("No wire found for port %s (pin %s) on source cell %s " log_error("No wire found for port %s (pin %s) on source cell %s "
"(bel %s).\n", "(bel %s).\n",
net_info->driver.port.c_str(), driver_port.c_str(), net_info->driver.port.c_str(), driver_port.c_str(),
net_info->driver.cell->name.c_str(), net_info->driver.cell->name.c_str(),
chip.getBelName(src_bel).c_str()); ctx->getBelName(src_bel).c_str());
if (verbose) 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<WireId, DelayInfo> src_wires; std::unordered_map<WireId, DelayInfo> src_wires;
src_wires[src_wire] = DelayInfo(); src_wires[src_wire] = DelayInfo();
net_info->wires[src_wire] = PipId(); 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) { for (auto &user_it : net_info->users) {
if (verbose) if (verbose)
@ -126,7 +124,7 @@ struct Router
if (verbose) if (verbose)
log(" Destination bel: %s\n", log(" Destination bel: %s\n",
chip.getBelName(dst_bel).c_str()); ctx->getBelName(dst_bel).c_str());
IdString user_port = user_it.port; IdString user_port = user_it.port;
@ -136,20 +134,20 @@ struct Router
user_port = user_port_it->second; user_port = user_port_it->second;
auto dst_wire = auto dst_wire =
chip.getWireBelPin(dst_bel, portPinFromId(user_port)); ctx->getWireBelPin(dst_bel, portPinFromId(user_port));
if (dst_wire == WireId()) if (dst_wire == WireId())
log_error("No wire found for port %s (pin %s) on destination " log_error("No wire found for port %s (pin %s) on destination "
"cell %s (bel %s).\n", "cell %s (bel %s).\n",
user_it.port.c_str(), user_port.c_str(), user_it.port.c_str(), user_port.c_str(),
user_it.cell->name.c_str(), user_it.cell->name.c_str(),
chip.getBelName(dst_bel).c_str()); ctx->getBelName(dst_bel).c_str());
if (verbose) { if (verbose) {
log(" Destination wire: %s\n", log(" Destination wire: %s\n",
chip.getWireName(dst_wire).c_str()); ctx->getWireName(dst_wire).c_str());
log(" Path delay estimate: %.2f\n", log(" Path delay estimate: %.2f\n",
float(chip.estimateDelay(src_wire, dst_wire))); float(ctx->estimateDelay(src_wire, dst_wire)));
} }
std::unordered_map<WireId, QueuedWire> visited; std::unordered_map<WireId, QueuedWire> visited;
@ -162,7 +160,7 @@ struct Router
qw.wire = it.first; qw.wire = it.first;
qw.pip = PipId(); qw.pip = PipId();
qw.delay = it.second.avgDelay(); qw.delay = it.second.avgDelay();
qw.togo = chip.estimateDelay(qw.wire, dst_wire); qw.togo = ctx->estimateDelay(qw.wire, dst_wire);
queue.push(qw); queue.push(qw);
visited[qw.wire] = qw; visited[qw.wire] = qw;
@ -172,26 +170,26 @@ struct Router
QueuedWire qw = queue.top(); QueuedWire qw = queue.top();
queue.pop(); queue.pop();
for (auto pip : chip.getPipsDownhill(qw.wire)) { for (auto pip : ctx->getPipsDownhill(qw.wire)) {
delay_t next_delay = qw.delay; delay_t next_delay = qw.delay;
IdString ripupNet = net_name; IdString ripupNet = net_name;
visitCnt++; visitCnt++;
if (!chip.checkPipAvail(pip)) { if (!ctx->checkPipAvail(pip)) {
if (!ripup) if (!ripup)
continue; continue;
ripupNet = chip.getPipNet(pip, true); ripupNet = ctx->getPipNet(pip, true);
if (ripupNet == net_name) if (ripupNet == net_name)
continue; continue;
} }
WireId next_wire = chip.getPipDstWire(pip); WireId next_wire = ctx->getPipDstWire(pip);
next_delay += chip.getPipDelay(pip).avgDelay(); next_delay += ctx->getPipDelay(pip).avgDelay();
if (!chip.checkWireAvail(next_wire)) { if (!ctx->checkWireAvail(next_wire)) {
if (!ripup) if (!ripup)
continue; continue;
ripupNet = chip.getWireNet(next_wire, true); ripupNet = ctx->getWireNet(next_wire, true);
if (ripupNet == net_name) if (ripupNet == net_name)
continue; continue;
} }
@ -207,7 +205,7 @@ struct Router
if (verbose) if (verbose)
log("Found better route to %s. Old vs new delay " log("Found better route to %s. Old vs new delay "
"estimate: %.2f %.2f\n", "estimate: %.2f %.2f\n",
chip.getWireName(next_wire).c_str(), ctx->getWireName(next_wire).c_str(),
float(visited.at(next_wire).delay), float(visited.at(next_wire).delay),
float(next_delay)); float(next_delay));
#endif #endif
@ -218,7 +216,7 @@ struct Router
next_qw.wire = next_wire; next_qw.wire = next_wire;
next_qw.pip = pip; next_qw.pip = pip;
next_qw.delay = next_delay; 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; visited[next_qw.wire] = next_qw;
queue.push(next_qw); queue.push(next_qw);
} }
@ -227,13 +225,13 @@ struct Router
if (visited.count(dst_wire) == 0) { if (visited.count(dst_wire) == 0) {
if (verbose) if (verbose)
log("Failed to route %s -> %s.\n", log("Failed to route %s -> %s.\n",
chip.getWireName(src_wire).c_str(), ctx->getWireName(src_wire).c_str(),
chip.getWireName(dst_wire).c_str()); ctx->getWireName(dst_wire).c_str());
else if (ripup) else if (ripup)
log_info("Failed to route %s -> %s.\n", log_info("Failed to route %s -> %s.\n",
chip.getWireName(src_wire).c_str(), ctx->getWireName(src_wire).c_str(),
chip.getWireName(dst_wire).c_str()); ctx->getWireName(dst_wire).c_str());
ripup_net(design, net_name); ripup_net(ctx, net_name);
failedDest = dst_wire; failedDest = dst_wire;
return; return;
} }
@ -251,35 +249,35 @@ struct Router
while (1) { while (1) {
if (verbose) if (verbose)
log(" %8.2f %s\n", float(visited[cursor].delay), log(" %8.2f %s\n", float(visited[cursor].delay),
chip.getWireName(cursor).c_str()); ctx->getWireName(cursor).c_str());
if (src_wires.count(cursor)) if (src_wires.count(cursor))
break; break;
IdString conflicting_net = chip.getWireNet(cursor, true); IdString conflicting_net = ctx->getWireNet(cursor, true);
if (conflicting_net != IdString()) { if (conflicting_net != IdString()) {
assert(ripup); assert(ripup);
assert(conflicting_net != net_name); assert(conflicting_net != net_name);
ripup_net(design, conflicting_net); ripup_net(ctx, conflicting_net);
rippedNets.insert(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()) { if (conflicting_net != IdString()) {
assert(ripup); assert(ripup);
assert(conflicting_net != net_name); assert(conflicting_net != net_name);
ripup_net(design, conflicting_net); ripup_net(ctx, conflicting_net);
rippedNets.insert(conflicting_net); rippedNets.insert(conflicting_net);
} }
net_info->wires[cursor] = visited[cursor].pip; net_info->wires[cursor] = visited[cursor].pip;
chip.bindWire(cursor, net_name); ctx->bindWire(cursor, net_name);
chip.bindPip(visited[cursor].pip, net_name); ctx->bindPip(visited[cursor].pip, net_name);
src_wires[cursor] = chip.getPipDelay(visited[cursor].pip); src_wires[cursor] = ctx->getPipDelay(visited[cursor].pip);
cursor = chip.getPipSrcWire(visited[cursor].pip); cursor = ctx->getPipSrcWire(visited[cursor].pip);
} }
} }
@ -291,16 +289,15 @@ struct Router
NEXTPNR_NAMESPACE_BEGIN 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; delay_t ripup_penalty = 5;
log_info("Routing..\n"); log_info("Routing..\n");
std::unordered_set<IdString> netsQueue; std::unordered_set<IdString> netsQueue;
for (auto &net_it : design->nets) { for (auto &net_it : ctx->nets) {
auto net_name = net_it.first; auto net_name = net_it.first;
auto net_info = net_it.second; auto net_info = net_it.second;
@ -325,7 +322,7 @@ bool route_design(Design *design, bool verbose)
int estimatedTotalDelayCnt = 0; int estimatedTotalDelayCnt = 0;
for (auto net_name : netsQueue) { 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; 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()) if (driver_port_it != net_info->driver.cell->pins.end())
driver_port = driver_port_it->second; 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()) if (src_wire == WireId())
continue; continue;
@ -357,12 +354,12 @@ bool route_design(Design *design, bool verbose)
user_port = user_port_it->second; user_port = user_port_it->second;
auto dst_wire = auto dst_wire =
chip.getWireBelPin(dst_bel, portPinFromId(user_port)); ctx->getWireBelPin(dst_bel, portPinFromId(user_port));
if (dst_wire == WireId()) if (dst_wire == WireId())
continue; continue;
estimatedTotalDelay += chip.estimateDelay(src_wire, dst_wire); estimatedTotalDelay += ctx->estimateDelay(src_wire, dst_wire);
estimatedTotalDelayCnt++; estimatedTotalDelayCnt++;
} }
} }
@ -390,9 +387,9 @@ bool route_design(Design *design, bool verbose)
for (auto net_name : netsQueue) { for (auto net_name : netsQueue) {
if (printNets) if (printNets)
log_info(" routing net %s. (%d users)\n", net_name.c_str(), 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++; netCnt++;
visitCnt += router.visitCnt; visitCnt += router.visitCnt;
@ -401,7 +398,7 @@ bool route_design(Design *design, bool verbose)
if (!router.routedOkay) { if (!router.routedOkay) {
if (printNets) if (printNets)
log_info(" failed to route to %s.\n", log_info(" failed to route to %s.\n",
chip.getWireName(router.failedDest).c_str()); ctx->getWireName(router.failedDest).c_str());
ripupQueue.insert(net_name); ripupQueue.insert(net_name);
} }
@ -433,9 +430,9 @@ bool route_design(Design *design, bool verbose)
for (auto net_name : ripupQueue) { for (auto net_name : ripupQueue) {
if (printNets) if (printNets)
log_info(" routing net %s. (%d users)\n", net_name.c_str(), 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)); ripup_penalty * (iterCnt - 1));
netCnt++; netCnt++;
@ -455,7 +452,7 @@ bool route_design(Design *design, bool verbose)
int(router.rippedNets.size())); int(router.rippedNets.size()));
for (auto n : router.rippedNets) for (auto n : router.rippedNets)
log_info(" %s (%d users)\n", n.c_str(), log_info(" %s (%d users)\n", n.c_str(),
int(design->nets.at(n)->users.size())); int(ctx->nets.at(n)->users.size()));
} else { } else {
log_info(" ripped up %d other nets.\n", log_info(" ripped up %d other nets.\n",
int(router.rippedNets.size())); int(router.rippedNets.size()));

View File

@ -24,7 +24,7 @@
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
extern bool route_design(Design *design, bool verbose = false); extern bool route_design(Context *ctx, bool verbose = false);
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END

View File

@ -5,13 +5,13 @@
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
bool check_all_nets_driven(Design *design) bool check_all_nets_driven(Context *ctx)
{ {
const bool debug = false; const bool debug = false;
log_info("Rule checker, Verifying pre-placed design\n"); 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; CellInfo *cell = cell_entry.second;
if (debug) if (debug)
@ -37,12 +37,12 @@ bool check_all_nets_driven(Design *design)
if (debug) if (debug)
log_info(" Checking for a net named \'%s\'\n", log_info(" Checking for a net named \'%s\'\n",
port.net->name.c_str()); 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; NetInfo *net = net_entry.second;
assert(net->name == net_entry.first); assert(net->name == net_entry.first);
@ -52,7 +52,7 @@ bool check_all_nets_driven(Design *design)
if (debug) if (debug)
log_info(" Checking for a driver cell named \'%s\'\n", log_info(" Checking for a driver cell named \'%s\'\n",
net->driver.cell->name.c_str()); 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) { for (auto user : net->users) {
@ -62,7 +62,7 @@ bool check_all_nets_driven(Design *design)
if (debug) if (debug)
log_info(" Checking for a user cell named \'%s\'\n", log_info(" Checking for a user cell named \'%s\'\n",
user.cell->name.c_str()); user.cell->name.c_str());
assert(design->cells.count(user.cell->name) > 0); assert(ctx->cells.count(user.cell->name) > 0);
} }
} }
} }

View File

@ -21,12 +21,12 @@
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
bool isValidBelForCell(Design *design, CellInfo *cell, BelId bel) bool isValidBelForCell(Context *ctx, CellInfo *cell, BelId bel)
{ {
return true; return true;
} }
bool isBelLocationValid(Design *design, BelId bel) bool isBelLocationValid(Context *ctx, BelId bel)
{ {
return true; return true;
} }

View File

@ -29,10 +29,10 @@ NEXTPNR_NAMESPACE_BEGIN
// Whether or not a given cell can be placed at a given Bel // 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 // This is not intended for Bel type checks, but finer-grained constraints
// such as conflicting set/reset signals, etc // 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 // 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 NEXTPNR_NAMESPACE_END

View File

@ -27,10 +27,10 @@ USING_NEXTPNR_NAMESPACE
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
Design design(ArchArgs{}); Context ctx(ArchArgs{});
QApplication a(argc, argv); QApplication a(argc, argv);
MainWindow w(&design); MainWindow w(&ctx);
w.show(); w.show();
return a.exec(); return a.exec();

View File

@ -31,7 +31,7 @@
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
extern bool check_all_nets_driven(Design *design); extern bool check_all_nets_driven(Context *ctx);
namespace JsonParser { namespace JsonParser {
@ -313,7 +313,7 @@ bool is_blackbox(JsonNode *node)
return true; 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, JsonNode *param_node,
std::unordered_map<IdString, std::string> *dest, std::unordered_map<IdString, std::string> *dest,
int param_id) int param_id)
@ -344,7 +344,7 @@ void json_import_cell_params(Design *design, string &modname, CellInfo *cell,
static int const_net_idx = 0; static int const_net_idx = 0;
template <typename F> template <typename F>
void json_import_ports(Design *design, const string &modname, void json_import_ports(Context *ctx, const string &modname,
const std::vector<IdString> &netnames, const std::vector<IdString> &netnames,
const string &obj_name, const string &port_name, const string &obj_name, const string &port_name,
JsonNode *dir_node, JsonNode *wire_group_node, F visitor) 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); net_id = netnames.at(net_num);
else else
net_id = std::to_string(net_num); 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) // The net doesn't exist in the design (yet)
// Create in now // Create in now
@ -449,13 +449,13 @@ void json_import_ports(Design *design, const string &modname,
this_net->name = net_id; this_net->name = net_id;
this_net->driver.cell = NULL; this_net->driver.cell = NULL;
this_net->driver.port = ""; this_net->driver.port = "";
design->nets[net_id] = this_net; ctx->nets[net_id] = this_net;
} else { } else {
// //
// The net already exists within the design. // The net already exists within the design.
// We'll connect to it // We'll connect to it
// //
this_net = design->nets[net_id]; this_net = ctx->nets[net_id];
if (json_debug) if (json_debug)
log_info(" Reusing net \'%s\', id \'%s\', " log_info(" Reusing net \'%s\', id \'%s\', "
"with driver \'%s\'\n", "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()); this_port.name.c_str(), obj_name.c_str());
visitor(this_port.type, this_port.name, this_net); visitor(this_port.type, this_port.name, this_net);
if (design->nets.count(this_net->name) == 0) if (ctx->nets.count(this_net->name) == 0)
design->nets[this_net->name] = this_net; 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<IdString> &netnames, const std::vector<IdString> &netnames,
JsonNode *cell_node, string cell_name) 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); for (int paramid = 0; paramid < GetSize(param_node->data_dict_keys);
paramid++) { paramid++) {
json_import_cell_params(design, modname, cell, param_node, json_import_cell_params(ctx, modname, cell, param_node,
&cell->params, paramid); &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); for (int attrid = 0; attrid < GetSize(attr_node->data_dict_keys);
attrid++) { attrid++) {
json_import_cell_params(design, modname, cell, attr_node, &cell->attrs, json_import_cell_params(ctx, modname, cell, attr_node, &cell->attrs,
attrid); attrid);
} }
@ -621,7 +621,7 @@ void json_import_cell(Design *design, string modname,
wire_group_node = connections->data_dict.at(port_name); wire_group_node = connections->data_dict.at(port_name);
json_import_ports( json_import_ports(
design, modname, netnames, cell->name, port_name, dir_node, ctx, modname, netnames, cell->name, port_name, dir_node,
wire_group_node, wire_group_node,
[cell](PortType type, const std::string &name, NetInfo *net) { [cell](PortType type, const std::string &name, NetInfo *net) {
cell->ports[name] = PortInfo{name, net, type}; cell->ports[name] = PortInfo{name, net, type};
@ -639,11 +639,11 @@ void json_import_cell(Design *design, string modname,
}); });
} }
design->cells[cell->name] = cell; ctx->cells[cell->name] = cell;
// check_all_nets_driven(design); // 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) const string &name)
{ {
// Instantiate a architecture-independent IO buffer connected to a given // 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 = net->driver;
net2->driver.cell->ports[net2->driver.port].net = net2; net2->driver.cell->ports[net2->driver.port].net = net2;
net->driver.cell = nullptr; net->driver.cell = nullptr;
design->nets[net2->name] = net2; ctx->nets[net2->name] = net2;
iobuf->ports["I"].net = net2; iobuf->ports["I"].net = net2;
PortRef ref; PortRef ref;
ref.cell = iobuf; ref.cell = iobuf;
@ -697,24 +697,24 @@ static void insert_iobuf(Design *design, NetInfo *net, PortType type,
} else { } else {
assert(false); 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<IdString> &netnames, const std::vector<IdString> &netnames,
const string &portname, JsonNode *node) const string &portname, JsonNode *node)
{ {
JsonNode *dir_node = node->data_dict.at("direction"); JsonNode *dir_node = node->data_dict.at("direction");
JsonNode *nets_node = node->data_dict.at("bits"); JsonNode *nets_node = node->data_dict.at("bits");
json_import_ports( json_import_ports(
design, modname, netnames, "Top Level IO", portname, dir_node, ctx, modname, netnames, "Top Level IO", portname, dir_node,
nets_node, nets_node,
[design](PortType type, const std::string &name, NetInfo *net) { [ctx](PortType type, const std::string &name, NetInfo *net) {
insert_iobuf(design, net, type, name); 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)) if (is_blackbox(node))
return; return;
@ -763,7 +763,7 @@ void json_import(Design *design, string modname, JsonNode *node)
here = cell_parent->data_dict.at( here = cell_parent->data_dict.at(
cell_parent->data_dict_keys[cellid]); 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]); 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( here = ports_parent->data_dict.at(
ports_parent->data_dict_keys[portid]); 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], ports_parent->data_dict_keys[portid],
here); here);
} }
} }
check_all_nets_driven(design); check_all_nets_driven(ctx);
} }
struct JsonFrontend struct JsonFrontend
@ -794,9 +794,9 @@ struct JsonFrontend
JsonFrontend(void) {} JsonFrontend(void) {}
virtual void help() {} virtual void help() {}
virtual void execute(std::istream *&f, std::string &filename, 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); JsonNode root(*f);
@ -810,17 +810,17 @@ struct JsonFrontend
log_error("JSON modules node is not a dictionary.\n"); log_error("JSON modules node is not a dictionary.\n");
for (auto &it : modules->data_dict) for (auto &it : modules->data_dict)
json_import(design, it.first, it.second); json_import(ctx, it.first, it.second);
} }
} }
}; // JsonFrontend; }; // JsonFrontend;
}; // End Namespace JsonParser }; // 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(); auto *parser = new JsonParser::JsonFrontend();
parser->execute(f, filename, design); parser->execute(f, filename, ctx);
} }
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END

View File

@ -26,7 +26,7 @@
NEXTPNR_NAMESPACE_BEGIN 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 NEXTPNR_NAMESPACE_END

View File

@ -77,8 +77,8 @@ class PipTreeItem : public ElementTreeItem
IdString data; IdString data;
}; };
DesignWidget::DesignWidget(Design *_design, QWidget *parent) DesignWidget::DesignWidget(Context *_ctx, QWidget *parent)
: QWidget(parent), design(_design) : QWidget(parent), ctx(_ctx)
{ {
treeWidget = new QTreeWidget(); treeWidget = new QTreeWidget();
@ -93,8 +93,8 @@ DesignWidget::DesignWidget(Design *_design, QWidget *parent)
bel_root->setText(0, QString("Bels")); bel_root->setText(0, QString("Bels"));
treeWidget->insertTopLevelItem(0, bel_root); treeWidget->insertTopLevelItem(0, bel_root);
QList<QTreeWidgetItem *> bel_items; QList<QTreeWidgetItem *> bel_items;
for (auto bel : design->chip.getBels()) { for (auto bel : ctx->getBels()) {
auto name = design->chip.getBelName(bel); auto name = ctx->getBelName(bel);
bel_items.append( bel_items.append(
new BelTreeItem(name, ElementType::BEL, QString(name.c_str()))); new BelTreeItem(name, ElementType::BEL, QString(name.c_str())));
} }
@ -105,8 +105,8 @@ DesignWidget::DesignWidget(Design *_design, QWidget *parent)
QList<QTreeWidgetItem *> wire_items; QList<QTreeWidgetItem *> wire_items;
wire_root->setText(0, QString("Wires")); wire_root->setText(0, QString("Wires"));
treeWidget->insertTopLevelItem(0, wire_root); treeWidget->insertTopLevelItem(0, wire_root);
for (auto wire : design->chip.getWires()) { for (auto wire : ctx->getWires()) {
auto name = design->chip.getWireName(wire); auto name = ctx->getWireName(wire);
wire_items.append(new WireTreeItem(name, ElementType::WIRE, wire_items.append(new WireTreeItem(name, ElementType::WIRE,
QString(name.c_str()))); QString(name.c_str())));
} }
@ -117,8 +117,8 @@ DesignWidget::DesignWidget(Design *_design, QWidget *parent)
QList<QTreeWidgetItem *> pip_items; QList<QTreeWidgetItem *> pip_items;
pip_root->setText(0, QString("Pips")); pip_root->setText(0, QString("Pips"));
treeWidget->insertTopLevelItem(0, pip_root); treeWidget->insertTopLevelItem(0, pip_root);
for (auto pip : design->chip.getPips()) { for (auto pip : ctx->getPips()) {
auto name = design->chip.getPipName(pip); auto name = ctx->getPipName(pip);
pip_items.append( pip_items.append(
new PipTreeItem(name, ElementType::PIP, QString(name.c_str()))); new PipTreeItem(name, ElementType::PIP, QString(name.c_str())));
} }

View File

@ -15,9 +15,9 @@ class DesignWidget : public QWidget
Q_OBJECT Q_OBJECT
public: public:
explicit DesignWidget(Design *design, QWidget *parent = 0); explicit DesignWidget(Context *ctx, QWidget *parent = 0);
~DesignWidget(); ~DesignWidget();
Design *getDesign() { return design; } Context *getContext() { return ctx; }
private: private:
void addProperty(QtVariantProperty *property, const QString &id); void addProperty(QtVariantProperty *property, const QString &id);
@ -32,7 +32,7 @@ class DesignWidget : public QWidget
void selectObject(); void selectObject();
private: private:
Design *design; Context *ctx;
QTreeWidget *treeWidget; QTreeWidget *treeWidget;

View File

@ -9,7 +9,7 @@
FPGAViewWidget::FPGAViewWidget(QWidget *parent) FPGAViewWidget::FPGAViewWidget(QWidget *parent)
: QOpenGLWidget(parent), m_xMove(0), m_yMove(0), m_zDistance(1.0) : QOpenGLWidget(parent), m_xMove(0), m_yMove(0), m_zDistance(1.0)
{ {
design = qobject_cast<MainWindow *>(getMainWindow())->getDesign(); ctx = qobject_cast<MainWindow *>(getMainWindow())->getContext();
} }
QMainWindow *FPGAViewWidget::getMainWindow() QMainWindow *FPGAViewWidget::getMainWindow()
@ -118,12 +118,12 @@ void FPGAViewWidget::paintGL()
glColor3f(0.1, 0.1, 0.1); glColor3f(0.1, 0.1, 0.1);
glLineWidth(0.1); glLineWidth(0.1);
// Draw Bels // Draw Bels
for (auto bel : design->chip.getBels()) { for (auto bel : ctx->getBels()) {
for (auto &el : design->chip.getBelGraphics(bel)) for (auto &el : ctx->getBelGraphics(bel))
drawElement(el); drawElement(el);
} }
// Draw Frame Graphics // Draw Frame Graphics
for (auto &el : design->chip.getFrameGraphics()) for (auto &el : ctx->getFrameGraphics())
drawElement(el); drawElement(el);
} }

View File

@ -46,7 +46,7 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
float m_yMove; float m_yMove;
float m_zDistance; float m_zDistance;
QPoint m_lastPos; QPoint m_lastPos;
Design *design; Context *ctx;
}; };
#endif #endif

View File

@ -11,10 +11,10 @@
#include "fpgaviewwidget.h" #include "fpgaviewwidget.h"
#include "pythontab.h" #include "pythontab.h"
MainWindow::MainWindow(Design *_design, QWidget *parent) MainWindow::MainWindow(Context *_ctx, QWidget *parent)
: QMainWindow(parent), design(_design) : QMainWindow(parent), ctx(_ctx)
{ {
std::string title = "nextpnr-ice40 - " + design->chip.getChipName(); std::string title = "nextpnr-ice40 - " + ctx->getChipName();
setWindowTitle(title.c_str()); setWindowTitle(title.c_str());
setObjectName(QStringLiteral("MainWindow")); setObjectName(QStringLiteral("MainWindow"));
resize(1024, 768); resize(1024, 768);
@ -35,7 +35,7 @@ MainWindow::MainWindow(Design *_design, QWidget *parent)
setCentralWidget(centralWidget); setCentralWidget(centralWidget);
DesignWidget *designview = new DesignWidget(design); DesignWidget *designview = new DesignWidget(ctx);
designview->setMinimumWidth(300); designview->setMinimumWidth(300);
designview->setMaximumWidth(300); designview->setMaximumWidth(300);
splitter_h->addWidget(designview); splitter_h->addWidget(designview);

View File

@ -15,9 +15,9 @@ class MainWindow : public QMainWindow
Q_OBJECT Q_OBJECT
public: public:
explicit MainWindow(Design *design, QWidget *parent = 0); explicit MainWindow(Context *ctx, QWidget *parent = 0);
~MainWindow(); ~MainWindow();
Design *getDesign() { return design; } Context *getContext() { return ctx; }
private: private:
void createMenusAndBars(); void createMenusAndBars();
@ -26,7 +26,7 @@ class MainWindow : public QMainWindow
void writeInfo(std::string text); void writeInfo(std::string text);
private: private:
Design *design; Context *ctx;
InfoTab *info; InfoTab *info;
}; };

View File

@ -88,40 +88,38 @@ static bool logicCellsCompatible(const std::vector<const CellInfo *> &cells)
return locals.size() <= 32; return locals.size() <= 32;
} }
bool isBelLocationValid(Design *design, BelId bel) bool isBelLocationValid(Context *ctx, BelId bel)
{ {
const Arch &chip = design->chip; if (ctx->getBelType(bel) == TYPE_ICESTORM_LC) {
if (chip.getBelType(bel) == TYPE_ICESTORM_LC) {
std::vector<const CellInfo *> cells; std::vector<const CellInfo *> cells;
for (auto bel_other : chip.getBelsAtSameTile(bel)) { for (auto bel_other : ctx->getBelsAtSameTile(bel)) {
IdString cell_other = chip.getBelCell(bel_other, false); IdString cell_other = ctx->getBelCell(bel_other, false);
if (cell_other != IdString()) { 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); cells.push_back(ci_other);
} }
} }
return logicCellsCompatible(cells); return logicCellsCompatible(cells);
} else { } else {
IdString cellId = chip.getBelCell(bel, false); IdString cellId = ctx->getBelCell(bel, false);
if (cellId == IdString()) if (cellId == IdString())
return true; return true;
else 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") { if (cell->type == "ICESTORM_LC") {
assert(chip.getBelType(bel) == TYPE_ICESTORM_LC); assert(ctx->getBelType(bel) == TYPE_ICESTORM_LC);
std::vector<const CellInfo *> cells; std::vector<const CellInfo *> cells;
for (auto bel_other : chip.getBelsAtSameTile(bel)) { for (auto bel_other : ctx->getBelsAtSameTile(bel)) {
IdString cell_other = chip.getBelCell(bel_other, false); IdString cell_other = ctx->getBelCell(bel_other, false);
if (cell_other != IdString()) { 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); cells.push_back(ci_other);
} }
} }
@ -129,7 +127,7 @@ bool isValidBelForCell(Design *design, CellInfo *cell, BelId bel)
cells.push_back(cell); cells.push_back(cell);
return logicCellsCompatible(cells); return logicCellsCompatible(cells);
} else if (cell->type == "SB_IO") { } else if (cell->type == "SB_IO") {
return design->chip.getBelPackagePin(bel) != ""; return ctx->getBelPackagePin(bel) != "";
} else if (cell->type == "SB_GB") { } else if (cell->type == "SB_GB") {
bool is_reset = false, is_cen = false; bool is_reset = false, is_cen = false;
assert(cell->ports.at("GLOBAL_BUFFER_OUTPUT").net != nullptr); 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)) if (is_enable_port(user))
is_cen = true; is_cen = true;
} }
IdString glb_net = chip.getWireName( IdString glb_net = ctx->getWireName(
chip.getWireBelPin(bel, PIN_GLOBAL_BUFFER_OUTPUT)); ctx->getWireBelPin(bel, PIN_GLOBAL_BUFFER_OUTPUT));
int glb_id = std::stoi(std::string("") + glb_net.str().back()); int glb_id = std::stoi(std::string("") + glb_net.str().back());
if (is_reset && is_cen) if (is_reset && is_cen)
return false; return false;

View File

@ -29,10 +29,10 @@ NEXTPNR_NAMESPACE_BEGIN
// Whether or not a given cell can be placed at a given Bel // 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 // This is not intended for Bel type checks, but finer-grained constraints
// such as conflicting set/reset signals, etc // 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 // 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 NEXTPNR_NAMESPACE_END

View File

@ -23,9 +23,9 @@
NEXTPNR_NAMESPACE_BEGIN 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, const ConfigEntryPOD &find_config(const TileInfoPOD &tile,
@ -95,18 +95,17 @@ std::string get_param_str_or_def(const CellInfo *cell, const std::string &param,
char get_hexdigit(int i) { return std::string("0123456789ABCDEF").at(i); } 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] // [y][x][row][col]
const ChipInfoPOD &ci = *chip.chip_info; const ChipInfoPOD &ci = *ctx->chip_info;
const BitstreamInfoPOD &bi = *ci.bits_info; const BitstreamInfoPOD &bi = *ci.bits_info;
std::vector<std::vector<std::vector<std::vector<int8_t>>>> config; std::vector<std::vector<std::vector<std::vector<int8_t>>>> config;
config.resize(ci.height); config.resize(ci.height);
for (int y = 0; y < ci.height; y++) { for (int y = 0; y < ci.height; y++) {
config.at(y).resize(ci.width); config.at(y).resize(ci.width);
for (int x = 0; x < ci.width; x++) { 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 rows = bi.tiles_nonrouting[tile].rows;
int cols = bi.tiles_nonrouting[tile].cols; int cols = bi.tiles_nonrouting[tile].cols;
config.at(y).at(x).resize(rows, std::vector<int8_t>(cols)); config.at(y).at(x).resize(rows, std::vector<int8_t>(cols));
@ -114,7 +113,7 @@ void write_asc(const Design &design, std::ostream &out)
} }
out << ".comment from next-pnr" << std::endl; out << ".comment from next-pnr" << std::endl;
switch (chip.args.type) { switch (ctx->args.type) {
case ArchArgs::LP384: case ArchArgs::LP384:
out << ".device 384" << std::endl; out << ".device 384" << std::endl;
break; break;
@ -133,8 +132,8 @@ void write_asc(const Design &design, std::ostream &out)
assert(false); assert(false);
} }
// Set pips // Set pips
for (auto pip : chip.getPips()) { for (auto pip : ctx->getPips()) {
if (chip.pip_to_net[pip.index] != IdString()) { if (ctx->pip_to_net[pip.index] != IdString()) {
const PipInfoPOD &pi = ci.pip_data[pip.index]; const PipInfoPOD &pi = ci.pip_data[pip.index];
const SwitchInfoPOD &swi = bi.switches[pi.switch_index]; const SwitchInfoPOD &swi = bi.switches[pi.switch_index];
for (int i = 0; i < swi.num_bits; i++) { 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 // Set logic cell config
for (auto cell : design.cells) { for (auto cell : ctx->cells) {
BelId bel = cell.second->bel; BelId bel = cell.second->bel;
if (bel == BelId()) { if (bel == BelId()) {
std::cout << "Found unplaced cell " << cell.first std::cout << "Found unplaced cell " << cell.first
@ -206,15 +205,15 @@ void write_asc(const Design &design, std::ostream &out)
assert(iez != -1); assert(iez != -1);
bool input_en = false; 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()) || 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())) { IdString())) {
input_en = true; input_en = true;
} }
if (chip.args.type == ArchArgs::LP1K || if (ctx->args.type == ArchArgs::LP1K ||
chip.args.type == ArchArgs::HX1K) { ctx->args.type == ArchArgs::HX1K) {
set_config(ti, config.at(iey).at(iex), set_config(ti, config.at(iey).at(iex),
"IoCtrl.IE_" + std::to_string(iez), !input_en); "IoCtrl.IE_" + std::to_string(iez), !input_en);
set_config(ti, config.at(iey).at(iex), 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; int x = beli.x, y = beli.y;
const TileInfoPOD &ti_ramt = bi.tiles_nonrouting[TILE_RAMT]; const TileInfoPOD &ti_ramt = bi.tiles_nonrouting[TILE_RAMT];
const TileInfoPOD &ti_ramb = bi.tiles_nonrouting[TILE_RAMB]; const TileInfoPOD &ti_ramb = bi.tiles_nonrouting[TILE_RAMB];
if (!(chip.args.type == ArchArgs::LP1K || if (!(ctx->args.type == ArchArgs::LP1K ||
chip.args.type == ArchArgs::HX1K)) { ctx->args.type == ArchArgs::HX1K)) {
set_config(ti_ramb, config.at(y).at(x), "RamConfig.PowerUp", set_config(ti_ramb, config.at(y).at(x), "RamConfig.PowerUp",
true); true);
} }
@ -258,9 +257,9 @@ void write_asc(const Design &design, std::ostream &out)
} }
} }
// Set config bits in unused IO and RAM // Set config bits in unused IO and RAM
for (auto bel : chip.getBels()) { for (auto bel : ctx->getBels()) {
if (chip.bel_to_cell[bel.index] == IdString() && if (ctx->bel_to_cell[bel.index] == IdString() &&
chip.getBelType(bel) == TYPE_SB_IO) { ctx->getBelType(bel) == TYPE_SB_IO) {
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO]; const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO];
const BelInfoPOD &beli = ci.bel_data[bel.index]; const BelInfoPOD &beli = ci.bel_data[bel.index];
int x = beli.x, y = beli.y, z = beli.z; 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; int iex, iey, iez;
std::tie(iex, iey, iez) = ieren; std::tie(iex, iey, iez) = ieren;
if (iez != -1) { if (iez != -1) {
if (chip.args.type == ArchArgs::LP1K || if (ctx->args.type == ArchArgs::LP1K ||
chip.args.type == ArchArgs::HX1K) { ctx->args.type == ArchArgs::HX1K) {
set_config(ti, config.at(iey).at(iex), set_config(ti, config.at(iey).at(iex),
"IoCtrl.IE_" + std::to_string(iez), true); "IoCtrl.IE_" + std::to_string(iez), true);
set_config(ti, config.at(iey).at(iex), set_config(ti, config.at(iey).at(iex),
"IoCtrl.REN_" + std::to_string(iez), false); "IoCtrl.REN_" + std::to_string(iez), false);
} }
} }
} else if (chip.bel_to_cell[bel.index] == IdString() && } else if (ctx->bel_to_cell[bel.index] == IdString() &&
chip.getBelType(bel) == TYPE_ICESTORM_RAM) { ctx->getBelType(bel) == TYPE_ICESTORM_RAM) {
const BelInfoPOD &beli = ci.bel_data[bel.index]; const BelInfoPOD &beli = ci.bel_data[bel.index];
int x = beli.x, y = beli.y; int x = beli.x, y = beli.y;
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_RAMB]; const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_RAMB];
if ((chip.args.type == ArchArgs::LP1K || if ((ctx->args.type == ArchArgs::LP1K ||
chip.args.type == ArchArgs::HX1K)) { ctx->args.type == ArchArgs::HX1K)) {
set_config(ti, config.at(y).at(x), "RamConfig.PowerUp", true); 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 // Set other config bits
for (int y = 0; y < ci.height; y++) { for (int y = 0; y < ci.height; y++) {
for (int x = 0; x < ci.width; x++) { 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]; const TileInfoPOD &ti = bi.tiles_nonrouting[tile];
// set all ColBufCtrl bits (FIXME) // set all ColBufCtrl bits (FIXME)
bool setColBufCtrl = true; bool setColBufCtrl = true;
if (chip.args.type == ArchArgs::LP1K || if (ctx->args.type == ArchArgs::LP1K ||
chip.args.type == ArchArgs::HX1K) { ctx->args.type == ArchArgs::HX1K) {
if (tile == TILE_RAMB || tile == TILE_RAMT) { if (tile == TILE_RAMB || tile == TILE_RAMT) {
setColBufCtrl = (y == 3 || y == 5 || y == 11 || y == 13); setColBufCtrl = (y == 3 || y == 5 || y == 11 || y == 13);
} else { } else {
setColBufCtrl = (y == 4 || y == 5 || y == 12 || y == 13); setColBufCtrl = (y == 4 || y == 5 || y == 12 || y == 13);
} }
} else if (chip.args.type == ArchArgs::LP8K || } else if (ctx->args.type == ArchArgs::LP8K ||
chip.args.type == ArchArgs::HX8K) { ctx->args.type == ArchArgs::HX8K) {
setColBufCtrl = (y == 8 || y == 9 || y == 24 || y == 25); 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) { if (tile == TILE_LOGIC) {
setColBufCtrl = (y == 4 || y == 5 || y == 14 || y == 15 || setColBufCtrl = (y == 4 || y == 5 || y == 14 || y == 15 ||
y == 26 || y == 27); y == 26 || y == 27);
@ -338,7 +337,7 @@ void write_asc(const Design &design, std::ostream &out)
// Write config out // Write config out
for (int y = 0; y < ci.height; y++) { for (int y = 0; y < ci.height; y++) {
for (int x = 0; x < ci.width; x++) { 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) if (tile == TILE_NONE)
continue; continue;
switch (tile) { switch (tile) {
@ -372,7 +371,7 @@ void write_asc(const Design &design, std::ostream &out)
} }
// Write RAM init data // Write RAM init data
for (auto cell : design.cells) { for (auto cell : ctx->cells) {
if (cell.second->bel != BelId()) { if (cell.second->bel != BelId()) {
if (cell.second->type == "ICESTORM_RAM") { if (cell.second->type == "ICESTORM_RAM") {
const BelInfoPOD &beli = ci.bel_data[cell.second->bel.index]; 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 // Write symbols
const bool write_symbols = 1; const bool write_symbols = 1;
for (auto wire : chip.getWires()) { for (auto wire : ctx->getWires()) {
IdString net = chip.getWireNet(wire, false); IdString net = ctx->getWireNet(wire, false);
if (net != IdString()) if (net != IdString())
out << ".sym " << wire.index << " " << net << std::endl; out << ".sym " << wire.index << " " << net << std::endl;
} }

View File

@ -26,7 +26,7 @@
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
void write_asc(const Design &design, std::ostream &out); void write_asc(const Context *ctx, std::ostream &out);
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END

View File

@ -29,7 +29,7 @@ static void add_port(CellInfo *cell, IdString name, PortType dir)
cell->ports[name] = PortInfo{name, nullptr, 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; static int auto_idx = 0;
CellInfo *new_cell = new CellInfo(); CellInfo *new_cell = new CellInfo();

View File

@ -27,7 +27,7 @@ NEXTPNR_NAMESPACE_BEGIN
// Create a standard iCE40 cell and return it // Create a standard iCE40 cell and return it
// Name will be automatically assigned if not specified // 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()); IdString name = IdString());
// Return true if a cell is a LUT // Return true if a cell is a LUT

View File

@ -193,21 +193,20 @@ int main(int argc, char *argv[])
if (vm.count("package")) if (vm.count("package"))
chipArgs.package = vm["package"].as<std::string>(); chipArgs.package = vm["package"].as<std::string>();
Design design(chipArgs); Context ctx(chipArgs);
init_python(argv[0]); init_python(argv[0]);
python_export_global("design", design); python_export_global("ctx", ctx);
python_export_global("chip", design.chip);
if (vm.count("svg")) { if (vm.count("svg")) {
std::cout << "<svg xmlns=\"http://www.w3.org/2000/svg\" " std::cout << "<svg xmlns=\"http://www.w3.org/2000/svg\" "
"xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n"; "xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
for (auto bel : design.chip.getBels()) { for (auto bel : ctx.getBels()) {
std::cout << "<!-- " << design.chip.getBelName(bel) << " -->\n"; std::cout << "<!-- " << ctx.getBelName(bel) << " -->\n";
for (auto &el : design.chip.getBelGraphics(bel)) for (auto &el : ctx.getBelGraphics(bel))
svg_dump_el(el); svg_dump_el(el);
} }
std::cout << "<!-- Frame -->\n"; std::cout << "<!-- Frame -->\n";
for (auto &el : design.chip.getFrameGraphics()) for (auto &el : ctx.getFrameGraphics())
svg_dump_el(el); svg_dump_el(el);
std::cout << "</svg>\n"; std::cout << "</svg>\n";
} }
@ -216,15 +215,15 @@ int main(int argc, char *argv[])
std::string filename = vm["json"].as<std::string>(); std::string filename = vm["json"].as<std::string>();
std::istream *f = new std::ifstream(filename); std::istream *f = new std::ifstream(filename);
parse_json_file(f, filename, &design); parse_json_file(f, filename, &ctx);
if (vm.count("pcf")) { if (vm.count("pcf")) {
std::ifstream pcf(vm["pcf"].as<std::string>()); std::ifstream pcf(vm["pcf"].as<std::string>());
apply_pcf(&design, pcf); apply_pcf(&ctx, pcf);
} }
pack_design(&design); pack_design(&ctx);
print_utilisation(&design); print_utilisation(&ctx);
int seed = 1; int seed = 1;
if (vm.count("seed")) { if (vm.count("seed")) {
@ -234,15 +233,15 @@ int main(int argc, char *argv[])
} }
if (!vm.count("pack-only")) { if (!vm.count("pack-only")) {
place_design_sa(&design, seed); place_design_sa(&ctx, seed);
route_design(&design, verbose); route_design(&ctx, verbose);
} }
} }
if (vm.count("asc")) { if (vm.count("asc")) {
std::string filename = vm["asc"].as<std::string>(); std::string filename = vm["asc"].as<std::string>();
std::ofstream f(filename); std::ofstream f(filename);
write_asc(design, f); write_asc(&ctx, f);
} }
if (vm.count("run")) { if (vm.count("run")) {
@ -254,7 +253,7 @@ int main(int argc, char *argv[])
if (vm.count("gui")) { if (vm.count("gui")) {
QApplication a(argc, argv); QApplication a(argc, argv);
MainWindow w(&design); MainWindow w(&ctx);
w.show(); w.show();
rc = a.exec(); rc = a.exec();

View File

@ -28,18 +28,18 @@
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
// Pack LUTs and LUT-FF pairs // 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"); log_info("Packing LUT-FFs..\n");
std::unordered_set<IdString> packed_cells; std::unordered_set<IdString> packed_cells;
std::vector<CellInfo *> new_cells; std::vector<CellInfo *> new_cells;
for (auto cell : design->cells) { for (auto cell : ctx->cells) {
CellInfo *ci = cell.second; CellInfo *ci = cell.second;
log_info("cell '%s' is of type '%s'\n", ci->name.c_str(), log_info("cell '%s' is of type '%s'\n", ci->name.c_str(),
ci->type.c_str()); ci->type.c_str());
if (is_lut(ci)) { if (is_lut(ci)) {
CellInfo *packed = create_ice_cell(design, "ICESTORM_LC", CellInfo *packed = create_ice_cell(ctx, "ICESTORM_LC",
ci->name.str() + "_LC"); ci->name.str() + "_LC");
std::copy(ci->attrs.begin(), ci->attrs.end(), std::copy(ci->attrs.begin(), ci->attrs.end(),
std::inserter(packed->attrs, packed->attrs.begin())); std::inserter(packed->attrs, packed->attrs.begin()));
@ -62,7 +62,7 @@ static void pack_lut_lutffs(Design *design)
} else { } else {
lut_to_lc(ci, packed, false); lut_to_lc(ci, packed, false);
dff_to_lc(dff, packed, false); dff_to_lc(dff, packed, false);
design->nets.erase(o->name); ctx->nets.erase(o->name);
if (dff_bel != dff->attrs.end()) if (dff_bel != dff->attrs.end())
packed->attrs["BEL"] = dff_bel->second; packed->attrs["BEL"] = dff_bel->second;
packed_cells.insert(dff->name); packed_cells.insert(dff->name);
@ -77,25 +77,25 @@ static void pack_lut_lutffs(Design *design)
} }
} }
for (auto pcell : packed_cells) { for (auto pcell : packed_cells) {
design->cells.erase(pcell); ctx->cells.erase(pcell);
} }
for (auto ncell : new_cells) { for (auto ncell : new_cells) {
design->cells[ncell->name] = ncell; ctx->cells[ncell->name] = ncell;
} }
} }
// Pack FFs not packed as LUTFFs // 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"); log_info("Packing non-LUT FFs..\n");
std::unordered_set<IdString> packed_cells; std::unordered_set<IdString> packed_cells;
std::vector<CellInfo *> new_cells; std::vector<CellInfo *> new_cells;
for (auto cell : design->cells) { for (auto cell : ctx->cells) {
CellInfo *ci = cell.second; CellInfo *ci = cell.second;
if (is_ff(ci)) { if (is_ff(ci)) {
CellInfo *packed = create_ice_cell(design, "ICESTORM_LC", CellInfo *packed = create_ice_cell(ctx, "ICESTORM_LC",
ci->name.str() + "_DFFLC"); ci->name.str() + "_DFFLC");
std::copy(ci->attrs.begin(), ci->attrs.end(), std::copy(ci->attrs.begin(), ci->attrs.end(),
std::inserter(packed->attrs, packed->attrs.begin())); std::inserter(packed->attrs, packed->attrs.begin()));
@ -107,25 +107,25 @@ static void pack_nonlut_ffs(Design *design)
} }
} }
for (auto pcell : packed_cells) { for (auto pcell : packed_cells) {
design->cells.erase(pcell); ctx->cells.erase(pcell);
} }
for (auto ncell : new_cells) { for (auto ncell : new_cells) {
design->cells[ncell->name] = ncell; ctx->cells[ncell->name] = ncell;
} }
} }
// "Pack" RAMs // "Pack" RAMs
static void pack_ram(Design *design) static void pack_ram(Context *ctx)
{ {
log_info("Packing RAMs..\n"); log_info("Packing RAMs..\n");
std::unordered_set<IdString> packed_cells; std::unordered_set<IdString> packed_cells;
std::vector<CellInfo *> new_cells; std::vector<CellInfo *> new_cells;
for (auto cell : design->cells) { for (auto cell : ctx->cells) {
CellInfo *ci = cell.second; CellInfo *ci = cell.second;
if (is_ram(ci)) { if (is_ram(ci)) {
CellInfo *packed = create_ice_cell(design, "ICESTORM_RAM", CellInfo *packed = create_ice_cell(ctx, "ICESTORM_RAM",
ci->name.str() + "_RAM"); ci->name.str() + "_RAM");
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
new_cells.push_back(packed); new_cells.push_back(packed);
@ -153,10 +153,10 @@ static void pack_ram(Design *design)
} }
for (auto pcell : packed_cells) { for (auto pcell : packed_cells) {
design->cells.erase(pcell); ctx->cells.erase(pcell);
} }
for (auto ncell : new_cells) { 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) // Pack constants (simple implementation)
static void pack_constants(Design *design) static void pack_constants(Context *ctx)
{ {
log_info("Packing constants..\n"); 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"; gnd_cell->params["LUT_INIT"] = "0";
NetInfo *gnd_net = new NetInfo; NetInfo *gnd_net = new NetInfo;
gnd_net->name = "$PACKER_GND_NET"; gnd_net->name = "$PACKER_GND_NET";
gnd_net->driver.cell = gnd_cell; gnd_net->driver.cell = gnd_cell;
gnd_net->driver.port = "O"; 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"; vcc_cell->params["LUT_INIT"] = "1";
NetInfo *vcc_net = new NetInfo; NetInfo *vcc_net = new NetInfo;
vcc_net->name = "$PACKER_VCC_NET"; vcc_net->name = "$PACKER_VCC_NET";
@ -200,24 +200,24 @@ static void pack_constants(Design *design)
std::vector<IdString> dead_nets; std::vector<IdString> dead_nets;
for (auto net : design->nets) { for (auto net : ctx->nets) {
NetInfo *ni = net.second; NetInfo *ni = net.second;
if (ni->driver.cell != nullptr && ni->driver.cell->type == "GND") { if (ni->driver.cell != nullptr && ni->driver.cell->type == "GND") {
set_net_constant(ni, gnd_net, false); set_net_constant(ni, gnd_net, false);
design->cells[gnd_cell->name] = gnd_cell; ctx->cells[gnd_cell->name] = gnd_cell;
design->nets[gnd_net->name] = gnd_net; ctx->nets[gnd_net->name] = gnd_net;
dead_nets.push_back(net.first); dead_nets.push_back(net.first);
} else if (ni->driver.cell != nullptr && } else if (ni->driver.cell != nullptr &&
ni->driver.cell->type == "VCC") { ni->driver.cell->type == "VCC") {
set_net_constant(ni, vcc_net, true); set_net_constant(ni, vcc_net, true);
design->cells[vcc_cell->name] = vcc_cell; ctx->cells[vcc_cell->name] = vcc_cell;
design->nets[vcc_net->name] = vcc_net; ctx->nets[vcc_net->name] = vcc_net;
dead_nets.push_back(net.first); dead_nets.push_back(net.first);
} }
} }
for (auto dn : dead_nets) for (auto dn : dead_nets)
design->nets.erase(dn); ctx->nets.erase(dn);
} }
static bool is_nextpnr_iob(CellInfo *cell) static bool is_nextpnr_iob(CellInfo *cell)
@ -227,14 +227,14 @@ static bool is_nextpnr_iob(CellInfo *cell)
} }
// Pack IO buffers // Pack IO buffers
static void pack_io(Design *design) static void pack_io(Context *ctx)
{ {
std::unordered_set<IdString> packed_cells; std::unordered_set<IdString> packed_cells;
std::vector<CellInfo *> new_cells; std::vector<CellInfo *> new_cells;
log_info("Packing IOs..\n"); log_info("Packing IOs..\n");
for (auto cell : design->cells) { for (auto cell : ctx->cells) {
CellInfo *ci = cell.second; CellInfo *ci = cell.second;
if (is_nextpnr_iob(ci)) { if (is_nextpnr_iob(ci)) {
CellInfo *sb = nullptr; CellInfo *sb = nullptr;
@ -254,12 +254,12 @@ static void pack_io(Design *design)
ci->name.c_str()); ci->name.c_str());
NetInfo *net = sb->ports.at("PACKAGE_PIN").net; NetInfo *net = sb->ports.at("PACKAGE_PIN").net;
if (net != nullptr) { if (net != nullptr) {
design->nets.erase(net->name); ctx->nets.erase(net->name);
sb->ports.at("PACKAGE_PIN").net = nullptr; sb->ports.at("PACKAGE_PIN").net = nullptr;
} }
} else { } else {
// Create a SB_IO buffer // Create a SB_IO buffer
sb = create_ice_cell(design, "SB_IO"); sb = create_ice_cell(ctx, "SB_IO");
nxio_to_sb(ci, sb); nxio_to_sb(ci, sb);
new_cells.push_back(sb); new_cells.push_back(sb);
} }
@ -269,19 +269,19 @@ static void pack_io(Design *design)
} }
} }
for (auto pcell : packed_cells) { for (auto pcell : packed_cells) {
design->cells.erase(pcell); ctx->cells.erase(pcell);
} }
for (auto ncell : new_cells) { 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) bool is_cen)
{ {
std::string glb_name = net->name.str() + std::string("_$glb_") + std::string glb_name = net->name.str() + std::string("_$glb_") +
(is_reset ? "sr" : (is_cen ? "ce" : "clk")); (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; gb->ports["USER_SIGNAL_TO_GLOBAL_BUFFER"].net = net;
PortRef pr; PortRef pr;
pr.cell = gb; pr.cell = gb;
@ -293,7 +293,7 @@ static void insert_global(Design *design, NetInfo *net, bool is_reset,
NetInfo *glbnet = new NetInfo(); NetInfo *glbnet = new NetInfo();
glbnet->name = glb_name; glbnet->name = glb_name;
glbnet->driver = pr; glbnet->driver = pr;
design->nets[glbnet->name] = glbnet; ctx->nets[glbnet->name] = glbnet;
gb->ports["GLOBAL_BUFFER_OUTPUT"].net = glbnet; gb->ports["GLOBAL_BUFFER_OUTPUT"].net = glbnet;
std::vector<PortRef> keep_users; std::vector<PortRef> keep_users;
for (auto user : net->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; net->users = keep_users;
design->cells[gb->name] = gb; ctx->cells[gb->name] = gb;
} }
// Simple global promoter (clock only) // Simple global promoter (clock only)
static void promote_globals(Design *design) static void promote_globals(Context *ctx)
{ {
log_info("Promoting globals..\n"); log_info("Promoting globals..\n");
std::unordered_map<IdString, int> clock_count, reset_count, cen_count; std::unordered_map<IdString, int> clock_count, reset_count, cen_count;
for (auto net : design->nets) { for (auto net : ctx->nets) {
NetInfo *ni = net.second; NetInfo *ni = net.second;
if (ni->driver.cell != nullptr && !is_global_net(ni)) { if (ni->driver.cell != nullptr && !is_global_net(ni)) {
clock_count[net.first] = 0; 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 prom_globals = 0, prom_resets = 0, prom_cens = 0;
int gbs_available = 8; int gbs_available = 8;
for (auto cell : design->cells) for (auto cell : ctx->cells)
if (is_gbuf(cell.second)) if (is_gbuf(cell.second))
--gbs_available; --gbs_available;
while (prom_globals < gbs_available) { while (prom_globals < gbs_available) {
@ -358,24 +358,24 @@ static void promote_globals(Design *design)
return a.second < b.second; return a.second < b.second;
}); });
if (global_reset->second > global_clock->second && prom_resets < 4) { if (global_reset->second > global_clock->second && prom_resets < 4) {
NetInfo *rstnet = design->nets[global_reset->first]; NetInfo *rstnet = ctx->nets[global_reset->first];
insert_global(design, rstnet, true, false); insert_global(ctx, rstnet, true, false);
++prom_globals; ++prom_globals;
++prom_resets; ++prom_resets;
clock_count.erase(rstnet->name); clock_count.erase(rstnet->name);
reset_count.erase(rstnet->name); reset_count.erase(rstnet->name);
cen_count.erase(rstnet->name); cen_count.erase(rstnet->name);
} else if (global_cen->second > global_clock->second && prom_cens < 4) { } else if (global_cen->second > global_clock->second && prom_cens < 4) {
NetInfo *cennet = design->nets[global_cen->first]; NetInfo *cennet = ctx->nets[global_cen->first];
insert_global(design, cennet, false, true); insert_global(ctx, cennet, false, true);
++prom_globals; ++prom_globals;
++prom_cens; ++prom_cens;
clock_count.erase(cennet->name); clock_count.erase(cennet->name);
reset_count.erase(cennet->name); reset_count.erase(cennet->name);
cen_count.erase(cennet->name); cen_count.erase(cennet->name);
} else if (global_clock->second != 0) { } else if (global_clock->second != 0) {
NetInfo *clknet = design->nets[global_clock->first]; NetInfo *clknet = ctx->nets[global_clock->first];
insert_global(design, clknet, false, false); insert_global(ctx, clknet, false, false);
++prom_globals; ++prom_globals;
clock_count.erase(clknet->name); clock_count.erase(clknet->name);
reset_count.erase(clknet->name); reset_count.erase(clknet->name);
@ -387,14 +387,14 @@ static void promote_globals(Design *design)
} }
// Main pack function // Main pack function
void pack_design(Design *design) void pack_design(Context *ctx)
{ {
pack_constants(design); pack_constants(ctx);
promote_globals(design); promote_globals(ctx);
pack_io(design); pack_io(ctx);
pack_lut_lutffs(design); pack_lut_lutffs(ctx);
pack_nonlut_ffs(design); pack_nonlut_ffs(ctx);
pack_ram(design); pack_ram(ctx);
} }
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END

View File

@ -25,7 +25,7 @@
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
void pack_design(Design *design); void pack_design(Context *ctx);
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END

View File

@ -27,7 +27,7 @@ NEXTPNR_NAMESPACE_BEGIN
// Read a w // Read a w
// Apply PCF constraints to a pre-packing design // 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) if (!in)
log_error("failed to open PCF file"); log_error("failed to open PCF file");
@ -50,16 +50,16 @@ void apply_pcf(Design *design, std::istream &in)
args_end++; args_end++;
std::string cell = words.at(args_end); std::string cell = words.at(args_end);
std::string pin = words.at(args_end + 1); std::string pin = words.at(args_end + 1);
auto fnd_cell = design->cells.find(cell); auto fnd_cell = ctx->cells.find(cell);
if (fnd_cell == design->cells.end()) { if (fnd_cell == ctx->cells.end()) {
log_warning("unmatched pcf constraint %s\n", cell.c_str()); log_warning("unmatched pcf constraint %s\n", cell.c_str());
} else { } else {
BelId pin_bel = design->chip.getPackagePinBel(pin); BelId pin_bel = ctx->getPackagePinBel(pin);
if (pin_bel == BelId()) if (pin_bel == BelId())
log_error("package does not have a pin named %s\n", log_error("package does not have a pin named %s\n",
pin.c_str()); pin.c_str());
fnd_cell->second->attrs["BEL"] = 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(), log_info("constrained '%s' to bel '%s'\n", cell.c_str(),
fnd_cell->second->attrs["BEL"].c_str()); fnd_cell->second->attrs["BEL"].c_str());
} }

View File

@ -27,7 +27,7 @@
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
// Apply PCF constraints to a pre-packing design // 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 NEXTPNR_NAMESPACE_END