aboutsummaryrefslogtreecommitdiffstats
path: root/ice40/arch_place.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ice40/arch_place.cc')
-rw-r--r--ice40/arch_place.cc50
1 files changed, 47 insertions, 3 deletions
diff --git a/ice40/arch_place.cc b/ice40/arch_place.cc
index 492ed846..1c6361a1 100644
--- a/ice40/arch_place.cc
+++ b/ice40/arch_place.cc
@@ -2,6 +2,7 @@
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2018 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 David Shah <david@symbioticeda.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -19,6 +20,7 @@
#include "arch_place.h"
#include "cells.h"
+#include "util.h"
NEXTPNR_NAMESPACE_BEGIN
@@ -39,7 +41,7 @@ static bool logicCellsCompatible(const std::vector<const CellInfo *> &cells)
std::unordered_set<const NetInfo *> locals;
for (auto cell : cells) {
- if (std::stoi(cell->params.at("DFF_ENABLE"))) {
+ if (bool_or_default(cell->params, "DFF_ENABLE")) {
if (!dffs_exist) {
dffs_exist = true;
cen = get_net_or_nullptr(cell, "CEN");
@@ -53,7 +55,7 @@ static bool logicCellsCompatible(const std::vector<const CellInfo *> &cells)
if (!is_global_net(sr))
locals.insert(sr);
- if (std::stoi(cell->params.at("NEG_CLK"))) {
+ if (bool_or_default(cell->params, "NEG_CLK")) {
dffs_neg = true;
}
} else {
@@ -63,7 +65,7 @@ static bool logicCellsCompatible(const std::vector<const CellInfo *> &cells)
return false;
if (sr != get_net_or_nullptr(cell, "SR"))
return false;
- if (dffs_neg != bool(std::stoi(cell->params.at("NEG_CLK"))))
+ if (dffs_neg != bool_or_default(cell->params, "NEG_CLK"))
return false;
}
}
@@ -79,6 +81,28 @@ static bool logicCellsCompatible(const std::vector<const CellInfo *> &cells)
return locals.size() <= 32;
}
+bool isBelLocationValid(Design *design, BelId bel)
+{
+ const Chip &chip = design->chip;
+ if (chip.getBelType(bel) == TYPE_ICESTORM_LC) {
+ std::vector<const CellInfo *> cells;
+ for (auto bel_other : chip.getBelsAtSameTile(bel)) {
+ IdString cell_other = chip.getBelCell(bel_other, false);
+ if (cell_other != IdString()) {
+ const CellInfo *ci_other = design->cells[cell_other];
+ cells.push_back(ci_other);
+ }
+ }
+ return logicCellsCompatible(cells);
+ } else {
+ IdString cellId = chip.getBelCell(bel, false);
+ if (cellId == IdString())
+ return true;
+ else
+ return isValidBelForCell(design, design->cells.at(cellId), bel);
+ }
+}
+
bool isValidBelForCell(Design *design, CellInfo *cell, BelId bel)
{
const Chip &chip = design->chip;
@@ -99,6 +123,26 @@ bool isValidBelForCell(Design *design, CellInfo *cell, BelId bel)
return logicCellsCompatible(cells);
} else if (cell->type == "SB_IO") {
return design->chip.getBelPackagePin(bel) != "";
+ } else if (cell->type == "SB_GB") {
+ bool is_reset = false, is_cen = false;
+ assert(cell->ports.at("GLOBAL_BUFFER_OUTPUT").net != nullptr);
+ for (auto user : cell->ports.at("GLOBAL_BUFFER_OUTPUT").net->users) {
+ if (is_reset_port(user))
+ is_reset = true;
+ if (is_enable_port(user))
+ is_cen = true;
+ }
+ IdString glb_net = chip.getWireName(
+ chip.getWireBelPin(bel, PIN_GLOBAL_BUFFER_OUTPUT));
+ int glb_id = std::stoi(std::string("") + glb_net.str().back());
+ if (is_reset && is_cen)
+ return false;
+ else if (is_reset)
+ return (glb_id % 2) == 0;
+ else if (is_cen)
+ return (glb_id % 2) == 1;
+ else
+ return true;
} else {
// TODO: IO cell clock checks
return true;