aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--CMakeLists.txt2
-rw-r--r--bba/bba.cmake12
-rw-r--r--bba/main.cc15
-rw-r--r--common/archcheck.cc5
-rw-r--r--common/nextpnr.h1
-rw-r--r--common/place_common.cc22
-rw-r--r--common/placer1.cc26
-rw-r--r--common/timing.cc3
-rw-r--r--ecp5/arch.cc46
-rw-r--r--ecp5/arch.h3
-rw-r--r--ecp5/arch_place.cc7
-rw-r--r--ecp5/bitstream.cc43
-rw-r--r--ecp5/main.cc4
-rw-r--r--generic/arch.cc40
-rw-r--r--generic/arch.h3
-rw-r--r--gui/fpgaviewwidget.cc6
-rw-r--r--ice40/arch.cc40
-rw-r--r--ice40/arch.h7
-rw-r--r--ice40/arch_place.cc7
-rw-r--r--ice40/arch_pybindings.cc2
-rw-r--r--ice40/chipdb.py38
-rw-r--r--ice40/family.cmake21
-rw-r--r--ice40/gfx.cc2
-rw-r--r--ice40/pack.cc4
-rw-r--r--ice40/place_legaliser.cc8
26 files changed, 196 insertions, 173 deletions
diff --git a/.gitignore b/.gitignore
index 6ca9e19f..f3be78e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,3 +25,5 @@ build/
/Testing/*
CTestTestfile.cmake
install_manifest.txt
+/bbasm
+/ImportExecutables.cmake
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c8ee6805..55e57763 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -167,6 +167,8 @@ if(MINGW)
add_definitions("-Wa,-mbig-obj")
endif(MINGW)
+include(bba/bba.cmake)
+
foreach (family ${ARCH})
message(STATUS "Configuring architecture : ${family}")
string(TOUPPER ${family} ufamily)
diff --git a/bba/bba.cmake b/bba/bba.cmake
new file mode 100644
index 00000000..4bb9ea0e
--- /dev/null
+++ b/bba/bba.cmake
@@ -0,0 +1,12 @@
+IF(CMAKE_CROSSCOMPILING)
+ SET(IMPORT_EXECUTABLES "IMPORTFILE-NOTFOUND" CACHE FILEPATH "Point it to the export file from a native build")
+ INCLUDE(${IMPORT_EXECUTABLES})
+ENDIF(CMAKE_CROSSCOMPILING)
+
+IF(NOT CMAKE_CROSSCOMPILING)
+ ADD_EXECUTABLE(bbasm bba/main.cc)
+ENDIF(NOT CMAKE_CROSSCOMPILING)
+
+IF(NOT CMAKE_CROSSCOMPILING)
+ EXPORT(TARGETS bbasm FILE ${CMAKE_BINARY_DIR}/ImportExecutables.cmake )
+ENDIF(NOT CMAKE_CROSSCOMPILING)
diff --git a/bba/main.cc b/bba/main.cc
new file mode 100644
index 00000000..42b79504
--- /dev/null
+++ b/bba/main.cc
@@ -0,0 +1,15 @@
+#include <unistd.h>
+#include <assert.h>
+int main()
+{
+ char buffer[512];
+ int i, j;
+ while (1) {
+ i = read(0, buffer, 512);
+ if (i == 0) break;
+ assert(i > 0);
+ j = write(1, buffer, i);
+ assert(i == j);
+ }
+ return 0;
+}
diff --git a/common/archcheck.cc b/common/archcheck.cc
index 5c4ef26c..5059066d 100644
--- a/common/archcheck.cc
+++ b/common/archcheck.cc
@@ -17,8 +17,8 @@
*
*/
-#include "nextpnr.h"
#include "log.h"
+#include "nextpnr.h"
#if 0
#define dbg(...) log(__VA_ARGS__)
@@ -84,8 +84,7 @@ void archcheck_locs(const Context *ctx)
log_info("Checking all locations..\n");
for (int x = 0; x < ctx->getGridDimX(); x++)
- for (int y = 0; y < ctx->getGridDimY(); y++)
- {
+ for (int y = 0; y < ctx->getGridDimY(); y++) {
dbg("> %d %d\n", x, y);
std::unordered_set<int> usedz;
diff --git a/common/nextpnr.h b/common/nextpnr.h
index 021772fe..3ba4f3b3 100644
--- a/common/nextpnr.h
+++ b/common/nextpnr.h
@@ -147,6 +147,7 @@ struct GraphicElement
{
G_NONE,
G_LINE,
+ G_ARROW,
G_BOX,
G_CIRCLE,
G_LABEL
diff --git a/common/place_common.cc b/common/place_common.cc
index 95b7b2aa..5673c847 100644
--- a/common/place_common.cc
+++ b/common/place_common.cc
@@ -28,19 +28,20 @@ NEXTPNR_NAMESPACE_BEGIN
wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type, float &tns)
{
wirelen_t wirelength = 0;
- int driver_x, driver_y;
+ Loc driver_loc;
bool driver_gb;
CellInfo *driver_cell = net->driver.cell;
if (!driver_cell)
return 0;
if (driver_cell->bel == BelId())
return 0;
- ctx->estimatePosition(driver_cell->bel, driver_x, driver_y, driver_gb);
+ driver_gb = ctx->getBelGlobalBuf(driver_cell->bel);
+ driver_loc = ctx->getBelLocation(driver_cell->bel);
WireId drv_wire = ctx->getBelPinWire(driver_cell->bel, ctx->portPinFromId(net->driver.port));
if (driver_gb)
return 0;
float worst_slack = 1000;
- int xmin = driver_x, xmax = driver_x, ymin = driver_y, ymax = driver_y;
+ int xmin = driver_loc.x, xmax = driver_loc.x, ymin = driver_loc.y, ymax = driver_loc.y;
for (auto load : net->users) {
if (load.cell == nullptr)
continue;
@@ -56,15 +57,14 @@ wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type
worst_slack = std::min(slack, worst_slack);
}
- int load_x, load_y;
- bool load_gb;
- ctx->estimatePosition(load_cell->bel, load_x, load_y, load_gb);
- if (load_gb)
+ if (ctx->getBelGlobalBuf(load_cell->bel))
continue;
- xmin = std::min(xmin, load_x);
- ymin = std::min(ymin, load_y);
- xmax = std::max(xmax, load_x);
- ymax = std::max(ymax, load_y);
+ Loc load_loc = ctx->getBelLocation(load_cell->bel);
+
+ xmin = std::min(xmin, load_loc.x);
+ ymin = std::min(ymin, load_loc.y);
+ xmax = std::max(xmax, load_loc.x);
+ ymax = std::max(ymax, load_loc.y);
}
if (ctx->timing_driven && type == MetricType::COST) {
wirelength = wirelen_t((((ymax - ymin) + (xmax - xmin)) * std::min(5.0, (1.0 + std::exp(-worst_slack / 5)))));
diff --git a/common/placer1.cc b/common/placer1.cc
index 025c7c15..f713fb88 100644
--- a/common/placer1.cc
+++ b/common/placer1.cc
@@ -50,9 +50,7 @@ class SAPlacer
{
int num_bel_types = 0;
for (auto bel : ctx->getBels()) {
- int x, y;
- bool gb;
- ctx->estimatePosition(bel, x, y, gb);
+ Loc loc = ctx->getBelLocation(bel);
BelType type = ctx->getBelType(bel);
int type_idx;
if (bel_types.find(type) == bel_types.end()) {
@@ -63,13 +61,13 @@ class SAPlacer
}
if (int(fast_bels.size()) < type_idx + 1)
fast_bels.resize(type_idx + 1);
- if (int(fast_bels.at(type_idx).size()) < (x + 1))
- fast_bels.at(type_idx).resize(x + 1);
- if (int(fast_bels.at(type_idx).at(x).size()) < (y + 1))
- fast_bels.at(type_idx).at(x).resize(y + 1);
- max_x = std::max(max_x, x);
- max_y = std::max(max_y, y);
- fast_bels.at(type_idx).at(x).at(y).push_back(bel);
+ if (int(fast_bels.at(type_idx).size()) < (loc.x + 1))
+ fast_bels.at(type_idx).resize(loc.x + 1);
+ if (int(fast_bels.at(type_idx).at(loc.x).size()) < (loc.y + 1))
+ fast_bels.at(type_idx).at(loc.x).resize(loc.y + 1);
+ max_x = std::max(max_x, loc.x);
+ max_y = std::max(max_y, loc.y);
+ fast_bels.at(type_idx).at(loc.x).at(loc.y).push_back(bel);
}
diameter = std::max(max_x, max_y) + 1;
}
@@ -404,12 +402,10 @@ class SAPlacer
BelId random_bel_for_cell(CellInfo *cell)
{
BelType targetType = ctx->belTypeFromId(cell->type);
- int x, y;
- bool gb;
- ctx->estimatePosition(cell->bel, x, y, gb);
+ Loc curr_loc = ctx->getBelLocation(cell->bel);
while (true) {
- int nx = ctx->rng(2 * diameter + 1) + std::max(x - diameter, 0);
- int ny = ctx->rng(2 * diameter + 1) + std::max(y - diameter, 0);
+ int nx = ctx->rng(2 * diameter + 1) + std::max(curr_loc.x - diameter, 0);
+ int ny = ctx->rng(2 * diameter + 1) + std::max(curr_loc.y - diameter, 0);
int beltype_idx = bel_types.at(targetType);
if (nx >= int(fast_bels.at(beltype_idx).size()))
continue;
diff --git a/common/timing.cc b/common/timing.cc
index 3a48935f..d91dea20 100644
--- a/common/timing.cc
+++ b/common/timing.cc
@@ -88,6 +88,9 @@ void assign_budget(Context *ctx)
IdString clock_domain = ctx->getPortClock(cell.second.get(), port.first);
if (clock_domain != IdString()) {
delay_t slack = delay_t(1.0e12 / ctx->target_freq); // TODO: clock constraints
+ delay_t clkToQ;
+ if (ctx->getCellDelay(cell.second.get(), clock_domain, port.first, clkToQ))
+ slack -= clkToQ;
if (port.second.net)
follow_net(ctx, port.second.net, 0, slack);
}
diff --git a/ecp5/arch.cc b/ecp5/arch.cc
index 7d67dd0c..5507d1e3 100644
--- a/ecp5/arch.cc
+++ b/ecp5/arch.cc
@@ -192,17 +192,20 @@ BelId Arch::getBelByName(IdString name) const
return ret;
}
-BelRange Arch::getBelsAtSameTile(BelId bel) const
+BelRange Arch::getBelsByTile(int x, int y) const
{
BelRange br;
- NPNR_ASSERT(bel != BelId());
- br.b.cursor_tile = bel.location.y * chip_info->width + bel.location.x;
- br.e.cursor_tile = bel.location.y * chip_info->width + bel.location.x;
+
+ br.b.cursor_tile = y * chip_info->width + x;
+ br.e.cursor_tile = y * chip_info->width + x;
br.b.cursor_index = 0;
- br.e.cursor_index = locInfo(bel)->num_bels - 1;
+ br.e.cursor_index = chip_info->locations[chip_info->location_type[br.b.cursor_tile]].num_bels - 1;
br.b.chip = chip_info;
br.e.chip = chip_info;
- ++br.e;
+ if (br.e.cursor_index == -1)
+ ++br.e.cursor_index;
+ else
+ ++br.e;
return br;
}
@@ -278,6 +281,7 @@ PipId Arch::getPipByName(IdString name) const
Location loc;
std::string basename;
std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this));
+ ret.location = loc;
const LocationTypePOD *loci = locInfo(ret);
for (int i = 0; i < loci->num_pips; i++) {
PipId curr;
@@ -285,6 +289,8 @@ PipId Arch::getPipByName(IdString name) const
curr.index = i;
pip_by_name[getPipName(curr)] = curr;
}
+ if (pip_by_name.find(name) == pip_by_name.end())
+ NPNR_ASSERT_FALSE_STR("no pip named " + name.str(this));
return pip_by_name[name];
}
@@ -399,36 +405,8 @@ BelId Arch::getBelByLocation(Loc loc) const
return BelId();
}
-BelRange Arch::getBelsByTile(int x, int y) const
-{
- BelRange br;
-
- int num_bels = 0;
-
- if (x < chip_info->width && y < chip_info->height) {
- const LocationTypePOD &locI = chip_info->locations[chip_info->location_type[y * chip_info->width + x]];
- num_bels = locI.num_bels;
- }
-
- br.b.cursor_tile = y * chip_info->width + x;
- br.e.cursor_tile = y * chip_info->width + x;
- br.b.cursor_index = 0;
- br.e.cursor_index = num_bels - 1;
- br.b.chip = chip_info;
- br.e.chip = chip_info;
- ++br.e;
- return br;
-}
-
// -----------------------------------------------------------------------
-void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const
-{
- x = bel.location.x;
- y = bel.location.y;
- gb = false;
-}
-
delay_t Arch::estimateDelay(WireId src, WireId dst) const
{
return 200 * (abs(src.location.x - dst.location.x) + abs(src.location.y - dst.location.y));
diff --git a/ecp5/arch.h b/ecp5/arch.h
index ce2b90c3..4400db5e 100644
--- a/ecp5/arch.h
+++ b/ecp5/arch.h
@@ -482,8 +482,6 @@ struct Arch : BaseCtx
return range;
}
- BelRange getBelsAtSameTile(BelId bel) const;
-
BelType getBelType(BelId bel) const
{
NPNR_ASSERT(bel != BelId());
@@ -752,7 +750,6 @@ struct Arch : BaseCtx
// -------------------------------------------------
- void estimatePosition(BelId bel, int &x, int &y, bool &gb) const;
delay_t estimateDelay(WireId src, WireId dst) const;
delay_t getDelayEpsilon() const { return 20; }
delay_t getRipupDelayPenalty() const { return 200; }
diff --git a/ecp5/arch_place.cc b/ecp5/arch_place.cc
index 22ebab67..84432043 100644
--- a/ecp5/arch_place.cc
+++ b/ecp5/arch_place.cc
@@ -66,7 +66,8 @@ bool Arch::isBelLocationValid(BelId bel) const
{
if (getBelType(bel) == TYPE_TRELLIS_SLICE) {
std::vector<const CellInfo *> bel_cells;
- for (auto bel_other : getBelsAtSameTile(bel)) {
+ Loc bel_loc = getBelLocation(bel);
+ for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
IdString cell_other = getBoundBelCell(bel_other);
if (cell_other != IdString()) {
const CellInfo *ci_other = cells.at(cell_other).get();
@@ -89,8 +90,8 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
NPNR_ASSERT(getBelType(bel) == TYPE_TRELLIS_SLICE);
std::vector<const CellInfo *> bel_cells;
-
- for (auto bel_other : getBelsAtSameTile(bel)) {
+ Loc bel_loc = getBelLocation(bel);
+ for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
IdString cell_other = getBoundBelCell(bel_other);
if (cell_other != IdString() && bel_other != bel) {
const CellInfo *ci_other = cells.at(cell_other).get();
diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc
index 19ddb9f9..c2218762 100644
--- a/ecp5/bitstream.cc
+++ b/ecp5/bitstream.cc
@@ -30,6 +30,7 @@
#include <fstream>
#include <streambuf>
+#include "io.h"
#include "log.h"
#include "util.h"
@@ -182,12 +183,34 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
}
}
}
+ // Find bank voltages
+ std::unordered_map<int, IOVoltage> bankVcc;
+ for (auto &cell : ctx->cells) {
+ CellInfo *ci = cell.second.get();
+ if (ci->bel != BelId() && ci->type == ctx->id("TRELLIS_IO")) {
+ int bank = ctx->getPioBelBank(ci->bel);
+ std::string iotype = str_or_default(ci->attrs, ctx->id("IO_TYPE"), "LVCMOS33");
+ IOVoltage vcc = get_vccio(ioType_from_str(iotype));
+ if (bankVcc.find(bank) != bankVcc.end()) {
+ // TODO: strong and weak constraints
+ if (bankVcc[bank] != vcc) {
+ log_error("Error processing '%s': incompatible IO voltages %s and %s on bank %d.",
+ cell.first.c_str(ctx), iovoltage_to_str(bankVcc[bank]).c_str(),
+ iovoltage_to_str(vcc).c_str(), bank);
+ }
+ } else {
+ bankVcc[bank] = vcc;
+ }
+ }
+ }
- // Set all bankref tiles to 3.3V (TODO)
+ // Set all bankref tiles to appropriate VccIO
for (const auto &tile : empty_chip.tiles) {
std::string type = tile.second->info.type;
if (type.find("BANKREF") != std::string::npos && type != "BANKREF8") {
- cc.tiles[tile.first].add_enum("BANK.VCCIO", "3V3");
+ int bank = std::stoi(type.substr(7));
+ if (bankVcc.find(bank) != bankVcc.end())
+ cc.tiles[tile.first].add_enum("BANK.VCCIO", iovoltage_to_str(bankVcc[bank]));
}
}
@@ -235,6 +258,20 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
std::string pic_tile = get_pic_tile(ctx, empty_chip, bel);
cc.tiles[pio_tile].add_enum(pio + ".BASE_TYPE", dir + "_" + iotype);
cc.tiles[pic_tile].add_enum(pio + ".BASE_TYPE", dir + "_" + iotype);
+ if (is_differential(ioType_from_str(iotype))) {
+ // Explicitly disable other pair
+ std::string other;
+ if (pio == "PIOA")
+ other = "PIOB";
+ else if (pio == "PIOC")
+ other = "PIOD";
+ else
+ log_error("cannot place differential IO at location %s\n", pio.c_str());
+ cc.tiles[pio_tile].add_enum(other + ".BASE_TYPE", "_NONE_");
+ cc.tiles[pic_tile].add_enum(other + ".BASE_TYPE", "_NONE_");
+ cc.tiles[pio_tile].add_enum(other + ".PULLMODE", "NONE");
+ cc.tiles[pio_tile].add_enum(pio + ".PULLMODE", "NONE");
+ }
if (dir != "INPUT" &&
(ci->ports.find(ctx->id("T")) == ci->ports.end() || ci->ports.at(ctx->id("T")).net == nullptr)) {
// Tie tristate low if unconnected for outputs or bidir
@@ -247,7 +284,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
std::string cib_wirename = ctx->locInfo(cib_wire)->wire_data[cib_wire.index].name.get();
cc.tiles[cib_tile].add_enum("CIB." + cib_wirename + "MUX", "0");
}
- if (dir == "INPUT") {
+ if (dir == "INPUT" && !is_differential(ioType_from_str(iotype))) {
cc.tiles[pio_tile].add_enum(pio + ".HYSTERESIS", "ON");
}
} else {
diff --git a/ecp5/main.cc b/ecp5/main.cc
index 5a4a900a..90096855 100644
--- a/ecp5/main.cc
+++ b/ecp5/main.cc
@@ -63,6 +63,7 @@ int main(int argc, char *argv[])
#ifndef NO_GUI
options.add_options()("gui", "start gui");
#endif
+ options.add_options()("test", "check architecture database integrity");
options.add_options()("25k", "set device type to LFE5U-25F");
options.add_options()("45k", "set device type to LFE5U-45F");
@@ -148,6 +149,9 @@ int main(int argc, char *argv[])
if (vm.count("no-tmdriv"))
ctx->timing_driven = false;
+ if (vm.count("test"))
+ ctx->archcheck();
+
#ifndef NO_GUI
if (vm.count("gui")) {
Application a(argc, argv);
diff --git a/generic/arch.cc b/generic/arch.cc
index 0fff2e4c..ac79ebea 100644
--- a/generic/arch.cc
+++ b/generic/arch.cc
@@ -77,18 +77,18 @@ void Arch::addBel(IdString name, IdString type, Loc loc, bool gb)
bel_ids.push_back(name);
bel_by_loc[loc] = name;
- if (bels_by_tile.size() <= loc.x)
+ if (int(bels_by_tile.size()) <= loc.x)
bels_by_tile.resize(loc.x + 1);
- if (bels_by_tile[loc.x].size() <= loc.y)
+ if (int(bels_by_tile[loc.x].size()) <= loc.y)
bels_by_tile[loc.x].resize(loc.y + 1);
bels_by_tile[loc.x][loc.y].push_back(name);
- if (tileDimZ.size() <= loc.x)
+ if (int(tileDimZ.size()) <= loc.x)
tileDimZ.resize(loc.x + 1);
- if (tileDimZ[loc.x].size() <= loc.y)
+ if (int(tileDimZ[loc.x].size()) <= loc.y)
tileDimZ[loc.x].resize(loc.y + 1);
gridDimX = std::max(gridDimX, loc.x + 1);
@@ -193,6 +193,30 @@ BelId Arch::getBelByName(IdString name) const
IdString Arch::getBelName(BelId bel) const { return bel; }
+Loc Arch::getBelLocation(BelId bel) const
+{
+ auto &info = bels.at(bel);
+ return Loc(info.x, info.y, info.z);
+}
+
+BelId Arch::getBelByLocation(Loc loc) const
+{
+ auto it = bel_by_loc.find(loc);
+ if (it != bel_by_loc.end())
+ return it->second;
+ return BelId();
+}
+
+const std::vector<BelId> &Arch::getBelsByTile(int x, int y) const
+{
+ return bels_by_tile.at(x).at(y);
+}
+
+bool Arch::getBelGlobalBuf(BelId bel) const
+{
+ return bels.at(bel).gb;
+}
+
uint32_t Arch::getBelChecksum(BelId bel) const
{
// FIXME
@@ -234,6 +258,7 @@ std::vector<PortPin> Arch::getBelPins(BelId bel) const
std::vector<PortPin> ret;
for (auto &it : bels.at(bel).pins)
ret.push_back(it.first);
+ return ret;
}
// ---------------------------------------------------------------
@@ -368,13 +393,6 @@ const std::vector<GroupId> &Arch::getGroupGroups(GroupId group) const { return g
// ---------------------------------------------------------------
-void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const
-{
- x = bels.at(bel).x;
- y = bels.at(bel).y;
- gb = bels.at(bel).gb;
-}
-
delay_t Arch::estimateDelay(WireId src, WireId dst) const
{
const WireInfo &s = wires.at(src);
diff --git a/generic/arch.h b/generic/arch.h
index 61e6b033..97ed1ac2 100644
--- a/generic/arch.h
+++ b/generic/arch.h
@@ -141,7 +141,7 @@ struct Arch : BaseCtx
IdString getBelName(BelId bel) const;
Loc getBelLocation(BelId bel) const;
BelId getBelByLocation(Loc loc) const;
- std::vector<BelId> getBelsByTile(int x, int y) const;
+ const std::vector<BelId> &getBelsByTile(int x, int y) const;
bool getBelGlobalBuf(BelId bel) const;
uint32_t getBelChecksum(BelId bel) const;
void bindBel(BelId bel, IdString cell, PlaceStrength strength);
@@ -191,7 +191,6 @@ struct Arch : BaseCtx
const std::vector<PipId> &getGroupPips(GroupId group) const;
const std::vector<GroupId> &getGroupGroups(GroupId group) const;
- void estimatePosition(BelId bel, int &x, int &y, bool &gb) const;
delay_t estimateDelay(WireId src, WireId dst) const;
delay_t getDelayEpsilon() const { return 0.01; }
delay_t getRipupDelayPenalty() const { return 1.0; }
diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc
index e21af678..7ccb3445 100644
--- a/gui/fpgaviewwidget.cc
+++ b/gui/fpgaviewwidget.cc
@@ -246,7 +246,7 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent)
{
colors_.background = QColor("#000000");
colors_.grid = QColor("#333");
- colors_.frame = QColor("#d0d0d0");
+ colors_.frame = QColor("#808080");
colors_.hidden = QColor("#606060");
colors_.inactive = QColor("#303030");
colors_.active = QColor("#f0f0f0");
@@ -327,7 +327,7 @@ void FPGAViewWidget::drawDecal(LineShaderData &out, const DecalXY &decal)
line.build(out);
}
- if (el.type == GraphicElement::G_LINE) {
+ if (el.type == GraphicElement::G_LINE || el.type == GraphicElement::G_ARROW) {
PolyLine(offsetX + scale * el.x1, offsetY + scale * el.y1, offsetX + scale * el.x2, offsetY + scale * el.y2)
.build(out);
}
@@ -360,7 +360,7 @@ void FPGAViewWidget::drawDecal(LineShaderData out[], const DecalXY &decal)
}
}
- if (el.type == GraphicElement::G_LINE) {
+ if (el.type == GraphicElement::G_LINE || el.type == GraphicElement::G_ARROW) {
auto line = PolyLine(offsetX + scale * el.x1, offsetY + scale * el.y1, offsetX + scale * el.x2,
offsetY + scale * el.y2);
switch (el.style) {
diff --git a/ice40/arch.cc b/ice40/arch.cc
index 5c632faa..1d7e9546 100644
--- a/ice40/arch.cc
+++ b/ice40/arch.cc
@@ -292,23 +292,6 @@ BelRange Arch::getBelsByTile(int x, int y) const
return br;
}
-BelRange Arch::getBelsAtSameTile(BelId bel) const
-{
- BelRange br;
- NPNR_ASSERT(bel != BelId());
- int x = chip_info->bel_data[bel.index].x;
- int y = chip_info->bel_data[bel.index].y;
- int start = bel.index, end = bel.index;
- while (start >= 0 && chip_info->bel_data[start].x == x && chip_info->bel_data[start].y == y)
- start--;
- start++;
- br.b.cursor = start;
- while (end < chip_info->num_bels && chip_info->bel_data[end].x == x && chip_info->bel_data[end].y == y)
- end++;
- br.e.cursor = end;
- return br;
-}
-
PortType Arch::getBelPinType(BelId bel, PortPin pin) const
{
NPNR_ASSERT(bel != BelId());
@@ -484,14 +467,6 @@ std::vector<GroupId> Arch::getGroupGroups(GroupId group) const
// -----------------------------------------------------------------------
-void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const
-{
- NPNR_ASSERT(bel != BelId());
- x = chip_info->bel_data[bel.index].x;
- y = chip_info->bel_data[bel.index].y;
- gb = chip_info->bel_data[bel.index].type == TYPE_SB_GB;
-}
-
delay_t Arch::estimateDelay(WireId src, WireId dst) const
{
NPNR_ASSERT(src != WireId());
@@ -735,6 +710,14 @@ bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort
} else if (fromPort == id("I2") && toPort == id("COUT")) {
delay = 230;
return true;
+ } else if (fromPort == id("CLK") && toPort == id("O")) {
+ delay = 540;
+ return true;
+ }
+ } else if (cell->type == id("ICESTORM_RAM")) {
+ if (fromPort == id("RCLK")) {
+ delay = 2140;
+ return true;
}
}
return false;
@@ -745,6 +728,11 @@ IdString Arch::getPortClock(const CellInfo *cell, IdString port) const
if (cell->type == id("ICESTORM_LC") && bool_or_default(cell->params, id("DFF_ENABLE"))) {
if (port != id("LO") && port != id("CIN") && port != id("COUT"))
return id("CLK");
+ } else if (cell->type == id("ICESTORM_RAM")) {
+ if (port.str(this)[0] == 'R')
+ return id("RCLK");
+ else
+ return id("WCLK");
}
return IdString();
}
@@ -753,6 +741,8 @@ bool Arch::isClockPort(const CellInfo *cell, IdString port) const
{
if (cell->type == id("ICESTORM_LC") && port == id("CLK"))
return true;
+ if (cell->type == id("ICESTORM_RAM") && (port == id("RCLK") || (port == id("WCLK"))))
+ return true;
return false;
}
diff --git a/ice40/arch.h b/ice40/arch.h
index f0060d48..3aec25a2 100644
--- a/ice40/arch.h
+++ b/ice40/arch.h
@@ -83,10 +83,6 @@ NPNR_PACKED_STRUCT(struct WireInfoPOD {
int32_t num_uphill, num_downhill;
RelPtr<int32_t> pips_uphill, pips_downhill;
- int32_t num_bels_uphill, num_bels_downhill;
- RelPtr<BelPortPOD> bels_uphill;
- RelPtr<BelPortPOD> bels_downhill;
-
int32_t num_bel_pins;
RelPtr<BelPortPOD> bel_pins;
@@ -453,8 +449,6 @@ struct Arch : BaseCtx
bool getBelGlobalBuf(BelId bel) const { return chip_info->bel_data[bel.index].type == TYPE_SB_GB; }
- BelRange getBelsAtSameTile(BelId bel) const NPNR_DEPRECATED;
-
BelType getBelType(BelId bel) const
{
NPNR_ASSERT(bel != BelId());
@@ -685,7 +679,6 @@ struct Arch : BaseCtx
// -------------------------------------------------
- void estimatePosition(BelId bel, int &x, int &y, bool &gb) const NPNR_DEPRECATED;
delay_t estimateDelay(WireId src, WireId dst) const;
delay_t getDelayEpsilon() const { return 20; }
delay_t getRipupDelayPenalty() const { return 200; }
diff --git a/ice40/arch_place.cc b/ice40/arch_place.cc
index 16cc757e..59e1807d 100644
--- a/ice40/arch_place.cc
+++ b/ice40/arch_place.cc
@@ -72,7 +72,8 @@ bool Arch::isBelLocationValid(BelId bel) const
{
if (getBelType(bel) == TYPE_ICESTORM_LC) {
std::vector<const CellInfo *> bel_cells;
- for (auto bel_other : getBelsAtSameTile(bel)) {
+ Loc bel_loc = getBelLocation(bel);
+ for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
IdString cell_other = getBoundBelCell(bel_other);
if (cell_other != IdString()) {
const CellInfo *ci_other = cells.at(cell_other).get();
@@ -95,8 +96,8 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
NPNR_ASSERT(getBelType(bel) == TYPE_ICESTORM_LC);
std::vector<const CellInfo *> bel_cells;
-
- for (auto bel_other : getBelsAtSameTile(bel)) {
+ Loc bel_loc = getBelLocation(bel);
+ for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
IdString cell_other = getBoundBelCell(bel_other);
if (cell_other != IdString() && bel_other != bel) {
const CellInfo *ci_other = cells.at(cell_other).get();
diff --git a/ice40/arch_pybindings.cc b/ice40/arch_pybindings.cc
index 246d0f57..98164e87 100644
--- a/ice40/arch_pybindings.cc
+++ b/ice40/arch_pybindings.cc
@@ -79,8 +79,6 @@ void arch_wrap_python()
conv_to_str<IdString>, conv_from_str<BelId>>::def_wrap(ctx_cls, "getConflictingBelCell");
fn_wrapper_0a<Context, decltype(&Context::getBels), &Context::getBels, wrap_context<BelRange>>::def_wrap(ctx_cls,
"getBels");
- fn_wrapper_1a<Context, decltype(&Context::getBelsAtSameTile), &Context::getBelsAtSameTile, wrap_context<BelRange>,
- conv_from_str<BelId>>::def_wrap(ctx_cls, "getBelsAtSameTile");
fn_wrapper_2a<Context, decltype(&Context::getBelPinWire), &Context::getBelPinWire, conv_to_str<WireId>,
conv_from_str<BelId>, conv_from_str<PortPin>>::def_wrap(ctx_cls, "getBelPinWire");
diff --git a/ice40/chipdb.py b/ice40/chipdb.py
index 63d90b45..108197c1 100644
--- a/ice40/chipdb.py
+++ b/ice40/chipdb.py
@@ -41,8 +41,6 @@ extra_cells = dict()
extra_cell_config = dict()
packages = list()
-wire_uphill_belports = dict()
-wire_downhill_belports = dict()
wire_belports = dict()
wire_names = dict()
@@ -453,18 +451,12 @@ for i in range(8):
add_wire(0, 0, "padin_%d" % i)
def add_bel_input(bel, wire, port):
- if wire not in wire_downhill_belports:
- wire_downhill_belports[wire] = set()
- wire_downhill_belports[wire].add((bel, port))
if wire not in wire_belports:
wire_belports[wire] = set()
wire_belports[wire].add((bel, port))
bel_wires[bel].append((wire, port, 0))
def add_bel_output(bel, wire, port):
- if wire not in wire_uphill_belports:
- wire_uphill_belports[wire] = set()
- wire_uphill_belports[wire].add((bel, port))
if wire not in wire_belports:
wire_belports[wire] = set()
wire_belports[wire].add((bel, port))
@@ -672,7 +664,7 @@ for tile_xy, tile_type in sorted(tiles.items()):
add_bel_ec(ec)
for ec in sorted(extra_cells.keys()):
- if ec[1] == 0 and ec[2] == 0:
+ if ec[1] in (0, dev_width - 1) and ec[2] in (0, dev_height - 1):
add_bel_ec(ec)
class BinaryBlobAssembler:
@@ -1011,24 +1003,6 @@ for wire in range(num_wires):
num_downhill = 0
list_downhill = None
- if wire in wire_uphill_belports:
- num_bels_uphill = len(wire_uphill_belports[wire])
- bba.l("wire%d_upbels" % wire, "BelPortPOD")
- for belport in sorted(wire_uphill_belports[wire]):
- bba.u32(belport[0], "bel_index")
- bba.u32(portpins[belport[1]], "port")
- else:
- num_bels_uphill = 0
-
- if wire in wire_downhill_belports:
- num_bels_downhill = len(wire_downhill_belports[wire])
- bba.l("wire%d_downbels" % wire, "BelPortPOD")
- for belport in sorted(wire_downhill_belports[wire]):
- bba.u32(belport[0], "bel_index")
- bba.u32(portpins[belport[1]], "port")
- else:
- num_bels_downhill = 0
-
if wire in wire_belports:
num_bel_pins = len(wire_belports[wire])
bba.l("wire%d_bels" % wire, "BelPortPOD")
@@ -1047,12 +1021,6 @@ for wire in range(num_wires):
info["num_downhill"] = num_downhill
info["list_downhill"] = list_downhill
- info["num_bels_downhill"] = num_bels_downhill
- info["list_bels_downhill"] = ("wire%d_downbels" % wire) if num_bels_downhill > 0 else None
-
- info["num_bels_uphill"] = num_bels_uphill
- info["list_bels_uphill"] = ("wire%d_upbels" % wire) if num_bels_uphill > 0 else None
-
info["num_bel_pins"] = num_bel_pins
info["list_bel_pins"] = ("wire%d_bels" % wire) if num_bel_pins > 0 else None
@@ -1130,10 +1098,6 @@ for wire, info in enumerate(wireinfo):
bba.u32(info["num_downhill"], "num_downhill")
bba.r(info["list_uphill"], "pips_uphill")
bba.r(info["list_downhill"], "pips_downhill")
- bba.u32(info["num_bels_uphill"], "num_bels_uphill")
- bba.u32(info["num_bels_downhill"], "num_bels_downhill")
- bba.r(info["list_bels_uphill"], "bels_uphill")
- bba.r(info["list_bels_downhill"], "bels_downhill")
bba.u32(info["num_bel_pins"], "num_bel_pins")
bba.r(info["list_bel_pins"], "bel_pins")
bba.u32(len(wire_segments[wire]), "num_segments")
diff --git a/ice40/family.cmake b/ice40/family.cmake
index 9af06f82..95cdf331 100644
--- a/ice40/family.cmake
+++ b/ice40/family.cmake
@@ -19,13 +19,18 @@ if (MSVC)
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/ice40/resources/chipdb.rc PROPERTIES LANGUAGE RC)
foreach (dev ${devices})
set(DEV_TXT_DB ${ICEBOX_ROOT}/chipdb-${dev}.txt)
+ set(DEV_CC_BBA_DB ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdbs/chipdb-${dev}.bba)
set(DEV_CC_DB ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdbs/chipdb-${dev}.bin)
set(DEV_PORTS_INC ${CMAKE_CURRENT_SOURCE_DIR}/ice40/portpins.inc)
set(DEV_GFXH ${CMAKE_CURRENT_SOURCE_DIR}/ice40/gfx.h)
- add_custom_command(OUTPUT ${DEV_CC_DB}
- COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -b -p ${DEV_PORTS_INC} -g ${DEV_GFXH} ${DEV_TXT_DB} > ${DEV_CC_DB}
+ add_custom_command(OUTPUT ${DEV_CC_BBA_DB}
+ COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -b -p ${DEV_PORTS_INC} -g ${DEV_GFXH} ${DEV_TXT_DB} > ${DEV_CC_BBA_DB}
DEPENDS ${DEV_TXT_DB} ${DB_PY}
)
+ add_custom_command(OUTPUT ${DEV_CC_DB}
+ COMMAND bbasm < ${DEV_CC_BBA_DB} > ${DEV_CC_DB}
+ DEPENDS bbasm ${DEV_CC_BBA_DB}
+ )
target_sources(ice40_chipdb PRIVATE ${DEV_CC_DB})
set_source_files_properties(${DEV_CC_DB} PROPERTIES HEADER_FILE_ONLY TRUE)
foreach (target ${family_targets})
@@ -36,14 +41,20 @@ else()
target_compile_options(ice40_chipdb PRIVATE -g0 -O0 -w)
foreach (dev ${devices})
set(DEV_TXT_DB ${ICEBOX_ROOT}/chipdb-${dev}.txt)
+ set(DEV_CC_BBA_DB ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdbs/chipdb-${dev}.bba)
set(DEV_CC_DB ${CMAKE_CURRENT_SOURCE_DIR}/ice40/chipdbs/chipdb-${dev}.cc)
set(DEV_PORTS_INC ${CMAKE_CURRENT_SOURCE_DIR}/ice40/portpins.inc)
set(DEV_GFXH ${CMAKE_CURRENT_SOURCE_DIR}/ice40/gfx.h)
+ add_custom_command(OUTPUT ${DEV_CC_BBA_DB}
+ COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -c -p ${DEV_PORTS_INC} -g ${DEV_GFXH} ${DEV_TXT_DB} > ${DEV_CC_BBA_DB}.new
+ COMMAND mv ${DEV_CC_BBA_DB}.new ${DEV_CC_BBA_DB}
+ DEPENDS ${DEV_TXT_DB} ${DB_PY}
+ )
add_custom_command(OUTPUT ${DEV_CC_DB}
- COMMAND ${PYTHON_EXECUTABLE} ${DB_PY} -c -p ${DEV_PORTS_INC} -g ${DEV_GFXH} ${DEV_TXT_DB} > ${DEV_CC_DB}.new
+ COMMAND bbasm < ${DEV_CC_BBA_DB} > ${DEV_CC_DB}.new
COMMAND mv ${DEV_CC_DB}.new ${DEV_CC_DB}
- DEPENDS ${DEV_TXT_DB} ${DB_PY}
- )
+ DEPENDS bbasm ${DEV_CC_BBA_DB}
+ )
target_sources(ice40_chipdb PRIVATE ${DEV_CC_DB})
foreach (target ${family_targets})
target_sources(${target} PRIVATE $<TARGET_OBJECTS:ice40_chipdb>)
diff --git a/ice40/gfx.cc b/ice40/gfx.cc
index f6ed789f..1b01cbd8 100644
--- a/ice40/gfx.cc
+++ b/ice40/gfx.cc
@@ -647,7 +647,7 @@ void pipGfx(std::vector<GraphicElement> &g, int x, int y, float x1, float y1, fl
float ty = 0.5 * (y1 + y2);
GraphicElement el;
- el.type = GraphicElement::G_LINE;
+ el.type = GraphicElement::G_ARROW;
el.style = style;
if (fabsf(x1 - swx1) < 0.001 && fabsf(x2 - swx1) < 0.001) {
diff --git a/ice40/pack.cc b/ice40/pack.cc
index 03b33190..b1e7380e 100644
--- a/ice40/pack.cc
+++ b/ice40/pack.cc
@@ -312,6 +312,10 @@ static void set_net_constant(const Context *ctx, NetInfo *orig, NetInfo *constne
(user.port != ctx->id("CLK") &&
((constval && user.port == ctx->id("CE")) || (!constval && user.port != ctx->id("CE"))))) {
uc->ports[user.port].net = nullptr;
+ } else if (is_ram(ctx, uc) && !constval && user.port != ctx->id("RCLK") && user.port != ctx->id("RCLKN") &&
+ user.port != ctx->id("WCLK") && user.port != ctx->id("WCLKN") && user.port != ctx->id("RCLKE") &&
+ user.port != ctx->id("WCLKE")) {
+ uc->ports[user.port].net = nullptr;
} else {
uc->ports[user.port].net = constnet;
constnet->users.push_back(user);
diff --git a/ice40/place_legaliser.cc b/ice40/place_legaliser.cc
index 2aefb839..ebc2b865 100644
--- a/ice40/place_legaliser.cc
+++ b/ice40/place_legaliser.cc
@@ -75,11 +75,9 @@ static void get_chain_midpoint(const Context *ctx, const CellChain &chain, float
for (auto cell : chain.cells) {
if (cell->bel == BelId())
continue;
- int bel_x, bel_y;
- bool bel_gb;
- ctx->estimatePosition(cell->bel, bel_x, bel_y, bel_gb);
- total_x += bel_x;
- total_y += bel_y;
+ Loc bel_loc = ctx->getBelLocation(cell->bel);
+ total_x += bel_loc.x;
+ total_y += bel_loc.y;
N++;
}
NPNR_ASSERT(N > 0);