aboutsummaryrefslogtreecommitdiffstats
path: root/ice40
diff options
context:
space:
mode:
authorDavid Shah <davey1576@gmail.com>2018-06-25 11:43:59 +0200
committerDavid Shah <davey1576@gmail.com>2018-06-25 11:43:59 +0200
commitbdd54a68471a68bb9e3f8125c1457cd039cc768b (patch)
tree7f96fc65d7714699b2b1ec2f707beeefedb76dd3 /ice40
parent1b7ed56f6ffd11d70d79cd96fb370f331e6d8df0 (diff)
downloadnextpnr-bdd54a68471a68bb9e3f8125c1457cd039cc768b.tar.gz
nextpnr-bdd54a68471a68bb9e3f8125c1457cd039cc768b.tar.bz2
nextpnr-bdd54a68471a68bb9e3f8125c1457cd039cc768b.zip
Refactor: remove PlacementValidityChecker and move methods to Arch
Signed-off-by: David Shah <davey1576@gmail.com>
Diffstat (limited to 'ice40')
-rw-r--r--ice40/arch.cc12
-rw-r--r--ice40/arch.h19
-rw-r--r--ice40/arch_place.cc71
-rw-r--r--ice40/arch_place.h52
-rw-r--r--ice40/cells.cc6
-rw-r--r--ice40/cells.h24
-rw-r--r--ice40/main.cc10
7 files changed, 84 insertions, 110 deletions
diff --git a/ice40/arch.cc b/ice40/arch.cc
index 5c700851..fbad6ab0 100644
--- a/ice40/arch.cc
+++ b/ice40/arch.cc
@@ -163,6 +163,18 @@ Arch::Arch(ArchArgs args) : args(args)
// Initialise regularly used IDStrings for performance
id_glb_buf_out = id("GLOBAL_BUFFER_OUTPUT");
+ id_icestorm_lc = id("ICESTORM_LC");
+ id_sb_io = id("SB_IO");
+ id_sb_gb = id("SB_GB");
+ id_cen = id("CEN");
+ id_clk = id("CLK");
+ id_sr = id("SR");
+ id_i0 = id("I0");
+ id_i1 = id("I1");
+ id_i2 = id("I2");
+ id_i3 = id("I3");
+ id_dff_en = id("DFF_ENABLE");
+ id_neg_clk = id("NEG_CLK");
}
// -----------------------------------------------------------------------
diff --git a/ice40/arch.h b/ice40/arch.h
index b5ec1dd2..2906cad7 100644
--- a/ice40/arch.h
+++ b/ice40/arch.h
@@ -815,7 +815,26 @@ struct Arch : BaseCtx
// Return true if a port is a net
bool isGlobalNet(const NetInfo *net) const;
+ // -------------------------------------------------
+
+ // Perform placement validity checks, returning false on failure (all implemented in arch_place.cc)
+
+ // Whether or not a given cell can be placed at a given Bel
+ // This is not intended for Bel type checks, but finer-grained constraints
+ // such as conflicting set/reset signals, etc
+ bool isValidBelForCell(CellInfo *cell, BelId bel) const;
+
+ // Return true whether all Bels at a given location are valid
+ bool isBelLocationValid(BelId bel) const;
+
+ // Helper function for above
+ bool logicCellsCompatible(const std::vector<const CellInfo *> &cells) const;
+
IdString id_glb_buf_out;
+ IdString id_icestorm_lc, id_sb_io, id_sb_gb;
+ IdString id_cen, id_clk, id_sr;
+ IdString id_i0, id_i1, id_i2, id_i3;
+ IdString id_dff_en, id_neg_clk;
};
NEXTPNR_NAMESPACE_END
diff --git a/ice40/arch_place.cc b/ice40/arch_place.cc
index 1a9c11df..129ebe18 100644
--- a/ice40/arch_place.cc
+++ b/ice40/arch_place.cc
@@ -18,19 +18,12 @@
*
*/
-#include "arch_place.h"
#include "cells.h"
+#include "nextpnr.h"
#include "util.h"
NEXTPNR_NAMESPACE_BEGIN
-PlaceValidityChecker::PlaceValidityChecker(Context *ctx)
- : ctx(ctx), id_icestorm_lc(ctx, "ICESTORM_LC"), id_sb_io(ctx, "SB_IO"), id_sb_gb(ctx, "SB_GB"),
- id_cen(ctx, "CEN"), id_clk(ctx, "CLK"), id_sr(ctx, "SR"), id_i0(ctx, "I0"), id_i1(ctx, "I1"),
- id_i2(ctx, "I2"), id_i3(ctx, "I3"), id_dff_en(ctx, "DFF_ENABLE"), id_neg_clk(ctx, "NEG_CLK")
-{
-}
-
static const NetInfo *get_net_or_empty(const CellInfo *cell, const IdString port)
{
auto found = cell->ports.find(port);
@@ -40,7 +33,7 @@ static const NetInfo *get_net_or_empty(const CellInfo *cell, const IdString port
return nullptr;
};
-bool PlaceValidityChecker::logicCellsCompatible(const Context *ctx, const std::vector<const CellInfo *> &cells)
+bool Arch::logicCellsCompatible(const std::vector<const CellInfo *> &cells) const
{
bool dffs_exist = false, dffs_neg = false;
const NetInfo *cen = nullptr, *clk = nullptr, *sr = nullptr;
@@ -54,11 +47,11 @@ bool PlaceValidityChecker::logicCellsCompatible(const Context *ctx, const std::v
clk = get_net_or_empty(cell, id_clk);
sr = get_net_or_empty(cell, id_sr);
- if (!ctx->isGlobalNet(cen) && cen != nullptr)
+ if (!isGlobalNet(cen) && cen != nullptr)
locals_count++;
- if (!ctx->isGlobalNet(clk) && clk != nullptr)
+ if (!isGlobalNet(clk) && clk != nullptr)
locals_count++;
- if (!ctx->isGlobalNet(sr) && sr != nullptr)
+ if (!isGlobalNet(sr) && sr != nullptr)
locals_count++;
if (bool_or_default(cell->params, id_neg_clk)) {
@@ -91,57 +84,57 @@ bool PlaceValidityChecker::logicCellsCompatible(const Context *ctx, const std::v
return locals_count <= 32;
}
-bool PlaceValidityChecker::isBelLocationValid(BelId bel)
+bool Arch::isBelLocationValid(BelId bel) const
{
- if (ctx->getBelType(bel) == TYPE_ICESTORM_LC) {
- std::vector<const CellInfo *> cells;
- for (auto bel_other : ctx->getBelsAtSameTile(bel)) {
- IdString cell_other = ctx->getBoundBelCell(bel_other);
+ if (getBelType(bel) == TYPE_ICESTORM_LC) {
+ std::vector<const CellInfo *> bel_cells;
+ for (auto bel_other : getBelsAtSameTile(bel)) {
+ IdString cell_other = getBoundBelCell(bel_other);
if (cell_other != IdString()) {
- const CellInfo *ci_other = ctx->cells[cell_other];
- cells.push_back(ci_other);
+ const CellInfo *ci_other = cells.at(cell_other);
+ bel_cells.push_back(ci_other);
}
}
- return logicCellsCompatible(ctx, cells);
+ return logicCellsCompatible(bel_cells);
} else {
- IdString cellId = ctx->getBoundBelCell(bel);
+ IdString cellId = getBoundBelCell(bel);
if (cellId == IdString())
return true;
else
- return isValidBelForCell(ctx->cells.at(cellId), bel);
+ return isValidBelForCell(cells.at(cellId), bel);
}
}
-bool PlaceValidityChecker::isValidBelForCell(CellInfo *cell, BelId bel)
+bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
{
if (cell->type == id_icestorm_lc) {
- assert(ctx->getBelType(bel) == TYPE_ICESTORM_LC);
+ assert(getBelType(bel) == TYPE_ICESTORM_LC);
- std::vector<const CellInfo *> cells;
+ std::vector<const CellInfo *> bel_cells;
- for (auto bel_other : ctx->getBelsAtSameTile(bel)) {
- IdString cell_other = ctx->getBoundBelCell(bel_other);
- if (cell_other != IdString()) {
- const CellInfo *ci_other = ctx->cells[cell_other];
- cells.push_back(ci_other);
+ for (auto bel_other : getBelsAtSameTile(bel)) {
+ IdString cell_other = getBoundBelCell(bel_other);
+ if (cell_other != IdString() && bel_other != bel) {
+ const CellInfo *ci_other = cells.at(cell_other);
+ bel_cells.push_back(ci_other);
}
}
- cells.push_back(cell);
- return logicCellsCompatible(ctx, cells);
+ bel_cells.push_back(cell);
+ return logicCellsCompatible(bel_cells);
} else if (cell->type == id_sb_io) {
- return ctx->getBelPackagePin(bel) != "";
+ return getBelPackagePin(bel) != "";
} else if (cell->type == id_sb_gb) {
bool is_reset = false, is_cen = false;
- assert(cell->ports.at(ctx->id("GLOBAL_BUFFER_OUTPUT")).net != nullptr);
- for (auto user : cell->ports.at(ctx->id("GLOBAL_BUFFER_OUTPUT")).net->users) {
- if (is_reset_port(ctx, user))
+ assert(cell->ports.at(id_glb_buf_out).net != nullptr);
+ for (auto user : cell->ports.at(id_glb_buf_out).net->users) {
+ if (is_reset_port(this, user))
is_reset = true;
- if (is_enable_port(ctx, user))
+ if (is_enable_port(this, user))
is_cen = true;
}
- IdString glb_net = ctx->getWireName(ctx->getWireBelPin(bel, PIN_GLOBAL_BUFFER_OUTPUT));
- int glb_id = std::stoi(std::string("") + glb_net.str(ctx).back());
+ IdString glb_net = getWireName(getWireBelPin(bel, PIN_GLOBAL_BUFFER_OUTPUT));
+ int glb_id = std::stoi(std::string("") + glb_net.str(this).back());
if (is_reset && is_cen)
return false;
else if (is_reset)
diff --git a/ice40/arch_place.h b/ice40/arch_place.h
deleted file mode 100644
index 84ad2d21..00000000
--- a/ice40/arch_place.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * nextpnr -- Next Generation Place and Route
- *
- * Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com>
- * 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
- * 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, NeEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#ifndef ICE40_ARCH_PLACE_H
-#define ICE40_ARCH_PLACE_H
-
-#include "nextpnr.h"
-// Architecure-specific placement functions
-
-NEXTPNR_NAMESPACE_BEGIN
-
-class PlaceValidityChecker
-{
- public:
- PlaceValidityChecker(Context *ctx);
- // Whether or not a given cell can be placed at a given Bel
- // This is not intended for Bel type checks, but finer-grained constraints
- // such as conflicting set/reset signals, etc
- bool isValidBelForCell(CellInfo *cell, BelId bel);
-
- // Return true whether all Bels at a given location are valid
- bool isBelLocationValid(BelId bel);
-
- private:
- bool logicCellsCompatible(const Context *ctx, const std::vector<const CellInfo *> &cells);
- Context *ctx;
- IdString id_icestorm_lc, id_sb_io, id_sb_gb;
- IdString id_cen, id_clk, id_sr;
- IdString id_i0, id_i1, id_i2, id_i3;
- IdString id_dff_en, id_neg_clk;
-};
-
-NEXTPNR_NAMESPACE_END
-
-#endif
diff --git a/ice40/cells.cc b/ice40/cells.cc
index faaabba0..ddb69f4f 100644
--- a/ice40/cells.cc
+++ b/ice40/cells.cc
@@ -227,7 +227,7 @@ void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio)
}
}
-bool is_clock_port(const Context *ctx, const PortRef &port)
+bool is_clock_port(const BaseCtx *ctx, const PortRef &port)
{
if (port.cell == nullptr)
return false;
@@ -240,7 +240,7 @@ bool is_clock_port(const Context *ctx, const PortRef &port)
return false;
}
-bool is_reset_port(const Context *ctx, const PortRef &port)
+bool is_reset_port(const BaseCtx *ctx, const PortRef &port)
{
if (port.cell == nullptr)
return false;
@@ -251,7 +251,7 @@ bool is_reset_port(const Context *ctx, const PortRef &port)
return false;
}
-bool is_enable_port(const Context *ctx, const PortRef &port)
+bool is_enable_port(const BaseCtx *ctx, const PortRef &port)
{
if (port.cell == nullptr)
return false;
diff --git a/ice40/cells.h b/ice40/cells.h
index 7b5e63d9..a8891598 100644
--- a/ice40/cells.h
+++ b/ice40/cells.h
@@ -30,10 +30,10 @@ NEXTPNR_NAMESPACE_BEGIN
CellInfo *create_ice_cell(Context *ctx, IdString type, std::string name = "");
// Return true if a cell is a LUT
-inline bool is_lut(const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_LUT4"); }
+inline bool is_lut(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_LUT4"); }
// Return true if a cell is a flipflop
-inline bool is_ff(const Context *ctx, const CellInfo *cell)
+inline bool is_ff(const BaseCtx *ctx, const CellInfo *cell)
{
return cell->type == ctx->id("SB_DFF") || cell->type == ctx->id("SB_DFFE") || cell->type == ctx->id("SB_DFFSR") ||
cell->type == ctx->id("SB_DFFR") || cell->type == ctx->id("SB_DFFSS") || cell->type == ctx->id("SB_DFFS") ||
@@ -46,26 +46,26 @@ inline bool is_ff(const Context *ctx, const CellInfo *cell)
cell->type == ctx->id("SB_DFFNESS") || cell->type == ctx->id("SB_DFFNES");
}
-inline bool is_carry(const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_CARRY"); }
+inline bool is_carry(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_CARRY"); }
-inline bool is_lc(const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("ICESTORM_LC"); }
+inline bool is_lc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("ICESTORM_LC"); }
// Return true if a cell is a SB_IO
-inline bool is_sb_io(const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_IO"); }
+inline bool is_sb_io(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_IO"); }
// Return true if a cell is a global buffer
-inline bool is_gbuf(const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_GB"); }
+inline bool is_gbuf(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_GB"); }
// Return true if a cell is a RAM
-inline bool is_ram(const Context *ctx, const CellInfo *cell)
+inline bool is_ram(const BaseCtx *ctx, const CellInfo *cell)
{
return cell->type == ctx->id("SB_RAM40_4K") || cell->type == ctx->id("SB_RAM40_4KNR") ||
cell->type == ctx->id("SB_RAM40_4KNW") || cell->type == ctx->id("SB_RAM40_4KNRNW");
}
-inline bool is_sb_lfosc(const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_LFOSC"); }
+inline bool is_sb_lfosc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_LFOSC"); }
-inline bool is_sb_hfosc(const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_HFOSC"); }
+inline bool is_sb_hfosc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_HFOSC"); }
// Convert a SB_LUT primitive to (part of) an ICESTORM_LC, swapping ports
// as needed. Set no_dff if a DFF is not being used, so that the output
@@ -82,13 +82,13 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l
void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio);
// Return true if a port is a clock port
-bool is_clock_port(const Context *ctx, const PortRef &port);
+bool is_clock_port(const BaseCtx *ctx, const PortRef &port);
// Return true if a port is a reset port
-bool is_reset_port(const Context *ctx, const PortRef &port);
+bool is_reset_port(const BaseCtx *ctx, const PortRef &port);
// Return true if a port is a clock enable port
-bool is_enable_port(const Context *ctx, const PortRef &port);
+bool is_enable_port(const BaseCtx *ctx, const PortRef &port);
NEXTPNR_NAMESPACE_END
diff --git a/ice40/main.cc b/ice40/main.cc
index 6a5e6687..8babf8b9 100644
--- a/ice40/main.cc
+++ b/ice40/main.cc
@@ -125,16 +125,18 @@ int main(int argc, char *argv[])
if (vm.count("help") || argc == 1) {
help:
- std::cout << boost::filesystem::basename(argv[0]) << " -- Next Generation Place and Route (git "
- "sha1 " GIT_COMMIT_HASH_STR ")\n";
+ std::cout << boost::filesystem::basename(argv[0])
+ << " -- Next Generation Place and Route (git "
+ "sha1 " GIT_COMMIT_HASH_STR ")\n";
std::cout << "\n";
std::cout << options << "\n";
return argc != 1;
}
if (vm.count("version")) {
- std::cout << boost::filesystem::basename(argv[0]) << " -- Next Generation Place and Route (git "
- "sha1 " GIT_COMMIT_HASH_STR ")\n";
+ std::cout << boost::filesystem::basename(argv[0])
+ << " -- Next Generation Place and Route (git "
+ "sha1 " GIT_COMMIT_HASH_STR ")\n";
return 1;
}