From 79d1075345010c025c014786d184ad648777f61c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 18 Jun 2018 17:08:35 +0200 Subject: Getting rid of old IdString API users, Add ctx to many internal APIs Signed-off-by: Clifford Wolf --- common/design_utils.h | 13 ++++--- common/place_sa.cc | 19 +++++----- common/rulecheck.cc | 23 ++++++------ ice40/arch_place.cc | 17 ++++----- ice40/bitstream.cc | 54 ++++++++++++++++------------- ice40/cells.cc | 96 ++++++++++++++++++++++++++------------------------- ice40/cells.h | 71 ++++++++++++++++++++++++------------- ice40/main.cc | 2 +- ice40/pack.cc | 47 +++++++++++++------------ 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 -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 -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 &cells) +static bool logicCellsCompatible(const Context *ctx, + const std::vector &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 &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 ¶m, - 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 ¶m, return defval; } -std::string get_param_str_or_def(const CellInfo *cell, const std::string ¶m, +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 lc(20, false); // From arachne-pnr static std::vector 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 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 << "\n"; for (auto bel : ctx.getBels()) { - std::cout << "\n"; + std::cout << "\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 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 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 = -- cgit v1.2.3