Merge branch 'master' of gitlab.com:SymbioticEDA/nextpnr

This commit is contained in:
Clifford Wolf 2018-06-19 12:08:51 +02:00
commit 8067ed9af0
3 changed files with 50 additions and 50 deletions

View File

@ -31,15 +31,15 @@ void add_port(const Context *ctx, CellInfo *cell, std::string name,
cell->ports[id] = PortInfo{id, nullptr, dir}; cell->ports[id] = PortInfo{id, nullptr, dir};
} }
CellInfo *create_ice_cell(Context *ctx, IdString type, IdString name) 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(); CellInfo *new_cell = new CellInfo();
if (name == IdString()) { if (name.empty()) {
new_cell->name = IdString("$nextpnr_" + type.str() + "_" + new_cell->name = IdString(ctx, "$nextpnr_" + type.str() + "_" +
std::to_string(auto_idx++)); std::to_string(auto_idx++));
} else { } else {
new_cell->name = name; new_cell->name = ctx->id(name);
} }
new_cell->type = type; new_cell->type = type;
if (type == ctx->id("ICESTORM_LC")) { if (type == ctx->id("ICESTORM_LC")) {
@ -251,7 +251,7 @@ bool is_enable_port(const Context *ctx, const PortRef &port)
bool is_global_net(const Context *ctx, const NetInfo *net) bool is_global_net(const Context *ctx, const NetInfo *net)
{ {
return bool(net_driven_by(ctx, net, is_gbuf, "GLOBAL_BUFFER_OUTPUT")); return bool(net_driven_by(ctx, net, is_gbuf, ctx->id("GLOBAL_BUFFER_OUTPUT")));
} }
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END

View File

@ -28,7 +28,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, CellInfo *create_ice_cell(Context *ctx, IdString type,
IdString name = IdString()); std::string name = "");
// Return true if a cell is a LUT // Return true if a cell is a LUT
inline bool is_lut(const Context *ctx, const CellInfo *cell) inline bool is_lut(const Context *ctx, const CellInfo *cell)

View File

@ -36,26 +36,26 @@ static void pack_lut_lutffs(Context *ctx)
std::vector<CellInfo *> new_cells; std::vector<CellInfo *> new_cells;
for (auto cell : ctx->cells) { for (auto cell : ctx->cells) {
CellInfo *ci = cell.second; CellInfo *ci = cell.second;
log_info("cell '%s' is of type '%s'\n", ci->name.c_str(), log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx),
ci->type.c_str()); ci->type.c_str(ctx));
if (is_lut(ctx, ci)) { if (is_lut(ctx, ci)) {
CellInfo *packed = CellInfo *packed =
create_ice_cell(ctx, "ICESTORM_LC", ci->name.str() + "_LC"); create_ice_cell(ctx, "ICESTORM_LC", ci->name.str(ctx) + "_LC");
std::copy(ci->attrs.begin(), ci->attrs.end(), std::copy(ci->attrs.begin(), ci->attrs.end(),
std::inserter(packed->attrs, packed->attrs.begin())); std::inserter(packed->attrs, packed->attrs.begin()));
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
new_cells.push_back(packed); new_cells.push_back(packed);
log_info("packed cell %s into %s\n", ci->name.c_str(), log_info("packed cell %s into %s\n", ci->name.c_str(ctx),
packed->name.c_str()); packed->name.c_str(ctx));
// See if we can pack into a DFF // See if we can pack into a DFF
// TODO: LUT cascade // TODO: LUT cascade
NetInfo *o = ci->ports.at("O").net; NetInfo *o = ci->ports.at(ctx->id("O")).net;
CellInfo *dff = net_only_drives(ctx, o, is_ff, "D", true); CellInfo *dff = net_only_drives(ctx, o, is_ff, "D", true);
auto lut_bel = ci->attrs.find("BEL"); auto lut_bel = ci->attrs.find(ctx->id("BEL"));
bool packed_dff = false; bool packed_dff = false;
if (dff) { if (dff) {
log_info("found attached dff %s\n", dff->name.c_str()); log_info("found attached dff %s\n", dff->name.c_str(ctx));
auto dff_bel = dff->attrs.find("BEL"); auto dff_bel = dff->attrs.find(ctx->id("BEL"));
if (lut_bel != ci->attrs.end() && dff_bel != dff->attrs.end() && if (lut_bel != ci->attrs.end() && dff_bel != dff->attrs.end() &&
lut_bel->second != dff_bel->second) { lut_bel->second != dff_bel->second) {
// Locations don't match, can't pack // Locations don't match, can't pack
@ -64,10 +64,10 @@ static void pack_lut_lutffs(Context *ctx)
dff_to_lc(ctx, dff, packed, false); dff_to_lc(ctx, dff, packed, 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["BEL"] = dff_bel->second; packed->attrs[ctx->id("BEL")] = dff_bel->second;
packed_cells.insert(dff->name); packed_cells.insert(dff->name);
log_info("packed cell %s into %s\n", dff->name.c_str(), log_info("packed cell %s into %s\n", dff->name.c_str(ctx),
packed->name.c_str()); packed->name.c_str(ctx));
packed_dff = true; packed_dff = true;
} }
} }
@ -96,11 +96,11 @@ static void pack_nonlut_ffs(Context *ctx)
CellInfo *ci = cell.second; CellInfo *ci = cell.second;
if (is_ff(ctx, ci)) { if (is_ff(ctx, ci)) {
CellInfo *packed = create_ice_cell(ctx, "ICESTORM_LC", CellInfo *packed = create_ice_cell(ctx, "ICESTORM_LC",
ci->name.str() + "_DFFLC"); ci->name.str(ctx) + "_DFFLC");
std::copy(ci->attrs.begin(), ci->attrs.end(), std::copy(ci->attrs.begin(), ci->attrs.end(),
std::inserter(packed->attrs, packed->attrs.begin())); std::inserter(packed->attrs, packed->attrs.begin()));
log_info("packed cell %s into %s\n", ci->name.c_str(), log_info("packed cell %s into %s\n", ci->name.c_str(ctx),
packed->name.c_str()); packed->name.c_str(ctx));
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
new_cells.push_back(packed); new_cells.push_back(packed);
dff_to_lc(ctx, ci, packed, true); dff_to_lc(ctx, ci, packed, true);
@ -126,18 +126,18 @@ static void pack_ram(Context *ctx)
CellInfo *ci = cell.second; CellInfo *ci = cell.second;
if (is_ram(ctx, ci)) { if (is_ram(ctx, ci)) {
CellInfo *packed = create_ice_cell(ctx, "ICESTORM_RAM", CellInfo *packed = create_ice_cell(ctx, "ICESTORM_RAM",
ci->name.str() + "_RAM"); ci->name.str(ctx) + "_RAM");
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
new_cells.push_back(packed); 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["NEG_CLK_W"] = packed->params["NEG_CLK_W"] =
std::to_string(ci->type == "SB_RAM40_4KNW" || std::to_string(ci->type == ctx->id("SB_RAM40_4KNW") ||
ci->type == "SB_RAM40_4KNRNW"); ci->type == ctx->id("SB_RAM40_4KNRNW"));
packed->params["NEG_CLK_R"] = packed->params["NEG_CLK_R"] =
std::to_string(ci->type == "SB_RAM40_4KNR" || std::to_string(ci->type == ctx->id("SB_RAM40_4KNR") ||
ci->type == "SB_RAM40_4KNRNW"); ci->type == ctx->id("SB_RAM40_4KNRNW"));
packed->type = "ICESTORM_RAM"; packed->type = ctx->id("ICESTORM_RAM");
for (auto port : ci->ports) { for (auto port : ci->ports) {
PortInfo &pi = port.second; PortInfo &pi = port.second;
std::string newname = pi.name; std::string newname = pi.name;
@ -168,8 +168,8 @@ static void set_net_constant(const Context *ctx, NetInfo *orig,
for (auto user : orig->users) { for (auto user : orig->users) {
if (user.cell != nullptr) { if (user.cell != nullptr) {
CellInfo *uc = user.cell; CellInfo *uc = user.cell;
log_info("%s user %s\n", orig->name.c_str(), uc->name.c_str()); log_info("%s user %s\n", orig->name.c_str(ctx), uc->name.c_str(ctx));
if (is_lut(ctx, uc) && (user.port.str().at(0) == 'I') && if (is_lut(ctx, uc) && (user.port.str(ctx).at(0) == 'I') &&
!constval) { !constval) {
uc->ports[user.port].net = nullptr; uc->ports[user.port].net = nullptr;
} else { } else {
@ -187,30 +187,30 @@ static void pack_constants(Context *ctx)
log_info("Packing constants..\n"); log_info("Packing constants..\n");
CellInfo *gnd_cell = create_ice_cell(ctx, "ICESTORM_LC", "$PACKER_GND"); CellInfo *gnd_cell = create_ice_cell(ctx, "ICESTORM_LC", "$PACKER_GND");
gnd_cell->params["LUT_INIT"] = "0"; gnd_cell->params[ctx->id("LUT_INIT")] = "0";
NetInfo *gnd_net = new NetInfo; NetInfo *gnd_net = new NetInfo;
gnd_net->name = "$PACKER_GND_NET"; gnd_net->name = "$PACKER_GND_NET";
gnd_net->driver.cell = gnd_cell; gnd_net->driver.cell = gnd_cell;
gnd_net->driver.port = "O"; gnd_net->driver.port = ctx->id("O");
CellInfo *vcc_cell = create_ice_cell(ctx, "ICESTORM_LC", "$PACKER_VCC"); CellInfo *vcc_cell = create_ice_cell(ctx, "ICESTORM_LC", "$PACKER_VCC");
vcc_cell->params["LUT_INIT"] = "1"; vcc_cell->params[ctx->id("LUT_INIT")] = "1";
NetInfo *vcc_net = new NetInfo; NetInfo *vcc_net = new NetInfo;
vcc_net->name = "$PACKER_VCC_NET"; vcc_net->name = ctx->id("$PACKER_VCC_NET");
vcc_net->driver.cell = vcc_cell; vcc_net->driver.cell = vcc_cell;
vcc_net->driver.port = "O"; vcc_net->driver.port = ctx->id("O");
std::vector<IdString> dead_nets; std::vector<IdString> dead_nets;
for (auto net : ctx->nets) { for (auto net : ctx->nets) {
NetInfo *ni = net.second; NetInfo *ni = net.second;
if (ni->driver.cell != nullptr && ni->driver.cell->type == "GND") { if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) {
set_net_constant(ctx, ni, gnd_net, false); set_net_constant(ctx, ni, gnd_net, false);
ctx->cells[gnd_cell->name] = gnd_cell; ctx->cells[gnd_cell->name] = gnd_cell;
ctx->nets[gnd_net->name] = gnd_net; ctx->nets[gnd_net->name] = gnd_net;
dead_nets.push_back(net.first); dead_nets.push_back(net.first);
} else if (ni->driver.cell != nullptr && } else if (ni->driver.cell != nullptr &&
ni->driver.cell->type == "VCC") { ni->driver.cell->type == ctx->id("VCC")) {
set_net_constant(ctx, ni, vcc_net, true); set_net_constant(ctx, ni, vcc_net, true);
ctx->cells[vcc_cell->name] = vcc_cell; ctx->cells[vcc_cell->name] = vcc_cell;
ctx->nets[vcc_net->name] = vcc_net; ctx->nets[vcc_net->name] = vcc_net;
@ -222,10 +222,10 @@ static void pack_constants(Context *ctx)
ctx->nets.erase(dn); ctx->nets.erase(dn);
} }
static bool is_nextpnr_iob(CellInfo *cell) static bool is_nextpnr_iob(Context *ctx, CellInfo *cell)
{ {
return cell->type == "$nextpnr_ibuf" || cell->type == "$nextpnr_obuf" || return cell->type == ctx->id("$nextpnr_ibuf") || cell->type == ctx->id("$nextpnr_obuf") ||
cell->type == "$nextpnr_iobuf"; cell->type == ctx->id("$nextpnr_iobuf");
} }
// Pack IO buffers // Pack IO buffers
@ -238,13 +238,13 @@ static void pack_io(Context *ctx)
for (auto cell : ctx->cells) { for (auto cell : ctx->cells) {
CellInfo *ci = cell.second; CellInfo *ci = cell.second;
if (is_nextpnr_iob(ci)) { if (is_nextpnr_iob(ctx, ci)) {
CellInfo *sb = nullptr; CellInfo *sb = nullptr;
if (ci->type == "$nextpnr_ibuf" || ci->type == "$nextpnr_iobuf") { if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_iobuf")) {
sb = net_only_drives(ctx, 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); "PACKAGE_PIN", true, ci);
} else if (ci->type == "$nextpnr_obuf") { } else if (ci->type == ctx->id("$nextpnr_obuf")) {
sb = net_only_drives(ctx, 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); "PACKAGE_PIN", true, ci);
} }
@ -252,8 +252,8 @@ static void pack_io(Context *ctx)
// Trivial case, SB_IO used. Just destroy the net and the // Trivial case, SB_IO used. Just destroy the net and the
// iobuf // iobuf
log_info("%s feeds SB_IO %s, removing %s %s.\n", log_info("%s feeds SB_IO %s, removing %s %s.\n",
ci->name.c_str(), sb->name.c_str(), ci->type.c_str(), ci->name.c_str(ctx), sb->name.c_str(ctx), ci->type.c_str(ctx),
ci->name.c_str()); ci->name.c_str(ctx));
NetInfo *net = sb->ports.at("PACKAGE_PIN").net; NetInfo *net = sb->ports.at("PACKAGE_PIN").net;
if (net != nullptr) { if (net != nullptr) {
ctx->nets.erase(net->name); ctx->nets.erase(net->name);
@ -281,22 +281,22 @@ static void pack_io(Context *ctx)
static void insert_global(Context *ctx, NetInfo *net, bool is_reset, static void insert_global(Context *ctx, NetInfo *net, bool is_reset,
bool is_cen) bool is_cen)
{ {
std::string glb_name = net->name.str() + std::string("_$glb_") + std::string glb_name = net->name.str(ctx) + std::string("_$glb_") +
(is_reset ? "sr" : (is_cen ? "ce" : "clk")); (is_reset ? "sr" : (is_cen ? "ce" : "clk"));
CellInfo *gb = create_ice_cell(ctx, "SB_GB", "$gbuf_" + glb_name); CellInfo *gb = create_ice_cell(ctx, "SB_GB", "$gbuf_" + glb_name);
gb->ports["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;
pr.port = "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;
pr.port = "GLOBAL_BUFFER_OUTPUT"; pr.port = ctx->id("GLOBAL_BUFFER_OUTPUT");
NetInfo *glbnet = new NetInfo(); NetInfo *glbnet = new NetInfo();
glbnet->name = glb_name; glbnet->name = ctx->id(glb_name);
glbnet->driver = pr; glbnet->driver = pr;
ctx->nets[glbnet->name] = glbnet; ctx->nets[glbnet->name] = glbnet;
gb->ports["GLOBAL_BUFFER_OUTPUT"].net = glbnet; 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) || if (is_clock_port(ctx, user) ||