nets and cells are unique_ptr's

This commit is contained in:
Miodrag Milanovic 2018-06-25 21:33:48 +02:00
parent 64208da1f9
commit db890d3a81
14 changed files with 207 additions and 213 deletions

View File

@ -56,8 +56,8 @@ void print_utilisation(const Context *ctx)
{ {
// Sort by Bel type // Sort by Bel type
std::map<BelType, int> used_types; std::map<BelType, int> used_types;
for (auto cell : ctx->cells) { for (auto& cell : ctx->cells) {
used_types[ctx->belTypeFromId(cell.second->type)]++; used_types[ctx->belTypeFromId(cell.second.get()->type)]++;
} }
std::map<BelType, int> available_types; std::map<BelType, int> available_types;
for (auto bel : ctx->getBels()) { for (auto bel : ctx->getBels()) {

View File

@ -163,7 +163,7 @@ uint32_t Context::checksum() const
void Context::check() const void Context::check() const
{ {
for (auto &n : nets) { for (auto &n : nets) {
auto ni = n.second; auto ni = n.second.get();
assert(n.first == ni->name); assert(n.first == ni->name);
for (auto &w : ni->wires) { for (auto &w : ni->wires) {
assert(n.first == getBoundWireNet(w.first)); assert(n.first == getBoundWireNet(w.first));

View File

@ -24,6 +24,7 @@
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include <vector> #include <vector>
#include <memory>
#ifndef NEXTPNR_H #ifndef NEXTPNR_H
#define NEXTPNR_H #define NEXTPNR_H
@ -194,8 +195,8 @@ struct BaseCtx
// -------------------------------------------------------------- // --------------------------------------------------------------
std::unordered_map<IdString, NetInfo *> nets; std::unordered_map<IdString, std::unique_ptr<NetInfo>> nets;
std::unordered_map<IdString, CellInfo *> cells; std::unordered_map<IdString, std::unique_ptr<CellInfo>> cells;
BaseCtx() BaseCtx()
{ {
@ -210,12 +211,6 @@ struct BaseCtx
~BaseCtx() ~BaseCtx()
{ {
for (auto &item : nets) {
delete item.second;
}
for (auto &item : cells) {
delete item.second;
}
delete idstring_str_to_idx; delete idstring_str_to_idx;
delete idstring_idx_to_str; delete idstring_idx_to_str;
} }

View File

@ -79,8 +79,8 @@ class SAPlacer
size_t placed_cells = 0; size_t placed_cells = 0;
// Initial constraints placer // Initial constraints placer
for (auto cell_entry : ctx->cells) { for (auto& cell_entry : ctx->cells) {
CellInfo *cell = cell_entry.second; CellInfo *cell = cell_entry.second.get();
auto loc = cell->attrs.find(ctx->id("BEL")); auto loc = cell->attrs.find(ctx->id("BEL"));
if (loc != cell->attrs.end()) { if (loc != cell->attrs.end()) {
std::string loc_name = loc->second; std::string loc_name = loc->second;
@ -109,10 +109,10 @@ class SAPlacer
// Sort to-place cells for deterministic initial placement // Sort to-place cells for deterministic initial placement
std::vector<CellInfo *> autoplaced; std::vector<CellInfo *> autoplaced;
for (auto cell : ctx->cells) { for (auto& cell : ctx->cells) {
CellInfo *ci = cell.second; CellInfo *ci = cell.second.get();
if (ci->bel == BelId()) { if (ci->bel == BelId()) {
autoplaced.push_back(cell.second); autoplaced.push_back(cell.second.get());
} }
} }
std::sort(autoplaced.begin(), autoplaced.end(), [](CellInfo *a, CellInfo *b) { return a->name < b->name; }); std::sort(autoplaced.begin(), autoplaced.end(), [](CellInfo *a, CellInfo *b) { return a->name < b->name; });
@ -137,8 +137,8 @@ class SAPlacer
// Calculate wirelength after initial placement // Calculate wirelength after initial placement
curr_wirelength = 0; curr_wirelength = 0;
curr_tns = 0; curr_tns = 0;
for (auto net : ctx->nets) { for (auto& net : ctx->nets) {
wirelen_t wl = get_wirelength(net.second, curr_tns); wirelen_t wl = get_wirelength(net.second.get(), curr_tns);
wirelengths[net.first] = wl; wirelengths[net.first] = wl;
curr_wirelength += wl; curr_wirelength += wl;
} }
@ -211,8 +211,8 @@ class SAPlacer
// accumulating over time // accumulating over time
curr_wirelength = 0; curr_wirelength = 0;
curr_tns = 0; curr_tns = 0;
for (auto net : ctx->nets) { for (auto& net : ctx->nets) {
wirelen_t wl = get_wirelength(net.second, curr_tns); wirelen_t wl = get_wirelength(net.second.get(), curr_tns);
wirelengths[net.first] = wl; wirelengths[net.first] = wl;
curr_wirelength += wl; curr_wirelength += wl;
} }
@ -266,7 +266,7 @@ class SAPlacer
uint64_t score = ctx->rng64(); uint64_t score = ctx->rng64();
if (score <= best_ripup_score) { if (score <= best_ripup_score) {
best_ripup_score = score; best_ripup_score = score;
ripup_target = ctx->cells.at(ctx->getBoundBelCell(bel)); ripup_target = ctx->cells.at(ctx->getBoundBelCell(bel)).get();
ripup_bel = bel; ripup_bel = bel;
} }
} }
@ -354,7 +354,7 @@ class SAPlacer
wirelen_t new_wirelength = 0, delta; wirelen_t new_wirelength = 0, delta;
ctx->unbindBel(oldBel); ctx->unbindBel(oldBel);
if (other != IdString()) { if (other != IdString()) {
other_cell = ctx->cells[other]; other_cell = ctx->cells[other].get();
ctx->unbindBel(newBel); ctx->unbindBel(newBel);
} }

View File

@ -75,7 +75,7 @@ struct RipupScoreboard
void ripup_net(Context *ctx, IdString net_name) void ripup_net(Context *ctx, IdString net_name)
{ {
auto net_info = ctx->nets.at(net_name); auto net_info = ctx->nets.at(net_name).get();
std::vector<PipId> pips; std::vector<PipId> pips;
std::vector<WireId> wires; std::vector<WireId> wires;
@ -249,7 +249,7 @@ struct Router
Router(Context *ctx, RipupScoreboard &scores, IdString net_name, bool ripup = false, delay_t ripup_penalty = 0) Router(Context *ctx, RipupScoreboard &scores, IdString net_name, bool ripup = false, delay_t ripup_penalty = 0)
: ctx(ctx), scores(scores), net_name(net_name), ripup(ripup), ripup_penalty(ripup_penalty) : ctx(ctx), scores(scores), net_name(net_name), ripup(ripup), ripup_penalty(ripup_penalty)
{ {
auto net_info = ctx->nets.at(net_name); auto net_info = ctx->nets.at(net_name).get();
if (ctx->debug) if (ctx->debug)
log("Routing net %s.\n", net_name.c_str(ctx)); log("Routing net %s.\n", net_name.c_str(ctx));
@ -416,7 +416,7 @@ bool route_design(Context *ctx)
for (auto &net_it : ctx->nets) { for (auto &net_it : ctx->nets) {
auto net_name = net_it.first; auto net_name = net_it.first;
auto net_info = net_it.second; auto net_info = net_it.second.get();
if (net_info->driver.cell == nullptr) if (net_info->driver.cell == nullptr)
continue; continue;
@ -438,7 +438,7 @@ bool route_design(Context *ctx)
int estimatedTotalDelayCnt = 0; int estimatedTotalDelayCnt = 0;
for (auto net_name : netsQueue) { for (auto net_name : netsQueue) {
auto net_info = ctx->nets.at(net_name); auto net_info = ctx->nets.at(net_name).get();
auto src_bel = net_info->driver.cell->bel; auto src_bel = net_info->driver.cell->bel;

View File

@ -11,8 +11,8 @@ bool check_all_nets_driven(Context *ctx)
log_info("Rule checker, Verifying pre-placed design\n"); log_info("Rule checker, Verifying pre-placed design\n");
for (auto cell_entry : ctx->cells) { for (auto& cell_entry : ctx->cells) {
CellInfo *cell = cell_entry.second; CellInfo *cell = cell_entry.second.get();
if (debug) if (debug)
log_info(" Examining cell \'%s\', of type \'%s\'\n", cell->name.c_str(ctx), cell->type.c_str(ctx)); log_info(" Examining cell \'%s\', of type \'%s\'\n", cell->name.c_str(ctx), cell->type.c_str(ctx));
@ -39,8 +39,8 @@ bool check_all_nets_driven(Context *ctx)
} }
} }
for (auto net_entry : ctx->nets) { for (auto& net_entry : ctx->nets) {
NetInfo *net = net_entry.second; NetInfo *net = net_entry.second.get();
assert(net->name == net_entry.first); assert(net->name == net_entry.first);
if ((net->driver.cell != NULL) && (net->driver.cell->type != ctx->id("GND")) && if ((net->driver.cell != NULL) && (net->driver.cell->type != ctx->id("GND")) &&

View File

@ -76,16 +76,16 @@ void assign_budget(Context *ctx, float default_clock)
log_info("Annotating ports with timing budgets\n"); log_info("Annotating ports with timing budgets\n");
// Clear delays to a very high value first // Clear delays to a very high value first
delay_t default_slack = delay_t(1.0e12 / default_clock); delay_t default_slack = delay_t(1.0e12 / default_clock);
for (auto net : ctx->nets) { for (auto& net : ctx->nets) {
for (auto &usr : net.second->users) { for (auto &usr : net.second->users) {
usr.budget = default_slack; usr.budget = default_slack;
} }
} }
// Go through all clocked drivers and set up paths // Go through all clocked drivers and set up paths
for (auto cell : ctx->cells) { for (auto& cell : ctx->cells) {
for (auto port : cell.second->ports) { for (auto port : cell.second->ports) {
if (port.second.type == PORT_OUT) { if (port.second.type == PORT_OUT) {
IdString clock_domain = ctx->getPortClock(cell.second, port.first); IdString clock_domain = ctx->getPortClock(cell.second.get(), port.first);
if (clock_domain != IdString()) { if (clock_domain != IdString()) {
delay_t slack = delay_t(1.0e12 / default_clock); // TODO: clock constraints delay_t slack = delay_t(1.0e12 / default_clock); // TODO: clock constraints
if (port.second.net) if (port.second.net)
@ -96,7 +96,7 @@ void assign_budget(Context *ctx, float default_clock)
} }
// Post-allocation check // Post-allocation check
for (auto net : ctx->nets) { for (auto& net : ctx->nets) {
for (auto user : net.second->users) { for (auto user : net.second->users) {
if (user.budget < 0) if (user.budget < 0)
log_warning("port %s.%s, connected to net '%s', has negative " log_warning("port %s.%s, connected to net '%s', has negative "

View File

@ -57,9 +57,12 @@ bool bool_or_default(const Container &ct, const KeyType &key, bool def = false)
}; };
// Wrap an unordered_map, and allow it to be iterated over sorted by key // Wrap an unordered_map, and allow it to be iterated over sorted by key
template <typename K, typename V> std::map<K, V> sorted(const std::unordered_map<K, V> &orig) template <typename K, typename V> std::map<K, V*> sorted(const std::unordered_map<K, std::unique_ptr<V>> &orig)
{ {
return std::map<K, V>(orig.begin(), orig.end()); std::map<K, V*> retVal;
for(auto& item : orig)
retVal.emplace(std::make_pair(item.first,item.second.get()));
return retVal;
}; };
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END

View File

@ -91,7 +91,7 @@ bool Arch::isBelLocationValid(BelId bel) const
for (auto bel_other : getBelsAtSameTile(bel)) { for (auto bel_other : getBelsAtSameTile(bel)) {
IdString cell_other = getBoundBelCell(bel_other); IdString cell_other = getBoundBelCell(bel_other);
if (cell_other != IdString()) { if (cell_other != IdString()) {
const CellInfo *ci_other = cells.at(cell_other); const CellInfo *ci_other = cells.at(cell_other).get();
bel_cells.push_back(ci_other); bel_cells.push_back(ci_other);
} }
} }
@ -101,7 +101,7 @@ bool Arch::isBelLocationValid(BelId bel) const
if (cellId == IdString()) if (cellId == IdString())
return true; return true;
else else
return isValidBelForCell(cells.at(cellId), bel); return isValidBelForCell(cells.at(cellId).get(), bel);
} }
} }
@ -115,7 +115,7 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
for (auto bel_other : getBelsAtSameTile(bel)) { for (auto bel_other : getBelsAtSameTile(bel)) {
IdString cell_other = getBoundBelCell(bel_other); IdString cell_other = getBoundBelCell(bel_other);
if (cell_other != IdString() && bel_other != bel) { if (cell_other != IdString() && bel_other != bel) {
const CellInfo *ci_other = cells.at(cell_other); const CellInfo *ci_other = cells.at(cell_other).get();
bel_cells.push_back(ci_other); bel_cells.push_back(ci_other);
} }
} }

View File

@ -140,8 +140,8 @@ void write_asc(const Context *ctx, std::ostream &out)
} }
} }
// Set logic cell config // Set logic cell config
for (auto cell : ctx->cells) { for (auto& cell : ctx->cells) {
BelId bel = cell.second->bel; BelId bel = cell.second.get()->bel;
if (bel == BelId()) { if (bel == BelId()) {
std::cout << "Found unplaced cell " << cell.first.str(ctx) << " while generating bitstream!" << std::endl; std::cout << "Found unplaced cell " << cell.first.str(ctx) << " while generating bitstream!" << std::endl;
continue; continue;
@ -150,12 +150,12 @@ void write_asc(const Context *ctx, std::ostream &out)
int x = beli.x, y = beli.y, z = beli.z; int x = beli.x, y = beli.y, z = beli.z;
if (cell.second->type == ctx->id("ICESTORM_LC")) { if (cell.second->type == ctx->id("ICESTORM_LC")) {
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_LOGIC]; const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_LOGIC];
unsigned lut_init = get_param_or_def(cell.second, ctx->id("LUT_INIT")); unsigned lut_init = get_param_or_def(cell.second.get(), ctx->id("LUT_INIT"));
bool neg_clk = get_param_or_def(cell.second, ctx->id("NEG_CLK")); bool neg_clk = get_param_or_def(cell.second.get(), ctx->id("NEG_CLK"));
bool dff_enable = get_param_or_def(cell.second, ctx->id("DFF_ENABLE")); bool dff_enable = get_param_or_def(cell.second.get(), ctx->id("DFF_ENABLE"));
bool async_sr = get_param_or_def(cell.second, ctx->id("ASYNC_SR")); bool async_sr = get_param_or_def(cell.second.get(), ctx->id("ASYNC_SR"));
bool set_noreset = get_param_or_def(cell.second, ctx->id("SET_NORESET")); bool set_noreset = get_param_or_def(cell.second.get(), ctx->id("SET_NORESET"));
bool carry_enable = get_param_or_def(cell.second, ctx->id("CARRY_ENABLE")); bool carry_enable = get_param_or_def(cell.second.get(), ctx->id("CARRY_ENABLE"));
std::vector<bool> lc(20, false); std::vector<bool> lc(20, false);
// From arachne-pnr // From arachne-pnr
static std::vector<int> lut_perm = { static std::vector<int> lut_perm = {
@ -176,9 +176,9 @@ void write_asc(const Context *ctx, std::ostream &out)
set_config(ti, config.at(y).at(x), "NegClk", neg_clk); set_config(ti, config.at(y).at(x), "NegClk", neg_clk);
} else if (cell.second->type == ctx->id("SB_IO")) { } else if (cell.second->type == ctx->id("SB_IO")) {
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO]; const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO];
unsigned pin_type = get_param_or_def(cell.second, ctx->id("PIN_TYPE")); unsigned pin_type = get_param_or_def(cell.second.get(), ctx->id("PIN_TYPE"));
bool neg_trigger = get_param_or_def(cell.second, ctx->id("NEG_TRIGGER")); bool neg_trigger = get_param_or_def(cell.second.get(), ctx->id("NEG_TRIGGER"));
bool pullup = get_param_or_def(cell.second, ctx->id("PULLUP")); bool pullup = get_param_or_def(cell.second.get(), ctx->id("PULLUP"));
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
bool val = (pin_type >> i) & 0x01; bool val = (pin_type >> i) & 0x01;
set_config(ti, config.at(y).at(x), "IOB_" + std::to_string(z) + ".PINTYPE_" + std::to_string(i), val); set_config(ti, config.at(y).at(x), "IOB_" + std::to_string(z) + ".PINTYPE_" + std::to_string(i), val);
@ -220,10 +220,10 @@ void write_asc(const Context *ctx, std::ostream &out)
if (!(ctx->args.type == ArchArgs::LP1K || ctx->args.type == ArchArgs::HX1K)) { if (!(ctx->args.type == ArchArgs::LP1K || ctx->args.type == ArchArgs::HX1K)) {
set_config(ti_ramb, config.at(y).at(x), "RamConfig.PowerUp", true); set_config(ti_ramb, config.at(y).at(x), "RamConfig.PowerUp", true);
} }
bool negclk_r = get_param_or_def(cell.second, ctx->id("NEG_CLK_R")); bool negclk_r = get_param_or_def(cell.second.get(), ctx->id("NEG_CLK_R"));
bool negclk_w = get_param_or_def(cell.second, ctx->id("NEG_CLK_W")); bool negclk_w = get_param_or_def(cell.second.get(), ctx->id("NEG_CLK_W"));
int write_mode = get_param_or_def(cell.second, ctx->id("WRITE_MODE")); int write_mode = get_param_or_def(cell.second.get(), ctx->id("WRITE_MODE"));
int read_mode = get_param_or_def(cell.second, ctx->id("READ_MODE")); int read_mode = get_param_or_def(cell.second.get(), ctx->id("READ_MODE"));
set_config(ti_ramb, config.at(y).at(x), "NegClk", negclk_w); 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); set_config(ti_ramt, config.at(y + 1).at(x), "NegClk", negclk_r);
@ -371,7 +371,7 @@ void write_asc(const Context *ctx, std::ostream &out)
} }
// Write RAM init data // Write RAM init data
for (auto cell : ctx->cells) { for (auto& cell : ctx->cells) {
if (cell.second->bel != BelId()) { if (cell.second->bel != BelId()) {
if (cell.second->type == ctx->id("ICESTORM_RAM")) { if (cell.second->type == ctx->id("ICESTORM_RAM")) {
const BelInfoPOD &beli = ci.bel_data[cell.second->bel.index]; const BelInfoPOD &beli = ci.bel_data[cell.second->bel.index];
@ -380,7 +380,7 @@ void write_asc(const Context *ctx, std::ostream &out)
for (int w = 0; w < 16; w++) { for (int w = 0; w < 16; w++) {
std::vector<bool> bits(256); std::vector<bool> bits(256);
std::string init = std::string init =
get_param_str_or_def(cell.second, ctx->id(std::string("INIT_") + get_hexdigit(w))); get_param_str_or_def(cell.second.get(), ctx->id(std::string("INIT_") + get_hexdigit(w)));
assert(init != ""); assert(init != "");
for (size_t i = 0; i < init.size(); i++) { for (size_t i = 0; i < init.size(); i++) {
bool val = (init.at((init.size() - 1) - i) == '1'); bool val = (init.at((init.size() - 1) - i) == '1');

View File

@ -30,10 +30,10 @@ void add_port(const Context *ctx, CellInfo *cell, std::string name, PortType dir
cell->ports[id] = PortInfo{id, nullptr, dir}; cell->ports[id] = PortInfo{id, nullptr, dir};
} }
CellInfo *create_ice_cell(Context *ctx, IdString type, std::string name) std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::string name)
{ {
static int auto_idx = 0; static int auto_idx = 0;
CellInfo *new_cell = new CellInfo(); std::unique_ptr<CellInfo> new_cell = std::unique_ptr<CellInfo>(new CellInfo());
if (name.empty()) { if (name.empty()) {
new_cell->name = ctx->id("$nextpnr_" + type.str(ctx) + "_" + std::to_string(auto_idx++)); new_cell->name = ctx->id("$nextpnr_" + type.str(ctx) + "_" + std::to_string(auto_idx++));
} else { } else {
@ -50,84 +50,84 @@ CellInfo *create_ice_cell(Context *ctx, IdString type, std::string name)
new_cell->params[ctx->id("CIN_CONST")] = "0"; new_cell->params[ctx->id("CIN_CONST")] = "0";
new_cell->params[ctx->id("CIN_SET")] = "0"; new_cell->params[ctx->id("CIN_SET")] = "0";
add_port(ctx, new_cell, "I0", PORT_IN); add_port(ctx, new_cell.get(), "I0", PORT_IN);
add_port(ctx, new_cell, "I1", PORT_IN); add_port(ctx, new_cell.get(), "I1", PORT_IN);
add_port(ctx, new_cell, "I2", PORT_IN); add_port(ctx, new_cell.get(), "I2", PORT_IN);
add_port(ctx, new_cell, "I3", PORT_IN); add_port(ctx, new_cell.get(), "I3", PORT_IN);
add_port(ctx, new_cell, "CIN", PORT_IN); add_port(ctx, new_cell.get(), "CIN", PORT_IN);
add_port(ctx, new_cell, "CLK", PORT_IN); add_port(ctx, new_cell.get(), "CLK", PORT_IN);
add_port(ctx, new_cell, "CEN", PORT_IN); add_port(ctx, new_cell.get(), "CEN", PORT_IN);
add_port(ctx, new_cell, "SR", PORT_IN); add_port(ctx, new_cell.get(), "SR", PORT_IN);
add_port(ctx, new_cell, "LO", PORT_OUT); add_port(ctx, new_cell.get(), "LO", PORT_OUT);
add_port(ctx, new_cell, "O", PORT_OUT); add_port(ctx, new_cell.get(), "O", PORT_OUT);
add_port(ctx, new_cell, "OUT", PORT_OUT); add_port(ctx, new_cell.get(), "OUT", PORT_OUT);
} else if (type == ctx->id("SB_IO")) { } else if (type == ctx->id("SB_IO")) {
new_cell->params[ctx->id("PIN_TYPE")] = "0"; new_cell->params[ctx->id("PIN_TYPE")] = "0";
new_cell->params[ctx->id("PULLUP")] = "0"; new_cell->params[ctx->id("PULLUP")] = "0";
new_cell->params[ctx->id("NEG_TRIGGER")] = "0"; new_cell->params[ctx->id("NEG_TRIGGER")] = "0";
new_cell->params[ctx->id("IOSTANDARD")] = "SB_LVCMOS"; new_cell->params[ctx->id("IOSTANDARD")] = "SB_LVCMOS";
add_port(ctx, new_cell, "PACKAGE_PIN", PORT_INOUT); add_port(ctx, new_cell.get(), "PACKAGE_PIN", PORT_INOUT);
add_port(ctx, new_cell, "LATCH_INPUT_VALUE", PORT_IN); add_port(ctx, new_cell.get(), "LATCH_INPUT_VALUE", PORT_IN);
add_port(ctx, new_cell, "CLOCK_ENABLE", PORT_IN); add_port(ctx, new_cell.get(), "CLOCK_ENABLE", PORT_IN);
add_port(ctx, new_cell, "INPUT_CLK", PORT_IN); add_port(ctx, new_cell.get(), "INPUT_CLK", PORT_IN);
add_port(ctx, new_cell, "OUTPUT_CLK", PORT_IN); add_port(ctx, new_cell.get(), "OUTPUT_CLK", PORT_IN);
add_port(ctx, new_cell, "OUTPUT_ENABLE", PORT_IN); add_port(ctx, new_cell.get(), "OUTPUT_ENABLE", PORT_IN);
add_port(ctx, new_cell, "D_OUT_0", PORT_IN); add_port(ctx, new_cell.get(), "D_OUT_0", PORT_IN);
add_port(ctx, new_cell, "D_OUT_1", PORT_IN); add_port(ctx, new_cell.get(), "D_OUT_1", PORT_IN);
add_port(ctx, new_cell, "D_IN_0", PORT_OUT); add_port(ctx, new_cell.get(), "D_IN_0", PORT_OUT);
add_port(ctx, new_cell, "D_IN_1", PORT_OUT); add_port(ctx, new_cell.get(), "D_IN_1", PORT_OUT);
} else if (type == ctx->id("ICESTORM_RAM")) { } else if (type == ctx->id("ICESTORM_RAM")) {
new_cell->params[ctx->id("NEG_CLK_W")] = "0"; new_cell->params[ctx->id("NEG_CLK_W")] = "0";
new_cell->params[ctx->id("NEG_CLK_R")] = "0"; new_cell->params[ctx->id("NEG_CLK_R")] = "0";
new_cell->params[ctx->id("WRITE_MODE")] = "0"; new_cell->params[ctx->id("WRITE_MODE")] = "0";
new_cell->params[ctx->id("READ_MODE")] = "0"; new_cell->params[ctx->id("READ_MODE")] = "0";
add_port(ctx, new_cell, "RCLK", PORT_IN); add_port(ctx, new_cell.get(), "RCLK", PORT_IN);
add_port(ctx, new_cell, "RCLKE", PORT_IN); add_port(ctx, new_cell.get(), "RCLKE", PORT_IN);
add_port(ctx, new_cell, "RE", PORT_IN); add_port(ctx, new_cell.get(), "RE", PORT_IN);
add_port(ctx, new_cell, "WCLK", PORT_IN); add_port(ctx, new_cell.get(), "WCLK", PORT_IN);
add_port(ctx, new_cell, "WCLKE", PORT_IN); add_port(ctx, new_cell.get(), "WCLKE", PORT_IN);
add_port(ctx, new_cell, "WE", PORT_IN); add_port(ctx, new_cell.get(), "WE", PORT_IN);
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
add_port(ctx, new_cell, "WDATA_" + std::to_string(i), PORT_IN); add_port(ctx, new_cell.get(), "WDATA_" + std::to_string(i), PORT_IN);
add_port(ctx, new_cell, "MASK_" + std::to_string(i), PORT_IN); add_port(ctx, new_cell.get(), "MASK_" + std::to_string(i), PORT_IN);
add_port(ctx, new_cell, "RDATA_" + std::to_string(i), PORT_OUT); add_port(ctx, new_cell.get(), "RDATA_" + std::to_string(i), PORT_OUT);
} }
for (int i = 0; i < 11; i++) { for (int i = 0; i < 11; i++) {
add_port(ctx, new_cell, "RADDR_" + std::to_string(i), PORT_IN); add_port(ctx, new_cell.get(), "RADDR_" + std::to_string(i), PORT_IN);
add_port(ctx, new_cell, "WADDR_" + std::to_string(i), PORT_IN); add_port(ctx, new_cell.get(), "WADDR_" + std::to_string(i), PORT_IN);
} }
} else if (type == ctx->id("ICESTORM_LFOSC")) { } else if (type == ctx->id("ICESTORM_LFOSC")) {
add_port(ctx, new_cell, "CLKLFEN", PORT_IN); add_port(ctx, new_cell.get(), "CLKLFEN", PORT_IN);
add_port(ctx, new_cell, "CLKLFPU", PORT_IN); add_port(ctx, new_cell.get(), "CLKLFPU", PORT_IN);
add_port(ctx, new_cell, "CLKLF", PORT_OUT); add_port(ctx, new_cell.get(), "CLKLF", PORT_OUT);
add_port(ctx, new_cell, "CLKLF_FABRIC", PORT_OUT); add_port(ctx, new_cell.get(), "CLKLF_FABRIC", PORT_OUT);
} else if (type == ctx->id("ICESTORM_HFOSC")) { } else if (type == ctx->id("ICESTORM_HFOSC")) {
new_cell->params[ctx->id("CLKHF_DIV")] = "0"; new_cell->params[ctx->id("CLKHF_DIV")] = "0";
new_cell->params[ctx->id("TRIM_EN")] = "0"; new_cell->params[ctx->id("TRIM_EN")] = "0";
add_port(ctx, new_cell, "CLKHFEN", PORT_IN); add_port(ctx, new_cell.get(), "CLKHFEN", PORT_IN);
add_port(ctx, new_cell, "CLKHFPU", PORT_IN); add_port(ctx, new_cell.get(), "CLKHFPU", PORT_IN);
add_port(ctx, new_cell, "CLKHF", PORT_OUT); add_port(ctx, new_cell.get(), "CLKHF", PORT_OUT);
add_port(ctx, new_cell, "CLKHF_FABRIC", PORT_OUT); add_port(ctx, new_cell.get(), "CLKHF_FABRIC", PORT_OUT);
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
add_port(ctx, new_cell, "TRIM" + std::to_string(i), PORT_IN); add_port(ctx, new_cell.get(), "TRIM" + std::to_string(i), PORT_IN);
} else if (type == ctx->id("SB_GB")) { } else if (type == ctx->id("SB_GB")) {
add_port(ctx, new_cell, "USER_SIGNAL_TO_GLOBAL_BUFFER", PORT_IN); add_port(ctx, new_cell.get(), "USER_SIGNAL_TO_GLOBAL_BUFFER", PORT_IN);
add_port(ctx, new_cell, "GLOBAL_BUFFER_OUTPUT", PORT_OUT); add_port(ctx, new_cell.get(), "GLOBAL_BUFFER_OUTPUT", PORT_OUT);
} else { } else {
log_error("unable to create iCE40 cell of type %s", type.c_str(ctx)); log_error("unable to create iCE40 cell of type %s", type.c_str(ctx));
} }
return new_cell; return std::move(new_cell);
} }
void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff) void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff)

View File

@ -27,7 +27,7 @@ NEXTPNR_NAMESPACE_BEGIN
// Create a standard iCE40 cell and return it // Create a standard iCE40 cell and return it
// Name will be automatically assigned if not specified // Name will be automatically assigned if not specified
CellInfo *create_ice_cell(Context *ctx, IdString type, std::string name = ""); std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::string name = "");
// Return true if a cell is a LUT // Return true if a cell is a LUT
inline bool is_lut(const BaseCtx *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"); }

View File

@ -34,16 +34,15 @@ static void pack_lut_lutffs(Context *ctx)
log_info("Packing LUT-FFs..\n"); log_info("Packing LUT-FFs..\n");
std::unordered_set<IdString> packed_cells; std::unordered_set<IdString> packed_cells;
std::vector<CellInfo *> new_cells; std::vector<std::unique_ptr<CellInfo>> new_cells;
for (auto cell : sorted(ctx->cells)) { for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second; CellInfo *ci = cell.second;
if (ctx->verbose) if (ctx->verbose)
log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx)); log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx));
if (is_lut(ctx, ci)) { if (is_lut(ctx, ci)) {
CellInfo *packed = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), ci->name.str(ctx) + "_LC"); std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), ci->name.str(ctx) + "_LC");
std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin())); std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin()));
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
new_cells.push_back(packed);
if (ctx->verbose) if (ctx->verbose)
log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx)); log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx));
// See if we can pack into a DFF // See if we can pack into a DFF
@ -59,8 +58,8 @@ static void pack_lut_lutffs(Context *ctx)
if (lut_bel != ci->attrs.end() && dff_bel != dff->attrs.end() && lut_bel->second != dff_bel->second) { if (lut_bel != ci->attrs.end() && dff_bel != dff->attrs.end() && lut_bel->second != dff_bel->second) {
// Locations don't match, can't pack // Locations don't match, can't pack
} else { } else {
lut_to_lc(ctx, ci, packed, false); lut_to_lc(ctx, ci, packed.get(), false);
dff_to_lc(ctx, dff, packed, false); dff_to_lc(ctx, dff, packed.get(), false);
ctx->nets.erase(o->name); ctx->nets.erase(o->name);
if (dff_bel != dff->attrs.end()) if (dff_bel != dff->attrs.end())
packed->attrs[ctx->id("BEL")] = dff_bel->second; packed->attrs[ctx->id("BEL")] = dff_bel->second;
@ -71,15 +70,16 @@ static void pack_lut_lutffs(Context *ctx)
} }
} }
if (!packed_dff) { if (!packed_dff) {
lut_to_lc(ctx, ci, packed, true); lut_to_lc(ctx, ci, packed.get(), true);
} }
new_cells.push_back(std::move(packed));
} }
} }
for (auto pcell : packed_cells) { for (auto pcell : packed_cells) {
ctx->cells.erase(pcell); ctx->cells.erase(pcell);
} }
for (auto ncell : new_cells) { for (auto& ncell : new_cells) {
ctx->cells[ncell->name] = ncell; ctx->cells[ncell->name] = std::move(ncell);
} }
} }
@ -89,25 +89,25 @@ static void pack_nonlut_ffs(Context *ctx)
log_info("Packing non-LUT FFs..\n"); log_info("Packing non-LUT FFs..\n");
std::unordered_set<IdString> packed_cells; std::unordered_set<IdString> packed_cells;
std::vector<CellInfo *> new_cells; std::vector<std::unique_ptr<CellInfo>> new_cells;
for (auto cell : sorted(ctx->cells)) { for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second; CellInfo *ci = cell.second;
if (is_ff(ctx, ci)) { if (is_ff(ctx, ci)) {
CellInfo *packed = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), ci->name.str(ctx) + "_DFFLC"); std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), ci->name.str(ctx) + "_DFFLC");
std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin())); std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(packed->attrs, packed->attrs.begin()));
if (ctx->verbose) if (ctx->verbose)
log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx)); log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx));
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
new_cells.push_back(packed); dff_to_lc(ctx, ci, packed.get(), true);
dff_to_lc(ctx, ci, packed, true); new_cells.push_back(std::move(packed));
} }
} }
for (auto pcell : packed_cells) { for (auto pcell : packed_cells) {
ctx->cells.erase(pcell); ctx->cells.erase(pcell);
} }
for (auto ncell : new_cells) { for (auto& ncell : new_cells) {
ctx->cells[ncell->name] = ncell; ctx->cells[ncell->name] = std::move(ncell);
} }
} }
@ -122,7 +122,7 @@ static void pack_carries(Context *ctx)
CellInfo *ci = cell.second; CellInfo *ci = cell.second;
if (is_carry(ctx, ci)) { if (is_carry(ctx, ci)) {
packed_cells.insert(cell.first); packed_cells.insert(cell.first);
CellInfo *carry_ci_lc = net_only_drives(ctx, ci->ports.at(ctx->id("CI")).net, is_lc, ctx->id("I3"), false); CellInfo * carry_ci_lc = net_only_drives(ctx, ci->ports.at(ctx->id("CI")).net, is_lc, ctx->id("I3"), false);
if (!ci->ports.at(ctx->id("I0")).net) if (!ci->ports.at(ctx->id("I0")).net)
log_error("SB_CARRY '%s' has disconnected port I0\n", cell.first.c_str(ctx)); log_error("SB_CARRY '%s' has disconnected port I0\n", cell.first.c_str(ctx));
if (!ci->ports.at(ctx->id("I1")).net) if (!ci->ports.at(ctx->id("I1")).net)
@ -156,7 +156,7 @@ static void pack_carries(Context *ctx)
log_error("SB_CARRY '%s' cannot be packed into any logic " log_error("SB_CARRY '%s' cannot be packed into any logic "
"cell (no logic cell connects to both I0 and I1)\n", "cell (no logic cell connects to both I0 and I1)\n",
cell.first.c_str(ctx)); cell.first.c_str(ctx));
carry_lc = ctx->cells.at(*carry_lcs.begin()); carry_lc = ctx->cells.at(*carry_lcs.begin()).get();
} }
carry_lc->attrs[ctx->id("CARRY_ENABLE")] = "1"; carry_lc->attrs[ctx->id("CARRY_ENABLE")] = "1";
replace_port(ci, ctx->id("CI"), carry_lc, ctx->id("CIN")); replace_port(ci, ctx->id("CI"), carry_lc, ctx->id("CIN"));
@ -182,14 +182,13 @@ static void pack_ram(Context *ctx)
log_info("Packing RAMs..\n"); log_info("Packing RAMs..\n");
std::unordered_set<IdString> packed_cells; std::unordered_set<IdString> packed_cells;
std::vector<CellInfo *> new_cells; std::vector<std::unique_ptr<CellInfo>> new_cells;
for (auto cell : sorted(ctx->cells)) { for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second; CellInfo *ci = cell.second;
if (is_ram(ctx, ci)) { if (is_ram(ctx, ci)) {
CellInfo *packed = create_ice_cell(ctx, ctx->id("ICESTORM_RAM"), ci->name.str(ctx) + "_RAM"); std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, ctx->id("ICESTORM_RAM"), ci->name.str(ctx) + "_RAM");
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
new_cells.push_back(packed);
for (auto param : ci->params) for (auto param : ci->params)
packed->params[param.first] = param.second; packed->params[param.first] = param.second;
packed->params[ctx->id("NEG_CLK_W")] = packed->params[ctx->id("NEG_CLK_W")] =
@ -204,16 +203,17 @@ static void pack_ram(Context *ctx)
if (bpos != std::string::npos) { if (bpos != std::string::npos) {
newname = newname.substr(0, bpos) + "_" + newname.substr(bpos + 1, (newname.size() - bpos) - 2); newname = newname.substr(0, bpos) + "_" + newname.substr(bpos + 1, (newname.size() - bpos) - 2);
} }
replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed, ctx->id(newname)); replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname));
} }
new_cells.push_back(std::move(packed));
} }
} }
for (auto pcell : packed_cells) { for (auto pcell : packed_cells) {
ctx->cells.erase(pcell); ctx->cells.erase(pcell);
} }
for (auto ncell : new_cells) { for (auto& ncell : new_cells) {
ctx->cells[ncell->name] = ncell; ctx->cells[ncell->name] = std::move(ncell);
} }
} }
@ -242,18 +242,18 @@ static void pack_constants(Context *ctx)
{ {
log_info("Packing constants..\n"); log_info("Packing constants..\n");
CellInfo *gnd_cell = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), "$PACKER_GND"); std::unique_ptr<CellInfo> gnd_cell = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), "$PACKER_GND");
gnd_cell->params[ctx->id("LUT_INIT")] = "0"; gnd_cell->params[ctx->id("LUT_INIT")] = "0";
NetInfo *gnd_net = new NetInfo; std::unique_ptr<NetInfo> gnd_net = std::unique_ptr<NetInfo>(new NetInfo);
gnd_net->name = ctx->id("$PACKER_GND_NET"); gnd_net->name = ctx->id("$PACKER_GND_NET");
gnd_net->driver.cell = gnd_cell; gnd_net->driver.cell = gnd_cell.get();
gnd_net->driver.port = ctx->id("O"); gnd_net->driver.port = ctx->id("O");
CellInfo *vcc_cell = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), "$PACKER_VCC"); std::unique_ptr<CellInfo> vcc_cell = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), "$PACKER_VCC");
vcc_cell->params[ctx->id("LUT_INIT")] = "1"; vcc_cell->params[ctx->id("LUT_INIT")] = "1";
NetInfo *vcc_net = new NetInfo; std::unique_ptr<NetInfo> vcc_net = std::unique_ptr<NetInfo>(new NetInfo);
vcc_net->name = ctx->id("$PACKER_VCC_NET"); vcc_net->name = ctx->id("$PACKER_VCC_NET");
vcc_net->driver.cell = vcc_cell; vcc_net->driver.cell = vcc_cell.get();
vcc_net->driver.port = ctx->id("O"); vcc_net->driver.port = ctx->id("O");
std::vector<IdString> dead_nets; std::vector<IdString> dead_nets;
@ -264,29 +264,26 @@ static void pack_constants(Context *ctx)
NetInfo *ni = net.second; NetInfo *ni = net.second;
if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) { if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) {
IdString drv_cell = ni->driver.cell->name; IdString drv_cell = ni->driver.cell->name;
set_net_constant(ctx, ni, gnd_net, false); set_net_constant(ctx, ni, gnd_net.get(), false);
gnd_used = true; gnd_used = true;
dead_nets.push_back(net.first); dead_nets.push_back(net.first);
ctx->cells.erase(drv_cell); ctx->cells.erase(drv_cell);
} else if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("VCC")) { } else if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("VCC")) {
IdString drv_cell = ni->driver.cell->name; IdString drv_cell = ni->driver.cell->name;
set_net_constant(ctx, ni, vcc_net, true); set_net_constant(ctx, ni, vcc_net.get(), true);
dead_nets.push_back(net.first); dead_nets.push_back(net.first);
ctx->cells.erase(drv_cell); ctx->cells.erase(drv_cell);
} }
} }
if (gnd_used) { if (gnd_used) {
ctx->cells[gnd_cell->name] = gnd_cell; ctx->cells[gnd_cell->name] = std::move(gnd_cell);
ctx->nets[gnd_net->name] = gnd_net; ctx->nets[gnd_net->name] = std::move(gnd_net);
} else {
delete gnd_net;
delete gnd_cell;
} }
// Vcc cell always inserted for now, as it may be needed during carry legalisation (TODO: trim later if actually // Vcc cell always inserted for now, as it may be needed during carry legalisation (TODO: trim later if actually
// never used?) // never used?)
ctx->cells[vcc_cell->name] = vcc_cell; ctx->cells[vcc_cell->name] = std::move(vcc_cell);
ctx->nets[vcc_net->name] = vcc_net; ctx->nets[vcc_net->name] = std::move(vcc_net);
for (auto dn : dead_nets) { for (auto dn : dead_nets) {
ctx->nets.erase(dn); ctx->nets.erase(dn);
@ -303,7 +300,7 @@ static bool is_nextpnr_iob(Context *ctx, CellInfo *cell)
static void pack_io(Context *ctx) static void pack_io(Context *ctx)
{ {
std::unordered_set<IdString> packed_cells; std::unordered_set<IdString> packed_cells;
std::vector<CellInfo *> new_cells; std::vector<std::unique_ptr<CellInfo>> new_cells;
log_info("Packing IOs..\n"); log_info("Packing IOs..\n");
@ -329,9 +326,10 @@ static void pack_io(Context *ctx)
} }
} else { } else {
// Create a SB_IO buffer // Create a SB_IO buffer
sb = create_ice_cell(ctx, ctx->id("SB_IO"), ci->name.str(ctx) + "$sb_io"); std::unique_ptr<CellInfo> ice_cell = create_ice_cell(ctx, ctx->id("SB_IO"), ci->name.str(ctx) + "$sb_io");
nxio_to_sb(ctx, ci, sb); nxio_to_sb(ctx, ci, ice_cell.get());
new_cells.push_back(sb); new_cells.push_back(std::move(ice_cell));
sb = new_cells.back().get();
} }
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(sb->attrs, sb->attrs.begin())); std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(sb->attrs, sb->attrs.begin()));
@ -340,40 +338,40 @@ static void pack_io(Context *ctx)
for (auto pcell : packed_cells) { for (auto pcell : packed_cells) {
ctx->cells.erase(pcell); ctx->cells.erase(pcell);
} }
for (auto ncell : new_cells) { for (auto& ncell : new_cells) {
ctx->cells[ncell->name] = ncell; ctx->cells[ncell->name] = std::move(ncell);
} }
} }
static void insert_global(Context *ctx, NetInfo *net, bool is_reset, bool is_cen) static void insert_global(Context *ctx, NetInfo *net, bool is_reset, bool is_cen)
{ {
std::string glb_name = net->name.str(ctx) + std::string("_$glb_") + (is_reset ? "sr" : (is_cen ? "ce" : "clk")); std::string glb_name = net->name.str(ctx) + std::string("_$glb_") + (is_reset ? "sr" : (is_cen ? "ce" : "clk"));
CellInfo *gb = create_ice_cell(ctx, ctx->id("SB_GB"), "$gbuf_" + glb_name); std::unique_ptr<CellInfo> gb = create_ice_cell(ctx, ctx->id("SB_GB"), "$gbuf_" + glb_name);
gb->ports[ctx->id("USER_SIGNAL_TO_GLOBAL_BUFFER")].net = net; gb->ports[ctx->id("USER_SIGNAL_TO_GLOBAL_BUFFER")].net = net;
PortRef pr; PortRef pr;
pr.cell = gb; pr.cell = gb.get();
pr.port = ctx->id("USER_SIGNAL_TO_GLOBAL_BUFFER"); pr.port = ctx->id("USER_SIGNAL_TO_GLOBAL_BUFFER");
net->users.push_back(pr); net->users.push_back(pr);
pr.cell = gb; pr.cell = gb.get();
pr.port = ctx->id("GLOBAL_BUFFER_OUTPUT"); pr.port = ctx->id("GLOBAL_BUFFER_OUTPUT");
NetInfo *glbnet = new NetInfo(); std::unique_ptr<NetInfo> glbnet = std::unique_ptr<NetInfo>(new NetInfo());
glbnet->name = ctx->id(glb_name); glbnet->name = ctx->id(glb_name);
glbnet->driver = pr; glbnet->driver = pr;
ctx->nets[glbnet->name] = glbnet; gb->ports[ctx->id("GLOBAL_BUFFER_OUTPUT")].net = glbnet.get();
gb->ports[ctx->id("GLOBAL_BUFFER_OUTPUT")].net = glbnet;
std::vector<PortRef> keep_users; std::vector<PortRef> keep_users;
for (auto user : net->users) { for (auto user : net->users) {
if (is_clock_port(ctx, user) || (is_reset && is_reset_port(ctx, user)) || if (is_clock_port(ctx, user) || (is_reset && is_reset_port(ctx, user)) ||
(is_cen && is_enable_port(ctx, user))) { (is_cen && is_enable_port(ctx, user))) {
user.cell->ports[user.port].net = glbnet; user.cell->ports[user.port].net = glbnet.get();
glbnet->users.push_back(user); glbnet->users.push_back(user);
} else { } else {
keep_users.push_back(user); keep_users.push_back(user);
} }
} }
net->users = keep_users; net->users = keep_users;
ctx->cells[gb->name] = gb; ctx->nets[glbnet->name] = std::move(glbnet);
ctx->cells[gb->name] = std::move(gb);
} }
// Simple global promoter (clock only) // Simple global promoter (clock only)
@ -401,8 +399,8 @@ static void promote_globals(Context *ctx)
} }
int prom_globals = 0, prom_resets = 0, prom_cens = 0; int prom_globals = 0, prom_resets = 0, prom_cens = 0;
int gbs_available = 8; int gbs_available = 8;
for (auto cell : ctx->cells) for (auto& cell : ctx->cells)
if (is_gbuf(ctx, cell.second)) if (is_gbuf(ctx, cell.second.get()))
--gbs_available; --gbs_available;
while (prom_globals < gbs_available) { while (prom_globals < gbs_available) {
auto global_clock = std::max_element(clock_count.begin(), clock_count.end(), auto global_clock = std::max_element(clock_count.begin(), clock_count.end(),
@ -419,7 +417,7 @@ static void promote_globals(Context *ctx)
return a.second < b.second; return a.second < b.second;
}); });
if (global_reset->second > global_clock->second && prom_resets < 4) { if (global_reset->second > global_clock->second && prom_resets < 4) {
NetInfo *rstnet = ctx->nets[global_reset->first]; NetInfo *rstnet = ctx->nets[global_reset->first].get();
insert_global(ctx, rstnet, true, false); insert_global(ctx, rstnet, true, false);
++prom_globals; ++prom_globals;
++prom_resets; ++prom_resets;
@ -427,7 +425,7 @@ static void promote_globals(Context *ctx)
reset_count.erase(rstnet->name); reset_count.erase(rstnet->name);
cen_count.erase(rstnet->name); cen_count.erase(rstnet->name);
} else if (global_cen->second > global_clock->second && prom_cens < 4) { } else if (global_cen->second > global_clock->second && prom_cens < 4) {
NetInfo *cennet = ctx->nets[global_cen->first]; NetInfo *cennet = ctx->nets[global_cen->first].get();
insert_global(ctx, cennet, false, true); insert_global(ctx, cennet, false, true);
++prom_globals; ++prom_globals;
++prom_cens; ++prom_cens;
@ -435,7 +433,7 @@ static void promote_globals(Context *ctx)
reset_count.erase(cennet->name); reset_count.erase(cennet->name);
cen_count.erase(cennet->name); cen_count.erase(cennet->name);
} else if (global_clock->second != 0) { } else if (global_clock->second != 0) {
NetInfo *clknet = ctx->nets[global_clock->first]; NetInfo *clknet = ctx->nets[global_clock->first].get();
insert_global(ctx, clknet, false, false); insert_global(ctx, clknet, false, false);
++prom_globals; ++prom_globals;
clock_count.erase(clknet->name); clock_count.erase(clknet->name);
@ -453,29 +451,29 @@ static void pack_intosc(Context *ctx)
log_info("Packing oscillators..\n"); log_info("Packing oscillators..\n");
std::unordered_set<IdString> packed_cells; std::unordered_set<IdString> packed_cells;
std::vector<CellInfo *> new_cells; std::vector<std::unique_ptr<CellInfo>> new_cells;
for (auto cell : sorted(ctx->cells)) { for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second; CellInfo *ci = cell.second;
if (is_sb_lfosc(ctx, ci)) { if (is_sb_lfosc(ctx, ci)) {
CellInfo *packed = create_ice_cell(ctx, ctx->id("ICESTORM_LFOSC"), ci->name.str(ctx) + "_OSC"); std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, ctx->id("ICESTORM_LFOSC"), ci->name.str(ctx) + "_OSC");
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
new_cells.push_back(packed); replace_port(ci, ctx->id("CLKLFEN"), packed.get(), ctx->id("CLKLFEN"));
replace_port(ci, ctx->id("CLKLFEN"), packed, ctx->id("CLKLFEN")); replace_port(ci, ctx->id("CLKLFPU"), packed.get(), ctx->id("CLKLFPU"));
replace_port(ci, ctx->id("CLKLFPU"), packed, ctx->id("CLKLFPU"));
if (bool_or_default(ci->attrs, ctx->id("ROUTE_THROUGH_FABRIC"))) { if (bool_or_default(ci->attrs, ctx->id("ROUTE_THROUGH_FABRIC"))) {
replace_port(ci, ctx->id("CLKLF"), packed, ctx->id("CLKLF_FABRIC")); replace_port(ci, ctx->id("CLKLF"), packed.get(), ctx->id("CLKLF_FABRIC"));
} else { } else {
replace_port(ci, ctx->id("CLKLF"), packed, ctx->id("CLKLF")); replace_port(ci, ctx->id("CLKLF"), packed.get(), ctx->id("CLKLF"));
} }
new_cells.push_back(std::move(packed));
} }
} }
for (auto pcell : packed_cells) { for (auto pcell : packed_cells) {
ctx->cells.erase(pcell); ctx->cells.erase(pcell);
} }
for (auto ncell : new_cells) { for (auto& ncell : new_cells) {
ctx->cells[ncell->name] = ncell; ctx->cells[ncell->name] = std::move(ncell);
} }
} }

View File

@ -216,9 +216,9 @@ struct JsonNode
} }
}; };
NetInfo *ground_net(Context *ctx, NetInfo *net) void ground_net(Context *ctx, NetInfo *net)
{ {
CellInfo *cell = new CellInfo; std::unique_ptr<CellInfo> cell = std::unique_ptr<CellInfo>(new CellInfo);
PortInfo port_info; PortInfo port_info;
PortRef port_ref; PortRef port_ref;
@ -229,20 +229,19 @@ NetInfo *ground_net(Context *ctx, NetInfo *net)
port_info.net = net; port_info.net = net;
port_info.type = PORT_OUT; port_info.type = PORT_OUT;
port_ref.cell = cell; port_ref.cell = cell.get();
port_ref.port = port_info.name; port_ref.port = port_info.name;
net->driver = port_ref; net->driver = port_ref;
cell->ports[port_info.name] = port_info; cell->ports[port_info.name] = port_info;
ctx->cells[cell->name] = cell; ctx->cells[cell->name] = std::move(cell);
return net;
} }
NetInfo *vcc_net(Context *ctx, NetInfo *net) void vcc_net(Context *ctx, NetInfo *net)
{ {
CellInfo *cell = new CellInfo; std::unique_ptr<CellInfo> cell = std::unique_ptr<CellInfo>(new CellInfo);
PortInfo port_info; PortInfo port_info;
PortRef port_ref; PortRef port_ref;
@ -253,18 +252,17 @@ NetInfo *vcc_net(Context *ctx, NetInfo *net)
port_info.net = net; port_info.net = net;
port_info.type = PORT_OUT; port_info.type = PORT_OUT;
port_ref.cell = cell; port_ref.cell = cell.get();
port_ref.port = port_info.name; port_ref.port = port_info.name;
net->driver = port_ref; net->driver = port_ref;
cell->ports[port_info.name] = port_info; cell->ports[port_info.name] = port_info;
ctx->cells[cell->name] = cell; ctx->cells[cell->name] = std::move(cell);
return net;
} }
NetInfo *floating_net(Context *ctx, NetInfo *net) void floating_net(Context *ctx, NetInfo *net)
{ {
PortInfo port_info; PortInfo port_info;
PortRef port_ref; PortRef port_ref;
@ -277,8 +275,6 @@ NetInfo *floating_net(Context *ctx, NetInfo *net)
port_ref.port = port_info.name; port_ref.port = port_info.name;
net->driver = port_ref; net->driver = port_ref;
return net;
} }
// //
@ -433,17 +429,19 @@ void json_import_ports(Context *ctx, const string &modname, const std::vector<Id
if (json_debug) if (json_debug)
log_info(" Generating a new net, \'%d\'\n", net_num); log_info(" Generating a new net, \'%d\'\n", net_num);
this_net = new NetInfo; std::unique_ptr<NetInfo> net = std::unique_ptr<NetInfo>(new NetInfo());
this_net->name = net_id; net->name = net_id;
this_net->driver.cell = NULL; net->driver.cell = NULL;
this_net->driver.port = IdString(); net->driver.port = IdString();
ctx->nets[net_id] = this_net; ctx->nets[net_id] = std::move(net);
this_net = ctx->nets[net_id].get();
} else { } else {
// //
// The net already exists within the design. // The net already exists within the design.
// We'll connect to it // We'll connect to it
// //
this_net = ctx->nets[net_id]; this_net = ctx->nets[net_id].get();
if (json_debug) if (json_debug)
log_info(" Reusing net \'%s\', id \'%s\', " log_info(" Reusing net \'%s\', id \'%s\', "
"with driver \'%s\'\n", "with driver \'%s\'\n",
@ -457,26 +455,26 @@ void json_import_ports(Context *ctx, const string &modname, const std::vector<Id
// values here. // values here.
// //
// Constants always get their own new net // Constants always get their own new net
this_net = new NetInfo; std::unique_ptr<NetInfo> net = std::unique_ptr<NetInfo>(new NetInfo());
this_net->name = ctx->id("$const_" + std::to_string(const_net_idx++)); net->name = ctx->id("$const_" + std::to_string(const_net_idx++));
if (wire_node->data_string.compare(string("0")) == 0) { if (wire_node->data_string.compare(string("0")) == 0) {
if (json_debug) if (json_debug)
log_info(" Generating a constant " log_info(" Generating a constant "
"zero net\n"); "zero net\n");
this_net = ground_net(ctx, this_net); ground_net(ctx, net.get());
} else if (wire_node->data_string.compare(string("1")) == 0) { } else if (wire_node->data_string.compare(string("1")) == 0) {
if (json_debug) if (json_debug)
log_info(" Generating a constant " log_info(" Generating a constant "
"one net\n"); "one net\n");
this_net = vcc_net(ctx, this_net); vcc_net(ctx, net.get());
} else if (wire_node->data_string.compare(string("x")) == 0) { } else if (wire_node->data_string.compare(string("x")) == 0) {
this_net = floating_net(ctx, this_net); floating_net(ctx, net.get());
log_warning(" Floating wire node value, " log_warning(" Floating wire node value, "
"\'%s\' of port \'%s\' " "\'%s\' of port \'%s\' "
"in cell \'%s\' of module \'%s\'\n", "in cell \'%s\' of module \'%s\'\n",
@ -486,14 +484,14 @@ void json_import_ports(Context *ctx, const string &modname, const std::vector<Id
log_error(" Unknown fixed type wire node " log_error(" Unknown fixed type wire node "
"value, \'%s\'\n", "value, \'%s\'\n",
wire_node->data_string.c_str()); wire_node->data_string.c_str());
IdString n = net->name;
ctx->nets[net->name] = std::move(net);
this_net = ctx->nets[n].get();
} }
if (json_debug) if (json_debug)
log_info(" Inserting port \'%s\' into cell \'%s\'\n", this_port.name.c_str(ctx), obj_name.c_str()); log_info(" Inserting port \'%s\' into cell \'%s\'\n", this_port.name.c_str(ctx), obj_name.c_str());
visitor(this_port.type, this_port.name.str(ctx), this_net); visitor(this_port.type, this_port.name.str(ctx), this_net);
if (ctx->nets.count(this_net->name) == 0)
ctx->nets[this_net->name] = this_net;
} }
} }
@ -506,7 +504,7 @@ void json_import_cell(Context *ctx, string modname, const std::vector<IdString>
if (cell_type == NULL) if (cell_type == NULL)
return; return;
CellInfo *cell = new CellInfo; std::unique_ptr<CellInfo> cell = std::unique_ptr<CellInfo>(new CellInfo);
cell->name = ctx->id(cell_name); cell->name = ctx->id(cell_name);
assert(cell_type->type == 'S'); assert(cell_type->type == 'S');
@ -526,7 +524,7 @@ void json_import_cell(Context *ctx, string modname, const std::vector<IdString>
// //
for (int paramid = 0; paramid < GetSize(param_node->data_dict_keys); paramid++) { for (int paramid = 0; paramid < GetSize(param_node->data_dict_keys); paramid++) {
json_import_cell_params(ctx, modname, cell, param_node, &cell->params, paramid); json_import_cell_params(ctx, modname, cell.get(), param_node, &cell->params, paramid);
} }
attr_node = cell_node->data_dict.at("attributes"); attr_node = cell_node->data_dict.at("attributes");
@ -539,7 +537,7 @@ void json_import_cell(Context *ctx, string modname, const std::vector<IdString>
// //
for (int attrid = 0; attrid < GetSize(attr_node->data_dict_keys); attrid++) { for (int attrid = 0; attrid < GetSize(attr_node->data_dict_keys); attrid++) {
json_import_cell_params(ctx, modname, cell, attr_node, &cell->attrs, attrid); json_import_cell_params(ctx, modname, cell.get(), attr_node, &cell->attrs, attrid);
} }
// //
@ -594,10 +592,10 @@ void json_import_cell(Context *ctx, string modname, const std::vector<IdString>
wire_group_node = connections->data_dict.at(port_name); wire_group_node = connections->data_dict.at(port_name);
json_import_ports(ctx, modname, netnames, cell->name.str(ctx), port_name, dir_node, wire_group_node, json_import_ports(ctx, modname, netnames, cell->name.str(ctx), port_name, dir_node, wire_group_node,
[cell, ctx](PortType type, const std::string &name, NetInfo *net) { [&cell, ctx](PortType type, const std::string &name, NetInfo *net) {
cell->ports[ctx->id(name)] = PortInfo{ctx->id(name), net, type}; cell->ports[ctx->id(name)] = PortInfo{ctx->id(name), net, type};
PortRef pr; PortRef pr;
pr.cell = cell; pr.cell = cell.get();
pr.port = ctx->id(name); pr.port = ctx->id(name);
if (net != nullptr) { if (net != nullptr) {
if (type == PORT_IN || type == PORT_INOUT) { if (type == PORT_IN || type == PORT_INOUT) {
@ -610,7 +608,7 @@ void json_import_cell(Context *ctx, string modname, const std::vector<IdString>
}); });
} }
ctx->cells[cell->name] = cell; ctx->cells[cell->name] = std::move(cell);
// check_all_nets_driven(ctx); // check_all_nets_driven(ctx);
} }
@ -622,7 +620,7 @@ static void insert_iobuf(Context *ctx, NetInfo *net, PortType type, const string
// During packing, this generic IO buffer will be converted to an // During packing, this generic IO buffer will be converted to an
// architecure primitive. // architecure primitive.
// //
CellInfo *iobuf = new CellInfo(); std::unique_ptr<CellInfo> iobuf = std::unique_ptr<CellInfo>(new CellInfo());
iobuf->name = ctx->id(name); iobuf->name = ctx->id(name);
std::copy(net->attrs.begin(), net->attrs.end(), std::inserter(iobuf->attrs, iobuf->attrs.begin())); std::copy(net->attrs.begin(), net->attrs.end(), std::inserter(iobuf->attrs, iobuf->attrs.begin()));
if (type == PORT_IN) { if (type == PORT_IN) {
@ -637,14 +635,14 @@ static void insert_iobuf(Context *ctx, NetInfo *net, PortType type, const string
} }
assert(net->driver.cell == nullptr); assert(net->driver.cell == nullptr);
net->driver.port = ctx->id("O"); net->driver.port = ctx->id("O");
net->driver.cell = iobuf; net->driver.cell = iobuf.get();
} else if (type == PORT_OUT) { } else if (type == PORT_OUT) {
if (ctx->verbose) if (ctx->verbose)
log_info("processing output port %s\n", name.c_str()); log_info("processing output port %s\n", name.c_str());
iobuf->type = ctx->id("$nextpnr_obuf"); iobuf->type = ctx->id("$nextpnr_obuf");
iobuf->ports[ctx->id("I")] = PortInfo{ctx->id("I"), net, PORT_IN}; iobuf->ports[ctx->id("I")] = PortInfo{ctx->id("I"), net, PORT_IN};
PortRef ref; PortRef ref;
ref.cell = iobuf; ref.cell = iobuf.get();
ref.port = ctx->id("I"); ref.port = ctx->id("I");
net->users.push_back(ref); net->users.push_back(ref);
} else if (type == PORT_INOUT) { } else if (type == PORT_INOUT) {
@ -654,28 +652,28 @@ static void insert_iobuf(Context *ctx, NetInfo *net, PortType type, const string
iobuf->ports[ctx->id("I")] = PortInfo{ctx->id("I"), nullptr, PORT_IN}; iobuf->ports[ctx->id("I")] = PortInfo{ctx->id("I"), nullptr, PORT_IN};
// Split the input and output nets for bidir ports // Split the input and output nets for bidir ports
NetInfo *net2 = new NetInfo(); std::unique_ptr<NetInfo> net2 = std::unique_ptr<NetInfo>(new NetInfo());
net2->name = ctx->id("$" + net->name.str(ctx) + "$iobuf_i"); net2->name = ctx->id("$" + net->name.str(ctx) + "$iobuf_i");
net2->driver = net->driver; net2->driver = net->driver;
if (net->driver.cell != nullptr) { if (net->driver.cell != nullptr) {
net2->driver.cell->ports[net2->driver.port].net = net2; net2->driver.cell->ports[net2->driver.port].net = net2.get();
net->driver.cell = nullptr; net->driver.cell = nullptr;
} }
ctx->nets[net2->name] = net2; iobuf->ports[ctx->id("I")].net = net2.get();
iobuf->ports[ctx->id("I")].net = net2;
PortRef ref; PortRef ref;
ref.cell = iobuf; ref.cell = iobuf.get();
ref.port = ctx->id("I"); ref.port = ctx->id("I");
net2->users.push_back(ref); net2->users.push_back(ref);
ctx->nets[net2->name] = std::move(net2);
iobuf->ports[ctx->id("O")] = PortInfo{ctx->id("O"), net, PORT_OUT}; iobuf->ports[ctx->id("O")] = PortInfo{ctx->id("O"), net, PORT_OUT};
assert(net->driver.cell == nullptr); assert(net->driver.cell == nullptr);
net->driver.port = ctx->id("O"); net->driver.port = ctx->id("O");
net->driver.cell = iobuf; net->driver.cell = iobuf.get();
} else { } else {
assert(false); assert(false);
} }
ctx->cells[iobuf->name] = iobuf; ctx->cells[iobuf->name] = std::move(iobuf);
} }
void json_import_toplevel_port(Context *ctx, const string &modname, const std::vector<IdString> &netnames, void json_import_toplevel_port(Context *ctx, const string &modname, const std::vector<IdString> &netnames,