aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/design_utils.h13
-rw-r--r--common/place_sa.cc19
-rw-r--r--common/rulecheck.cc23
-rw-r--r--ice40/arch_place.cc17
-rw-r--r--ice40/bitstream.cc54
-rw-r--r--ice40/cells.cc96
-rw-r--r--ice40/cells.h71
-rw-r--r--ice40/main.cc2
-rw-r--r--ice40/pack.cc47
9 files changed, 191 insertions, 151 deletions
diff --git a/common/design_utils.h b/common/design_utils.h
index 2177c0e5..d7f0b733 100644
--- a/common/design_utils.h
+++ b/common/design_utils.h
@@ -41,8 +41,9 @@ void replace_port(CellInfo *old_cell, IdString old_name, CellInfo *rep_cell,
// true, then this cell must be the only load. If ignore_cell is set, that cell
// is not considered
template <typename F1>
-CellInfo *net_only_drives(NetInfo *net, F1 cell_pred, IdString port,
- bool exclusive = false, CellInfo *exclude = nullptr)
+CellInfo *net_only_drives(const Context *ctx, NetInfo *net, F1 cell_pred,
+ IdString port, bool exclusive = false,
+ CellInfo *exclude = nullptr)
{
if (net == nullptr)
return nullptr;
@@ -63,7 +64,8 @@ CellInfo *net_only_drives(NetInfo *net, F1 cell_pred, IdString port,
}
}
for (const auto &load : net->users) {
- if (load.cell != exclude && cell_pred(load.cell) && load.port == port) {
+ if (load.cell != exclude && cell_pred(ctx, load.cell) &&
+ load.port == port) {
return load.cell;
}
}
@@ -73,11 +75,12 @@ CellInfo *net_only_drives(NetInfo *net, F1 cell_pred, IdString port,
// If a net is driven by a given port of a cell matching a predicate, return
// that cell, otherwise nullptr
template <typename F1>
-CellInfo *net_driven_by(const NetInfo *net, F1 cell_pred, IdString port)
+CellInfo *net_driven_by(const Context *ctx, const NetInfo *net, F1 cell_pred,
+ IdString port)
{
if (net == nullptr)
return nullptr;
- if (cell_pred(net->driver.cell) && net->driver.port == port) {
+ if (cell_pred(ctx, net->driver.cell) && net->driver.port == port) {
return net->driver.cell;
} else {
return nullptr;
diff --git a/common/place_sa.cc b/common/place_sa.cc
index e49cff7a..a5e7c55d 100644
--- a/common/place_sa.cc
+++ b/common/place_sa.cc
@@ -108,7 +108,7 @@ static void place_initial(Context *ctx, CellInfo *cell, rnd_state &rnd)
if (best_bel == BelId()) {
if (iters == 0 || ripup_bel == BelId())
log_error("failed to place cell '%s' of type '%s'\n",
- cell->name.c_str(), cell->type.c_str());
+ cell->name.c_str(ctx), cell->type.c_str(ctx));
--iters;
ctx->unbindBel(ripup_target->bel);
ripup_target->bel = BelId();
@@ -120,7 +120,7 @@ static void place_initial(Context *ctx, CellInfo *cell, rnd_state &rnd)
ctx->bindBel(cell->bel, cell->name);
// Back annotate location
- cell->attrs["BEL"] = ctx->getBelName(cell->bel).str();
+ cell->attrs[ctx->id("BEL")] = ctx->getBelName(cell->bel).str(ctx);
cell = ripup_target;
}
}
@@ -294,22 +294,23 @@ void place_design_sa(Context *ctx, int seed)
// Initial constraints placer
for (auto cell_entry : ctx->cells) {
CellInfo *cell = cell_entry.second;
- auto loc = cell->attrs.find("BEL");
+ auto loc = cell->attrs.find(ctx->id("BEL"));
if (loc != cell->attrs.end()) {
std::string loc_name = loc->second;
- BelId bel = ctx->getBelByName(IdString(loc_name));
+ BelId bel = ctx->getBelByName(ctx->id(loc_name));
if (bel == BelId()) {
log_error("No Bel named \'%s\' located for "
"this chip (processing BEL attribute on \'%s\')\n",
- loc_name.c_str(), cell->name.c_str());
+ loc_name.c_str(), cell->name.c_str(ctx));
}
BelType bel_type = ctx->getBelType(bel);
if (bel_type != ctx->belTypeFromId(cell->type)) {
log_error("Bel \'%s\' of type \'%s\' does not match cell "
"\'%s\' of type \'%s\'",
- loc_name.c_str(), ctx->belTypeToId(bel_type).c_str(),
- cell->name.c_str(), cell->type.c_str());
+ loc_name.c_str(),
+ ctx->belTypeToId(bel_type).c_str(ctx),
+ cell->name.c_str(ctx), cell->type.c_str(ctx));
}
cell->bel = bel;
@@ -436,9 +437,9 @@ void place_design_sa(Context *ctx, int seed)
std::string cell_text = "no cell";
IdString cell = ctx->getBelCell(bel, false);
if (cell != IdString())
- cell_text = std::string("cell '") + cell.str() + "'";
+ cell_text = std::string("cell '") + cell.str(ctx) + "'";
log_error("post-placement validity check failed for Bel '%s' (%s)",
- ctx->getBelName(bel).c_str(), cell_text.c_str());
+ ctx->getBelName(bel).c_str(ctx), cell_text.c_str());
}
}
}
diff --git a/common/rulecheck.cc b/common/rulecheck.cc
index 2f70498f..9b1ee7fe 100644
--- a/common/rulecheck.cc
+++ b/common/rulecheck.cc
@@ -16,27 +16,27 @@ bool check_all_nets_driven(Context *ctx)
if (debug)
log_info(" Examining cell \'%s\', of type \'%s\'\n",
- cell->name.c_str(), cell->type.c_str());
+ cell->name.c_str(ctx), cell->type.c_str(ctx));
for (auto port_entry : cell->ports) {
PortInfo &port = port_entry.second;
if (debug)
log_info(" Checking name of port \'%s\' "
"against \'%s\'\n",
- port_entry.first.c_str(), port.name.c_str());
+ port_entry.first.c_str(ctx), port.name.c_str(ctx));
assert(port.name == port_entry.first);
- assert(port.name.size() > 0);
+ assert(!port.name.empty());
if (port.net == NULL) {
if (debug)
log_warning(
" Port \'%s\' in cell \'%s\' is unconnected\n",
- port.name.c_str(), cell->name.c_str());
+ port.name.c_str(ctx), cell->name.c_str(ctx));
} else {
assert(port.net);
if (debug)
log_info(" Checking for a net named \'%s\'\n",
- port.net->name.c_str());
+ port.net->name.c_str(ctx));
assert(ctx->nets.count(port.net->name) > 0);
}
}
@@ -46,22 +46,23 @@ bool check_all_nets_driven(Context *ctx)
NetInfo *net = net_entry.second;
assert(net->name == net_entry.first);
- if ((net->driver.cell != NULL) && (net->driver.cell->type != "GND") &&
- (net->driver.cell->type != "VCC")) {
+ if ((net->driver.cell != NULL) &&
+ (net->driver.cell->type != ctx->id("GND")) &&
+ (net->driver.cell->type != ctx->id("VCC"))) {
if (debug)
log_info(" Checking for a driver cell named \'%s\'\n",
- net->driver.cell->name.c_str());
+ net->driver.cell->name.c_str(ctx));
assert(ctx->cells.count(net->driver.cell->name) > 0);
}
for (auto user : net->users) {
- if ((user.cell != NULL) && (user.cell->type != "GND") &&
- (user.cell->type != "VCC")) {
+ if ((user.cell != NULL) && (user.cell->type != ctx->id("GND")) &&
+ (user.cell->type != ctx->id("VCC"))) {
if (debug)
log_info(" Checking for a user cell named \'%s\'\n",
- user.cell->name.c_str());
+ user.cell->name.c_str(ctx));
assert(ctx->cells.count(user.cell->name) > 0);
}
}
diff --git a/ice40/arch_place.cc b/ice40/arch_place.cc
index faa6b187..6223c801 100644
--- a/ice40/arch_place.cc
+++ b/ice40/arch_place.cc
@@ -34,7 +34,8 @@ static const NetInfo *get_net_or_empty(const CellInfo *cell,
return nullptr;
};
-static bool logicCellsCompatible(const std::vector<const CellInfo *> &cells)
+static bool logicCellsCompatible(const Context *ctx,
+ const std::vector<const CellInfo *> &cells)
{
bool dffs_exist = false, dffs_neg = false;
const NetInfo *cen = nullptr, *clk = nullptr, *sr = nullptr;
@@ -49,11 +50,11 @@ static bool logicCellsCompatible(const std::vector<const CellInfo *> &cells)
clk = get_net_or_empty(cell, "CLK");
sr = get_net_or_empty(cell, "SR");
- if (!is_global_net(cen) && cen != nullptr)
+ if (!is_global_net(ctx, cen) && cen != nullptr)
locals.insert(cen->name);
- if (!is_global_net(clk) && clk != nullptr)
+ if (!is_global_net(ctx, clk) && clk != nullptr)
locals.insert(clk->name);
- if (!is_global_net(sr) && sr != nullptr)
+ if (!is_global_net(ctx, sr) && sr != nullptr)
locals.insert(sr->name);
if (bool_or_default(cell->params, "NEG_CLK")) {
@@ -99,7 +100,7 @@ bool isBelLocationValid(Context *ctx, BelId bel)
cells.push_back(ci_other);
}
}
- return logicCellsCompatible(cells);
+ return logicCellsCompatible(ctx, cells);
} else {
IdString cellId = ctx->getBelCell(bel, false);
if (cellId == IdString())
@@ -125,16 +126,16 @@ bool isValidBelForCell(Context *ctx, CellInfo *cell, BelId bel)
}
cells.push_back(cell);
- return logicCellsCompatible(cells);
+ return logicCellsCompatible(ctx, cells);
} else if (cell->type == "SB_IO") {
return ctx->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))
+ if (is_reset_port(ctx, user))
is_reset = true;
- if (is_enable_port(user))
+ if (is_enable_port(ctx, user))
is_cen = true;
}
IdString glb_net = ctx->getWireName(
diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc
index 8b28842c..8754fef7 100644
--- a/ice40/bitstream.cc
+++ b/ice40/bitstream.cc
@@ -73,8 +73,7 @@ void set_config(const TileInfoPOD &ti,
}
}
-int get_param_or_def(const CellInfo *cell, const std::string &param,
- int defval = 0)
+int get_param_or_def(const CellInfo *cell, const IdString param, int defval = 0)
{
auto found = cell->params.find(param);
if (found != cell->params.end())
@@ -83,7 +82,7 @@ int get_param_or_def(const CellInfo *cell, const std::string &param,
return defval;
}
-std::string get_param_str_or_def(const CellInfo *cell, const std::string &param,
+std::string get_param_str_or_def(const CellInfo *cell, const IdString param,
std::string defval = "")
{
auto found = cell->params.find(param);
@@ -153,20 +152,24 @@ void write_asc(const Context *ctx, std::ostream &out)
for (auto cell : ctx->cells) {
BelId bel = cell.second->bel;
if (bel == BelId()) {
- std::cout << "Found unplaced cell " << cell.first
+ std::cout << "Found unplaced cell " << cell.first.str(ctx)
<< " while generating bitstream!" << std::endl;
continue;
}
const BelInfoPOD &beli = ci.bel_data[bel.index];
int x = beli.x, y = beli.y, z = beli.z;
- if (cell.second->type == "ICESTORM_LC") {
+ if (cell.second->type == ctx->id("ICESTORM_LC")) {
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_LOGIC];
- unsigned lut_init = get_param_or_def(cell.second, "LUT_INIT");
- bool neg_clk = get_param_or_def(cell.second, "NEG_CLK");
- bool dff_enable = get_param_or_def(cell.second, "DFF_ENABLE");
- bool async_sr = get_param_or_def(cell.second, "ASYNC_SR");
- bool set_noreset = get_param_or_def(cell.second, "SET_NORESET");
- bool carry_enable = get_param_or_def(cell.second, "CARRY_ENABLE");
+ unsigned lut_init =
+ get_param_or_def(cell.second, ctx->id("LUT_INIT"));
+ bool neg_clk = get_param_or_def(cell.second, ctx->id("NEG_CLK"));
+ bool dff_enable =
+ get_param_or_def(cell.second, ctx->id("DFF_ENABLE"));
+ bool async_sr = get_param_or_def(cell.second, ctx->id("ASYNC_SR"));
+ bool set_noreset =
+ get_param_or_def(cell.second, ctx->id("SET_NORESET"));
+ bool carry_enable =
+ get_param_or_def(cell.second, ctx->id("CARRY_ENABLE"));
std::vector<bool> lc(20, false);
// From arachne-pnr
static std::vector<int> lut_perm = {
@@ -186,11 +189,13 @@ void write_asc(const Context *ctx, std::ostream &out)
lc.at(i), i);
if (dff_enable)
set_config(ti, config.at(y).at(x), "NegClk", neg_clk);
- } else if (cell.second->type == "SB_IO") {
+ } else if (cell.second->type == ctx->id("SB_IO")) {
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO];
- unsigned pin_type = get_param_or_def(cell.second, "PIN_TYPE");
- bool neg_trigger = get_param_or_def(cell.second, "NEG_TRIGGER");
- bool pullup = get_param_or_def(cell.second, "PULLUP");
+ unsigned pin_type =
+ get_param_or_def(cell.second, ctx->id("PIN_TYPE"));
+ bool neg_trigger =
+ get_param_or_def(cell.second, ctx->id("NEG_TRIGGER"));
+ bool pullup = get_param_or_def(cell.second, ctx->id("PULLUP"));
for (int i = 0; i < 6; i++) {
bool val = (pin_type >> i) & 0x01;
set_config(ti, config.at(y).at(x),
@@ -224,9 +229,9 @@ void write_asc(const Context *ctx, std::ostream &out)
set_config(ti, config.at(iey).at(iex),
"IoCtrl.REN_" + std::to_string(iez), !pullup);
}
- } else if (cell.second->type == "SB_GB") {
+ } else if (cell.second->type == ctx->id("SB_GB")) {
// no cell config bits
- } else if (cell.second->type == "ICESTORM_RAM") {
+ } else if (cell.second->type == ctx->id("ICESTORM_RAM")) {
const BelInfoPOD &beli = ci.bel_data[bel.index];
int x = beli.x, y = beli.y;
const TileInfoPOD &ti_ramt = bi.tiles_nonrouting[TILE_RAMT];
@@ -236,10 +241,11 @@ void write_asc(const Context *ctx, std::ostream &out)
set_config(ti_ramb, config.at(y).at(x), "RamConfig.PowerUp",
true);
}
- bool negclk_r = get_param_or_def(cell.second, "NEG_CLK_R");
- bool negclk_w = get_param_or_def(cell.second, "NEG_CLK_W");
- int write_mode = get_param_or_def(cell.second, "WRITE_MODE");
- int read_mode = get_param_or_def(cell.second, "READ_MODE");
+ bool negclk_r = get_param_or_def(cell.second, ctx->id("NEG_CLK_R"));
+ bool negclk_w = get_param_or_def(cell.second, ctx->id("NEG_CLK_W"));
+ int write_mode =
+ get_param_or_def(cell.second, ctx->id("WRITE_MODE"));
+ int read_mode = get_param_or_def(cell.second, ctx->id("READ_MODE"));
set_config(ti_ramb, config.at(y).at(x), "NegClk", negclk_w);
set_config(ti_ramt, config.at(y + 1).at(x), "NegClk", negclk_r);
@@ -373,7 +379,7 @@ void write_asc(const Context *ctx, std::ostream &out)
// Write RAM init data
for (auto cell : ctx->cells) {
if (cell.second->bel != BelId()) {
- if (cell.second->type == "ICESTORM_RAM") {
+ if (cell.second->type == ctx->id("ICESTORM_RAM")) {
const BelInfoPOD &beli = ci.bel_data[cell.second->bel.index];
int x = beli.x, y = beli.y;
out << ".ram_data " << x << " " << y << std::endl;
@@ -381,7 +387,7 @@ void write_asc(const Context *ctx, std::ostream &out)
std::vector<bool> bits(256);
std::string init = get_param_str_or_def(
cell.second,
- std::string("INIT_") + get_hexdigit(w));
+ ctx->id(std::string("INIT_") + get_hexdigit(w)));
assert(init != "");
for (int i = 0; i < init.size(); i++) {
bool val = (init.at((init.size() - 1) - i) == '1');
@@ -404,7 +410,7 @@ void write_asc(const Context *ctx, std::ostream &out)
for (auto wire : ctx->getWires()) {
IdString net = ctx->getWireNet(wire, false);
if (net != IdString())
- out << ".sym " << wire.index << " " << net << std::endl;
+ out << ".sym " << wire.index << " " << net.str(ctx) << std::endl;
}
}
diff --git a/ice40/cells.cc b/ice40/cells.cc
index 16cbd68d..35761949 100644
--- a/ice40/cells.cc
+++ b/ice40/cells.cc
@@ -24,7 +24,8 @@
NEXTPNR_NAMESPACE_BEGIN
-static void add_port(CellInfo *cell, IdString name, PortType dir)
+static void add_port(const Context *ctx, CellInfo *cell, IdString name,
+ PortType dir)
{
cell->ports[name] = PortInfo{name, nullptr, dir};
}
@@ -48,72 +49,72 @@ CellInfo *create_ice_cell(Context *ctx, IdString type, IdString name)
new_cell->params["SET_NORESET"] = "0";
new_cell->params["ASYNC_SR"] = "0";
- add_port(new_cell, "I0", PORT_IN);
- add_port(new_cell, "I1", PORT_IN);
- add_port(new_cell, "I2", PORT_IN);
- add_port(new_cell, "I3", PORT_IN);
- add_port(new_cell, "CIN", PORT_IN);
+ add_port(ctx, new_cell, "I0", PORT_IN);
+ add_port(ctx, new_cell, "I1", PORT_IN);
+ add_port(ctx, new_cell, "I2", PORT_IN);
+ add_port(ctx, new_cell, "I3", PORT_IN);
+ add_port(ctx, new_cell, "CIN", PORT_IN);
- add_port(new_cell, "CLK", PORT_IN);
- add_port(new_cell, "CEN", PORT_IN);
- add_port(new_cell, "SR", PORT_IN);
+ add_port(ctx, new_cell, "CLK", PORT_IN);
+ add_port(ctx, new_cell, "CEN", PORT_IN);
+ add_port(ctx, new_cell, "SR", PORT_IN);
- add_port(new_cell, "LO", PORT_OUT);
- add_port(new_cell, "O", PORT_OUT);
- add_port(new_cell, "OUT", PORT_OUT);
+ add_port(ctx, new_cell, "LO", PORT_OUT);
+ add_port(ctx, new_cell, "O", PORT_OUT);
+ add_port(ctx, new_cell, "OUT", PORT_OUT);
} else if (type == "SB_IO") {
new_cell->params["PIN_TYPE"] = "0";
new_cell->params["PULLUP"] = "0";
new_cell->params["NEG_TRIGGER"] = "0";
new_cell->params["IOSTANDARD"] = "SB_LVCMOS";
- add_port(new_cell, "PACKAGE_PIN", PORT_INOUT);
+ add_port(ctx, new_cell, "PACKAGE_PIN", PORT_INOUT);
- add_port(new_cell, "LATCH_INPUT_VALUE", PORT_IN);
- add_port(new_cell, "CLOCK_ENABLE", PORT_IN);
- add_port(new_cell, "INPUT_CLK", PORT_IN);
- add_port(new_cell, "OUTPUT_CLK", PORT_IN);
+ add_port(ctx, new_cell, "LATCH_INPUT_VALUE", PORT_IN);
+ add_port(ctx, new_cell, "CLOCK_ENABLE", PORT_IN);
+ add_port(ctx, new_cell, "INPUT_CLK", PORT_IN);
+ add_port(ctx, new_cell, "OUTPUT_CLK", PORT_IN);
- add_port(new_cell, "OUTPUT_ENABLE", PORT_IN);
- add_port(new_cell, "D_OUT_0", PORT_IN);
- add_port(new_cell, "D_OUT_1", PORT_IN);
+ add_port(ctx, new_cell, "OUTPUT_ENABLE", PORT_IN);
+ add_port(ctx, new_cell, "D_OUT_0", PORT_IN);
+ add_port(ctx, new_cell, "D_OUT_1", PORT_IN);
- add_port(new_cell, "D_IN_0", PORT_OUT);
- add_port(new_cell, "D_IN_1", PORT_OUT);
+ add_port(ctx, new_cell, "D_IN_0", PORT_OUT);
+ add_port(ctx, new_cell, "D_IN_1", PORT_OUT);
} else if (type == "ICESTORM_RAM") {
new_cell->params["NEG_CLK_W"] = "0";
new_cell->params["NEG_CLK_R"] = "0";
new_cell->params["WRITE_MODE"] = "0";
new_cell->params["READ_MODE"] = "0";
- add_port(new_cell, "RCLK", PORT_IN);
- add_port(new_cell, "RCLKE", PORT_IN);
- add_port(new_cell, "RE", PORT_IN);
+ add_port(ctx, new_cell, "RCLK", PORT_IN);
+ add_port(ctx, new_cell, "RCLKE", PORT_IN);
+ add_port(ctx, new_cell, "RE", PORT_IN);
- add_port(new_cell, "WCLK", PORT_IN);
- add_port(new_cell, "WCLKE", PORT_IN);
- add_port(new_cell, "WE", PORT_IN);
+ add_port(ctx, new_cell, "WCLK", PORT_IN);
+ add_port(ctx, new_cell, "WCLKE", PORT_IN);
+ add_port(ctx, new_cell, "WE", PORT_IN);
for (int i = 0; i < 16; i++) {
- add_port(new_cell, "WDATA_" + std::to_string(i), PORT_IN);
- add_port(new_cell, "MASK_" + std::to_string(i), PORT_IN);
- add_port(new_cell, "RDATA_" + std::to_string(i), PORT_OUT);
+ add_port(ctx, new_cell, "WDATA_" + std::to_string(i), PORT_IN);
+ add_port(ctx, new_cell, "MASK_" + std::to_string(i), PORT_IN);
+ add_port(ctx, new_cell, "RDATA_" + std::to_string(i), PORT_OUT);
}
for (int i = 0; i < 11; i++) {
- add_port(new_cell, "RADDR_" + std::to_string(i), PORT_IN);
- add_port(new_cell, "WADDR_" + std::to_string(i), PORT_IN);
+ add_port(ctx, new_cell, "RADDR_" + std::to_string(i), PORT_IN);
+ add_port(ctx, new_cell, "WADDR_" + std::to_string(i), PORT_IN);
}
} else if (type == "SB_GB") {
- add_port(new_cell, "USER_SIGNAL_TO_GLOBAL_BUFFER", PORT_IN);
- add_port(new_cell, "GLOBAL_BUFFER_OUTPUT", PORT_OUT);
+ add_port(ctx, new_cell, "USER_SIGNAL_TO_GLOBAL_BUFFER", PORT_IN);
+ add_port(ctx, new_cell, "GLOBAL_BUFFER_OUTPUT", PORT_OUT);
} else {
log_error("unable to create iCE40 cell of type %s", type.c_str());
}
return new_cell;
}
-void lut_to_lc(CellInfo *lut, CellInfo *lc, bool no_dff)
+void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff)
{
lc->params["LUT_INIT"] = lut->params["LUT_INIT"];
replace_port(lut, "I0", lc, "I0");
@@ -126,7 +127,8 @@ void lut_to_lc(CellInfo *lut, CellInfo *lc, bool no_dff)
}
}
-void dff_to_lc(CellInfo *dff, CellInfo *lc, bool pass_thru_lut)
+void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc,
+ bool pass_thru_lut)
{
lc->params["DFF_ENABLE"] = "1";
std::string config = dff->type.str().substr(6);
@@ -176,7 +178,7 @@ void dff_to_lc(CellInfo *dff, CellInfo *lc, bool pass_thru_lut)
replace_port(dff, "Q", lc, "O");
}
-void nxio_to_sb(CellInfo *nxio, CellInfo *sbio)
+void nxio_to_sb(const Context *ctx, CellInfo *nxio, CellInfo *sbio)
{
if (nxio->type == "$nextpnr_ibuf") {
sbio->params["PIN_TYPE"] = "1";
@@ -192,44 +194,44 @@ void nxio_to_sb(CellInfo *nxio, CellInfo *sbio)
}
}
-bool is_clock_port(const PortRef &port)
+bool is_clock_port(const Context *ctx, const PortRef &port)
{
if (port.cell == nullptr)
return false;
- if (is_ff(port.cell))
+ if (is_ff(ctx, port.cell))
return port.port == "C";
if (port.cell->type == "ICESTORM_LC")
return port.port == "CLK";
- if (is_ram(port.cell) || port.cell->type == "ICESTORM_RAM")
+ if (is_ram(ctx, port.cell) || port.cell->type == "ICESTORM_RAM")
return port.port == "RCLK" || port.port == "WCLK";
return false;
}
-bool is_reset_port(const PortRef &port)
+bool is_reset_port(const Context *ctx, const PortRef &port)
{
if (port.cell == nullptr)
return false;
- if (is_ff(port.cell))
+ if (is_ff(ctx, port.cell))
return port.port == "R" || port.port == "S";
if (port.cell->type == "ICESTORM_LC")
return port.port == "SR";
return false;
}
-bool is_enable_port(const PortRef &port)
+bool is_enable_port(const Context *ctx, const PortRef &port)
{
if (port.cell == nullptr)
return false;
- if (is_ff(port.cell))
+ if (is_ff(ctx, port.cell))
return port.port == "E";
if (port.cell->type == "ICESTORM_LC")
return port.port == "CEN";
return false;
}
-bool is_global_net(const NetInfo *net)
+bool is_global_net(const Context *ctx, const NetInfo *net)
{
- return bool(net_driven_by(net, is_gbuf, "GLOBAL_BUFFER_OUTPUT"));
+ return bool(net_driven_by(ctx, net, is_gbuf, "GLOBAL_BUFFER_OUTPUT"));
}
NEXTPNR_NAMESPACE_END
diff --git a/ice40/cells.h b/ice40/cells.h
index 5bea420d..bd07563e 100644
--- a/ice40/cells.h
+++ b/ice40/cells.h
@@ -31,61 +31,84 @@ CellInfo *create_ice_cell(Context *ctx, IdString type,
IdString name = IdString());
// Return true if a cell is a LUT
-inline bool is_lut(const CellInfo *cell) { return cell->type == "SB_LUT4"; }
+inline bool is_lut(const Context *ctx, const CellInfo *cell)
+{
+ return cell->type == ctx->id("SB_LUT4");
+}
// Return true if a cell is a flipflop
-inline bool is_ff(const CellInfo *cell)
+inline bool is_ff(const Context *ctx, const CellInfo *cell)
{
- return cell->type == "SB_DFF" || cell->type == "SB_DFFE" ||
- cell->type == "SB_DFFSR" || cell->type == "SB_DFFR" ||
- cell->type == "SB_DFFSS" || cell->type == "SB_DFFS" ||
- cell->type == "SB_DFFESR" || cell->type == "SB_DFFER" ||
- cell->type == "SB_DFFESS" || cell->type == "SB_DFFES" ||
- cell->type == "SB_DFFN" || cell->type == "SB_DFFNE" ||
- cell->type == "SB_DFFNSR" || cell->type == "SB_DFFNR" ||
- cell->type == "SB_DFFNSS" || cell->type == "SB_DFFNS" ||
- cell->type == "SB_DFFNESR" || cell->type == "SB_DFFNER" ||
- cell->type == "SB_DFFNESS" || cell->type == "SB_DFFNES";
+ 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") ||
+ cell->type == ctx->id("SB_DFFESR") ||
+ cell->type == ctx->id("SB_DFFER") ||
+ cell->type == ctx->id("SB_DFFESS") ||
+ cell->type == ctx->id("SB_DFFES") ||
+ cell->type == ctx->id("SB_DFFN") ||
+ cell->type == ctx->id("SB_DFFNE") ||
+ cell->type == ctx->id("SB_DFFNSR") ||
+ cell->type == ctx->id("SB_DFFNR") ||
+ cell->type == ctx->id("SB_DFFNSS") ||
+ cell->type == ctx->id("SB_DFFNS") ||
+ cell->type == ctx->id("SB_DFFNESR") ||
+ cell->type == ctx->id("SB_DFFNER") ||
+ cell->type == ctx->id("SB_DFFNESS") ||
+ cell->type == ctx->id("SB_DFFNES");
}
// Return true if a cell is a SB_IO
-inline bool is_sb_io(const CellInfo *cell) { return cell->type == "SB_IO"; }
+inline bool is_sb_io(const Context *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 CellInfo *cell) { return cell->type == "SB_GB"; }
+inline bool is_gbuf(const Context *ctx, const CellInfo *cell)
+{
+ return cell->type == ctx->id("SB_GB");
+}
// Return true if a cell is a RAM
-inline bool is_ram(const CellInfo *cell)
+inline bool is_ram(const Context *ctx, const CellInfo *cell)
{
- return cell->type == "SB_RAM40_4K" || cell->type == "SB_RAM40_4KNR" ||
- cell->type == "SB_RAM40_4KNW" || cell->type == "SB_RAM40_4KNRNW";
+ 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");
}
// 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
// can be reconnected
-void lut_to_lc(CellInfo *lut, CellInfo *lc, bool no_dff = true);
+void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc,
+ bool no_dff = true);
// Convert a SB_DFFx primitive to (part of) an ICESTORM_LC, setting parameters
// and reconnecting signals as necessary. If pass_thru_lut is True, the LUT will
// be configured as pass through and D connected to I0, otherwise D will be
// ignored
-void dff_to_lc(CellInfo *dff, CellInfo *lc, bool pass_thru_lut = false);
+void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc,
+ bool pass_thru_lut = false);
// Convert a nextpnr IO buffer to a SB_IO
-void nxio_to_sb(CellInfo *nxio, CellInfo *sbio);
+void nxio_to_sb(const Context *ctx, CellInfo *nxio, CellInfo *sbio);
// Return true if a net is a global net
-bool is_global_net(const NetInfo *net);
+bool is_global_net(const Context *ctx, const NetInfo *net);
// Return true if a port is a clock port
-bool is_clock_port(const PortRef &port);
+bool is_clock_port(const Context *ctx, const PortRef &port);
// Return true if a port is a reset port
-bool is_reset_port(const PortRef &port);
+bool is_reset_port(const Context *ctx, const PortRef &port);
// Return true if a port is a clock enable port
-bool is_enable_port(const PortRef &port);
+bool is_enable_port(const Context *ctx, const PortRef &port);
NEXTPNR_NAMESPACE_END
diff --git a/ice40/main.cc b/ice40/main.cc
index 02dfe038..4fb5ea24 100644
--- a/ice40/main.cc
+++ b/ice40/main.cc
@@ -201,7 +201,7 @@ int main(int argc, char *argv[])
std::cout << "<svg xmlns=\"http://www.w3.org/2000/svg\" "
"xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
for (auto bel : ctx.getBels()) {
- std::cout << "<!-- " << ctx.getBelName(bel) << " -->\n";
+ std::cout << "<!-- " << ctx.getBelName(bel).str(&ctx) << " -->\n";
for (auto &el : ctx.getBelGraphics(bel))
svg_dump_el(el);
}
diff --git a/ice40/pack.cc b/ice40/pack.cc
index 7cdfc643..f20d3a9e 100644
--- a/ice40/pack.cc
+++ b/ice40/pack.cc
@@ -38,7 +38,7 @@ static void pack_lut_lutffs(Context *ctx)
CellInfo *ci = cell.second;
log_info("cell '%s' is of type '%s'\n", ci->name.c_str(),
ci->type.c_str());
- if (is_lut(ci)) {
+ if (is_lut(ctx, ci)) {
CellInfo *packed =
create_ice_cell(ctx, "ICESTORM_LC", ci->name.str() + "_LC");
std::copy(ci->attrs.begin(), ci->attrs.end(),
@@ -50,7 +50,7 @@ static void pack_lut_lutffs(Context *ctx)
// See if we can pack into a DFF
// TODO: LUT cascade
NetInfo *o = ci->ports.at("O").net;
- CellInfo *dff = net_only_drives(o, is_ff, "D", true);
+ CellInfo *dff = net_only_drives(ctx, o, is_ff, "D", true);
auto lut_bel = ci->attrs.find("BEL");
bool packed_dff = false;
if (dff) {
@@ -60,8 +60,8 @@ static void pack_lut_lutffs(Context *ctx)
lut_bel->second != dff_bel->second) {
// Locations don't match, can't pack
} else {
- lut_to_lc(ci, packed, false);
- dff_to_lc(dff, packed, false);
+ lut_to_lc(ctx, ci, packed, false);
+ dff_to_lc(ctx, dff, packed, false);
ctx->nets.erase(o->name);
if (dff_bel != dff->attrs.end())
packed->attrs["BEL"] = dff_bel->second;
@@ -72,7 +72,7 @@ static void pack_lut_lutffs(Context *ctx)
}
}
if (!packed_dff) {
- lut_to_lc(ci, packed, true);
+ lut_to_lc(ctx, ci, packed, true);
}
}
}
@@ -94,7 +94,7 @@ static void pack_nonlut_ffs(Context *ctx)
for (auto cell : ctx->cells) {
CellInfo *ci = cell.second;
- if (is_ff(ci)) {
+ if (is_ff(ctx, ci)) {
CellInfo *packed = create_ice_cell(ctx, "ICESTORM_LC",
ci->name.str() + "_DFFLC");
std::copy(ci->attrs.begin(), ci->attrs.end(),
@@ -103,7 +103,7 @@ static void pack_nonlut_ffs(Context *ctx)
packed->name.c_str());
packed_cells.insert(ci->name);
new_cells.push_back(packed);
- dff_to_lc(ci, packed, true);
+ dff_to_lc(ctx, ci, packed, true);
}
}
for (auto pcell : packed_cells) {
@@ -124,7 +124,7 @@ static void pack_ram(Context *ctx)
for (auto cell : ctx->cells) {
CellInfo *ci = cell.second;
- if (is_ram(ci)) {
+ if (is_ram(ctx, ci)) {
CellInfo *packed = create_ice_cell(ctx, "ICESTORM_RAM",
ci->name.str() + "_RAM");
packed_cells.insert(ci->name);
@@ -161,14 +161,16 @@ static void pack_ram(Context *ctx)
}
// Merge a net into a constant net
-static void set_net_constant(NetInfo *orig, NetInfo *constnet, bool constval)
+static void set_net_constant(const Context *ctx, NetInfo *orig,
+ NetInfo *constnet, bool constval)
{
orig->driver.cell = nullptr;
for (auto user : orig->users) {
if (user.cell != nullptr) {
CellInfo *uc = user.cell;
log_info("%s user %s\n", orig->name.c_str(), uc->name.c_str());
- if (is_lut(uc) && (user.port.str().at(0) == 'I') && !constval) {
+ if (is_lut(ctx, uc) && (user.port.str().at(0) == 'I') &&
+ !constval) {
uc->ports[user.port].net = nullptr;
} else {
uc->ports[user.port].net = constnet;
@@ -203,13 +205,13 @@ static void pack_constants(Context *ctx)
for (auto net : ctx->nets) {
NetInfo *ni = net.second;
if (ni->driver.cell != nullptr && ni->driver.cell->type == "GND") {
- set_net_constant(ni, gnd_net, false);
+ set_net_constant(ctx, ni, gnd_net, false);
ctx->cells[gnd_cell->name] = gnd_cell;
ctx->nets[gnd_net->name] = gnd_net;
dead_nets.push_back(net.first);
} else if (ni->driver.cell != nullptr &&
ni->driver.cell->type == "VCC") {
- set_net_constant(ni, vcc_net, true);
+ set_net_constant(ctx, ni, vcc_net, true);
ctx->cells[vcc_cell->name] = vcc_cell;
ctx->nets[vcc_net->name] = vcc_net;
dead_nets.push_back(net.first);
@@ -239,11 +241,11 @@ static void pack_io(Context *ctx)
if (is_nextpnr_iob(ci)) {
CellInfo *sb = nullptr;
if (ci->type == "$nextpnr_ibuf" || ci->type == "$nextpnr_iobuf") {
- sb = net_only_drives(ci->ports.at("O").net, is_sb_io,
+ sb = net_only_drives(ctx, ci->ports.at("O").net, is_sb_io,
"PACKAGE_PIN", true, ci);
} else if (ci->type == "$nextpnr_obuf") {
- sb = net_only_drives(ci->ports.at("I").net, is_sb_io,
+ sb = net_only_drives(ctx, ci->ports.at("I").net, is_sb_io,
"PACKAGE_PIN", true, ci);
}
if (sb != nullptr) {
@@ -260,7 +262,7 @@ static void pack_io(Context *ctx)
} else {
// Create a SB_IO buffer
sb = create_ice_cell(ctx, "SB_IO");
- nxio_to_sb(ci, sb);
+ nxio_to_sb(ctx, ci, sb);
new_cells.push_back(sb);
}
packed_cells.insert(ci->name);
@@ -297,8 +299,9 @@ static void insert_global(Context *ctx, NetInfo *net, bool is_reset,
gb->ports["GLOBAL_BUFFER_OUTPUT"].net = glbnet;
std::vector<PortRef> keep_users;
for (auto user : net->users) {
- if (is_clock_port(user) || (is_reset && is_reset_port(user)) ||
- (is_cen && is_enable_port(user))) {
+ if (is_clock_port(ctx, user) ||
+ (is_reset && is_reset_port(ctx, user)) ||
+ (is_cen && is_enable_port(ctx, user))) {
user.cell->ports[user.port].net = glbnet;
glbnet->users.push_back(user);
} else {
@@ -317,17 +320,17 @@ static void promote_globals(Context *ctx)
std::unordered_map<IdString, int> clock_count, reset_count, cen_count;
for (auto net : ctx->nets) {
NetInfo *ni = net.second;
- if (ni->driver.cell != nullptr && !is_global_net(ni)) {
+ if (ni->driver.cell != nullptr && !is_global_net(ctx, ni)) {
clock_count[net.first] = 0;
reset_count[net.first] = 0;
cen_count[net.first] = 0;
for (auto user : ni->users) {
- if (is_clock_port(user))
+ if (is_clock_port(ctx, user))
clock_count[net.first]++;
- if (is_reset_port(user))
+ if (is_reset_port(ctx, user))
reset_count[net.first]++;
- if (is_enable_port(user))
+ if (is_enable_port(ctx, user))
cen_count[net.first]++;
}
}
@@ -335,7 +338,7 @@ static void promote_globals(Context *ctx)
int prom_globals = 0, prom_resets = 0, prom_cens = 0;
int gbs_available = 8;
for (auto cell : ctx->cells)
- if (is_gbuf(cell.second))
+ if (is_gbuf(ctx, cell.second))
--gbs_available;
while (prom_globals < gbs_available) {
auto global_clock =