aboutsummaryrefslogtreecommitdiffstats
path: root/ecp5
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2022-02-18 10:52:37 +0000
committergatecat <gatecat@ds0.me>2022-02-18 11:13:18 +0000
commit6a32aca4ac8705b637943c236cedd2f36422fb21 (patch)
tree28483964fb3c92bc104ab6162d1c9196651ced26 /ecp5
parent61d1db16be2c68cf6ae8b4d2ff3266b5c7086ad2 (diff)
downloadnextpnr-6a32aca4ac8705b637943c236cedd2f36422fb21.tar.gz
nextpnr-6a32aca4ac8705b637943c236cedd2f36422fb21.tar.bz2
nextpnr-6a32aca4ac8705b637943c236cedd2f36422fb21.zip
refactor: New member functions to replace design_utils
Signed-off-by: gatecat <gatecat@ds0.me>
Diffstat (limited to 'ecp5')
-rw-r--r--ecp5/arch_place.cc4
-rw-r--r--ecp5/bitstream.cc28
-rw-r--r--ecp5/cells.cc139
-rw-r--r--ecp5/globals.cc6
-rw-r--r--ecp5/pack.cc299
5 files changed, 238 insertions, 238 deletions
diff --git a/ecp5/arch_place.cc b/ecp5/arch_place.cc
index a1f8aa1f..b1849ee6 100644
--- a/ecp5/arch_place.cc
+++ b/ecp5/arch_place.cc
@@ -124,10 +124,10 @@ void Arch::permute_luts()
for (int i = 0; i < 4; i++) {
IdString p = port_names.at(i);
// log_info("%s %s %f\n", p.c_str(ctx), port_names.at(inputs.at(i).second).c_str(ctx), inputs.at(i).first);
- disconnect_port(getCtx(), ci, p);
+ ci->disconnectPort(p);
ci->ports.at(p).net = nullptr;
if (orig_nets.at(inputs.at(i).second) != nullptr) {
- connect_port(getCtx(), orig_nets.at(inputs.at(i).second), ci, p);
+ ci->connectPort(p, orig_nets.at(inputs.at(i).second));
ci->params[id(p.str(this) + "MUX")] = p.str(this);
} else {
ci->params[id(p.str(this) + "MUX")] = std::string("1");
diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc
index 11a855ec..a23e4cd2 100644
--- a/ecp5/bitstream.cc
+++ b/ecp5/bitstream.cc
@@ -1043,7 +1043,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
if (trimux_tsreg != "PADDT")
cc.tiles[pic_tile].add_enum(pio + ".TRIMUX_TSREG", trimux_tsreg);
} else if (ci->type == id_DCCA) {
- const NetInfo *cen = get_net_or_empty(ci, id_CE);
+ const NetInfo *cen = ci->getPort(id_CE);
if (cen != nullptr) {
std::string belname = ctx->loc_info(bel)->bel_data[bel.index].name.get();
Loc loc = ctx->getBelLocation(bel);
@@ -1347,13 +1347,13 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
tg.config.add_enum("CLKOS_TRIM_DELAY", intstr_or_default(ci->params, id_CLKOS_TRIM_DELAY, "0"));
tg.config.add_enum("OUTDIVIDER_MUXA", str_or_default(ci->params, id_OUTDIVIDER_MUXA,
- get_net_or_empty(ci, id_CLKOP) ? "DIVA" : "REFCLK"));
+ ci->getPort(id_CLKOP) ? "DIVA" : "REFCLK"));
tg.config.add_enum("OUTDIVIDER_MUXB", str_or_default(ci->params, id_OUTDIVIDER_MUXB,
- get_net_or_empty(ci, id_CLKOP) ? "DIVB" : "REFCLK"));
+ ci->getPort(id_CLKOP) ? "DIVB" : "REFCLK"));
tg.config.add_enum("OUTDIVIDER_MUXC", str_or_default(ci->params, id_OUTDIVIDER_MUXC,
- get_net_or_empty(ci, id_CLKOP) ? "DIVC" : "REFCLK"));
+ ci->getPort(id_CLKOP) ? "DIVC" : "REFCLK"));
tg.config.add_enum("OUTDIVIDER_MUXD", str_or_default(ci->params, id_OUTDIVIDER_MUXD,
- get_net_or_empty(ci, id_CLKOP) ? "DIVD" : "REFCLK"));
+ ci->getPort(id_CLKOP) ? "DIVD" : "REFCLK"));
tg.config.add_word("PLL_LOCK_MODE", int_to_bitvector(int_or_default(ci->params, id_PLL_LOCK_MODE, 0), 3));
@@ -1404,7 +1404,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
else
cc.tiles[pic_tile].add_enum(prim + "." + param.first.str(ctx), param.second.as_string());
}
- if (get_net_or_empty(ci, id_LOADN) != nullptr) {
+ if (ci->getPort(id_LOADN) != nullptr) {
cc.tiles[pic_tile].add_enum(prim + ".LOADNMUX", "LOADN");
}
} else if (ci->type == id_DCUA) {
@@ -1481,14 +1481,12 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
lo_del_value = (256 - lo_del_value) & 0xFF;
tg.config.add_word("DQS.DQS_LI_DEL_VAL", int_to_bitvector(li_del_value, 8));
tg.config.add_word("DQS.DQS_LO_DEL_VAL", int_to_bitvector(lo_del_value, 8));
- tg.config.add_enum("DQS.WRLOADN_USED", get_net_or_empty(ci, id_WRLOADN) != nullptr ? "YES" : "NO");
- tg.config.add_enum("DQS.RDLOADN_USED", get_net_or_empty(ci, id_RDLOADN) != nullptr ? "YES" : "NO");
- tg.config.add_enum("DQS.PAUSE_USED", get_net_or_empty(ci, id_PAUSE) != nullptr ? "YES" : "NO");
+ tg.config.add_enum("DQS.WRLOADN_USED", ci->getPort(id_WRLOADN) != nullptr ? "YES" : "NO");
+ tg.config.add_enum("DQS.RDLOADN_USED", ci->getPort(id_RDLOADN) != nullptr ? "YES" : "NO");
+ tg.config.add_enum("DQS.PAUSE_USED", ci->getPort(id_PAUSE) != nullptr ? "YES" : "NO");
tg.config.add_enum("DQS.READ_USED",
- (get_net_or_empty(ci, id_READ0) != nullptr || get_net_or_empty(ci, id_READ1) != nullptr)
- ? "YES"
- : "NO");
- tg.config.add_enum("DQS.DDRDEL", get_net_or_empty(ci, id_DDRDEL) != nullptr ? "DDRDEL" : "0");
+ (ci->getPort(id_READ0) != nullptr || ci->getPort(id_READ1) != nullptr) ? "YES" : "NO");
+ tg.config.add_enum("DQS.DDRDEL", ci->getPort(id_DDRDEL) != nullptr ? "DDRDEL" : "0");
tg.config.add_enum("DQS.GSR", str_or_default(ci->params, id_GSR, "DISABLED"));
cc.tilegroups.push_back(tg);
} else if (ci->type == id_ECLKSYNCB) {
@@ -1496,14 +1494,14 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
bool r = loc.x > 5;
std::string eclksync = ctx->loc_info(bel)->bel_data[bel.index].name.get();
std::string tile = ctx->get_tile_by_type(std::string("ECLK_") + (r ? "R" : "L"));
- if (get_net_or_empty(ci, id_STOP) != nullptr)
+ if (ci->getPort(id_STOP) != nullptr)
cc.tiles[tile].add_enum(eclksync + ".MODE", "ECLKSYNCB");
} else if (ci->type == id_ECLKBRIDGECS) {
Loc loc = ctx->getBelLocation(ci->bel);
bool r = loc.x > 5;
std::string eclkb = ctx->loc_info(bel)->bel_data[bel.index].name.get();
std::string tile = ctx->get_tile_by_type(std::string("ECLK_") + (r ? "R" : "L"));
- if (get_net_or_empty(ci, id_STOP) != nullptr)
+ if (ci->getPort(id_STOP) != nullptr)
cc.tiles[tile].add_enum(eclkb + ".MODE", "ECLKBRIDGECS");
} else if (ci->type == id_DDRDLL) {
Loc loc = ctx->getBelLocation(ci->bel);
diff --git a/ecp5/cells.cc b/ecp5/cells.cc
index 6d88af75..a5d484ff 100644
--- a/ecp5/cells.cc
+++ b/ecp5/cells.cc
@@ -217,7 +217,7 @@ static void replace_port_safe(bool has_ff, CellInfo *ff, IdString ff_port, CellI
[ff, ff_port](PortRef port) { return port.cell == ff && port.port == ff_port; }),
ffnet->users.end());
} else {
- replace_port(ff, ff_port, lc, lc_port);
+ ff->movePortTo(ff_port, lc, lc_port);
}
}
@@ -242,21 +242,21 @@ void ff_to_slice(Context *ctx, CellInfo *ff, CellInfo *lc, int index, bool drive
if (ff->ports.find(id_CE) != ff->ports.end())
replace_port_safe(has_ff, ff, id_CE, lc, id_CE);
- replace_port(ff, id_Q, lc, ctx->id("Q" + std::to_string(index)));
- if (get_net_or_empty(ff, id_M) != nullptr) {
+ ff->movePortTo(id_Q, lc, ctx->id("Q" + std::to_string(index)));
+ if (ff->getPort(id_M) != nullptr) {
// PRLD FFs that use both M and DI
NPNR_ASSERT(!driven_by_lut);
// As M is used; must route DI through a new LUT
lc->params[ctx->id(reg + "_SD")] = std::string("1");
lc->params[ctx->id("LUT" + std::to_string(index) + "_INITVAL")] = Property(0xFF00, 16);
- replace_port(ff, id_DI, lc, ctx->id("D" + std::to_string(index)));
- replace_port(ff, id_M, lc, ctx->id("M" + std::to_string(index)));
- connect_ports(ctx, lc, ctx->id("F" + std::to_string(index)), lc, ctx->id("DI" + std::to_string(index)));
+ ff->movePortTo(id_DI, lc, ctx->id("D" + std::to_string(index)));
+ ff->movePortTo(id_M, lc, ctx->id("M" + std::to_string(index)));
+ lc->connectPorts(ctx->id("F" + std::to_string(index)), lc, ctx->id("DI" + std::to_string(index)));
} else {
if (driven_by_lut) {
- replace_port(ff, id_DI, lc, ctx->id("DI" + std::to_string(index)));
+ ff->movePortTo(id_DI, lc, ctx->id("DI" + std::to_string(index)));
} else {
- replace_port(ff, id_DI, lc, ctx->id("M" + std::to_string(index)));
+ ff->movePortTo(id_DI, lc, ctx->id("M" + std::to_string(index)));
}
}
}
@@ -267,11 +267,11 @@ void lut_to_slice(Context *ctx, CellInfo *lut, CellInfo *lc, int index)
lc->hierpath = lut->hierpath;
lc->params[ctx->id("LUT" + std::to_string(index) + "_INITVAL")] =
get_or_default(lut->params, id_INIT, Property(0, 16));
- replace_port(lut, id_A, lc, ctx->id("A" + std::to_string(index)));
- replace_port(lut, id_B, lc, ctx->id("B" + std::to_string(index)));
- replace_port(lut, id_C, lc, ctx->id("C" + std::to_string(index)));
- replace_port(lut, id_D, lc, ctx->id("D" + std::to_string(index)));
- replace_port(lut, id_Z, lc, ctx->id("F" + std::to_string(index)));
+ lut->movePortTo(id_A, lc, ctx->id("A" + std::to_string(index)));
+ lut->movePortTo(id_B, lc, ctx->id("B" + std::to_string(index)));
+ lut->movePortTo(id_C, lc, ctx->id("C" + std::to_string(index)));
+ lut->movePortTo(id_D, lc, ctx->id("D" + std::to_string(index)));
+ lut->movePortTo(id_Z, lc, ctx->id("F" + std::to_string(index)));
}
void ccu2c_to_slice(Context *ctx, CellInfo *ccu, CellInfo *lc)
@@ -285,22 +285,22 @@ void ccu2c_to_slice(Context *ctx, CellInfo *ccu, CellInfo *lc)
lc->params[id_CCU2_INJECT1_0] = str_or_default(ccu->params, id_INJECT1_0, "YES");
lc->params[id_CCU2_INJECT1_1] = str_or_default(ccu->params, id_INJECT1_1, "YES");
- replace_port(ccu, id_CIN, lc, id_FCI);
+ ccu->movePortTo(id_CIN, lc, id_FCI);
- replace_port(ccu, id_A0, lc, id_A0);
- replace_port(ccu, id_B0, lc, id_B0);
- replace_port(ccu, id_C0, lc, id_C0);
- replace_port(ccu, id_D0, lc, id_D0);
+ ccu->movePortTo(id_A0, lc, id_A0);
+ ccu->movePortTo(id_B0, lc, id_B0);
+ ccu->movePortTo(id_C0, lc, id_C0);
+ ccu->movePortTo(id_D0, lc, id_D0);
- replace_port(ccu, id_A1, lc, id_A1);
- replace_port(ccu, id_B1, lc, id_B1);
- replace_port(ccu, id_C1, lc, id_C1);
- replace_port(ccu, id_D1, lc, id_D1);
+ ccu->movePortTo(id_A1, lc, id_A1);
+ ccu->movePortTo(id_B1, lc, id_B1);
+ ccu->movePortTo(id_C1, lc, id_C1);
+ ccu->movePortTo(id_D1, lc, id_D1);
- replace_port(ccu, id_S0, lc, id_F0);
- replace_port(ccu, id_S1, lc, id_F1);
+ ccu->movePortTo(id_S0, lc, id_F0);
+ ccu->movePortTo(id_S1, lc, id_F1);
- replace_port(ccu, id_COUT, lc, id_FCO);
+ ccu->movePortTo(id_COUT, lc, id_FCO);
}
void dram_to_ramw(Context *ctx, CellInfo *ram, CellInfo *lc)
@@ -308,15 +308,15 @@ void dram_to_ramw(Context *ctx, CellInfo *ram, CellInfo *lc)
if (lc->hierpath == IdString())
lc->hierpath = ram->hierpath;
lc->params[id_MODE] = std::string("RAMW");
- replace_port(ram, ctx->id("WAD[0]"), lc, id_D0);
- replace_port(ram, ctx->id("WAD[1]"), lc, id_B0);
- replace_port(ram, ctx->id("WAD[2]"), lc, id_C0);
- replace_port(ram, ctx->id("WAD[3]"), lc, id_A0);
-
- replace_port(ram, ctx->id("DI[0]"), lc, id_C1);
- replace_port(ram, ctx->id("DI[1]"), lc, id_A1);
- replace_port(ram, ctx->id("DI[2]"), lc, id_D1);
- replace_port(ram, ctx->id("DI[3]"), lc, id_B1);
+ ram->movePortTo(ctx->id("WAD[0]"), lc, id_D0);
+ ram->movePortTo(ctx->id("WAD[1]"), lc, id_B0);
+ ram->movePortTo(ctx->id("WAD[2]"), lc, id_C0);
+ ram->movePortTo(ctx->id("WAD[3]"), lc, id_A0);
+
+ ram->movePortTo(ctx->id("DI[0]"), lc, id_C1);
+ ram->movePortTo(ctx->id("DI[1]"), lc, id_A1);
+ ram->movePortTo(ctx->id("DI[2]"), lc, id_D1);
+ ram->movePortTo(ctx->id("DI[3]"), lc, id_B1);
}
static unsigned get_dram_init(const Context *ctx, const CellInfo *ram, int bit)
@@ -367,45 +367,45 @@ void dram_to_ram_slice(Context *ctx, CellInfo *ram, CellInfo *lc, CellInfo *ramw
lc->params[id_LUT1_INITVAL] = Property(permuted_init1, 16);
if (ram->ports.count(ctx->id("RAD[0]"))) {
- connect_port(ctx, ram->ports.at(ctx->id("RAD[0]")).net, lc, id_D0);
- connect_port(ctx, ram->ports.at(ctx->id("RAD[0]")).net, lc, id_D1);
+ lc->connectPort(id_D0, ram->ports.at(ctx->id("RAD[0]")).net);
+ lc->connectPort(id_D1, ram->ports.at(ctx->id("RAD[0]")).net);
}
if (ram->ports.count(ctx->id("RAD[1]"))) {
- connect_port(ctx, ram->ports.at(ctx->id("RAD[1]")).net, lc, id_B0);
- connect_port(ctx, ram->ports.at(ctx->id("RAD[1]")).net, lc, id_B1);
+ lc->connectPort(id_B0, ram->ports.at(ctx->id("RAD[1]")).net);
+ lc->connectPort(id_B1, ram->ports.at(ctx->id("RAD[1]")).net);
}
if (ram->ports.count(ctx->id("RAD[2]"))) {
- connect_port(ctx, ram->ports.at(ctx->id("RAD[2]")).net, lc, id_C0);
- connect_port(ctx, ram->ports.at(ctx->id("RAD[2]")).net, lc, id_C1);
+ lc->connectPort(id_C0, ram->ports.at(ctx->id("RAD[2]")).net);
+ lc->connectPort(id_C1, ram->ports.at(ctx->id("RAD[2]")).net);
}
if (ram->ports.count(ctx->id("RAD[3]"))) {
- connect_port(ctx, ram->ports.at(ctx->id("RAD[3]")).net, lc, id_A0);
- connect_port(ctx, ram->ports.at(ctx->id("RAD[3]")).net, lc, id_A1);
+ lc->connectPort(id_A0, ram->ports.at(ctx->id("RAD[3]")).net);
+ lc->connectPort(id_A1, ram->ports.at(ctx->id("RAD[3]")).net);
}
if (ram->ports.count(id_WRE))
- connect_port(ctx, ram->ports.at(id_WRE).net, lc, id_WRE);
+ lc->connectPort(id_WRE, ram->ports.at(id_WRE).net);
if (ram->ports.count(id_WCK))
- connect_port(ctx, ram->ports.at(id_WCK).net, lc, id_WCK);
+ lc->connectPort(id_WCK, ram->ports.at(id_WCK).net);
- connect_ports(ctx, ramw, id_WADO0, lc, id_WAD0);
- connect_ports(ctx, ramw, id_WADO1, lc, id_WAD1);
- connect_ports(ctx, ramw, id_WADO2, lc, id_WAD2);
- connect_ports(ctx, ramw, id_WADO3, lc, id_WAD3);
+ ramw->connectPorts(id_WADO0, lc, id_WAD0);
+ ramw->connectPorts(id_WADO1, lc, id_WAD1);
+ ramw->connectPorts(id_WADO2, lc, id_WAD2);
+ ramw->connectPorts(id_WADO3, lc, id_WAD3);
if (index == 0) {
- connect_ports(ctx, ramw, id_WDO0, lc, id_WD0);
- connect_ports(ctx, ramw, id_WDO1, lc, id_WD1);
+ ramw->connectPorts(id_WDO0, lc, id_WD0);
+ ramw->connectPorts(id_WDO1, lc, id_WD1);
- replace_port(ram, ctx->id("DO[0]"), lc, id_F0);
- replace_port(ram, ctx->id("DO[1]"), lc, id_F1);
+ ram->movePortTo(ctx->id("DO[0]"), lc, id_F0);
+ ram->movePortTo(ctx->id("DO[1]"), lc, id_F1);
} else if (index == 1) {
- connect_ports(ctx, ramw, id_WDO2, lc, id_WD0);
- connect_ports(ctx, ramw, id_WDO3, lc, id_WD1);
+ ramw->connectPorts(id_WDO2, lc, id_WD0);
+ ramw->connectPorts(id_WDO3, lc, id_WD1);
- replace_port(ram, ctx->id("DO[2]"), lc, id_F0);
- replace_port(ram, ctx->id("DO[3]"), lc, id_F1);
+ ram->movePortTo(ctx->id("DO[2]"), lc, id_F0);
+ ram->movePortTo(ctx->id("DO[3]"), lc, id_F1);
} else {
NPNR_ASSERT_FALSE("bad DPRAM index");
}
@@ -416,21 +416,21 @@ void nxio_to_tr(Context *ctx, CellInfo *nxio, CellInfo *trio, std::vector<std::u
{
if (nxio->type == ctx->id("$nextpnr_ibuf")) {
trio->params[id_DIR] = std::string("INPUT");
- replace_port(nxio, id_O, trio, id_O);
+ nxio->movePortTo(id_O, trio, id_O);
} else if (nxio->type == ctx->id("$nextpnr_obuf")) {
trio->params[id_DIR] = std::string("OUTPUT");
- replace_port(nxio, id_I, trio, id_I);
+ nxio->movePortTo(id_I, trio, id_I);
} else if (nxio->type == ctx->id("$nextpnr_iobuf")) {
// N.B. tristate will be dealt with below
- NetInfo *i = get_net_or_empty(nxio, id_I);
+ NetInfo *i = nxio->getPort(id_I);
if (i == nullptr || i->driver.cell == nullptr)
trio->params[id_DIR] = std::string("INPUT");
else {
log_info("%s: %s.%s\n", ctx->nameOf(i), ctx->nameOf(i->driver.cell), ctx->nameOf(i->driver.port));
trio->params[id_DIR] = std::string("BIDIR");
}
- replace_port(nxio, id_I, trio, id_I);
- replace_port(nxio, id_O, trio, id_O);
+ nxio->movePortTo(id_I, trio, id_I);
+ nxio->movePortTo(id_O, trio, id_O);
} else {
NPNR_ASSERT(false);
}
@@ -438,9 +438,11 @@ void nxio_to_tr(Context *ctx, CellInfo *nxio, CellInfo *trio, std::vector<std::u
// Rename I/O nets to avoid conflicts
if (donet != nullptr && donet->name == nxio->name)
- rename_net(ctx, donet, ctx->id(donet->name.str(ctx) + "$TRELLIS_IO_OUT"));
+ if (donet)
+ ctx->renameNet(donet->name, ctx->id(donet->name.str(ctx) + "$TRELLIS_IO_OUT"));
if (dinet != nullptr && dinet->name == nxio->name)
- rename_net(ctx, dinet, ctx->id(dinet->name.str(ctx) + "$TRELLIS_IO_IN"));
+ if (dinet)
+ ctx->renameNet(dinet->name, ctx->id(dinet->name.str(ctx) + "$TRELLIS_IO_IN"));
if (ctx->nets.count(nxio->name)) {
int i = 0;
@@ -448,7 +450,8 @@ void nxio_to_tr(Context *ctx, CellInfo *nxio, CellInfo *trio, std::vector<std::u
do {
new_name = ctx->id(nxio->name.str(ctx) + "$rename$" + std::to_string(i++));
} while (ctx->nets.count(new_name));
- rename_net(ctx, ctx->nets.at(nxio->name).get(), new_name);
+ if (ctx->nets.at(nxio->name).get())
+ ctx->renameNet(ctx->nets.at(nxio->name).get()->name, new_name);
}
// Create a new top port net for accurate IO timing analysis and simulation netlists
@@ -458,7 +461,7 @@ void nxio_to_tr(Context *ctx, CellInfo *nxio, CellInfo *trio, std::vector<std::u
ctx->net_aliases.erase(tn_netname);
NetInfo *toplevel_net = ctx->createNet(tn_netname);
toplevel_net->name = tn_netname;
- connect_port(ctx, toplevel_net, trio, id_B);
+ trio->connectPort(id_B, toplevel_net);
ctx->ports[nxio->name].net = toplevel_net;
}
@@ -466,12 +469,12 @@ void nxio_to_tr(Context *ctx, CellInfo *nxio, CellInfo *trio, std::vector<std::u
ctx, donet, [](const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("$_TBUF_"); },
id_Y);
if (tbuf) {
- replace_port(tbuf, id_A, trio, id_I);
+ tbuf->movePortTo(id_A, trio, id_I);
// Need to invert E to form T
std::unique_ptr<CellInfo> inv_lut = create_ecp5_cell(ctx, id_LUT4, trio->name.str(ctx) + "$invert_T");
- replace_port(tbuf, id_E, inv_lut.get(), id_A);
+ tbuf->movePortTo(id_E, inv_lut.get(), id_A);
inv_lut->params[id_INIT] = Property(21845, 16);
- connect_ports(ctx, inv_lut.get(), id_Z, trio, id_T);
+ inv_lut->connectPorts(id_Z, trio, id_T);
created_cells.push_back(std::move(inv_lut));
if (donet->users.size() > 1) {
diff --git a/ecp5/globals.cc b/ecp5/globals.cc
index 844c596b..7b48e693 100644
--- a/ecp5/globals.cc
+++ b/ecp5/globals.cc
@@ -399,7 +399,7 @@ class Ecp5GlobalRouter
{
BelId best_bel;
WireId best_bel_pclkcib;
- bool using_ce = get_net_or_empty(dcc, id_CE) != nullptr;
+ bool using_ce = dcc->getPort(id_CE) != nullptr;
wirelen_t best_wirelen = 9999999;
bool dedicated_routing = false;
for (auto bel : ctx->getBels()) {
@@ -533,7 +533,7 @@ class Ecp5GlobalRouter
}
for (auto ci : dcsc_cells) {
for (auto port : {id_CLK0, id_CLK1}) {
- NetInfo *net = get_net_or_empty(ci, port);
+ NetInfo *net = ci->getPort(port);
if (net != nullptr)
insert_dcc(net, ci);
}
@@ -609,7 +609,7 @@ class Ecp5GlobalRouter
pins.push_back(id_CLK1);
}
for (auto pin : pins) {
- NetInfo *ni = get_net_or_empty(ci, pin);
+ NetInfo *ni = ci->getPort(pin);
if (ni == nullptr)
continue;
log_info(" trying dedicated routing for edge clock source %s\n", ctx->nameOf(ni));
diff --git a/ecp5/pack.cc b/ecp5/pack.cc
index d49dbdf3..2b069db0 100644
--- a/ecp5/pack.cc
+++ b/ecp5/pack.cc
@@ -112,7 +112,7 @@ class Ecp5Packer
if (znet != nullptr) {
CellInfo *ff = net_only_drives(ctx, znet, is_ff, id_DI, false);
// Can't combine preload FF with LUT due to conflict on M
- if (ff != nullptr && get_net_or_empty(ff, id_M) == nullptr) {
+ if (ff != nullptr && ff->getPort(id_M) == nullptr) {
lutffPairs[ci->name] = ff->name;
fflutPairs[ff->name] = ci->name;
}
@@ -124,9 +124,9 @@ class Ecp5Packer
// Check if a flipflop is available in a slice
bool is_ff_available(CellInfo *slice, int ff)
{
- if (get_net_or_empty(slice, (ff == 1) ? id_Q1 : id_Q0) != nullptr)
+ if (slice->getPort((ff == 1) ? id_Q1 : id_Q0) != nullptr)
return false;
- if (get_net_or_empty(slice, (ff == 1) ? id_M1 : id_M0) != nullptr)
+ if (slice->getPort((ff == 1) ? id_M1 : id_M0) != nullptr)
return false;
return true;
}
@@ -146,8 +146,8 @@ class Ecp5Packer
if (wremux != lsrmux && !(wremux == "WRE" && lsrmux == "LSR"))
return false;
}
- bool has_ff0 = get_net_or_empty(slice, id_Q0) != nullptr;
- bool has_ff1 = get_net_or_empty(slice, id_Q1) != nullptr;
+ bool has_ff0 = slice->getPort(id_Q0) != nullptr;
+ bool has_ff1 = slice->getPort(id_Q1) != nullptr;
if (!has_ff0 && !has_ff1)
return true;
if (str_or_default(ff->params, id_GSR, "DISABLED") != str_or_default(slice->params, id_GSR, "DISABLED"))
@@ -224,7 +224,7 @@ class Ecp5Packer
// Return true if a FF can be added to a DPRAM slice
bool can_pack_ff_dram(CellInfo *dpram, CellInfo *ff)
{
- if (get_net_or_empty(ff, id_M) != nullptr)
+ if (ff->getPort(id_M) != nullptr)
return false; // skip PRLD FFs due to M/DI conflict
std::string wckmux = str_or_default(dpram->params, id_WCKMUX, "WCK");
std::string clkmux = str_or_default(ff->params, id_CLKMUX, "CLK");
@@ -452,7 +452,7 @@ class Ecp5Packer
// No IO buffer insertion in out-of-context mode, just remove the nextpnr buffer
// and leave the top level port
for (auto &port : ci->ports)
- disconnect_port(ctx, ci, port.first);
+ ci->disconnectPort(port.first);
} else if (trio != nullptr) {
// Trivial case, TRELLIS_IO used. Just remove the IOBUF
log_info("%s feeds TRELLIS_IO %s, removing %s %s.\n", ci->name.c_str(ctx), trio->name.c_str(ctx),
@@ -498,7 +498,7 @@ class Ecp5Packer
trio = new_cells.back().get();
}
for (auto port : ci->ports)
- disconnect_port(ctx, ci, port.first);
+ ci->disconnectPort(port.first);
packed_cells.insert(ci->name);
if (trio != nullptr) {
for (const auto &attr : ci->attrs)
@@ -546,16 +546,16 @@ class Ecp5Packer
log_error("PFUMX '%s' has ALUT driven by cell other than a LUT\n", ci->name.c_str(ctx));
if (ctx->verbose)
log_info(" mux '%s' forms part of a LUT5\n", cell.first.c_str(ctx));
- replace_port(lut0, id_A, packed.get(), id_A0);
- replace_port(lut0, id_B, packed.get(), id_B0);
- replace_port(lut0, id_C, packed.get(), id_C0);
- replace_port(lut0, id_D, packed.get(), id_D0);
- replace_port(lut1, id_A, packed.get(), id_A1);
- replace_port(lut1, id_B, packed.get(), id_B1);
- replace_port(lut1, id_C, packed.get(), id_C1);
- replace_port(lut1, id_D, packed.get(), id_D1);
- replace_port(ci, id_C0, packed.get(), id_M0);
- replace_port(ci, id_Z, packed.get(), id_OFX0);
+ lut0->movePortTo(id_A, packed.get(), id_A0);
+ lut0->movePortTo(id_B, packed.get(), id_B0);
+ lut0->movePortTo(id_C, packed.get(), id_C0);
+ lut0->movePortTo(id_D, packed.get(), id_D0);
+ lut1->movePortTo(id_A, packed.get(), id_A1);
+ lut1->movePortTo(id_B, packed.get(), id_B1);
+ lut1->movePortTo(id_C, packed.get(), id_C1);
+ lut1->movePortTo(id_D, packed.get(), id_D1);
+ ci->movePortTo(id_C0, packed.get(), id_M0);
+ ci->movePortTo(id_Z, packed.get(), id_OFX0);
packed->params[id_LUT0_INITVAL] = get_or_default(lut0->params, id_INIT, Property(0, 16));
packed->params[id_LUT1_INITVAL] = get_or_default(lut1->params, id_INIT, Property(0, 16));
@@ -611,10 +611,10 @@ class Ecp5Packer
}
if (ctx->verbose)
log_info(" mux '%s' forms part of a LUT6\n", cell.first.c_str(ctx));
- replace_port(ci, id_D0, slice1, id_FXA);
- replace_port(ci, id_D1, slice1, id_FXB);
- replace_port(ci, id_SD, slice1, id_M1);
- replace_port(ci, id_Z, slice1, id_OFX1);
+ ci->movePortTo(id_D0, slice1, id_FXA);
+ ci->movePortTo(id_D1, slice1, id_FXB);
+ ci->movePortTo(id_SD, slice1, id_M1);
+ ci->movePortTo(id_Z, slice1, id_OFX1);
slice0->constr_z = 1;
slice0->constr_x = 0;
slice0->constr_y = 0;
@@ -676,10 +676,10 @@ class Ecp5Packer
slice3->name.c_str(ctx), fxa_1->driver.cell->name.c_str(ctx),
fxa_1->driver.port.c_str(ctx));
- replace_port(ci, id_D0, slice2, id_FXA);
- replace_port(ci, id_D1, slice2, id_FXB);
- replace_port(ci, id_SD, slice2, id_M1);
- replace_port(ci, id_Z, slice2, id_OFX1);
+ ci->movePortTo(id_D0, slice2, id_FXA);
+ ci->movePortTo(id_D1, slice2, id_FXB);
+ ci->movePortTo(id_SD, slice2, id_M1);
+ ci->movePortTo(id_Z, slice2, id_OFX1);
for (auto slice : {slice0, slice1, slice2, slice3}) {
slice->constr_children.clear();
@@ -747,12 +747,12 @@ class Ecp5Packer
return user.port == chain_in.port && user.cell == chain_in.cell;
}),
carry->users.end());
- connect_port(ctx, carry, feedin.get(), id_A0);
+ feedin->connectPort(id_A0, carry);
NetInfo *new_carry = ctx->createNet(ctx->id(feedin->name.str(ctx) + "$COUT"));
- connect_port(ctx, new_carry, feedin.get(), id_COUT);
+ feedin->connectPort(id_COUT, new_carry);
chain_in.cell->ports[chain_in.port].net = nullptr;
- connect_port(ctx, new_carry, chain_in.cell, chain_in.port);
+ chain_in.cell->connectPort(chain_in.port, new_carry);
CellInfo *feedin_ptr = feedin.get();
IdString feedin_name = feedin->name;
@@ -772,16 +772,16 @@ class Ecp5Packer
PortRef carry_drv = carry->driver;
carry->driver.cell = nullptr;
- connect_port(ctx, carry, feedout.get(), id_S0);
+ feedout->connectPort(id_S0, carry);
NetInfo *new_cin = ctx->createNet(ctx->id(feedout->name.str(ctx) + "$CIN"));
new_cin->driver = carry_drv;
carry_drv.cell->ports.at(carry_drv.port).net = new_cin;
- connect_port(ctx, new_cin, feedout.get(), id_CIN);
+ feedout->connectPort(id_CIN, new_cin);
if (chain_next) {
// Loop back into LUT4_1 for feedthrough
- connect_port(ctx, carry, feedout.get(), id_A1);
+ feedout->connectPort(id_A1, carry);
carry->users.erase(std::remove_if(carry->users.begin(), carry->users.end(),
[chain_next](const PortRef &user) {
@@ -790,10 +790,10 @@ class Ecp5Packer
carry->users.end());
NetInfo *new_cout = ctx->createNet(ctx->id(feedout->name.str(ctx) + "$COUT"));
- connect_port(ctx, new_cout, feedout.get(), id_COUT);
+ feedout->connectPort(id_COUT, new_cout);
chain_next->cell->ports[chain_next->port].net = nullptr;
- connect_port(ctx, new_cout, chain_next->cell, chain_next->port);
+ chain_next->cell->connectPort(chain_next->port, new_cout);
}
CellInfo *feedout_ptr = feedout.get();
@@ -970,13 +970,13 @@ class Ecp5Packer
dram_to_ram_slice(ctx, ci, ram1_slice.get(), ramw_slice.get(), 1);
// Disconnect ports of original cell after packing
- disconnect_port(ctx, ci, id_WCK);
- disconnect_port(ctx, ci, id_WRE);
+ ci->disconnectPort(id_WCK);
+ ci->disconnectPort(id_WRE);
- disconnect_port(ctx, ci, ctx->id("RAD[0]"));
- disconnect_port(ctx, ci, ctx->id("RAD[1]"));
- disconnect_port(ctx, ci, ctx->id("RAD[2]"));
- disconnect_port(ctx, ci, ctx->id("RAD[3]"));
+ ci->disconnectPort(ctx->id("RAD[0]"));
+ ci->disconnectPort(ctx->id("RAD[1]"));
+ ci->disconnectPort(ctx->id("RAD[2]"));
+ ci->disconnectPort(ctx->id("RAD[3]"));
// Attempt to pack FFs into RAM slices
std::vector<std::tuple<CellInfo *, CellInfo *, int>> ff_packing;
@@ -1159,7 +1159,7 @@ class Ecp5Packer
CellInfo *ci = cell.second.get();
if (is_ff(ctx, ci)) {
bool pack_dense = used_slices > (dense_pack_mode_thresh * available_slices);
- bool requires_m = get_net_or_empty(ci, id_M) != nullptr;
+ bool requires_m = ci->getPort(id_M) != nullptr;
if (pack_dense && !requires_m) {
// If dense packing threshold exceeded; always try and pack the FF into an existing slice
// Find a SLICE with space "near" the flipflop in the netlist
@@ -1421,8 +1421,8 @@ class Ecp5Packer
auto rename_bus = [&](CellInfo *c, const std::string &oldname, const std::string &newname, int width,
int oldoffset, int newoffset) {
for (int i = 0; i < width; i++)
- rename_port(ctx, c, ctx->id(oldname + std::to_string(i + oldoffset)),
- ctx->id(newname + std::to_string(i + newoffset)));
+ c->renamePort(ctx->id(oldname + std::to_string(i + oldoffset)),
+ ctx->id(newname + std::to_string(i + newoffset)));
};
auto rename_param = [&](CellInfo *c, const std::string &oldname, const std::string &newname) {
IdString o = ctx->id(oldname), n = ctx->id(newname);
@@ -1446,11 +1446,11 @@ class Ecp5Packer
rename_bus(ci, "DI", "DIB", 18, 18, 0);
rename_bus(ci, "DO", "DOA", 18, 18, 0);
rename_bus(ci, "DO", "DOB", 18, 0, 0);
- rename_port(ctx, ci, id_CLKW, id_CLKA);
- rename_port(ctx, ci, id_CLKR, id_CLKB);
- rename_port(ctx, ci, id_CEW, id_CEA);
- rename_port(ctx, ci, id_CER, id_CEB);
- rename_port(ctx, ci, id_OCER, id_OCEB);
+ ci->renamePort(id_CLKW, id_CLKA);
+ ci->renamePort(id_CLKR, id_CLKB);
+ ci->renamePort(id_CEW, id_CEA);
+ ci->renamePort(id_CER, id_CEB);
+ ci->renamePort(id_OCER, id_OCEB);
rename_param(ci, "CLKWMUX", "CLKAMUX");
if (str_or_default(ci->params, id_CLKAMUX) == "CLKW")
ci->params[id_CLKAMUX] = std::string("CLKA");
@@ -1468,9 +1468,9 @@ class Ecp5Packer
autocreate_empty_port(ci, id_RSTA);
autocreate_empty_port(ci, id_RSTB);
NetInfo *rst = ci->ports.at(id_RST).net;
- connect_port(ctx, rst, ci, id_RSTA);
- connect_port(ctx, rst, ci, id_RSTB);
- disconnect_port(ctx, ci, id_RST);
+ ci->connectPort(id_RSTA, rst);
+ ci->connectPort(id_RSTB, rst);
+ ci->disconnectPort(id_RST);
ci->ports.erase(id_RST);
}
ci->type = id_DP16KD;
@@ -1721,12 +1721,12 @@ class Ecp5Packer
// Disconnect these ports if connected to constant to prevent routing failure
for (auto ndport : {id_D_TXBIT_CLKP_FROM_ND, id_D_TXBIT_CLKN_FROM_ND, id_D_SYNC_ND,
id_D_TXPLL_LOL_FROM_ND, id_CH0_HDINN, id_CH0_HDINP, id_CH1_HDINN, id_CH1_HDINP}) {
- const NetInfo *net = get_net_or_empty(ci, ndport);
+ const NetInfo *net = ci->getPort(ndport);
if (net == nullptr || net->driver.cell == nullptr)
continue;
IdString ct = net->driver.cell->type;
if (ct == id_GND || ct == id_VCC) {
- disconnect_port(ctx, ci, ndport);
+ ci->disconnectPort(ndport);
ci->ports.erase(ndport);
}
}
@@ -1814,9 +1814,9 @@ class Ecp5Packer
for (auto &cell : ctx->cells) {
CellInfo *ci = cell.second.get();
if (ci->type == id_USRMCLK) {
- rename_port(ctx, ci, id_USRMCLKI, id_PADDO);
- rename_port(ctx, ci, id_USRMCLKTS, id_PADDT);
- rename_port(ctx, ci, id_USRMCLKO, id_PADDI);
+ ci->renamePort(id_USRMCLKI, id_PADDO);
+ ci->renamePort(id_USRMCLKTS, id_PADDT);
+ ci->renamePort(id_USRMCLKO, id_PADDI);
} else if (ci->type == id_GSR || ci->type == id_SGSR) {
ci->params[id_MODE] = std::string("ACTIVE_LOW");
ci->params[id_SYNCMODE] = ci->type == id_SGSR ? std::string("SYNC") : std::string("ASYNC");
@@ -1959,8 +1959,8 @@ class Ecp5Packer
eclkbuf->attrs[id_BEL] = ctx->getBelName(target_bel).str(ctx);
- connect_port(ctx, ecknet, eclkbuf.get(), id_ECLKI);
- connect_port(ctx, eclk.buf, eclkbuf.get(), id_ECLKO);
+ eclkbuf->connectPort(id_ECLKI, ecknet);
+ eclkbuf->connectPort(id_ECLKO, eclk.buf);
found_eclk = free_eclk;
eclk.buffer = eclkbuf.get();
new_cells.push_back(std::move(eclkbuf));
@@ -1968,9 +1968,9 @@ class Ecp5Packer
}
auto &eclk = eclks[std::make_pair(bank, found_eclk)];
- disconnect_port(ctx, usr_cell, usr_port.name);
+ usr_cell->disconnectPort(usr_port.name);
usr_port.net = nullptr;
- connect_port(ctx, eclk.buf, usr_cell, usr_port.name);
+ usr_cell->connectPort(usr_port.name, eclk.buf);
// Simple ECLK router
WireId userWire = ctx->getBelPinWire(usr_bel, usr_port.name);
@@ -2024,8 +2024,8 @@ class Ecp5Packer
auto zero_cell = std::make_unique<CellInfo>(ctx, name, id_GND);
NetInfo *zero_net = ctx->createNet(name);
zero_cell->addOutput(id_GND);
- connect_port(ctx, zero_net, zero_cell.get(), id_GND);
- connect_port(ctx, zero_net, ci, port);
+ zero_cell->connectPort(id_GND, zero_net);
+ ci->connectPort(port, zero_net);
new_cells.push_back(std::move(zero_cell));
}
@@ -2136,11 +2136,11 @@ class Ecp5Packer
log_error("IOLOGIC '%s' has conflicting clocks '%s' and '%s'\n", iol->name.c_str(ctx),
iol->ports[id_CLK].net->name.c_str(ctx), sclk->name.c_str(ctx));
} else {
- connect_port(ctx, sclk, iol, id_CLK);
+ iol->connectPort(id_CLK, sclk);
}
}
if (prim->ports.count(port) && disconnect)
- disconnect_port(ctx, prim, port);
+ prim->disconnectPort(port);
};
auto set_iologic_eclk = [&](CellInfo *iol, CellInfo *prim, IdString port) {
@@ -2155,10 +2155,10 @@ class Ecp5Packer
log_error("IOLOGIC '%s' has conflicting ECLKs '%s' and '%s'\n", iol->name.c_str(ctx),
iol->ports[id_ECLK].net->name.c_str(ctx), eclk->name.c_str(ctx));
} else {
- connect_port(ctx, eclk, iol, id_ECLK);
+ iol->connectPort(id_ECLK, eclk);
}
if (prim->ports.count(port))
- disconnect_port(ctx, prim, port);
+ prim->disconnectPort(port);
};
auto set_iologic_lsr = [&](CellInfo *iol, CellInfo *prim, IdString port, bool input, bool disconnect = true) {
@@ -2174,11 +2174,11 @@ class Ecp5Packer
log_error("IOLOGIC '%s' has conflicting LSR signals '%s' and '%s'\n", iol->name.c_str(ctx),
iol->ports[id_LSR].net->name.c_str(ctx), lsr->name.c_str(ctx));
} else if (iol->ports[id_LSR].net == nullptr) {
- connect_port(ctx, lsr, iol, id_LSR);
+ iol->connectPort(id_LSR, lsr);
}
}
if (prim->ports.count(port) && disconnect)
- disconnect_port(ctx, prim, port);
+ prim->disconnectPort(port);
};
bool warned_oddrx_iddrx = false;
@@ -2245,7 +2245,7 @@ class Ecp5Packer
log_error("IOLOGIC '%s' has conflicting %s signals '%s' and '%s'\n", iol->name.c_str(ctx),
port.c_str(ctx), iol->ports[port].net->name.c_str(ctx), sig->name.c_str(ctx));
}
- disconnect_port(ctx, prim, port);
+ prim->disconnectPort(port);
} else {
bool dqsr;
int dqsgroup;
@@ -2263,7 +2263,7 @@ class Ecp5Packer
"%cDQ%d\n",
port.c_str(ctx), prim->name.c_str(ctx), dqsr ? 'R' : 'L', dqsgroup,
sig->driver.cell->name.c_str(ctx), driver_group.first ? 'R' : 'L', driver_group.second);
- replace_port(prim, port, iol, port);
+ prim->movePortTo(port, iol, port);
}
};
@@ -2284,18 +2284,18 @@ class Ecp5Packer
if (drives_iologic) {
// Reconnect to PIO which the packer expects later on
NetInfo *input_net = ci->ports.at(id_A).net, *dly_net = ci->ports.at(id_Z).net;
- disconnect_port(ctx, i_pio, id_O);
+ i_pio->disconnectPort(id_O);
i_pio->ports.at(id_O).net = nullptr;
- disconnect_port(ctx, ci, id_A);
+ ci->disconnectPort(id_A);
ci->ports.at(id_A).net = nullptr;
- disconnect_port(ctx, ci, id_Z);
+ ci->disconnectPort(id_Z);
ci->ports.at(id_Z).net = nullptr;
- connect_port(ctx, dly_net, i_pio, id_O);
- connect_port(ctx, input_net, iol, id_INDD);
- connect_port(ctx, input_net, iol, id_DI);
+ i_pio->connectPort(id_O, dly_net);
+ iol->connectPort(id_INDD, input_net);
+ iol->connectPort(id_DI, input_net);
} else {
- replace_port(ci, id_A, iol, id_PADDI);
- replace_port(ci, id_Z, iol, id_INDD);
+ ci->movePortTo(id_A, iol, id_PADDI);
+ ci->movePortTo(id_Z, iol, id_INDD);
}
packed_cells.insert(cell.first);
} else if (o_pio != nullptr) {
@@ -2307,22 +2307,22 @@ class Ecp5Packer
input_net->driver.port == id_Q)
driven_by_iol = true;
if (driven_by_iol) {
- disconnect_port(ctx, o_pio, id_I);
+ o_pio->disconnectPort(id_I);
o_pio->ports.at(id_I).net = nullptr;
- disconnect_port(ctx, ci, id_A);
+ ci->disconnectPort(id_A);
ci->ports.at(id_A).net = nullptr;
- disconnect_port(ctx, ci, id_Z);
+ ci->disconnectPort(id_Z);
ci->ports.at(id_Z).net = nullptr;
- connect_port(ctx, input_net, o_pio, id_I);
+ o_pio->connectPort(id_I, input_net);
ctx->nets.erase(dly_net->name);
} else {
- replace_port(ci, id_A, iol, id_TXDATA0);
- replace_port(ci, id_Z, iol, id_IOLDO);
+ ci->movePortTo(id_A, iol, id_TXDATA0);
+ ci->movePortTo(id_Z, iol, id_IOLDO);
if (!o_pio->ports.count(id_IOLDO)) {
o_pio->ports[id_IOLDO].name = id_IOLDO;
o_pio->ports[id_IOLDO].type = PORT_IN;
}
- replace_port(o_pio, id_I, o_pio, id_IOLDO);
+ o_pio->movePortTo(id_I, o_pio, id_IOLDO);
}
packed_cells.insert(cell.first);
} else {
@@ -2336,19 +2336,19 @@ class Ecp5Packer
std::string(ci->params.at(id_DEL_VALUE).as_string()).substr(0, 5) != "DELAY"))
iol->params[ctx->id("DELAY.DEL_VALUE")] = ci->params.at(id_DEL_VALUE);
if (ci->ports.count(id_LOADN))
- replace_port(ci, id_LOADN, iol, id_LOADN);
+ ci->movePortTo(id_LOADN, iol, id_LOADN);
else
tie_zero(iol, id_LOADN);
if (ci->ports.count(id_MOVE))
- replace_port(ci, id_MOVE, iol, id_MOVE);
+ ci->movePortTo(id_MOVE, iol, id_MOVE);
else
tie_zero(iol, id_MOVE);
if (ci->ports.count(id_DIRECTION))
- replace_port(ci, id_DIRECTION, iol, id_DIRECTION);
+ ci->movePortTo(id_DIRECTION, iol, id_DIRECTION);
else
tie_zero(iol, id_DIRECTION);
if (ci->ports.count(id_CFLAG))
- replace_port(ci, id_CFLAG, iol, id_CFLAG);
+ ci->movePortTo(id_CFLAG, iol, id_CFLAG);
}
}
@@ -2365,11 +2365,11 @@ class Ecp5Packer
else
iol = create_pio_iologic(pio, ci);
set_iologic_mode(iol, "IDDRX1_ODDRX1");
- replace_port(ci, id_D, iol, id_PADDI);
+ ci->movePortTo(id_D, iol, id_PADDI);
set_iologic_sclk(iol, ci, id_SCLK, true);
set_iologic_lsr(iol, ci, id_RST, true);
- replace_port(ci, id_Q0, iol, id_RXDATA0);
- replace_port(ci, id_Q1, iol, id_RXDATA1);
+ ci->movePortTo(id_Q0, iol, id_RXDATA0);
+ ci->movePortTo(id_Q1, iol, id_RXDATA1);
iol->params[id_GSR] = str_or_default(ci->params, id_GSR, "DISABLED");
packed_cells.insert(cell.first);
} else if (ci->type == id_ODDRX1F) {
@@ -2383,17 +2383,17 @@ class Ecp5Packer
else
iol = create_pio_iologic(pio, ci);
set_iologic_mode(iol, "IDDRX1_ODDRX1");
- replace_port(ci, id_Q, iol, id_IOLDO);
+ ci->movePortTo(id_Q, iol, id_IOLDO);
if (!pio->ports.count(id_IOLDO)) {
pio->ports[id_IOLDO].name = id_IOLDO;
pio->ports[id_IOLDO].type = PORT_IN;
}
- replace_port(pio, id_I, pio, id_IOLDO);
+ pio->movePortTo(id_I, pio, id_IOLDO);
pio->params[id_DATAMUX_ODDR] = std::string("IOLDO");
set_iologic_sclk(iol, ci, id_SCLK, false);
set_iologic_lsr(iol, ci, id_RST, false);
- replace_port(ci, id_D0, iol, id_TXDATA0);
- replace_port(ci, id_D1, iol, id_TXDATA1);
+ ci->movePortTo(id_D0, iol, id_TXDATA0);
+ ci->movePortTo(id_D1, iol, id_TXDATA1);
iol->params[id_GSR] = str_or_default(ci->params, id_GSR, "DISABLED");
packed_cells.insert(cell.first);
} else if (ci->type == id_ODDRX2F || ci->type == id_ODDR71B) {
@@ -2407,28 +2407,28 @@ class Ecp5Packer
else
iol = create_pio_iologic(pio, ci);
set_iologic_mode(iol, "ODDRXN");
- replace_port(ci, id_Q, iol, id_IOLDO);
+ ci->movePortTo(id_Q, iol, id_IOLDO);
if (!pio->ports.count(id_IOLDO)) {
pio->ports[id_IOLDO].name = id_IOLDO;
pio->ports[id_IOLDO].type = PORT_IN;
}
- replace_port(pio, id_I, pio, id_IOLDO);
+ pio->movePortTo(id_I, pio, id_IOLDO);
set_iologic_sclk(iol, ci, id_SCLK, false, false);
set_iologic_sclk(iol, ci, id_SCLK, true);
set_iologic_eclk(iol, ci, id_ECLK);
set_iologic_lsr(iol, ci, id_RST, false, false);
set_iologic_lsr(iol, ci, id_RST, true);
- replace_port(ci, id_D0, iol, id_TXDATA0);
- replace_port(ci, id_D1, iol, id_TXDATA1);
- replace_port(ci, id_D2, iol, id_TXDATA2);
- replace_port(ci, id_D3, iol, id_TXDATA3);
+ ci->movePortTo(id_D0, iol, id_TXDATA0);
+ ci->movePortTo(id_D1, iol, id_TXDATA1);
+ ci->movePortTo(id_D2, iol, id_TXDATA2);
+ ci->movePortTo(id_D3, iol, id_TXDATA3);
if (ci->type == id_ODDR71B) {
Loc loc = ctx->getBelLocation(ctx->getBelByNameStr(pio->attrs.at(id_BEL).as_string()));
if (loc.z % 2 == 1)
log_error("ODDR71B '%s' can only be used at 'A' or 'C' locations\n", ci->name.c_str(ctx));
- replace_port(ci, id_D4, iol, id_TXDATA4);
- replace_port(ci, id_D5, iol, id_TXDATA5);
- replace_port(ci, id_D6, iol, id_TXDATA6);
+ ci->movePortTo(id_D4, iol, id_TXDATA4);
+ ci->movePortTo(id_D5, iol, id_TXDATA5);
+ ci->movePortTo(id_D6, iol, id_TXDATA6);
iol->params[ctx->id("ODDRXN.MODE")] = std::string("ODDR71");
} else {
iol->params[ctx->id("ODDRXN.MODE")] = std::string("ODDRX2");
@@ -2447,22 +2447,22 @@ class Ecp5Packer
else
iol = create_pio_iologic(pio, ci);
set_iologic_mode(iol, "IDDRXN");
- replace_port(ci, id_D, iol, id_PADDI);
+ ci->movePortTo(id_D, iol, id_PADDI);
set_iologic_sclk(iol, ci, id_SCLK, true);
set_iologic_eclk(iol, ci, id_ECLK);
set_iologic_lsr(iol, ci, id_RST, true);
- replace_port(ci, id_Q0, iol, id_RXDATA0);
- replace_port(ci, id_Q1, iol, id_RXDATA1);
- replace_port(ci, id_Q2, iol, id_RXDATA2);
- replace_port(ci, id_Q3, iol, id_RXDATA3);
+ ci->movePortTo(id_Q0, iol, id_RXDATA0);
+ ci->movePortTo(id_Q1, iol, id_RXDATA1);
+ ci->movePortTo(id_Q2, iol, id_RXDATA2);
+ ci->movePortTo(id_Q3, iol, id_RXDATA3);
if (ci->type == id_IDDR71B) {
Loc loc = ctx->getBelLocation(ctx->getBelByNameStr(pio->attrs.at(id_BEL).as_string()));
if (loc.z % 2 == 1)
log_error("IDDR71B '%s' can only be used at 'A' or 'C' locations\n", ci->name.c_str(ctx));
- replace_port(ci, id_Q4, iol, id_RXDATA4);
- replace_port(ci, id_Q5, iol, id_RXDATA5);
- replace_port(ci, id_Q6, iol, id_RXDATA6);
- replace_port(ci, id_ALIGNWD, iol, id_SLIP);
+ ci->movePortTo(id_Q4, iol, id_RXDATA4);
+ ci->movePortTo(id_Q5, iol, id_RXDATA5);
+ ci->movePortTo(id_Q6, iol, id_RXDATA6);
+ ci->movePortTo(id_ALIGNWD, iol, id_SLIP);
iol->params[ctx->id("IDDRXN.MODE")] = std::string("IDDR71");
} else {
iol->params[ctx->id("IDDRXN.MODE")] = std::string("IDDRX2");
@@ -2480,18 +2480,18 @@ class Ecp5Packer
else
iol = create_pio_iologic(pio, ci);
set_iologic_mode(iol, "MIDDRX_MODDRX");
- replace_port(ci, id_Q, iol, id_IOLDO);
+ ci->movePortTo(id_Q, iol, id_IOLDO);
if (!pio->ports.count(id_IOLDO)) {
pio->ports[id_IOLDO].name = id_IOLDO;
pio->ports[id_IOLDO].type = PORT_IN;
}
- replace_port(pio, id_I, pio, id_IOLDO);
+ pio->movePortTo(id_I, pio, id_IOLDO);
set_iologic_sclk(iol, ci, id_SCLK, false);
set_iologic_eclk(iol, ci, id_ECLK);
set_iologic_lsr(iol, ci, id_RST, false, false);
set_iologic_lsr(iol, ci, id_RST, true);
- replace_port(ci, id_D0, iol, id_TXDATA0);
- replace_port(ci, id_D1, iol, id_TXDATA2);
+ ci->movePortTo(id_D0, iol, id_TXDATA0);
+ ci->movePortTo(id_D1, iol, id_TXDATA2);
iol->params[id_GSR] = str_or_default(ci->params, id_GSR, "DISABLED");
iol->params[ctx->id("MODDRX.MODE")] = std::string("MOSHX2");
pio->params[id_DATAMUX_MDDR] = std::string("IOLDO");
@@ -2507,20 +2507,20 @@ class Ecp5Packer
else
iol = create_pio_iologic(pio, ci);
set_iologic_mode(iol, "MIDDRX_MODDRX");
- replace_port(ci, id_Q, iol, id_IOLDO);
+ ci->movePortTo(id_Q, iol, id_IOLDO);
if (!pio->ports.count(id_IOLDO)) {
pio->ports[id_IOLDO].name = id_IOLDO;
pio->ports[id_IOLDO].type = PORT_IN;
}
- replace_port(pio, id_I, pio, id_IOLDO);
+ pio->movePortTo(id_I, pio, id_IOLDO);
set_iologic_sclk(iol, ci, id_SCLK, false);
set_iologic_eclk(iol, ci, id_ECLK);
set_iologic_lsr(iol, ci, id_RST, false, false);
set_iologic_lsr(iol, ci, id_RST, true);
- replace_port(ci, id_D0, iol, id_TXDATA0);
- replace_port(ci, id_D1, iol, id_TXDATA1);
- replace_port(ci, id_D2, iol, id_TXDATA2);
- replace_port(ci, id_D3, iol, id_TXDATA3);
+ ci->movePortTo(id_D0, iol, id_TXDATA0);
+ ci->movePortTo(id_D1, iol, id_TXDATA1);
+ ci->movePortTo(id_D2, iol, id_TXDATA2);
+ ci->movePortTo(id_D3, iol, id_TXDATA3);
iol->params[id_GSR] = str_or_default(ci->params, id_GSR, "DISABLED");
iol->params[ctx->id("MODDRX.MODE")] = std::string("MODDRX2");
iol->params[ctx->id("MIDDRX_MODDRX.WRCLKMUX")] =
@@ -2539,15 +2539,15 @@ class Ecp5Packer
else
iol = create_pio_iologic(pio, ci);
set_iologic_mode(iol, "MIDDRX_MODDRX");
- replace_port(ci, id_D, iol, id_PADDI);
+ ci->movePortTo(id_D, iol, id_PADDI);
set_iologic_sclk(iol, ci, id_SCLK, true);
set_iologic_eclk(iol, ci, id_ECLK);
set_iologic_lsr(iol, ci, id_RST, true);
- replace_port(ci, id_Q0, iol, id_RXDATA0);
- replace_port(ci, id_Q1, iol, id_RXDATA1);
- replace_port(ci, id_Q2, iol, id_RXDATA2);
- replace_port(ci, id_Q3, iol, id_RXDATA3);
- replace_port(ci, id_QWL, iol, id_INFF);
+ ci->movePortTo(id_Q0, iol, id_RXDATA0);
+ ci->movePortTo(id_Q1, iol, id_RXDATA1);
+ ci->movePortTo(id_Q2, iol, id_RXDATA2);
+ ci->movePortTo(id_Q3, iol, id_RXDATA3);
+ ci->movePortTo(id_QWL, iol, id_INFF);
iol->params[id_GSR] = str_or_default(ci->params, id_GSR, "DISABLED");
iol->params[ctx->id("MIDDRX.MODE")] = std::string("MIDDRX2");
process_dqs_port(ci, pio, iol, id_DQSR90);
@@ -2569,17 +2569,17 @@ class Ecp5Packer
else
iol = create_pio_iologic(pio, ci);
set_iologic_mode(iol, "MIDDRX_MODDRX");
- replace_port(ci, id_Q, iol, id_IOLTO);
+ ci->movePortTo(id_Q, iol, id_IOLTO);
if (!pio->ports.count(id_IOLTO)) {
pio->ports[id_IOLTO].name = id_IOLTO;
pio->ports[id_IOLTO].type = PORT_IN;
}
- replace_port(pio, id_T, pio, id_IOLTO);
+ pio->movePortTo(id_T, pio, id_IOLTO);
set_iologic_sclk(iol, ci, id_SCLK, false);
set_iologic_eclk(iol, ci, id_ECLK);
set_iologic_lsr(iol, ci, id_RST, false);
- replace_port(ci, id_T0, iol, id_TSDATA0);
- replace_port(ci, id_T1, iol, id_TSDATA1);
+ ci->movePortTo(id_T0, iol, id_TSDATA0);
+ ci->movePortTo(id_T1, iol, id_TSDATA1);
process_dqs_port(ci, pio, iol, ci->type == id_TSHX2DQSA ? id_DQSW : id_DQSW270);
iol->params[id_GSR] = str_or_default(ci->params, id_GSR, "DISABLED");
iol->params[ctx->id("MTDDRX.MODE")] = std::string("MTSHX2");
@@ -2595,7 +2595,7 @@ class Ecp5Packer
std::string mode = str_or_default(ci->attrs, id_ioff_dir, "");
if (mode != "output") {
// See if it can be packed as an input ff
- NetInfo *d = get_net_or_empty(ci, id_DI);
+ NetInfo *d = ci->getPort(id_DI);
CellInfo *pio = net_driven_by(ctx, d, is_trellis_io, id_O);
if (pio != nullptr && d->users.size() == 1) {
// Input FF
@@ -2613,10 +2613,10 @@ class Ecp5Packer
if (str_or_default(ci->params, id_CEMUX, "CE") == "CE") {
iol->params[id_CEIMUX] = std::string("CEMUX");
iol->params[id_CEMUX] = std::string("CE");
- if (get_net_or_empty(ci, id_CE) == nullptr)
- replace_port(ci, id_CE, iol, id_CE);
+ if (ci->getPort(id_CE) == nullptr)
+ ci->movePortTo(id_CE, iol, id_CE);
else
- disconnect_port(ctx, ci, id_CE);
+ ci->disconnectPort(id_CE);
} else {
iol->params[id_CEIMUX] = std::string("1");
}
@@ -2625,8 +2625,8 @@ class Ecp5Packer
iol->params[ctx->id("FF.REGSET")] = str_or_default(ci->params, id_REGSET, "RESET");
iol->params[id_SRMODE] = str_or_default(ci->params, id_SRMODE, "ASYNC");
iol->params[id_GSR] = str_or_default(ci->params, id_GSR, "DISABLED");
- replace_port(ci, id_DI, iol, id_PADDI);
- replace_port(ci, id_Q, iol, id_INFF);
+ ci->movePortTo(id_DI, iol, id_PADDI);
+ ci->movePortTo(id_Q, iol, id_INFF);
packed_cells.insert(cell.first);
continue;
}
@@ -2645,21 +2645,21 @@ class Ecp5Packer
iol = create_pio_iologic(pio, ci);
set_iologic_mode(iol, "IREG_OREG");
// Connection between FF and PIO
- replace_port(ci, id_Q, iol, tri ? id_IOLTO : id_IOLDO);
+ ci->movePortTo(id_Q, iol, tri ? id_IOLTO : id_IOLDO);
if (tri) {
if (!pio->ports.count(id_IOLTO)) {
pio->ports[id_IOLTO].name = id_IOLTO;
pio->ports[id_IOLTO].type = PORT_IN;
}
pio->params[id_TRIMUX_TSREG] = std::string("IOLTO");
- replace_port(pio, id_T, pio, id_IOLTO);
+ pio->movePortTo(id_T, pio, id_IOLTO);
} else {
if (!pio->ports.count(id_IOLDO)) {
pio->ports[id_IOLDO].name = id_IOLDO;
pio->ports[id_IOLDO].type = PORT_IN;
}
pio->params[id_DATAMUX_OREG] = std::string("IOLDO");
- replace_port(pio, id_I, pio, id_IOLDO);
+ pio->movePortTo(id_I, pio, id_IOLDO);
}
set_iologic_sclk(iol, ci, id_CLK, false);
@@ -2671,10 +2671,10 @@ class Ecp5Packer
if (str_or_default(ci->params, id_CEMUX, "CE") == "CE") {
iol->params[id_CEOMUX] = std::string("CEMUX");
iol->params[id_CEMUX] = std::string("CE");
- if (get_net_or_empty(ci, id_CE) == nullptr)
- replace_port(ci, id_CE, iol, id_CE);
+ if (ci->getPort(id_CE) == nullptr)
+ ci->movePortTo(id_CE, iol, id_CE);
else
- disconnect_port(ctx, ci, id_CE);
+ ci->disconnectPort(id_CE);
} else {
iol->params[id_CEOMUX] = std::string("1");
}
@@ -2684,7 +2684,7 @@ class Ecp5Packer
str_or_default(ci->params, id_REGSET, "RESET");
iol->params[id_SRMODE] = str_or_default(ci->params, id_SRMODE, "ASYNC");
// Data input
- replace_port(ci, id_DI, iol, tri ? id_TSDATA0 : id_TXDATA0);
+ ci->movePortTo(id_DI, iol, tri ? id_TSDATA0 : id_TXDATA0);
iol->params[id_GSR] = str_or_default(ci->params, id_GSR, "DISABLED");
packed_cells.insert(cell.first);
continue;
@@ -2699,8 +2699,7 @@ class Ecp5Packer
CellInfo *ci = cell.second.get();
if (ci->type == id_ECLKBRIDGECS) {
Loc loc;
- NetInfo *i0 = get_net_or_empty(ci, id_CLK0), *i1 = get_net_or_empty(ci, id_CLK1),
- *o = get_net_or_empty(ci, id_ECSOUT);
+ NetInfo *i0 = ci->getPort(id_CLK0), *i1 = ci->getPort(id_CLK1), *o = ci->getPort(id_ECSOUT);
for (NetInfo *input : {i0, i1}) {
if (input == nullptr)
continue;
@@ -2753,7 +2752,7 @@ class Ecp5Packer
for (auto user2 : o->users) {
// Set side hint to ensure edge clock choice is routeable
if (user2.cell->type == id_ECLKSYNCB && user2.port == id_ECLKI) {
- NetInfo *synco = get_net_or_empty(user2.cell, id_ECLKO);
+ NetInfo *synco = user2.cell->getPort(id_ECLKO);
if (synco != nullptr)
bridge_side_hint[synco] = (loc.x > 1) ? 0 : 1;
}