Merge branch 'refactor'
This commit is contained in:
commit
f30d477c81
@ -70,17 +70,15 @@ struct CellInfo
|
|||||||
std::unordered_map<IdString, IdString> pins;
|
std::unordered_map<IdString, IdString> pins;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Design
|
struct Context : Arch
|
||||||
{
|
{
|
||||||
struct Chip chip;
|
std::unordered_map<IdString, NetInfo *> nets;
|
||||||
|
std::unordered_map<IdString, CellInfo *> cells;
|
||||||
|
|
||||||
Design(ChipArgs 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
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ void IdString::initialize()
|
|||||||
void IdString::initialize_add(const char *s, int idx)
|
void IdString::initialize_add(const char *s, int idx)
|
||||||
{
|
{
|
||||||
assert(database_str_to_idx->count(s) == 0);
|
assert(database_str_to_idx->count(s) == 0);
|
||||||
assert(database_idx_to_str->size() == idx);
|
assert(int(database_idx_to_str->size()) == idx);
|
||||||
auto insert_rc = database_str_to_idx->insert({s, idx});
|
auto insert_rc = database_str_to_idx->insert({s, idx});
|
||||||
database_idx_to_str->push_back(&insert_rc.first->first);
|
database_idx_to_str->push_back(&insert_rc.first->first);
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ struct GraphicElement
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
#include "chip.h"
|
#include "arch.h"
|
||||||
#include "design.h"
|
#include "design.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -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();
|
||||||
Chip &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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,7 +140,7 @@ struct SAState
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Get the total estimated wirelength for a net
|
// Get the total estimated wirelength for a net
|
||||||
static float get_wirelength(Chip *chip, NetInfo *net)
|
static float get_wirelength(Arch *chip, NetInfo *net)
|
||||||
{
|
{
|
||||||
float wirelength = 0;
|
float wirelength = 0;
|
||||||
int driver_x = 0, driver_y = 0;
|
int driver_x = 0, driver_y = 0;
|
||||||
@ -174,22 +173,21 @@ static float get_wirelength(Chip *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();
|
||||||
Chip &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)
|
||||||
{
|
{
|
||||||
Chip &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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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, ChipArgs 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);
|
||||||
|
107
common/route.cc
107
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 = 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()));
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
179
dummy/arch.cc
Normal file
179
dummy/arch.cc
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
* nextpnr -- Next Generation Place and Route
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Clifford Wolf <clifford@clifford.at>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "nextpnr.h"
|
||||||
|
|
||||||
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
Arch::Arch(ArchArgs) {}
|
||||||
|
|
||||||
|
std::string Arch::getChipName() { return "Dummy"; }
|
||||||
|
|
||||||
|
void IdString::initialize_chip() {}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
|
BelId Arch::getBelByName(IdString name) const { return BelId(); }
|
||||||
|
|
||||||
|
IdString Arch::getBelName(BelId bel) const { return IdString(); }
|
||||||
|
|
||||||
|
void Arch::bindBel(BelId bel, IdString cell) {}
|
||||||
|
|
||||||
|
void Arch::unbindBel(BelId bel) {}
|
||||||
|
|
||||||
|
bool Arch::checkBelAvail(BelId bel) const { return false; }
|
||||||
|
|
||||||
|
IdString Arch::getBelCell(BelId bel, bool conflicting) const
|
||||||
|
{
|
||||||
|
return IdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<BelId> &Arch::getBels() const
|
||||||
|
{
|
||||||
|
static std::vector<BelId> ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<BelId> &Arch::getBelsByType(BelType type) const
|
||||||
|
{
|
||||||
|
static std::vector<BelId> ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
BelType Arch::getBelType(BelId bel) const { return BelType(); }
|
||||||
|
|
||||||
|
WireId Arch::getWireBelPin(BelId bel, PortPin pin) const { return WireId(); }
|
||||||
|
|
||||||
|
BelPin Arch::getBelPinUphill(WireId wire) const { return BelPin(); }
|
||||||
|
|
||||||
|
const std::vector<BelPin> &Arch::getBelPinsDownhill(WireId wire) const
|
||||||
|
{
|
||||||
|
static std::vector<BelPin> ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
|
WireId Arch::getWireByName(IdString name) const { return WireId(); }
|
||||||
|
|
||||||
|
IdString Arch::getWireName(WireId wire) const { return IdString(); }
|
||||||
|
|
||||||
|
void Arch::bindWire(WireId wire, IdString net) {}
|
||||||
|
|
||||||
|
void Arch::unbindWire(WireId wire) {}
|
||||||
|
|
||||||
|
bool Arch::checkWireAvail(WireId wire) const { return false; }
|
||||||
|
|
||||||
|
IdString Arch::getWireNet(WireId wire, bool conflicting) const
|
||||||
|
{
|
||||||
|
return IdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<WireId> &Arch::getWires() const
|
||||||
|
{
|
||||||
|
static std::vector<WireId> ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
|
PipId Arch::getPipByName(IdString name) const { return PipId(); }
|
||||||
|
|
||||||
|
IdString Arch::getPipName(PipId pip) const { return IdString(); }
|
||||||
|
|
||||||
|
void Arch::bindPip(PipId pip, IdString net) {}
|
||||||
|
|
||||||
|
void Arch::unbindPip(PipId pip) {}
|
||||||
|
|
||||||
|
bool Arch::checkPipAvail(PipId pip) const { return false; }
|
||||||
|
|
||||||
|
IdString Arch::getPipNet(PipId pip, bool conflicting) const
|
||||||
|
{
|
||||||
|
return IdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<PipId> &Arch::getPips() const
|
||||||
|
{
|
||||||
|
static std::vector<PipId> ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
WireId Arch::getPipSrcWire(PipId pip) const { return WireId(); }
|
||||||
|
|
||||||
|
WireId Arch::getPipDstWire(PipId pip) const { return WireId(); }
|
||||||
|
|
||||||
|
DelayInfo Arch::getPipDelay(PipId pip) const { return DelayInfo(); }
|
||||||
|
|
||||||
|
const std::vector<PipId> &Arch::getPipsDownhill(WireId wire) const
|
||||||
|
{
|
||||||
|
static std::vector<PipId> ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<PipId> &Arch::getPipsUphill(WireId wire) const
|
||||||
|
{
|
||||||
|
static std::vector<PipId> ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<PipId> &Arch::getWireAliases(WireId wire) const
|
||||||
|
{
|
||||||
|
static std::vector<PipId> ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
|
bool Arch::estimatePosition(BelId bel, int &x, int &y) const
|
||||||
|
{
|
||||||
|
x = 0.0;
|
||||||
|
y = 0.0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
delay_t Arch::estimateDelay(WireId src, WireId dst) const { return 0.0; }
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
|
std::vector<GraphicElement> Arch::getFrameGraphics() const
|
||||||
|
{
|
||||||
|
static std::vector<GraphicElement> ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<GraphicElement> Arch::getBelGraphics(BelId bel) const
|
||||||
|
{
|
||||||
|
static std::vector<GraphicElement> ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<GraphicElement> Arch::getWireGraphics(WireId wire) const
|
||||||
|
{
|
||||||
|
static std::vector<GraphicElement> ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<GraphicElement> Arch::getPipGraphics(PipId pip) const
|
||||||
|
{
|
||||||
|
static std::vector<GraphicElement> ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
NEXTPNR_NAMESPACE_END
|
@ -21,7 +21,7 @@
|
|||||||
#define CHIP_H
|
#define CHIP_H
|
||||||
|
|
||||||
#ifndef NEXTPNR_H
|
#ifndef NEXTPNR_H
|
||||||
#error Include "chip.h" via "nextpnr.h" only.
|
#error Include "arch.h" via "nextpnr.h" only.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
@ -63,15 +63,13 @@ struct BelPin
|
|||||||
PortPin pin;
|
PortPin pin;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ChipArgs
|
struct ArchArgs
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string getChipName(ChipArgs id);
|
struct Arch
|
||||||
|
|
||||||
struct Chip
|
|
||||||
{
|
{
|
||||||
Chip(ChipArgs args);
|
Arch(ArchArgs args);
|
||||||
|
|
||||||
std::string getChipName();
|
std::string getChipName();
|
||||||
|
|
@ -21,14 +21,8 @@
|
|||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
179
dummy/chip.cc
179
dummy/chip.cc
@ -1,179 +0,0 @@
|
|||||||
/*
|
|
||||||
* nextpnr -- Next Generation Place and Route
|
|
||||||
*
|
|
||||||
* Copyright (C) 2018 Clifford Wolf <clifford@clifford.at>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include "nextpnr.h"
|
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
Chip::Chip(ChipArgs) {}
|
|
||||||
|
|
||||||
std::string Chip::getChipName() { return "Dummy"; }
|
|
||||||
|
|
||||||
void IdString::initialize_chip() {}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
|
|
||||||
BelId Chip::getBelByName(IdString name) const { return BelId(); }
|
|
||||||
|
|
||||||
IdString Chip::getBelName(BelId bel) const { return IdString(); }
|
|
||||||
|
|
||||||
void Chip::bindBel(BelId bel, IdString cell) {}
|
|
||||||
|
|
||||||
void Chip::unbindBel(BelId bel) {}
|
|
||||||
|
|
||||||
bool Chip::checkBelAvail(BelId bel) const { return false; }
|
|
||||||
|
|
||||||
IdString Chip::getBelCell(BelId bel, bool conflicting) const
|
|
||||||
{
|
|
||||||
return IdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<BelId> &Chip::getBels() const
|
|
||||||
{
|
|
||||||
static std::vector<BelId> ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<BelId> &Chip::getBelsByType(BelType type) const
|
|
||||||
{
|
|
||||||
static std::vector<BelId> ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
BelType Chip::getBelType(BelId bel) const { return BelType(); }
|
|
||||||
|
|
||||||
WireId Chip::getWireBelPin(BelId bel, PortPin pin) const { return WireId(); }
|
|
||||||
|
|
||||||
BelPin Chip::getBelPinUphill(WireId wire) const { return BelPin(); }
|
|
||||||
|
|
||||||
const std::vector<BelPin> &Chip::getBelPinsDownhill(WireId wire) const
|
|
||||||
{
|
|
||||||
static std::vector<BelPin> ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
|
|
||||||
WireId Chip::getWireByName(IdString name) const { return WireId(); }
|
|
||||||
|
|
||||||
IdString Chip::getWireName(WireId wire) const { return IdString(); }
|
|
||||||
|
|
||||||
void Chip::bindWire(WireId wire, IdString net) {}
|
|
||||||
|
|
||||||
void Chip::unbindWire(WireId wire) {}
|
|
||||||
|
|
||||||
bool Chip::checkWireAvail(WireId wire) const { return false; }
|
|
||||||
|
|
||||||
IdString Chip::getWireNet(WireId wire, bool conflicting) const
|
|
||||||
{
|
|
||||||
return IdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<WireId> &Chip::getWires() const
|
|
||||||
{
|
|
||||||
static std::vector<WireId> ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
|
|
||||||
PipId Chip::getPipByName(IdString name) const { return PipId(); }
|
|
||||||
|
|
||||||
IdString Chip::getPipName(PipId pip) const { return IdString(); }
|
|
||||||
|
|
||||||
void Chip::bindPip(PipId pip, IdString net) {}
|
|
||||||
|
|
||||||
void Chip::unbindPip(PipId pip) {}
|
|
||||||
|
|
||||||
bool Chip::checkPipAvail(PipId pip) const { return false; }
|
|
||||||
|
|
||||||
IdString Chip::getPipNet(PipId pip, bool conflicting) const
|
|
||||||
{
|
|
||||||
return IdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<PipId> &Chip::getPips() const
|
|
||||||
{
|
|
||||||
static std::vector<PipId> ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
WireId Chip::getPipSrcWire(PipId pip) const { return WireId(); }
|
|
||||||
|
|
||||||
WireId Chip::getPipDstWire(PipId pip) const { return WireId(); }
|
|
||||||
|
|
||||||
DelayInfo Chip::getPipDelay(PipId pip) const { return DelayInfo(); }
|
|
||||||
|
|
||||||
const std::vector<PipId> &Chip::getPipsDownhill(WireId wire) const
|
|
||||||
{
|
|
||||||
static std::vector<PipId> ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<PipId> &Chip::getPipsUphill(WireId wire) const
|
|
||||||
{
|
|
||||||
static std::vector<PipId> ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<PipId> &Chip::getWireAliases(WireId wire) const
|
|
||||||
{
|
|
||||||
static std::vector<PipId> ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
|
|
||||||
bool Chip::estimatePosition(BelId bel, int &x, int &y) const
|
|
||||||
{
|
|
||||||
x = 0.0;
|
|
||||||
y = 0.0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
delay_t Chip::estimateDelay(WireId src, WireId dst) const { return 0.0; }
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
|
|
||||||
std::vector<GraphicElement> Chip::getFrameGraphics() const
|
|
||||||
{
|
|
||||||
static std::vector<GraphicElement> ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<GraphicElement> Chip::getBelGraphics(BelId bel) const
|
|
||||||
{
|
|
||||||
static std::vector<GraphicElement> ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<GraphicElement> Chip::getWireGraphics(WireId wire) const
|
|
||||||
{
|
|
||||||
static std::vector<GraphicElement> ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<GraphicElement> Chip::getPipGraphics(PipId pip) const
|
|
||||||
{
|
|
||||||
static std::vector<GraphicElement> ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
|
@ -27,10 +27,10 @@ USING_NEXTPNR_NAMESPACE
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
Design design(ChipArgs{});
|
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();
|
||||||
|
@ -23,6 +23,6 @@
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
void arch_wrap_python() { class_<ChipArgs>("ChipArgs"); }
|
void arch_wrap_python() { class_<ArchArgs>("ArchArgs"); }
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -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,8 +547,8 @@ 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,
|
||||||
&cell->params, paramid);
|
paramid);
|
||||||
}
|
}
|
||||||
|
|
||||||
attr_node = cell_node->data_dict.at("attributes");
|
attr_node = cell_node->data_dict.at("attributes");
|
||||||
@ -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;
|
||||||
@ -741,10 +741,9 @@ void json_import(Design *design, string modname, JsonNode *node)
|
|||||||
netnames.resize(netid + 1);
|
netnames.resize(netid + 1);
|
||||||
netnames.at(netid) =
|
netnames.at(netid) =
|
||||||
basename +
|
basename +
|
||||||
(num_bits == 1
|
(num_bits == 1 ? "" : std::string("[") +
|
||||||
? ""
|
std::to_string(i) +
|
||||||
: std::string("[") + std::to_string(i) +
|
std::string("]"));
|
||||||
std::string("]"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -763,7 +762,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 +779,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
|
||||||
@ -793,10 +792,9 @@ struct JsonFrontend
|
|||||||
// JsonFrontend() : Frontend("json", "read JSON file") { }
|
// JsonFrontend() : Frontend("json", "read JSON file") { }
|
||||||
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, Context *ctx)
|
||||||
Design *design)
|
|
||||||
{
|
{
|
||||||
// log_header(design, "Executing JSON frontend.\n");
|
// log_header(ctx, "Executing JSON frontend.\n");
|
||||||
|
|
||||||
JsonNode root(*f);
|
JsonNode root(*f);
|
||||||
|
|
||||||
@ -810,17 +808,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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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())));
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,10 +78,10 @@ PortPin portPinFromId(IdString id)
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
Chip::Chip(ChipArgs args) : args(args)
|
Arch::Arch(ArchArgs args) : args(args)
|
||||||
{
|
{
|
||||||
#ifdef ICE40_HX1K_ONLY
|
#ifdef ICE40_HX1K_ONLY
|
||||||
if (args.type == ChipArgs::HX1K) {
|
if (args.type == ArchArgs::HX1K) {
|
||||||
chip_info =
|
chip_info =
|
||||||
reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_1k)
|
reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_1k)
|
||||||
->get();
|
->get();
|
||||||
@ -89,19 +89,19 @@ Chip::Chip(ChipArgs args) : args(args)
|
|||||||
log_error("Unsupported iCE40 chip type.\n");
|
log_error("Unsupported iCE40 chip type.\n");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (args.type == ChipArgs::LP384) {
|
if (args.type == ArchArgs::LP384) {
|
||||||
chip_info =
|
chip_info =
|
||||||
reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_384)
|
reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_384)
|
||||||
->get();
|
->get();
|
||||||
} else if (args.type == ChipArgs::LP1K || args.type == ChipArgs::HX1K) {
|
} else if (args.type == ArchArgs::LP1K || args.type == ArchArgs::HX1K) {
|
||||||
chip_info =
|
chip_info =
|
||||||
reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_1k)
|
reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_1k)
|
||||||
->get();
|
->get();
|
||||||
} else if (args.type == ChipArgs::UP5K) {
|
} else if (args.type == ArchArgs::UP5K) {
|
||||||
chip_info =
|
chip_info =
|
||||||
reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_5k)
|
reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_5k)
|
||||||
->get();
|
->get();
|
||||||
} else if (args.type == ChipArgs::LP8K || args.type == ChipArgs::HX8K) {
|
} else if (args.type == ArchArgs::LP8K || args.type == ArchArgs::HX8K) {
|
||||||
chip_info =
|
chip_info =
|
||||||
reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_8k)
|
reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_8k)
|
||||||
->get();
|
->get();
|
||||||
@ -128,26 +128,26 @@ Chip::Chip(ChipArgs args) : args(args)
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
std::string Chip::getChipName()
|
std::string Arch::getChipName()
|
||||||
{
|
{
|
||||||
#ifdef ICE40_HX1K_ONLY
|
#ifdef ICE40_HX1K_ONLY
|
||||||
if (args.type == ChipArgs::HX1K) {
|
if (args.type == ArchArgs::HX1K) {
|
||||||
return "Lattice LP1K";
|
return "Lattice LP1K";
|
||||||
} else {
|
} else {
|
||||||
log_error("Unsupported iCE40 chip type.\n");
|
log_error("Unsupported iCE40 chip type.\n");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (args.type == ChipArgs::LP384) {
|
if (args.type == ArchArgs::LP384) {
|
||||||
return "Lattice LP384";
|
return "Lattice LP384";
|
||||||
} else if (args.type == ChipArgs::LP1K) {
|
} else if (args.type == ArchArgs::LP1K) {
|
||||||
return "Lattice LP1K";
|
return "Lattice LP1K";
|
||||||
} else if (args.type == ChipArgs::HX1K) {
|
} else if (args.type == ArchArgs::HX1K) {
|
||||||
return "Lattice HX1K";
|
return "Lattice HX1K";
|
||||||
} else if (args.type == ChipArgs::UP5K) {
|
} else if (args.type == ArchArgs::UP5K) {
|
||||||
return "Lattice UP5K";
|
return "Lattice UP5K";
|
||||||
} else if (args.type == ChipArgs::LP8K) {
|
} else if (args.type == ArchArgs::LP8K) {
|
||||||
return "Lattice LP8K";
|
return "Lattice LP8K";
|
||||||
} else if (args.type == ChipArgs::HX8K) {
|
} else if (args.type == ArchArgs::HX8K) {
|
||||||
return "Lattice HX8K";
|
return "Lattice HX8K";
|
||||||
} else {
|
} else {
|
||||||
log_error("Unknown chip\n");
|
log_error("Unknown chip\n");
|
||||||
@ -157,7 +157,7 @@ std::string Chip::getChipName()
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
BelId Chip::getBelByName(IdString name) const
|
BelId Arch::getBelByName(IdString name) const
|
||||||
{
|
{
|
||||||
BelId ret;
|
BelId ret;
|
||||||
|
|
||||||
@ -173,7 +173,7 @@ BelId Chip::getBelByName(IdString name) const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
BelRange Chip::getBelsAtSameTile(BelId bel) const
|
BelRange Arch::getBelsAtSameTile(BelId bel) const
|
||||||
{
|
{
|
||||||
BelRange br;
|
BelRange br;
|
||||||
assert(bel != BelId());
|
assert(bel != BelId());
|
||||||
@ -193,7 +193,7 @@ BelRange Chip::getBelsAtSameTile(BelId bel) const
|
|||||||
return br;
|
return br;
|
||||||
}
|
}
|
||||||
|
|
||||||
WireId Chip::getWireBelPin(BelId bel, PortPin pin) const
|
WireId Arch::getWireBelPin(BelId bel, PortPin pin) const
|
||||||
{
|
{
|
||||||
WireId ret;
|
WireId ret;
|
||||||
|
|
||||||
@ -214,7 +214,7 @@ WireId Chip::getWireBelPin(BelId bel, PortPin pin) const
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
WireId Chip::getWireByName(IdString name) const
|
WireId Arch::getWireByName(IdString name) const
|
||||||
{
|
{
|
||||||
WireId ret;
|
WireId ret;
|
||||||
|
|
||||||
@ -232,7 +232,7 @@ WireId Chip::getWireByName(IdString name) const
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
PipId Chip::getPipByName(IdString name) const
|
PipId Arch::getPipByName(IdString name) const
|
||||||
{
|
{
|
||||||
PipId ret;
|
PipId ret;
|
||||||
|
|
||||||
@ -251,7 +251,7 @@ PipId Chip::getPipByName(IdString name) const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
IdString Chip::getPipName(PipId pip) const
|
IdString Arch::getPipName(PipId pip) const
|
||||||
{
|
{
|
||||||
assert(pip != PipId());
|
assert(pip != PipId());
|
||||||
|
|
||||||
@ -272,7 +272,7 @@ IdString Chip::getPipName(PipId pip) const
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
BelId Chip::getPackagePinBel(const std::string &pin) const
|
BelId Arch::getPackagePinBel(const std::string &pin) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < package_info->num_pins; i++) {
|
for (int i = 0; i < package_info->num_pins; i++) {
|
||||||
if (package_info->pins[i].name.get() == pin) {
|
if (package_info->pins[i].name.get() == pin) {
|
||||||
@ -284,7 +284,7 @@ BelId Chip::getPackagePinBel(const std::string &pin) const
|
|||||||
return BelId();
|
return BelId();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Chip::getBelPackagePin(BelId bel) const
|
std::string Arch::getBelPackagePin(BelId bel) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < package_info->num_pins; i++) {
|
for (int i = 0; i < package_info->num_pins; i++) {
|
||||||
if (package_info->pins[i].bel_index == bel.index) {
|
if (package_info->pins[i].bel_index == bel.index) {
|
||||||
@ -295,7 +295,7 @@ std::string Chip::getBelPackagePin(BelId bel) const
|
|||||||
}
|
}
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
bool Chip::estimatePosition(BelId bel, int &x, int &y) const
|
bool Arch::estimatePosition(BelId bel, int &x, int &y) const
|
||||||
{
|
{
|
||||||
assert(bel != BelId());
|
assert(bel != BelId());
|
||||||
x = chip_info->bel_data[bel.index].x;
|
x = chip_info->bel_data[bel.index].x;
|
||||||
@ -304,7 +304,7 @@ bool Chip::estimatePosition(BelId bel, int &x, int &y) const
|
|||||||
return chip_info->bel_data[bel.index].type != TYPE_SB_GB;
|
return chip_info->bel_data[bel.index].type != TYPE_SB_GB;
|
||||||
}
|
}
|
||||||
|
|
||||||
delay_t Chip::estimateDelay(WireId src, WireId dst) const
|
delay_t Arch::estimateDelay(WireId src, WireId dst) const
|
||||||
{
|
{
|
||||||
assert(src != WireId());
|
assert(src != WireId());
|
||||||
delay_t x1 = chip_info->wire_data[src.index].x;
|
delay_t x1 = chip_info->wire_data[src.index].x;
|
||||||
@ -319,7 +319,7 @@ delay_t Chip::estimateDelay(WireId src, WireId dst) const
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
std::vector<GraphicElement> Chip::getFrameGraphics() const
|
std::vector<GraphicElement> Arch::getFrameGraphics() const
|
||||||
{
|
{
|
||||||
std::vector<GraphicElement> ret;
|
std::vector<GraphicElement> ret;
|
||||||
|
|
||||||
@ -336,7 +336,7 @@ std::vector<GraphicElement> Chip::getFrameGraphics() const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<GraphicElement> Chip::getBelGraphics(BelId bel) const
|
std::vector<GraphicElement> Arch::getBelGraphics(BelId bel) const
|
||||||
{
|
{
|
||||||
std::vector<GraphicElement> ret;
|
std::vector<GraphicElement> ret;
|
||||||
|
|
||||||
@ -402,14 +402,14 @@ std::vector<GraphicElement> Chip::getBelGraphics(BelId bel) const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<GraphicElement> Chip::getWireGraphics(WireId wire) const
|
std::vector<GraphicElement> Arch::getWireGraphics(WireId wire) const
|
||||||
{
|
{
|
||||||
std::vector<GraphicElement> ret;
|
std::vector<GraphicElement> ret;
|
||||||
// FIXME
|
// FIXME
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<GraphicElement> Chip::getPipGraphics(PipId pip) const
|
std::vector<GraphicElement> Arch::getPipGraphics(PipId pip) const
|
||||||
{
|
{
|
||||||
std::vector<GraphicElement> ret;
|
std::vector<GraphicElement> ret;
|
||||||
// FIXME
|
// FIXME
|
@ -21,7 +21,7 @@
|
|||||||
#define CHIP_H
|
#define CHIP_H
|
||||||
|
|
||||||
#ifndef NEXTPNR_H
|
#ifndef NEXTPNR_H
|
||||||
#error Include "chip.h" via "nextpnr.h" only.
|
#error Include "arch.h" via "nextpnr.h" only.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
@ -443,7 +443,7 @@ struct PipRange
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
struct ChipArgs
|
struct ArchArgs
|
||||||
{
|
{
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -458,7 +458,7 @@ struct ChipArgs
|
|||||||
std::string package;
|
std::string package;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Chip
|
struct Arch
|
||||||
{
|
{
|
||||||
const ChipInfoPOD *chip_info;
|
const ChipInfoPOD *chip_info;
|
||||||
const PackageInfoPOD *package_info;
|
const PackageInfoPOD *package_info;
|
||||||
@ -471,13 +471,14 @@ struct Chip
|
|||||||
std::vector<IdString> wire_to_net;
|
std::vector<IdString> wire_to_net;
|
||||||
std::vector<IdString> pip_to_net;
|
std::vector<IdString> pip_to_net;
|
||||||
std::vector<IdString> switches_locked;
|
std::vector<IdString> switches_locked;
|
||||||
Chip(ChipArgs args);
|
|
||||||
|
|
||||||
ChipArgs args;
|
ArchArgs args;
|
||||||
// -------------------------------------------------
|
Arch(ArchArgs args);
|
||||||
|
|
||||||
std::string getChipName();
|
std::string getChipName();
|
||||||
|
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
BelId getBelByName(IdString name) const;
|
BelId getBelByName(IdString name) const;
|
||||||
|
|
||||||
IdString getBelName(BelId bel) const
|
IdString getBelName(BelId bel) const
|
||||||
@ -641,7 +642,7 @@ struct Chip
|
|||||||
bool checkPipAvail(PipId pip) const
|
bool checkPipAvail(PipId pip) const
|
||||||
{
|
{
|
||||||
assert(pip != PipId());
|
assert(pip != PipId());
|
||||||
if (args.type == ChipArgs::UP5K) {
|
if (args.type == ArchArgs::UP5K) {
|
||||||
int x = chip_info->pip_data[pip.index].x;
|
int x = chip_info->pip_data[pip.index].x;
|
||||||
if (x == 0 || x == (chip_info->width - 1))
|
if (x == 0 || x == (chip_info->width - 1))
|
||||||
return false;
|
return false;
|
||||||
@ -746,8 +747,7 @@ NEXTPNR_NAMESPACE_END
|
|||||||
namespace std {
|
namespace std {
|
||||||
template <> struct hash<NEXTPNR_NAMESPACE_PREFIX BelType>
|
template <> struct hash<NEXTPNR_NAMESPACE_PREFIX BelType>
|
||||||
{
|
{
|
||||||
std::size_t operator()(NEXTPNR_NAMESPACE_PREFIX BelType bt) const
|
std::size_t operator()(NEXTPNR_NAMESPACE_PREFIX BelType bt) const noexcept
|
||||||
noexcept
|
|
||||||
{
|
{
|
||||||
return std::hash<int>()(int(bt));
|
return std::hash<int>()(int(bt));
|
||||||
}
|
}
|
@ -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 Chip &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 Chip &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;
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -23,9 +23,9 @@
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
inline TileType tile_at(const Chip &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 ¶m,
|
|||||||
|
|
||||||
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 Chip &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,27 +113,27 @@ 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 ChipArgs::LP384:
|
case ArchArgs::LP384:
|
||||||
out << ".device 384" << std::endl;
|
out << ".device 384" << std::endl;
|
||||||
break;
|
break;
|
||||||
case ChipArgs::HX1K:
|
case ArchArgs::HX1K:
|
||||||
case ChipArgs::LP1K:
|
case ArchArgs::LP1K:
|
||||||
out << ".device 1k" << std::endl;
|
out << ".device 1k" << std::endl;
|
||||||
break;
|
break;
|
||||||
case ChipArgs::HX8K:
|
case ArchArgs::HX8K:
|
||||||
case ChipArgs::LP8K:
|
case ArchArgs::LP8K:
|
||||||
out << ".device 8k" << std::endl;
|
out << ".device 8k" << std::endl;
|
||||||
break;
|
break;
|
||||||
case ChipArgs::UP5K:
|
case ArchArgs::UP5K:
|
||||||
out << ".device 5k" << std::endl;
|
out << ".device 5k" << std::endl;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
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 == ChipArgs::LP1K ||
|
if (ctx->args.type == ArchArgs::LP1K ||
|
||||||
chip.args.type == ChipArgs::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 == ChipArgs::LP1K ||
|
if (!(ctx->args.type == ArchArgs::LP1K ||
|
||||||
chip.args.type == ChipArgs::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 == ChipArgs::LP1K ||
|
if (ctx->args.type == ArchArgs::LP1K ||
|
||||||
chip.args.type == ChipArgs::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 == ChipArgs::LP1K ||
|
if ((ctx->args.type == ArchArgs::LP1K ||
|
||||||
chip.args.type == ChipArgs::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 == ChipArgs::LP1K ||
|
if (ctx->args.type == ArchArgs::LP1K ||
|
||||||
chip.args.type == ChipArgs::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 == ChipArgs::LP8K ||
|
} else if (ctx->args.type == ArchArgs::LP8K ||
|
||||||
chip.args.type == ChipArgs::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 == ChipArgs::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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -134,56 +134,56 @@ int main(int argc, char *argv[])
|
|||||||
verbose = true;
|
verbose = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChipArgs chipArgs;
|
ArchArgs chipArgs;
|
||||||
|
|
||||||
if (vm.count("lp384")) {
|
if (vm.count("lp384")) {
|
||||||
if (chipArgs.type != ChipArgs::NONE)
|
if (chipArgs.type != ArchArgs::NONE)
|
||||||
goto help;
|
goto help;
|
||||||
chipArgs.type = ChipArgs::LP384;
|
chipArgs.type = ArchArgs::LP384;
|
||||||
chipArgs.package = "qn32";
|
chipArgs.package = "qn32";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.count("lp1k")) {
|
if (vm.count("lp1k")) {
|
||||||
if (chipArgs.type != ChipArgs::NONE)
|
if (chipArgs.type != ArchArgs::NONE)
|
||||||
goto help;
|
goto help;
|
||||||
chipArgs.type = ChipArgs::LP1K;
|
chipArgs.type = ArchArgs::LP1K;
|
||||||
chipArgs.package = "tq144";
|
chipArgs.package = "tq144";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.count("lp8k")) {
|
if (vm.count("lp8k")) {
|
||||||
if (chipArgs.type != ChipArgs::NONE)
|
if (chipArgs.type != ArchArgs::NONE)
|
||||||
goto help;
|
goto help;
|
||||||
chipArgs.type = ChipArgs::LP8K;
|
chipArgs.type = ArchArgs::LP8K;
|
||||||
chipArgs.package = "ct256";
|
chipArgs.package = "ct256";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.count("hx1k")) {
|
if (vm.count("hx1k")) {
|
||||||
if (chipArgs.type != ChipArgs::NONE)
|
if (chipArgs.type != ArchArgs::NONE)
|
||||||
goto help;
|
goto help;
|
||||||
chipArgs.type = ChipArgs::HX1K;
|
chipArgs.type = ArchArgs::HX1K;
|
||||||
chipArgs.package = "tq144";
|
chipArgs.package = "tq144";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.count("hx8k")) {
|
if (vm.count("hx8k")) {
|
||||||
if (chipArgs.type != ChipArgs::NONE)
|
if (chipArgs.type != ArchArgs::NONE)
|
||||||
goto help;
|
goto help;
|
||||||
chipArgs.type = ChipArgs::HX8K;
|
chipArgs.type = ArchArgs::HX8K;
|
||||||
chipArgs.package = "ct256";
|
chipArgs.package = "ct256";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.count("up5k")) {
|
if (vm.count("up5k")) {
|
||||||
if (chipArgs.type != ChipArgs::NONE)
|
if (chipArgs.type != ArchArgs::NONE)
|
||||||
goto help;
|
goto help;
|
||||||
chipArgs.type = ChipArgs::UP5K;
|
chipArgs.type = ArchArgs::UP5K;
|
||||||
chipArgs.package = "sg48";
|
chipArgs.package = "sg48";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chipArgs.type == ChipArgs::NONE) {
|
if (chipArgs.type == ArchArgs::NONE) {
|
||||||
chipArgs.type = ChipArgs::HX1K;
|
chipArgs.type = ArchArgs::HX1K;
|
||||||
chipArgs.package = "tq144";
|
chipArgs.package = "tq144";
|
||||||
}
|
}
|
||||||
#ifdef ICE40_HX1K_ONLY
|
#ifdef ICE40_HX1K_ONLY
|
||||||
if (chipArgs.type != ChipArgs::HX1K) {
|
if (chipArgs.type != ArchArgs::HX1K) {
|
||||||
std::cout << "This version of nextpnr-ice40 is built with HX1K-support "
|
std::cout << "This version of nextpnr-ice40 is built with HX1K-support "
|
||||||
"only.\n";
|
"only.\n";
|
||||||
return 1;
|
return 1;
|
||||||
@ -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();
|
||||||
|
104
ice40/pack.cc
104
ice40/pack.cc
@ -28,19 +28,19 @@
|
|||||||
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 =
|
||||||
ci->name.str() + "_LC");
|
create_ice_cell(ctx, "ICESTORM_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()));
|
||||||
packed_cells.insert(ci->name);
|
packed_cells.insert(ci->name);
|
||||||
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
11
ice40/pcf.cc
11
ice40/pcf.cc
@ -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,15 @@ 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"] = ctx->getBelName(pin_bel).str();
|
||||||
design->chip.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());
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -25,16 +25,16 @@ NEXTPNR_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
void arch_wrap_python()
|
void arch_wrap_python()
|
||||||
{
|
{
|
||||||
class_<ChipArgs>("ChipArgs").def_readwrite("type", &ChipArgs::type);
|
class_<ArchArgs>("ArchArgs").def_readwrite("type", &ArchArgs::type);
|
||||||
|
|
||||||
enum_<decltype(std::declval<ChipArgs>().type)>("iCE40Type")
|
enum_<decltype(std::declval<ArchArgs>().type)>("iCE40Type")
|
||||||
.value("NONE", ChipArgs::NONE)
|
.value("NONE", ArchArgs::NONE)
|
||||||
.value("LP384", ChipArgs::LP384)
|
.value("LP384", ArchArgs::LP384)
|
||||||
.value("LP1K", ChipArgs::LP1K)
|
.value("LP1K", ArchArgs::LP1K)
|
||||||
.value("LP8K", ChipArgs::LP8K)
|
.value("LP8K", ArchArgs::LP8K)
|
||||||
.value("HX1K", ChipArgs::HX1K)
|
.value("HX1K", ArchArgs::HX1K)
|
||||||
.value("HX8K", ChipArgs::HX8K)
|
.value("HX8K", ArchArgs::HX8K)
|
||||||
.value("UP5K", ChipArgs::UP5K)
|
.value("UP5K", ArchArgs::UP5K)
|
||||||
.export_values();
|
.export_values();
|
||||||
|
|
||||||
class_<BelId>("BelId").def_readwrite("index", &BelId::index);
|
class_<BelId>("BelId").def_readwrite("index", &BelId::index);
|
||||||
@ -53,28 +53,28 @@ void arch_wrap_python()
|
|||||||
;
|
;
|
||||||
#undef X
|
#undef X
|
||||||
|
|
||||||
class_<Chip>("Chip", init<ChipArgs>())
|
class_<Arch>("Arch", init<ArchArgs>())
|
||||||
.def("getBelByName", &Chip::getBelByName)
|
.def("getBelByName", &Arch::getBelByName)
|
||||||
.def("getWireByName", &Chip::getWireByName)
|
.def("getWireByName", &Arch::getWireByName)
|
||||||
.def("getBelName", &Chip::getBelName)
|
.def("getBelName", &Arch::getBelName)
|
||||||
.def("getWireName", &Chip::getWireName)
|
.def("getWireName", &Arch::getWireName)
|
||||||
.def("getBels", &Chip::getBels)
|
.def("getBels", &Arch::getBels)
|
||||||
.def("getBelType", &Chip::getBelType)
|
.def("getBelType", &Arch::getBelType)
|
||||||
.def("getWireBelPin", &Chip::getWireBelPin)
|
.def("getWireBelPin", &Arch::getWireBelPin)
|
||||||
.def("getBelPinUphill", &Chip::getBelPinUphill)
|
.def("getBelPinUphill", &Arch::getBelPinUphill)
|
||||||
.def("getBelPinsDownhill", &Chip::getBelPinsDownhill)
|
.def("getBelPinsDownhill", &Arch::getBelPinsDownhill)
|
||||||
.def("getWires", &Chip::getWires)
|
.def("getWires", &Arch::getWires)
|
||||||
.def("getPipByName", &Chip::getPipByName)
|
.def("getPipByName", &Arch::getPipByName)
|
||||||
.def("getPipName", &Chip::getPipName)
|
.def("getPipName", &Arch::getPipName)
|
||||||
.def("getPips", &Chip::getPips)
|
.def("getPips", &Arch::getPips)
|
||||||
.def("getPipSrcWire", &Chip::getPipSrcWire)
|
.def("getPipSrcWire", &Arch::getPipSrcWire)
|
||||||
.def("getPipDstWire", &Chip::getPipDstWire)
|
.def("getPipDstWire", &Arch::getPipDstWire)
|
||||||
.def("getPipDelay", &Chip::getPipDelay)
|
.def("getPipDelay", &Arch::getPipDelay)
|
||||||
.def("getPipsDownhill", &Chip::getPipsDownhill)
|
.def("getPipsDownhill", &Arch::getPipsDownhill)
|
||||||
.def("getPipsUphill", &Chip::getPipsUphill)
|
.def("getPipsUphill", &Arch::getPipsUphill)
|
||||||
.def("getWireAliases", &Chip::getWireAliases)
|
.def("getWireAliases", &Arch::getWireAliases)
|
||||||
.def("estimatePosition", &Chip::estimatePosition)
|
.def("estimatePosition", &Arch::estimatePosition)
|
||||||
.def("estimateDelay", &Chip::estimateDelay);
|
.def("estimateDelay", &Arch::estimateDelay);
|
||||||
|
|
||||||
WRAP_RANGE(Bel);
|
WRAP_RANGE(Bel);
|
||||||
WRAP_RANGE(BelPin);
|
WRAP_RANGE(BelPin);
|
||||||
|
Loading…
Reference in New Issue
Block a user