ice40: Preserve top level IO properly
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
cf5cbd1153
commit
a22f86f861
@ -419,9 +419,9 @@ void nxio_to_tr(Context *ctx, CellInfo *nxio, CellInfo *trio, std::vector<std::u
|
|||||||
NetInfo *donet = trio->ports.at(ctx->id("I")).net, *dinet = trio->ports.at(ctx->id("O")).net;
|
NetInfo *donet = trio->ports.at(ctx->id("I")).net, *dinet = trio->ports.at(ctx->id("O")).net;
|
||||||
|
|
||||||
// Rename I/O nets to avoid conflicts
|
// Rename I/O nets to avoid conflicts
|
||||||
if (donet != nullptr)
|
if (donet != nullptr && donet->name == nxio->name)
|
||||||
rename_net(ctx, donet, ctx->id(donet->name.str(ctx) + "$TRELLIS_IO_OUT"));
|
rename_net(ctx, donet, ctx->id(donet->name.str(ctx) + "$TRELLIS_IO_OUT"));
|
||||||
if (dinet != nullptr)
|
if (dinet != nullptr && dinet->name == nxio->name)
|
||||||
rename_net(ctx, dinet, ctx->id(dinet->name.str(ctx) + "$TRELLIS_IO_IN"));
|
rename_net(ctx, dinet, ctx->id(dinet->name.str(ctx) + "$TRELLIS_IO_IN"));
|
||||||
|
|
||||||
// Create a new top port net for accurate IO timing analysis and simulation netlists
|
// Create a new top port net for accurate IO timing analysis and simulation netlists
|
||||||
|
@ -426,7 +426,25 @@ void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio, std::unordered_set
|
|||||||
} else {
|
} else {
|
||||||
NPNR_ASSERT(false);
|
NPNR_ASSERT(false);
|
||||||
}
|
}
|
||||||
NetInfo *donet = sbio->ports.at(ctx->id("D_OUT_0")).net;
|
NetInfo *donet = sbio->ports.at(ctx->id("D_OUT_0")).net, *dinet = sbio->ports.at(ctx->id("D_IN_0")).net;
|
||||||
|
|
||||||
|
// Rename I/O nets to avoid conflicts
|
||||||
|
if (donet != nullptr && donet->name == nxio->name)
|
||||||
|
rename_net(ctx, donet, ctx->id(donet->name.str(ctx) + "$SB_IO_OUT"));
|
||||||
|
if (dinet != nullptr && dinet->name == nxio->name)
|
||||||
|
rename_net(ctx, dinet, ctx->id(dinet->name.str(ctx) + "$SB_IO_IN"));
|
||||||
|
|
||||||
|
// Create a new top port net for accurate IO timing analysis and simulation netlists
|
||||||
|
if (ctx->ports.count(nxio->name)) {
|
||||||
|
IdString tn_netname = nxio->name;
|
||||||
|
NPNR_ASSERT(!ctx->nets.count(tn_netname));
|
||||||
|
std::unique_ptr<NetInfo> toplevel_net{new NetInfo};
|
||||||
|
toplevel_net->name = tn_netname;
|
||||||
|
connect_port(ctx, toplevel_net.get(), sbio, ctx->id("PACKAGE_PIN"));
|
||||||
|
ctx->ports[nxio->name].net = toplevel_net.get();
|
||||||
|
ctx->nets[tn_netname] = std::move(toplevel_net);
|
||||||
|
}
|
||||||
|
|
||||||
CellInfo *tbuf = net_driven_by(
|
CellInfo *tbuf = net_driven_by(
|
||||||
ctx, donet, [](const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("$_TBUF_"); },
|
ctx, donet, [](const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("$_TBUF_"); },
|
||||||
ctx->id("Y"));
|
ctx->id("Y"));
|
||||||
|
@ -459,7 +459,6 @@ static void pack_io(Context *ctx)
|
|||||||
{
|
{
|
||||||
std::unordered_set<IdString> packed_cells;
|
std::unordered_set<IdString> packed_cells;
|
||||||
std::unordered_set<IdString> delete_nets;
|
std::unordered_set<IdString> delete_nets;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
std::vector<std::unique_ptr<CellInfo>> new_cells;
|
||||||
log_info("Packing IOs..\n");
|
log_info("Packing IOs..\n");
|
||||||
|
|
||||||
@ -478,8 +477,7 @@ static void pack_io(Context *ctx)
|
|||||||
rgb = net->driver.cell;
|
rgb = net->driver.cell;
|
||||||
}
|
}
|
||||||
if (sb != nullptr) {
|
if (sb != nullptr) {
|
||||||
// Trivial case, SB_IO used. Just destroy the net and the
|
// Trivial case, SB_IO used. Just destroy the iobuf
|
||||||
// iobuf
|
|
||||||
log_info("%s feeds SB_IO %s, removing %s %s.\n", ci->name.c_str(ctx), sb->name.c_str(ctx),
|
log_info("%s feeds SB_IO %s, removing %s %s.\n", ci->name.c_str(ctx), sb->name.c_str(ctx),
|
||||||
ci->type.c_str(ctx), ci->name.c_str(ctx));
|
ci->type.c_str(ctx), ci->name.c_str(ctx));
|
||||||
NetInfo *net = sb->ports.at(ctx->id("PACKAGE_PIN")).net;
|
NetInfo *net = sb->ports.at(ctx->id("PACKAGE_PIN")).net;
|
||||||
@ -490,7 +488,6 @@ static void pack_io(Context *ctx)
|
|||||||
sb->type.c_str(ctx), sb->name.c_str(ctx));
|
sb->type.c_str(ctx), sb->name.c_str(ctx));
|
||||||
|
|
||||||
if (net != nullptr) {
|
if (net != nullptr) {
|
||||||
|
|
||||||
if (net->clkconstr != nullptr) {
|
if (net->clkconstr != nullptr) {
|
||||||
if (sb->ports.count(id_D_IN_0)) {
|
if (sb->ports.count(id_D_IN_0)) {
|
||||||
NetInfo *din0_net = sb->ports.at(id_D_IN_0).net;
|
NetInfo *din0_net = sb->ports.at(id_D_IN_0).net;
|
||||||
@ -509,15 +506,6 @@ static void pack_io(Context *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_nets.insert(net->name);
|
|
||||||
sb->ports.at(ctx->id("PACKAGE_PIN")).net = nullptr;
|
|
||||||
}
|
|
||||||
if (ci->type == ctx->id("$nextpnr_iobuf")) {
|
|
||||||
NetInfo *net2 = ci->ports.at(ctx->id("I")).net;
|
|
||||||
if (net2 != nullptr) {
|
|
||||||
delete_nets.insert(net2->name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (rgb != nullptr) {
|
} else if (rgb != nullptr) {
|
||||||
log_info("%s use by SB_RGBA_DRV/SB_RGB_DRV %s, not creating SB_IO\n", ci->name.c_str(ctx),
|
log_info("%s use by SB_RGBA_DRV/SB_RGB_DRV %s, not creating SB_IO\n", ci->name.c_str(ctx),
|
||||||
@ -533,6 +521,8 @@ static void pack_io(Context *ctx)
|
|||||||
new_cells.push_back(std::move(ice_cell));
|
new_cells.push_back(std::move(ice_cell));
|
||||||
sb = new_cells.back().get();
|
sb = new_cells.back().get();
|
||||||
}
|
}
|
||||||
|
for (auto port : ci->ports)
|
||||||
|
disconnect_port(ctx, ci, port.first);
|
||||||
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()));
|
||||||
} else if (is_sb_io(ctx, ci) || is_sb_gb_io(ctx, ci)) {
|
} else if (is_sb_io(ctx, ci) || is_sb_gb_io(ctx, ci)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user