aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/basectx.cc15
-rw-r--r--common/basectx.h1
-rw-r--r--common/design_utils.cc143
-rw-r--r--common/design_utils.h26
-rw-r--r--common/nextpnr_types.cc133
-rw-r--r--common/nextpnr_types.h21
-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
-rw-r--r--fpga_interchange/arch_pack_clusters.cc2
-rw-r--r--fpga_interchange/macros.cc6
-rw-r--r--fpga_interchange/site_router.cc2
-rw-r--r--frontend/frontend_base.h18
-rw-r--r--generic/arch.cc2
-rw-r--r--generic/cells.cc22
-rw-r--r--generic/pack.cc2
-rw-r--r--generic/viaduct/example/example.cc6
-rw-r--r--generic/viaduct_helpers.cc8
-rw-r--r--gowin/arch.cc6
-rw-r--r--gowin/cells.cc38
-rw-r--r--gowin/pack.cc66
-rw-r--r--ice40/arch.cc14
-rw-r--r--ice40/cells.cc47
-rw-r--r--ice40/pack.cc36
-rw-r--r--machxo2/cells.cc18
-rw-r--r--machxo2/pack.cc2
-rw-r--r--mistral/bitstream.cc9
-rw-r--r--mistral/lab.cc46
-rw-r--r--mistral/pack.cc42
-rw-r--r--nexus/fasm.cc8
-rw-r--r--nexus/pack.cc310
-rw-r--r--nexus/post_place.cc8
34 files changed, 765 insertions, 768 deletions
diff --git a/common/basectx.cc b/common/basectx.cc
index b55cd072..83a2deea 100644
--- a/common/basectx.cc
+++ b/common/basectx.cc
@@ -22,7 +22,6 @@
#include <boost/algorithm/string.hpp>
#include "context.h"
-#include "design_utils.h"
#include "log.h"
NEXTPNR_NAMESPACE_BEGIN
@@ -223,13 +222,23 @@ void BaseCtx::connectPort(IdString net, IdString cell, IdString port)
{
NetInfo *net_info = getNetByAlias(net);
CellInfo *cell_info = cells.at(cell).get();
- connect_port(getCtx(), net_info, cell_info, port);
+ cell_info->connectPort(port, net_info);
}
void BaseCtx::disconnectPort(IdString cell, IdString port)
{
CellInfo *cell_info = cells.at(cell).get();
- disconnect_port(getCtx(), cell_info, port);
+ cell_info->disconnectPort(port);
+}
+
+void BaseCtx::renameNet(IdString old_name, IdString new_name)
+{
+ NetInfo *net = nets.at(old_name).get();
+ NPNR_ASSERT(!nets.count(new_name));
+ nets[new_name];
+ std::swap(nets.at(net->name), nets.at(new_name));
+ nets.erase(net->name);
+ net->name = new_name;
}
void BaseCtx::ripupNet(IdString name)
diff --git a/common/basectx.h b/common/basectx.h
index 507f29cd..21d6d63a 100644
--- a/common/basectx.h
+++ b/common/basectx.h
@@ -226,6 +226,7 @@ struct BaseCtx
void disconnectPort(IdString cell, IdString port);
void ripupNet(IdString name);
void lockNetRouting(IdString name);
+ void renameNet(IdString old_name, IdString new_name);
CellInfo *createCell(IdString name, IdString type);
void copyBelPorts(IdString cell, BelId bel);
diff --git a/common/design_utils.cc b/common/design_utils.cc
index 9432b6cd..f52cc304 100644
--- a/common/design_utils.cc
+++ b/common/design_utils.cc
@@ -25,42 +25,6 @@
#include "util.h"
NEXTPNR_NAMESPACE_BEGIN
-void replace_port(CellInfo *old_cell, IdString old_name, CellInfo *rep_cell, IdString rep_name)
-{
- if (!old_cell->ports.count(old_name))
- return;
- PortInfo &old = old_cell->ports.at(old_name);
-
- // Create port on the replacement cell if it doesn't already exist
- if (!rep_cell->ports.count(rep_name)) {
- rep_cell->ports[rep_name].name = rep_name;
- rep_cell->ports[rep_name].type = old.type;
- }
-
- PortInfo &rep = rep_cell->ports.at(rep_name);
- NPNR_ASSERT(old.type == rep.type);
-
- rep.net = old.net;
- old.net = nullptr;
- if (rep.type == PORT_OUT) {
- if (rep.net != nullptr) {
- rep.net->driver.cell = rep_cell;
- rep.net->driver.port = rep_name;
- }
- } else if (rep.type == PORT_IN) {
- if (rep.net != nullptr) {
- for (PortRef &load : rep.net->users) {
- if (load.cell == old_cell && load.port == old_name) {
- load.cell = rep_cell;
- load.port = rep_name;
- }
- }
- }
- } else {
- NPNR_ASSERT(false);
- }
-}
-
// Print utilisation of a design
void print_utilisation(const Context *ctx)
{
@@ -85,111 +49,4 @@ void print_utilisation(const Context *ctx)
log_break();
}
-// Connect a net to a port
-void connect_port(const Context *ctx, NetInfo *net, CellInfo *cell, IdString port_name)
-{
- if (net == nullptr)
- return;
- PortInfo &port = cell->ports.at(port_name);
- NPNR_ASSERT(port.net == nullptr);
- port.net = net;
- if (port.type == PORT_OUT) {
- NPNR_ASSERT(net->driver.cell == nullptr);
- net->driver.cell = cell;
- net->driver.port = port_name;
- } else if (port.type == PORT_IN || port.type == PORT_INOUT) {
- PortRef user;
- user.cell = cell;
- user.port = port_name;
- net->users.push_back(user);
- } else {
- NPNR_ASSERT_FALSE("invalid port type for connect_port");
- }
-}
-
-void disconnect_port(const Context *ctx, CellInfo *cell, IdString port_name)
-{
- if (!cell->ports.count(port_name))
- return;
- PortInfo &port = cell->ports.at(port_name);
- if (port.net != nullptr) {
- port.net->users.erase(std::remove_if(port.net->users.begin(), port.net->users.end(),
- [cell, port_name](const PortRef &user) {
- return user.cell == cell && user.port == port_name;
- }),
- port.net->users.end());
- if (port.net->driver.cell == cell && port.net->driver.port == port_name)
- port.net->driver.cell = nullptr;
- port.net = nullptr;
- }
-}
-
-void connect_ports(Context *ctx, CellInfo *cell1, IdString port1_name, CellInfo *cell2, IdString port2_name)
-{
- PortInfo &port1 = cell1->ports.at(port1_name);
- if (port1.net == nullptr) {
- // No net on port1; need to create one
- NetInfo *p1net = ctx->createNet(ctx->id(cell1->name.str(ctx) + "$conn$" + port1_name.str(ctx)));
- connect_port(ctx, p1net, cell1, port1_name);
- }
- connect_port(ctx, port1.net, cell2, port2_name);
-}
-
-void rename_port(Context *ctx, CellInfo *cell, IdString old_name, IdString new_name)
-{
- if (!cell->ports.count(old_name))
- return;
- PortInfo pi = cell->ports.at(old_name);
- if (pi.net != nullptr) {
- if (pi.net->driver.cell == cell && pi.net->driver.port == old_name)
- pi.net->driver.port = new_name;
- for (auto &usr : pi.net->users)
- if (usr.cell == cell && usr.port == old_name)
- usr.port = new_name;
- }
- cell->ports.erase(old_name);
- pi.name = new_name;
- cell->ports[new_name] = pi;
-}
-
-void rename_net(Context *ctx, NetInfo *net, IdString new_name)
-{
- if (net == nullptr)
- return;
- NPNR_ASSERT(!ctx->nets.count(new_name));
- ctx->nets[new_name];
- std::swap(ctx->nets.at(net->name), ctx->nets.at(new_name));
- ctx->nets.erase(net->name);
- net->name = new_name;
-}
-
-void replace_bus(Context *ctx, CellInfo *old_cell, IdString old_name, int old_offset, bool old_brackets,
- CellInfo *new_cell, IdString new_name, int new_offset, bool new_brackets, int width)
-{
- for (int i = 0; i < width; i++) {
- IdString old_port = ctx->id(stringf(old_brackets ? "%s[%d]" : "%s%d", old_name.c_str(ctx), i + old_offset));
- IdString new_port = ctx->id(stringf(new_brackets ? "%s[%d]" : "%s%d", new_name.c_str(ctx), i + new_offset));
- replace_port(old_cell, old_port, new_cell, new_port);
- }
-}
-
-void copy_port(Context *ctx, CellInfo *old_cell, IdString old_name, CellInfo *new_cell, IdString new_name)
-{
- if (!old_cell->ports.count(old_name))
- return;
- new_cell->ports[new_name].name = new_name;
- new_cell->ports[new_name].type = old_cell->ports.at(old_name).type;
- connect_port(ctx, old_cell->ports.at(old_name).net, new_cell, new_name);
-}
-
-void copy_bus(Context *ctx, CellInfo *old_cell, IdString old_name, int old_offset, bool old_brackets,
- CellInfo *new_cell, IdString new_name, int new_offset, bool new_brackets, int width)
-{
- for (int i = 0; i < width; i++) {
- IdString old_port = ctx->id(stringf(old_brackets ? "%s[%d]" : "%s%d", old_name.c_str(ctx), i + old_offset));
- IdString new_port = ctx->id(stringf(new_brackets ? "%s[%d]" : "%s%d", new_name.c_str(ctx), i + new_offset));
- copy_port(ctx, old_cell, old_port, new_cell, new_port);
- }
-}
-
NEXTPNR_NAMESPACE_END
diff --git a/common/design_utils.h b/common/design_utils.h
index 82c9ac45..63cb71d7 100644
--- a/common/design_utils.h
+++ b/common/design_utils.h
@@ -89,34 +89,8 @@ inline bool port_used(CellInfo *cell, IdString port_name)
return port_fnd != cell->ports.end() && port_fnd->second.net != nullptr;
}
-// Connect a net to a port
-void connect_port(const Context *ctx, NetInfo *net, CellInfo *cell, IdString port_name);
-
-// Disconnect a net from a port
-void disconnect_port(const Context *ctx, CellInfo *cell, IdString port_name);
-
-// Connect two ports together
-void connect_ports(Context *ctx, CellInfo *cell1, IdString port1_name, CellInfo *cell2, IdString port2_name);
-
-// Rename a port if it exists on a cell
-void rename_port(Context *ctx, CellInfo *cell, IdString old_name, IdString new_name);
-
-// Rename a net without invalidating pointers to it
-void rename_net(Context *ctx, NetInfo *net, IdString new_name);
-
void print_utilisation(const Context *ctx);
-// Disconnect a bus of nets (if connected) from old, and connect it to the new ports
-void replace_bus(Context *ctx, CellInfo *old_cell, IdString old_name, int old_offset, bool old_brackets,
- CellInfo *new_cell, IdString new_name, int new_offset, bool new_brackets, int width);
-
-// Copy a bus of nets (if connected) from old, and connect it to the new ports
-void copy_bus(Context *ctx, CellInfo *old_cell, IdString old_name, int old_offset, bool old_brackets,
- CellInfo *new_cell, IdString new_name, int new_offset, bool new_brackets, int width);
-
-// Copy a port from one cell to another
-void copy_port(Context *ctx, CellInfo *old_cell, IdString old_name, CellInfo *new_cell, IdString new_name);
-
NEXTPNR_NAMESPACE_END
#endif
diff --git a/common/nextpnr_types.cc b/common/nextpnr_types.cc
index 3deed46f..c89a0071 100644
--- a/common/nextpnr_types.cc
+++ b/common/nextpnr_types.cc
@@ -18,6 +18,8 @@
*/
#include "nextpnr_types.h"
+#include "context.h"
+#include "log.h"
#include "nextpnr_namespaces.h"
@@ -49,4 +51,135 @@ bool CellInfo::testRegion(BelId bel) const
return region == nullptr || !region->constr_bels || region->bels.count(bel);
}
+void CellInfo::connectPort(IdString port_name, NetInfo *net)
+{
+ if (net == nullptr)
+ return;
+ PortInfo &port = ports.at(port_name);
+ NPNR_ASSERT(port.net == nullptr);
+ port.net = net;
+ if (port.type == PORT_OUT) {
+ NPNR_ASSERT(net->driver.cell == nullptr);
+ net->driver.cell = this;
+ net->driver.port = port_name;
+ } else if (port.type == PORT_IN || port.type == PORT_INOUT) {
+ PortRef user;
+ user.cell = this;
+ user.port = port_name;
+ net->users.push_back(user);
+ } else {
+ NPNR_ASSERT_FALSE("invalid port type for connect_port");
+ }
+}
+
+void CellInfo::disconnectPort(IdString port_name)
+{
+ if (!ports.count(port_name))
+ return;
+ PortInfo &port = ports.at(port_name);
+ if (port.net != nullptr) {
+ port.net->users.erase(std::remove_if(port.net->users.begin(), port.net->users.end(),
+ [this, port_name](const PortRef &user) {
+ return user.cell == this && user.port == port_name;
+ }),
+ port.net->users.end());
+ if (port.net->driver.cell == this && port.net->driver.port == port_name)
+ port.net->driver.cell = nullptr;
+ port.net = nullptr;
+ }
+}
+
+void CellInfo::connectPorts(IdString port, CellInfo *other, IdString other_port)
+{
+ PortInfo &port1 = ports.at(port);
+ if (port1.net == nullptr) {
+ // No net on port1; need to create one
+ NetInfo *p1net = ctx->createNet(ctx->id(name.str(ctx) + "$conn$" + port.str(ctx)));
+ connectPort(port, p1net);
+ }
+ other->connectPort(other_port, port1.net);
+}
+
+void CellInfo::movePortTo(IdString port, CellInfo *other, IdString other_port)
+{
+ if (!ports.count(port))
+ return;
+ PortInfo &old = ports.at(port);
+
+ // Create port on the replacement cell if it doesn't already exist
+ if (!other->ports.count(other_port)) {
+ other->ports[other_port].name = other_port;
+ other->ports[other_port].type = old.type;
+ }
+
+ PortInfo &rep = other->ports.at(other_port);
+ NPNR_ASSERT(old.type == rep.type);
+
+ rep.net = old.net;
+ old.net = nullptr;
+ if (rep.type == PORT_OUT) {
+ if (rep.net != nullptr) {
+ rep.net->driver.cell = other;
+ rep.net->driver.port = other_port;
+ }
+ } else if (rep.type == PORT_IN) {
+ if (rep.net != nullptr) {
+ for (PortRef &load : rep.net->users) {
+ if (load.cell == this && load.port == port) {
+ load.cell = other;
+ load.port = other_port;
+ }
+ }
+ }
+ } else {
+ NPNR_ASSERT(false);
+ }
+}
+
+void CellInfo::renamePort(IdString old_name, IdString new_name)
+{
+ if (!ports.count(old_name))
+ return;
+ PortInfo pi = ports.at(old_name);
+ if (pi.net != nullptr) {
+ if (pi.net->driver.cell == this && pi.net->driver.port == old_name)
+ pi.net->driver.port = new_name;
+ for (auto &usr : pi.net->users)
+ if (usr.cell == this && usr.port == old_name)
+ usr.port = new_name;
+ }
+ ports.erase(old_name);
+ pi.name = new_name;
+ ports[new_name] = pi;
+}
+
+void CellInfo::movePortBusTo(IdString old_name, int old_offset, bool old_brackets, CellInfo *new_cell,
+ IdString new_name, int new_offset, bool new_brackets, int width)
+{
+ for (int i = 0; i < width; i++) {
+ IdString old_port = ctx->id(stringf(old_brackets ? "%s[%d]" : "%s%d", old_name.c_str(ctx), i + old_offset));
+ IdString new_port = ctx->id(stringf(new_brackets ? "%s[%d]" : "%s%d", new_name.c_str(ctx), i + new_offset));
+ movePortTo(old_port, new_cell, new_port);
+ }
+}
+
+void CellInfo::copyPortTo(IdString port, CellInfo *other, IdString other_port)
+{
+ if (!ports.count(port))
+ return;
+ other->ports[other_port].name = other_port;
+ other->ports[other_port].type = ports.at(port).type;
+ other->connectPort(other_port, ports.at(port).net);
+}
+
+void CellInfo::copyPortBusTo(IdString old_name, int old_offset, bool old_brackets, CellInfo *new_cell,
+ IdString new_name, int new_offset, bool new_brackets, int width)
+{
+ for (int i = 0; i < width; i++) {
+ IdString old_port = ctx->id(stringf(old_brackets ? "%s[%d]" : "%s%d", old_name.c_str(ctx), i + old_offset));
+ IdString new_port = ctx->id(stringf(new_brackets ? "%s[%d]" : "%s%d", new_name.c_str(ctx), i + new_offset));
+ copyPortTo(old_port, new_cell, new_port);
+ }
+}
+
NEXTPNR_NAMESPACE_END
diff --git a/common/nextpnr_types.h b/common/nextpnr_types.h
index 6debd2b8..cf93a071 100644
--- a/common/nextpnr_types.h
+++ b/common/nextpnr_types.h
@@ -187,6 +187,27 @@ struct CellInfo : ArchCellInfo
void unsetAttr(IdString name);
// check whether a bel complies with the cell's region constraint
bool testRegion(BelId bel) const;
+
+ NetInfo *getPort(IdString name)
+ {
+ auto found = ports.find(name);
+ return (found == ports.end()) ? nullptr : found->second.net;
+ }
+ const NetInfo *getPort(IdString name) const
+ {
+ auto found = ports.find(name);
+ return (found == ports.end()) ? nullptr : found->second.net;
+ }
+ void connectPort(IdString port, NetInfo *net);
+ void disconnectPort(IdString port);
+ void connectPorts(IdString port, CellInfo *other, IdString other_port);
+ void movePortTo(IdString port, CellInfo *other, IdString other_port);
+ void renamePort(IdString old_name, IdString new_name);
+ void movePortBusTo(IdString old_name, int old_offset, bool old_brackets, CellInfo *new_cell, IdString new_name,
+ int new_offset, bool new_brackets, int width);
+ void copyPortTo(IdString port, CellInfo *other, IdString other_port);
+ void copyPortBusTo(IdString old_name, int old_offset, bool old_brackets, CellInfo *new_cell, IdString new_name,
+ int new_offset, bool new_brackets, int width);
};
enum TimingPortClass
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;
}
diff --git a/fpga_interchange/arch_pack_clusters.cc b/fpga_interchange/arch_pack_clusters.cc
index b003812e..31e0522b 100644
--- a/fpga_interchange/arch_pack_clusters.cc
+++ b/fpga_interchange/arch_pack_clusters.cc
@@ -901,7 +901,7 @@ void Arch::prepare_cluster(const ClusterPOD *cluster, uint32_t index)
// reachable due to the fixed dedicated interconnect.
// E.g.: The CI input of carry chains in 7series corresponds to the CIN bel port,
// which can only be connected to the COUT output of the tile below.
- disconnect_port(ctx, ci, sink_port);
+ ci->disconnectPort(sink_port);
}
}
diff --git a/fpga_interchange/macros.cc b/fpga_interchange/macros.cc
index aa7d3184..8f7f8231 100644
--- a/fpga_interchange/macros.cc
+++ b/fpga_interchange/macros.cc
@@ -99,9 +99,9 @@ void Arch::expand_macros()
// TODO: case of multiple top level ports on the same net?
NPNR_ASSERT(net == nullptr);
// Use the corresponding pre-expansion port net
- net = get_net_or_empty(cell, IdString(net_port.port));
+ net = cell->getPort(IdString(net_port.port));
// Disconnect the original port pre-expansion
- disconnect_port(ctx, cell, IdString(net_port.port));
+ cell->disconnectPort(IdString(net_port.port));
}
// If not on a top level port, create a new net
if (net == nullptr)
@@ -115,7 +115,7 @@ void Arch::expand_macros()
ctx->cells.at(derived_name(ctx, cell->name, IdString(net_port.instance))).get();
inst_cell->ports[port_name].name = port_name;
inst_cell->ports[port_name].type = PortType(net_port.dir);
- connect_port(ctx, net, inst_cell, port_name);
+ inst_cell->connectPort(port_name, net);
}
}
diff --git a/fpga_interchange/site_router.cc b/fpga_interchange/site_router.cc
index 08e950e2..4e3d460a 100644
--- a/fpga_interchange/site_router.cc
+++ b/fpga_interchange/site_router.cc
@@ -953,7 +953,7 @@ static void apply_constant_routing(Context *ctx, const SiteArch &site_arch, NetI
new_cell->belStrength = STRENGTH_PLACER;
ctx->tileStatus.at(inverting_bel.tile).boundcells[inverting_bel.index] = new_cell;
- connect_port(ctx, net_before_inverter, new_cell, id_I);
+ new_cell->connectPort(id_I, net_before_inverter);
// The original BEL pin is now routed, but only through the inverter.
// Because the cell/net model doesn't allow for multiple source pins
diff --git a/frontend/frontend_base.h b/frontend/frontend_base.h
index ed9354b6..8ac61bbe 100644
--- a/frontend/frontend_base.h
+++ b/frontend/frontend_base.h
@@ -484,7 +484,7 @@ template <typename FrontendType> struct GenericFrontend
log_error("Net '%s' is multiply driven by cell ports %s.%s and %s.%s\n", ctx->nameOf(net),
ctx->nameOf(net->driver.cell), ctx->nameOf(net->driver.port), ctx->nameOf(inst_name),
port_bit_name.c_str());
- connect_port(ctx, net, ci, port_bit_ids);
+ ci->connectPort(port_bit_ids, net);
}
});
// Import attributes and parameters
@@ -578,12 +578,12 @@ template <typename FrontendType> struct GenericFrontend
}
NPNR_ASSERT(net->driver.cell == nullptr);
// Connect IBUF output and net
- connect_port(ctx, net, iobuf, ctx->id("O"));
+ iobuf->connectPort(ctx->id("O"), net);
} else if (dir == PORT_OUT) {
iobuf->type = ctx->id("$nextpnr_obuf");
iobuf->addInput(ctx->id("I"));
// Connect IBUF input and net
- connect_port(ctx, net, iobuf, ctx->id("I"));
+ iobuf->connectPort(ctx->id("I"), net);
} else if (dir == PORT_INOUT) {
iobuf->type = ctx->id("$nextpnr_iobuf");
@@ -597,16 +597,16 @@ template <typename FrontendType> struct GenericFrontend
NetInfo *split_iobuf_i = ctx->createNet(unique_name("", "$" + name + "$iobuf_i", true));
auto drv = net->driver;
if (drv.cell != nullptr) {
- disconnect_port(ctx, drv.cell, drv.port);
+ drv.cell->disconnectPort(drv.port);
drv.cell->ports[drv.port].net = nullptr;
- connect_port(ctx, split_iobuf_i, drv.cell, drv.port);
+ drv.cell->connectPort(drv.port, split_iobuf_i);
}
- connect_port(ctx, split_iobuf_i, iobuf, ctx->id("I"));
+ iobuf->connectPort(ctx->id("I"), split_iobuf_i);
NPNR_ASSERT(net->driver.cell == nullptr);
- connect_port(ctx, net, iobuf, ctx->id("O"));
+ iobuf->connectPort(ctx->id("O"), net);
} else {
iobuf->addInout(ctx->id("IO"));
- connect_port(ctx, net, iobuf, ctx->id("IO"));
+ iobuf->connectPort(ctx->id("IO"), net);
}
}
@@ -669,7 +669,7 @@ template <typename FrontendType> struct GenericFrontend
if (net->driver.cell != nullptr)
log_error("Net '%s' is multiply driven by port %s.%s and constant '%c'\n", ctx->nameOf(net),
ctx->nameOf(net->driver.cell), ctx->nameOf(net->driver.port), constval);
- connect_port(ctx, net, cc, ctx->id("Y"));
+ cc->connectPort(ctx->id("Y"), net);
}
// Merge two nets - e.g. if one net in a submodule bifurcates to two output bits and therefore two different
diff --git a/generic/arch.cc b/generic/arch.cc
index ad054efd..c4814bab 100644
--- a/generic/arch.cc
+++ b/generic/arch.cc
@@ -721,7 +721,7 @@ void Arch::assignArchInfo()
CellInfo *ci = cell.second.get();
if (ci->type == id("GENERIC_SLICE")) {
ci->is_slice = true;
- ci->slice_clk = get_net_or_empty(ci, id("CLK"));
+ ci->slice_clk = ci->getPort(id("CLK"));
} else {
ci->is_slice = false;
}
diff --git a/generic/cells.cc b/generic/cells.cc
index c14ddf73..76d6474f 100644
--- a/generic/cells.cc
+++ b/generic/cells.cc
@@ -66,19 +66,19 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff)
for (int i = 0; i < lut_k; i++) {
IdString port = ctx->id("I[" + std::to_string(i) + "]");
- replace_port(lut, port, lc, port);
+ lut->movePortTo(port, lc, port);
}
if (no_dff) {
lc->params[ctx->id("FF_USED")] = 0;
- replace_port(lut, ctx->id("Q"), lc, ctx->id("F"));
+ lut->movePortTo(ctx->id("Q"), lc, ctx->id("F"));
}
}
void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut)
{
lc->params[ctx->id("FF_USED")] = 1;
- replace_port(dff, ctx->id("CLK"), lc, ctx->id("CLK"));
+ dff->movePortTo(ctx->id("CLK"), lc, ctx->id("CLK"));
if (pass_thru_lut) {
// Fill LUT with alternating 10
@@ -89,26 +89,26 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l
init.append("10");
lc->params[ctx->id("INIT")] = Property::from_string(init);
- replace_port(dff, ctx->id("D"), lc, ctx->id("I[0]"));
+ dff->movePortTo(ctx->id("D"), lc, ctx->id("I[0]"));
}
- replace_port(dff, ctx->id("Q"), lc, ctx->id("Q"));
+ dff->movePortTo(ctx->id("Q"), lc, ctx->id("Q"));
}
void nxio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *iob, pool<IdString> &todelete_cells)
{
if (nxio->type == ctx->id("$nextpnr_ibuf")) {
iob->params[ctx->id("INPUT_USED")] = 1;
- replace_port(nxio, ctx->id("O"), iob, ctx->id("O"));
+ nxio->movePortTo(ctx->id("O"), iob, ctx->id("O"));
} else if (nxio->type == ctx->id("$nextpnr_obuf")) {
iob->params[ctx->id("OUTPUT_USED")] = 1;
- replace_port(nxio, ctx->id("I"), iob, ctx->id("I"));
+ nxio->movePortTo(ctx->id("I"), iob, ctx->id("I"));
} else if (nxio->type == ctx->id("$nextpnr_iobuf")) {
// N.B. tristate will be dealt with below
iob->params[ctx->id("INPUT_USED")] = 1;
iob->params[ctx->id("OUTPUT_USED")] = 1;
- replace_port(nxio, ctx->id("I"), iob, ctx->id("I"));
- replace_port(nxio, ctx->id("O"), iob, ctx->id("O"));
+ nxio->movePortTo(ctx->id("I"), iob, ctx->id("I"));
+ nxio->movePortTo(ctx->id("O"), iob, ctx->id("O"));
} else {
NPNR_ASSERT(false);
}
@@ -118,8 +118,8 @@ void nxio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *iob, pool<IdString> &to
ctx->id("Y"));
if (tbuf) {
iob->params[ctx->id("ENABLE_USED")] = 1;
- replace_port(tbuf, ctx->id("A"), iob, ctx->id("I"));
- replace_port(tbuf, ctx->id("E"), iob, ctx->id("EN"));
+ tbuf->movePortTo(ctx->id("A"), iob, ctx->id("I"));
+ tbuf->movePortTo(ctx->id("E"), iob, ctx->id("EN"));
if (donet->users.size() > 1) {
for (auto user : donet->users)
diff --git a/generic/pack.cc b/generic/pack.cc
index 8bdbbed0..cb3f5897 100644
--- a/generic/pack.cc
+++ b/generic/pack.cc
@@ -242,7 +242,7 @@ static void pack_io(Context *ctx)
} else if (bool_or_default(ctx->settings, ctx->id("disable_iobs"))) {
// No IO buffer insertion; just remove nextpnr_[io]buf
for (auto &p : ci->ports)
- disconnect_port(ctx, ci, p.first);
+ ci->disconnectPort(p.first);
} else {
// Create a GENERIC_IOB buffer
std::unique_ptr<CellInfo> ice_cell =
diff --git a/generic/viaduct/example/example.cc b/generic/viaduct/example/example.cc
index 3d1c201c..49b36792 100644
--- a/generic/viaduct/example/example.cc
+++ b/generic/viaduct/example/example.cc
@@ -253,10 +253,10 @@ struct ExampleImpl : ViaductAPI
CellInfo *ci = cell.second.get();
auto &fc = fast_cell_info.at(ci->flat_index);
if (ci->type == id_LUT4) {
- fc.lut_f = get_net_or_empty(ci, id_F);
- fc.lut_i3_used = (get_net_or_empty(ci, ctx->id(stringf("I[%d]", K - 1))) != nullptr);
+ fc.lut_f = ci->getPort(id_F);
+ fc.lut_i3_used = (ci->getPort(ctx->id(stringf("I[%d]", K - 1))) != nullptr);
} else if (ci->type == id_DFF) {
- fc.ff_d = get_net_or_empty(ci, id_D);
+ fc.ff_d = ci->getPort(id_D);
}
}
}
diff --git a/generic/viaduct_helpers.cc b/generic/viaduct_helpers.cc
index e9f7fa60..10c3b802 100644
--- a/generic/viaduct_helpers.cc
+++ b/generic/viaduct_helpers.cc
@@ -59,13 +59,13 @@ void ViaductHelpers::remove_nextpnr_iobs(const pool<CellTypePort> &top_ports)
auto &ci = *cell.second;
if (!ci.type.in(ctx->id("$nextpnr_ibuf"), ctx->id("$nextpnr_obuf"), ctx->id("$nextpnr_iobuf")))
continue;
- NetInfo *i = get_net_or_empty(&ci, ctx->id("I"));
+ NetInfo *i = ci.getPort(ctx->id("I"));
if (i && i->driver.cell) {
if (!top_ports.count(CellTypePort(i->driver)))
log_error("Top-level port '%s' driven by illegal port %s.%s\n", ctx->nameOf(&ci),
ctx->nameOf(i->driver.cell), ctx->nameOf(i->driver.port));
}
- NetInfo *o = get_net_or_empty(&ci, ctx->id("O"));
+ NetInfo *o = ci.getPort(ctx->id("O"));
if (o) {
for (auto &usr : o->users) {
if (!top_ports.count(CellTypePort(usr)))
@@ -73,8 +73,8 @@ void ViaductHelpers::remove_nextpnr_iobs(const pool<CellTypePort> &top_ports)
ctx->nameOf(usr.cell), ctx->nameOf(usr.port));
}
}
- disconnect_port(ctx, &ci, ctx->id("I"));
- disconnect_port(ctx, &ci, ctx->id("O"));
+ ci.disconnectPort(ctx->id("I"));
+ ci.disconnectPort(ctx->id("O"));
to_remove.push_back(ci.name);
}
for (IdString cell_name : to_remove)
diff --git a/gowin/arch.cc b/gowin/arch.cc
index b104013d..af851467 100644
--- a/gowin/arch.cc
+++ b/gowin/arch.cc
@@ -1600,9 +1600,9 @@ void Arch::assignArchInfo()
ci->is_slice = true;
ci->ff_used = ci->params.at(id_FF_USED).as_bool();
ci->ff_type = id(ci->params.at(id_FF_TYPE).as_string());
- ci->slice_clk = get_net_or_empty(ci, id_CLK);
- ci->slice_ce = get_net_or_empty(ci, id_CE);
- ci->slice_lsr = get_net_or_empty(ci, id_LSR);
+ ci->slice_clk = ci->getPort(id_CLK);
+ ci->slice_ce = ci->getPort(id_CE);
+ ci->slice_lsr = ci->getPort(id_LSR);
// add timing paths
addCellTimingClock(cname, id_CLK);
diff --git a/gowin/cells.cc b/gowin/cells.cc
index aef34f53..d862458c 100644
--- a/gowin/cells.cc
+++ b/gowin/cells.cc
@@ -93,12 +93,12 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff)
IdString sim_names[4] = {id_I0, id_I1, id_I2, id_I3};
IdString wire_names[4] = {id_A, id_B, id_C, id_D};
for (int i = 0; i < 4; i++) {
- replace_port(lut, sim_names[i], lc, wire_names[i]);
+ lut->movePortTo(sim_names[i], lc, wire_names[i]);
}
if (no_dff) {
lc->params[id_FF_USED] = 0;
- replace_port(lut, id_F, lc, id_F);
+ lut->movePortTo(id_F, lc, id_F);
}
}
@@ -106,12 +106,12 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l
{
lc->params[id_FF_USED] = 1;
lc->params[id_FF_TYPE] = dff->type.str(ctx);
- replace_port(dff, id_CLK, lc, id_CLK);
- replace_port(dff, id_CE, lc, id_CE);
- replace_port(dff, id_SET, lc, id_LSR);
- replace_port(dff, id_RESET, lc, id_LSR);
- replace_port(dff, id_CLEAR, lc, id_LSR);
- replace_port(dff, id_PRESET, lc, id_LSR);
+ dff->movePortTo(id_CLK, lc, id_CLK);
+ dff->movePortTo(id_CE, lc, id_CE);
+ dff->movePortTo(id_SET, lc, id_LSR);
+ dff->movePortTo(id_RESET, lc, id_LSR);
+ dff->movePortTo(id_CLEAR, lc, id_LSR);
+ dff->movePortTo(id_PRESET, lc, id_LSR);
if (pass_thru_lut) {
// Fill LUT with alternating 10
const int init_size = 1 << 4;
@@ -121,10 +121,10 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l
init.append("10");
lc->params[id_INIT] = Property::from_string(init);
- replace_port(dff, id_D, lc, id_A);
+ dff->movePortTo(id_D, lc, id_A);
}
- replace_port(dff, id_Q, lc, id_Q);
+ dff->movePortTo(id_Q, lc, id_Q);
}
void gwio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *iob, pool<IdString> &todelete_cells)
@@ -132,29 +132,29 @@ void gwio_to_iob(Context *ctx, CellInfo *nxio, CellInfo *iob, pool<IdString> &to
if (nxio->type == id_IBUF) {
if (iob->type == id_IOBS) {
// VCC -> OEN
- connect_port(ctx, ctx->nets[ctx->id("$PACKER_VCC_NET")].get(), iob, id_OEN);
+ iob->connectPort(id_OEN, ctx->nets[ctx->id("$PACKER_VCC_NET")].get());
}
iob->params[id_INPUT_USED] = 1;
- replace_port(nxio, id_O, iob, id_O);
+ nxio->movePortTo(id_O, iob, id_O);
} else if (nxio->type == id_OBUF) {
if (iob->type == id_IOBS) {
// VSS -> OEN
- connect_port(ctx, ctx->nets[ctx->id("$PACKER_GND_NET")].get(), iob, id_OEN);
+ iob->connectPort(id_OEN, ctx->nets[ctx->id("$PACKER_GND_NET")].get());
}
iob->params[id_OUTPUT_USED] = 1;
- replace_port(nxio, id_I, iob, id_I);
+ nxio->movePortTo(id_I, iob, id_I);
} else if (nxio->type == id_TBUF) {
iob->params[id_ENABLE_USED] = 1;
iob->params[id_OUTPUT_USED] = 1;
- replace_port(nxio, id_I, iob, id_I);
- replace_port(nxio, id_OEN, iob, id_OEN);
+ nxio->movePortTo(id_I, iob, id_I);
+ nxio->movePortTo(id_OEN, iob, id_OEN);
} else if (nxio->type == id_IOBUF) {
iob->params[id_ENABLE_USED] = 1;
iob->params[id_INPUT_USED] = 1;
iob->params[id_OUTPUT_USED] = 1;
- replace_port(nxio, id_I, iob, id_I);
- replace_port(nxio, id_O, iob, id_O);
- replace_port(nxio, id_OEN, iob, id_OEN);
+ nxio->movePortTo(id_I, iob, id_I);
+ nxio->movePortTo(id_O, iob, id_O);
+ nxio->movePortTo(id_OEN, iob, id_OEN);
} else {
NPNR_ASSERT(false);
}
diff --git a/gowin/pack.cc b/gowin/pack.cc
index 1201e310..268f26ef 100644
--- a/gowin/pack.cc
+++ b/gowin/pack.cc
@@ -96,7 +96,7 @@ static void pack_alus(Context *ctx)
log_info("packed ALU head into %s. CIN net is %s\n", ctx->nameOf(packed_head.get()),
ctx->nameOf(cin_netId));
}
- connect_port(ctx, ctx->nets[ctx->id("$PACKER_VCC_NET")].get(), packed_head.get(), id_C);
+ packed_head->connectPort(id_C, ctx->nets[ctx->id("$PACKER_VCC_NET")].get());
if (cin_netId == ctx->id("$PACKER_GND_NET")) {
// CIN = 0
packed_head->params[id_ALU_MODE] = std::string("C2L");
@@ -106,8 +106,8 @@ static void pack_alus(Context *ctx)
packed_head->params[id_ALU_MODE] = std::string("ONE2C");
} else {
// CIN from logic
- connect_port(ctx, ctx->nets[cin_netId].get(), packed_head.get(), id_B);
- connect_port(ctx, ctx->nets[cin_netId].get(), packed_head.get(), id_D);
+ packed_head->connectPort(id_B, ctx->nets[cin_netId].get());
+ packed_head->connectPort(id_D, ctx->nets[cin_netId].get());
packed_head->params[id_ALU_MODE] = std::string("0"); // ADD
}
}
@@ -123,9 +123,9 @@ static void pack_alus(Context *ctx)
packed_cells.insert(ci->name);
// CIN/COUT are hardwired, delete
- disconnect_port(ctx, ci, id_CIN);
+ ci->disconnectPort(id_CIN);
NetInfo *cout = ci->ports.at(id_COUT).net;
- disconnect_port(ctx, ci, id_COUT);
+ ci->disconnectPort(id_COUT);
std::unique_ptr<CellInfo> packed = create_generic_cell(ctx, id_SLICE, ci->name.str(ctx) + "_ALULC");
if (ctx->verbose) {
@@ -135,9 +135,9 @@ static void pack_alus(Context *ctx)
int mode = int_or_default(ci->params, id_ALU_MODE);
packed->params[id_ALU_MODE] = mode;
if (mode == 9) { // MULT
- connect_port(ctx, ctx->nets[ctx->id("$PACKER_GND_NET")].get(), packed.get(), id_C);
+ packed->connectPort(id_C, ctx->nets[ctx->id("$PACKER_GND_NET")].get());
} else {
- connect_port(ctx, ctx->nets[ctx->id("$PACKER_VCC_NET")].get(), packed.get(), id_C);
+ packed->connectPort(id_C, ctx->nets[ctx->id("$PACKER_VCC_NET")].get());
}
// add to cluster
@@ -149,30 +149,30 @@ static void pack_alus(Context *ctx)
++alu_idx;
// connect all remainig ports
- replace_port(ci, id_SUM, packed.get(), id_F);
+ ci->movePortTo(id_SUM, packed.get(), id_F);
switch (mode) {
case 0: // ADD
- replace_port(ci, id_I0, packed.get(), id_B);
- replace_port(ci, id_I1, packed.get(), id_D);
+ ci->movePortTo(id_I0, packed.get(), id_B);
+ ci->movePortTo(id_I1, packed.get(), id_D);
break;
case 1: // SUB
- replace_port(ci, id_I0, packed.get(), id_A);
- replace_port(ci, id_I1, packed.get(), id_D);
+ ci->movePortTo(id_I0, packed.get(), id_A);
+ ci->movePortTo(id_I1, packed.get(), id_D);
break;
case 5: // LE
- replace_port(ci, id_I0, packed.get(), id_A);
- replace_port(ci, id_I1, packed.get(), id_B);
+ ci->movePortTo(id_I0, packed.get(), id_A);
+ ci->movePortTo(id_I1, packed.get(), id_B);
break;
case 9: // MULT
- replace_port(ci, id_I0, packed.get(), id_A);
- replace_port(ci, id_I1, packed.get(), id_B);
- disconnect_port(ctx, packed.get(), id_D);
- connect_port(ctx, ctx->nets[ctx->id("$PACKER_VCC_NET")].get(), packed.get(), id_D);
+ ci->movePortTo(id_I0, packed.get(), id_A);
+ ci->movePortTo(id_I1, packed.get(), id_B);
+ packed->disconnectPort(id_D);
+ packed->connectPort(id_D, ctx->nets[ctx->id("$PACKER_VCC_NET")].get());
break;
default:
- replace_port(ci, id_I0, packed.get(), id_A);
- replace_port(ci, id_I1, packed.get(), id_B);
- replace_port(ci, id_I3, packed.get(), id_D);
+ ci->movePortTo(id_I0, packed.get(), id_A);
+ ci->movePortTo(id_I1, packed.get(), id_B);
+ ci->movePortTo(id_I3, packed.get(), id_D);
}
new_cells.push_back(std::move(packed));
@@ -191,7 +191,7 @@ static void pack_alus(Context *ctx)
ctx->nameOf(cout));
}
packed_tail->params[id_ALU_MODE] = std::string("C2L");
- connect_port(ctx, cout, packed_tail.get(), id_F);
+ packed_tail->connectPort(id_F, cout);
// add to cluster
packed_tail->cluster = packed_head->name;
packed_tail->constr_z = alu_idx % 6;
@@ -275,8 +275,8 @@ static void pack_mux2_lut5(Context *ctx, CellInfo *ci, pool<IdString> &packed_ce
packed->constr_children.clear();
// reconnect MUX ports
- replace_port(ci, id_O, packed.get(), id_OF);
- replace_port(ci, id_I1, packed.get(), id_I1);
+ ci->movePortTo(id_O, packed.get(), id_OF);
+ ci->movePortTo(id_I1, packed.get(), id_I1);
// remove cells
packed_cells.insert(ci->name);
@@ -320,10 +320,10 @@ static void pack_mux2_lut5(Context *ctx, CellInfo *ci, pool<IdString> &packed_ce
packed->constr_children.clear();
// reconnect MUX ports
- replace_port(ci, id_O, packed.get(), id_OF);
- replace_port(ci, id_S0, packed.get(), id_SEL);
- replace_port(ci, id_I0, packed.get(), id_I0);
- replace_port(ci, id_I1, packed.get(), id_I1);
+ ci->movePortTo(id_O, packed.get(), id_OF);
+ ci->movePortTo(id_S0, packed.get(), id_SEL);
+ ci->movePortTo(id_I0, packed.get(), id_I0);
+ ci->movePortTo(id_I1, packed.get(), id_I1);
// remove cells
packed_cells.insert(ci->name);
@@ -394,10 +394,10 @@ static void pack_mux2_lut(Context *ctx, CellInfo *ci, bool (*pred)(const BaseCtx
packed->constr_children.push_back(mux1);
// reconnect MUX ports
- replace_port(ci, id_O, packed.get(), id_OF);
- replace_port(ci, id_S0, packed.get(), id_SEL);
- replace_port(ci, id_I0, packed.get(), id_I0);
- replace_port(ci, id_I1, packed.get(), id_I1);
+ ci->movePortTo(id_O, packed.get(), id_OF);
+ ci->movePortTo(id_S0, packed.get(), id_SEL);
+ ci->movePortTo(id_I0, packed.get(), id_I0);
+ ci->movePortTo(id_I1, packed.get(), id_I1);
// remove cells
packed_cells.insert(ci->name);
@@ -711,7 +711,7 @@ static void pack_io(Context *ctx)
// delete the $nexpnr_[io]buf
for (auto &p : iob->ports) {
IdString netname = p.second.net->name;
- disconnect_port(ctx, iob, p.first);
+ iob->disconnectPort(p.first);
delete_nets.insert(netname);
}
packed_cells.insert(iob->name);
diff --git a/ice40/arch.cc b/ice40/arch.cc
index cf7e99a5..b36c82d5 100644
--- a/ice40/arch.cc
+++ b/ice40/arch.cc
@@ -1219,17 +1219,17 @@ void Arch::assignCellInfo(CellInfo *cell)
cell->lcInfo.dffEnable = bool_or_default(cell->params, id_DFF_ENABLE);
cell->lcInfo.carryEnable = bool_or_default(cell->params, id_CARRY_ENABLE);
cell->lcInfo.negClk = bool_or_default(cell->params, id_NEG_CLK);
- cell->lcInfo.clk = get_net_or_empty(cell, id_CLK);
- cell->lcInfo.cen = get_net_or_empty(cell, id_CEN);
- cell->lcInfo.sr = get_net_or_empty(cell, id_SR);
+ cell->lcInfo.clk = cell->getPort(id_CLK);
+ cell->lcInfo.cen = cell->getPort(id_CEN);
+ cell->lcInfo.sr = cell->getPort(id_SR);
cell->lcInfo.inputCount = 0;
- if (get_net_or_empty(cell, id_I0))
+ if (cell->getPort(id_I0))
cell->lcInfo.inputCount++;
- if (get_net_or_empty(cell, id_I1))
+ if (cell->getPort(id_I1))
cell->lcInfo.inputCount++;
- if (get_net_or_empty(cell, id_I2))
+ if (cell->getPort(id_I2))
cell->lcInfo.inputCount++;
- if (get_net_or_empty(cell, id_I3))
+ if (cell->getPort(id_I3))
cell->lcInfo.inputCount++;
} else if (cell->type == id_SB_IO) {
cell->ioInfo.lvds = str_or_default(cell->params, id_IO_STANDARD, "SB_LVCMOS") == "SB_LVDS_INPUT";
diff --git a/ice40/cells.cc b/ice40/cells.cc
index a8d30347..b5f759b2 100644
--- a/ice40/cells.cc
+++ b/ice40/cells.cc
@@ -340,12 +340,12 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff)
if (lc->hierpath == IdString())
lc->hierpath = lut->hierpath;
lc->params[id_LUT_INIT] = lut->params[id_LUT_INIT].extract(0, 16, Property::State::S0);
- replace_port(lut, id_I0, lc, id_I0);
- replace_port(lut, id_I1, lc, id_I1);
- replace_port(lut, id_I2, lc, id_I2);
- replace_port(lut, id_I3, lc, id_I3);
+ lut->movePortTo(id_I0, lc, id_I0);
+ lut->movePortTo(id_I1, lc, id_I1);
+ lut->movePortTo(id_I2, lc, id_I2);
+ lut->movePortTo(id_I3, lc, id_I3);
if (no_dff) {
- replace_port(lut, id_O, lc, id_O);
+ lut->movePortTo(id_O, lc, id_O);
lc->params[id_DFF_ENABLE] = Property::State::S0;
}
}
@@ -357,7 +357,7 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l
lc->params[id_DFF_ENABLE] = Property::State::S1;
std::string config = dff->type.str(ctx).substr(6);
auto citer = config.begin();
- replace_port(dff, id_C, lc, id_CLK);
+ dff->movePortTo(id_C, lc, id_CLK);
if (citer != config.end() && *citer == 'N') {
lc->params[id_NEG_CLK] = Property::State::S1;
@@ -367,7 +367,7 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l
}
if (citer != config.end() && *citer == 'E') {
- replace_port(dff, id_E, lc, id_CEN);
+ dff->movePortTo(id_E, lc, id_CEN);
++citer;
}
@@ -382,12 +382,12 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l
if (*citer == 'S') {
citer++;
- replace_port(dff, id_S, lc, id_SR);
+ dff->movePortTo(id_S, lc, id_SR);
lc->params[id_SET_NORESET] = Property::State::S1;
} else {
NPNR_ASSERT(*citer == 'R');
citer++;
- replace_port(dff, id_R, lc, id_SR);
+ dff->movePortTo(id_R, lc, id_SR);
lc->params[id_SET_NORESET] = Property::State::S0;
}
}
@@ -396,10 +396,10 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l
if (pass_thru_lut) {
lc->params[id_LUT_INIT] = Property(2, 16);
- replace_port(dff, id_D, lc, id_I0);
+ dff->movePortTo(id_D, lc, id_I0);
}
- replace_port(dff, id_Q, lc, id_O);
+ dff->movePortTo(id_Q, lc, id_O);
}
void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &todelete_cells)
@@ -409,13 +409,13 @@ void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &to
auto pu_attr = nxio->attrs.find(id_PULLUP);
if (pu_attr != nxio->attrs.end())
sbio->params[id_PULLUP] = pu_attr->second;
- replace_port(nxio, id_O, sbio, id_D_IN_0);
+ nxio->movePortTo(id_O, sbio, id_D_IN_0);
} else if (nxio->type == ctx->id("$nextpnr_obuf")) {
sbio->params[id_PIN_TYPE] = 25;
- replace_port(nxio, id_I, sbio, id_D_OUT_0);
+ nxio->movePortTo(id_I, sbio, id_D_OUT_0);
} 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)
sbio->params[id_PIN_TYPE] = 1;
else
@@ -423,8 +423,8 @@ void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &to
auto pu_attr = nxio->attrs.find(id_PULLUP);
if (pu_attr != nxio->attrs.end())
sbio->params[id_PULLUP] = pu_attr->second;
- replace_port(nxio, id_I, sbio, id_D_OUT_0);
- replace_port(nxio, id_O, sbio, id_D_IN_0);
+ nxio->movePortTo(id_I, sbio, id_D_OUT_0);
+ nxio->movePortTo(id_O, sbio, id_D_IN_0);
} else {
NPNR_ASSERT(false);
}
@@ -432,9 +432,11 @@ void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &to
// 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 (donet)
+ ctx->renameNet(donet->name, 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"));
+ if (dinet)
+ ctx->renameNet(dinet->name, ctx->id(dinet->name.str(ctx) + "$SB_IO_IN"));
if (ctx->nets.count(nxio->name)) {
int i = 0;
@@ -442,7 +444,8 @@ void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &to
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
@@ -451,7 +454,7 @@ void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &to
NPNR_ASSERT(!ctx->nets.count(tn_netname));
ctx->net_aliases.erase(tn_netname);
NetInfo *toplevel_net = ctx->createNet(tn_netname);
- connect_port(ctx, toplevel_net, sbio, id_PACKAGE_PIN);
+ sbio->connectPort(id_PACKAGE_PIN, toplevel_net);
ctx->ports[nxio->name].net = toplevel_net;
}
@@ -460,8 +463,8 @@ void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &to
id_Y);
if (tbuf) {
sbio->params[id_PIN_TYPE] = 41;
- replace_port(tbuf, id_A, sbio, id_D_OUT_0);
- replace_port(tbuf, id_E, sbio, id_OUTPUT_ENABLE);
+ tbuf->movePortTo(id_A, sbio, id_D_OUT_0);
+ tbuf->movePortTo(id_E, sbio, id_OUTPUT_ENABLE);
if (donet->users.size() > 1) {
for (auto user : donet->users)
diff --git a/ice40/pack.cc b/ice40/pack.cc
index 0220d4fe..4244f192 100644
--- a/ice40/pack.cc
+++ b/ice40/pack.cc
@@ -227,8 +227,8 @@ static void pack_carries(Context *ctx)
++carry_only;
}
carry_lc->params[id_CARRY_ENABLE] = Property::State::S1;
- replace_port(ci, id_CI, carry_lc, id_CIN);
- replace_port(ci, id_CO, carry_lc, id_COUT);
+ ci->movePortTo(id_CI, carry_lc, id_CIN);
+ ci->movePortTo(id_CO, carry_lc, id_COUT);
if (i0_net) {
auto &i0_usrs = i0_net->users;
i0_usrs.erase(std::remove_if(i0_usrs.begin(), i0_usrs.end(), [ci, ctx](const PortRef &pr) {
@@ -300,7 +300,7 @@ static void pack_ram(Context *ctx)
newname = "RCLK";
else if (pi.name == id_WCLKN)
newname = "WCLK";
- replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname));
+ ci->movePortTo(ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname));
}
new_cells.push_back(std::move(packed));
}
@@ -442,7 +442,7 @@ static std::unique_ptr<CellInfo> create_padin_gbuf(Context *ctx, CellInfo *cell,
gb->attrs[id_BEL] = ctx->getBelName(gb_bel).str(ctx);
// Reconnect the net to that port for easier identification it's a global net
- replace_port(cell, port_name, gb.get(), id_GLOBAL_BUFFER_OUTPUT);
+ cell->movePortTo(port_name, gb.get(), id_GLOBAL_BUFFER_OUTPUT);
return gb;
}
@@ -514,7 +514,7 @@ static void pack_io(Context *ctx)
} 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),
rgb->name.c_str(ctx));
- disconnect_port(ctx, ci, id_I);
+ ci->disconnectPort(id_I);
packed_cells.insert(ci->name);
continue;
} else {
@@ -525,7 +525,7 @@ static void pack_io(Context *ctx)
sb = new_cells.back().get();
}
for (auto port : ci->ports)
- disconnect_port(ctx, ci, port.first);
+ ci->disconnectPort(port.first);
packed_cells.insert(ci->name);
for (auto &attr : ci->attrs)
sb->attrs[attr.first] = attr.second;
@@ -1138,13 +1138,13 @@ static void pack_special(Context *ctx)
std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, id_ICESTORM_LFOSC, ci->name.str(ctx) + "_OSC");
packed_cells.insert(ci->name);
cell_place_unique(ctx, packed.get());
- replace_port(ci, id_CLKLFEN, packed.get(), id_CLKLFEN);
- replace_port(ci, id_CLKLFPU, packed.get(), id_CLKLFPU);
+ ci->movePortTo(id_CLKLFEN, packed.get(), id_CLKLFEN);
+ ci->movePortTo(id_CLKLFPU, packed.get(), id_CLKLFPU);
if (bool_or_default(ci->attrs, id_ROUTE_THROUGH_FABRIC)) {
- replace_port(ci, id_CLKLF, packed.get(), id_CLKLF_FABRIC);
+ ci->movePortTo(id_CLKLF, packed.get(), id_CLKLF_FABRIC);
set_period(ctx, packed.get(), id_CLKLF_FABRIC, 100000000); // 10kHz
} else {
- replace_port(ci, id_CLKLF, packed.get(), id_CLKLF);
+ ci->movePortTo(id_CLKLF, packed.get(), id_CLKLF);
std::unique_ptr<CellInfo> gb =
create_padin_gbuf(ctx, packed.get(), id_CLKLF, "$gbuf_" + ci->name.str(ctx) + "_lfosc");
set_period(ctx, gb.get(), id_GLOBAL_BUFFER_OUTPUT, 100000000); // 10kHz
@@ -1157,11 +1157,11 @@ static void pack_special(Context *ctx)
cell_place_unique(ctx, packed.get());
packed->params[id_TRIM_EN] = str_or_default(ci->params, id_TRIM_EN, "0b0");
packed->params[id_CLKHF_DIV] = str_or_default(ci->params, id_CLKHF_DIV, "0b00");
- replace_port(ci, id_CLKHFEN, packed.get(), id_CLKHFEN);
- replace_port(ci, id_CLKHFPU, packed.get(), id_CLKHFPU);
+ ci->movePortTo(id_CLKHFEN, packed.get(), id_CLKHFEN);
+ ci->movePortTo(id_CLKHFPU, packed.get(), id_CLKHFPU);
for (int i = 0; i < 10; i++) {
auto port = ctx->id("TRIM" + std::to_string(i));
- replace_port(ci, port, packed.get(), port);
+ ci->movePortTo(port, packed.get(), port);
}
std::string div = packed->params[id_CLKHF_DIV].as_string();
int frequency;
@@ -1176,10 +1176,10 @@ static void pack_special(Context *ctx)
else
log_error("Invalid HFOSC divider value '%s' - expecting 0b00, 0b01, 0b10 or 0b11\n", div.c_str());
if (bool_or_default(ci->attrs, id_ROUTE_THROUGH_FABRIC)) {
- replace_port(ci, id_CLKHF, packed.get(), id_CLKHF_FABRIC);
+ ci->movePortTo(id_CLKHF, packed.get(), id_CLKHF_FABRIC);
set_period(ctx, packed.get(), id_CLKHF_FABRIC, 1000000 / frequency);
} else {
- replace_port(ci, id_CLKHF, packed.get(), id_CLKHF);
+ ci->movePortTo(id_CLKHF, packed.get(), id_CLKHF);
std::unique_ptr<CellInfo> gb =
create_padin_gbuf(ctx, packed.get(), id_CLKHF, "$gbuf_" + ci->name.str(ctx) + "_hfosc");
set_period(ctx, gb.get(), id_GLOBAL_BUFFER_OUTPUT, 1000000 / frequency);
@@ -1198,7 +1198,7 @@ static void pack_special(Context *ctx)
if (bpos != std::string::npos) {
newname = newname.substr(0, bpos) + "_" + newname.substr(bpos + 1, (newname.size() - bpos) - 2);
}
- replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname));
+ ci->movePortTo(ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname));
}
new_cells.push_back(std::move(packed));
} else if (is_sb_mac16(ctx, ci)) {
@@ -1216,7 +1216,7 @@ static void pack_special(Context *ctx)
if (bpos != std::string::npos) {
newname = newname.substr(0, bpos) + "_" + newname.substr(bpos + 1, (newname.size() - bpos) - 2);
}
- replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname));
+ ci->movePortTo(ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname));
}
new_cells.push_back(std::move(packed));
} else if (is_sb_rgba_drv(ctx, ci) || is_sb_rgb_drv(ctx, ci)) {
@@ -1410,7 +1410,7 @@ void pack_plls(Context *ctx)
}
}
}
- replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname));
+ ci->movePortTo(ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname));
}
// Compute derive constraints
diff --git a/machxo2/cells.cc b/machxo2/cells.cc
index 1c4f753b..c5464892 100644
--- a/machxo2/cells.cc
+++ b/machxo2/cells.cc
@@ -131,10 +131,10 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff)
for (std::string i : {"A", "B", "C", "D"}) {
IdString lut_port = ctx->id(i);
IdString lc_port = ctx->id(i + "0");
- replace_port(lut, lut_port, lc, lc_port);
+ lut->movePortTo(lut_port, lc, lc_port);
}
- replace_port(lut, id_Z, lc, id_F0);
+ lut->movePortTo(id_Z, lc, id_F0);
}
void dff_to_lc(Context *ctx, CellInfo *dff, CellInfo *lc, LutType lut_type)
@@ -142,26 +142,26 @@ void dff_to_lc(Context *ctx, CellInfo *dff, CellInfo *lc, LutType lut_type)
// FIXME: This will have to change once we support FFs with reset value of 1.
lc->params[id_REG0_REGSET] = std::string("RESET");
- replace_port(dff, id_CLK, lc, id_CLK);
- replace_port(dff, id_LSR, lc, id_LSR);
- replace_port(dff, id_Q, lc, id_Q0);
+ dff->movePortTo(id_CLK, lc, id_CLK);
+ dff->movePortTo(id_LSR, lc, id_LSR);
+ dff->movePortTo(id_Q, lc, id_Q0);
if (lut_type == LutType::PassThru) {
// If a register's DI port is fed by a constant, options for placing are
// limited. Use the LUT to get around this.
// LUT output will go to F0, which will feed back to DI0 input.
lc->params[id_LUT0_INITVAL] = Property(0xAAAA, 16);
- replace_port(dff, id_DI, lc, id_A0);
- connect_ports(ctx, lc, id_F0, lc, id_DI0);
+ dff->movePortTo(id_DI, lc, id_A0);
+ lc->connectPorts(id_F0, lc, id_DI0);
} else if (lut_type == LutType::None) {
// If there is no LUT, use the M0 input because DI0 requires
// going through the LUTs.
lc->params[id_REG0_SD] = std::string("0");
- replace_port(dff, id_DI, lc, id_M0);
+ dff->movePortTo(id_DI, lc, id_M0);
} else {
// Otherwise, there's a LUT being used in the slice and mapping DI to
// DI0 input is fine.
- replace_port(dff, id_DI, lc, id_DI0);
+ dff->movePortTo(id_DI, lc, id_DI0);
}
}
diff --git a/machxo2/pack.cc b/machxo2/pack.cc
index de607865..5051a981 100644
--- a/machxo2/pack.cc
+++ b/machxo2/pack.cc
@@ -286,7 +286,7 @@ static void pack_io(Context *ctx)
log_info("Removing top-level IOBUF '%s' of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx));
for (auto &p : ci->ports)
- disconnect_port(ctx, ci, p.first);
+ ci->disconnectPort(p.first);
packed_cells.insert(ci->name);
} else if (is_facade_iob(ctx, ci)) {
// If FACADE_IO has LOC attribute, convert the LOC (pin) to a BEL
diff --git a/mistral/bitstream.cc b/mistral/bitstream.cc
index e18d1413..35c1303a 100644
--- a/mistral/bitstream.cc
+++ b/mistral/bitstream.cc
@@ -86,8 +86,7 @@ struct MistralBitgen
void write_io_cell(CellInfo *ci, int x, int y, int bi)
{
- bool is_output =
- (ci->type == id_MISTRAL_OB || (ci->type == id_MISTRAL_IO && get_net_or_empty(ci, id_OE) != nullptr));
+ bool is_output = (ci->type == id_MISTRAL_OB || (ci->type == id_MISTRAL_IO && ci->getPort(id_OE) != nullptr));
auto pos = CycloneV::xy2pos(x, y);
// TODO: configurable pull, IO standard, etc
cv->bmux_b_set(CycloneV::GPIO, pos, CycloneV::USE_WEAK_PULLUP, bi, false);
@@ -229,8 +228,8 @@ struct MistralBitgen
cv->bmux_m_set(block_type, pos, clk_sel[i / 2], alm, clk_choice[ce_idx]);
if (ff->ffInfo.ctrlset.clk.inverted)
cv->bmux_b_set(block_type, pos, clk_inv[ce_idx], 0, true);
- if (get_net_or_empty(ff, id_ENA) != nullptr) { // not using ffInfo.ctrlset, this has a fake net always to
- // ensure different constants don't collide
+ if (ff->getPort(id_ENA) != nullptr) { // not using ffInfo.ctrlset, this has a fake net always to
+ // ensure different constants don't collide
cv->bmux_b_set(block_type, pos, en_en[ce_idx], 0, true);
cv->bmux_b_set(block_type, pos, en_ninv[ce_idx], 0, ff->ffInfo.ctrlset.ena.inverted);
} else {
@@ -262,7 +261,7 @@ struct MistralBitgen
cv->bmux_m_set(block_type, pos, clk_sel[1], alm, clk_choice[ce_idx]);
if (lut->combInfo.wclk.inverted)
cv->bmux_b_set(block_type, pos, clk_inv[ce_idx], 0, true);
- if (get_net_or_empty(lut, id_A1EN) != nullptr) {
+ if (lut->getPort(id_A1EN) != nullptr) {
cv->bmux_b_set(block_type, pos, en_en[ce_idx], 0, true);
cv->bmux_b_set(block_type, pos, en_ninv[ce_idx], 0, lut->combInfo.we.inverted);
} else {
diff --git a/mistral/lab.cc b/mistral/lab.cc
index 4f6b9b00..4b66ed0c 100644
--- a/mistral/lab.cc
+++ b/mistral/lab.cc
@@ -212,7 +212,7 @@ namespace {
ControlSig get_ctrlsig(const Context *ctx, const CellInfo *cell, IdString port, bool explicit_const = false)
{
ControlSig result;
- result.net = get_net_or_empty(cell, port);
+ result.net = cell->getPort(port);
if (result.net == nullptr && explicit_const) {
// For ENA, 1 (and 0) are explicit control set choices even though they aren't routed, as "no ENA" still
// consumes a clock+ENA pair
@@ -278,10 +278,10 @@ void Arch::assign_comb_info(CellInfo *cell) const
cell->combInfo.lut_input_count = 5;
cell->combInfo.lut_bits_count = 32;
for (int i = 0; i < 5; i++)
- cell->combInfo.lut_in[i] = get_net_or_empty(cell, id(stringf("B1ADDR[%d]", i)));
+ cell->combInfo.lut_in[i] = cell->getPort(id(stringf("B1ADDR[%d]", i)));
auto key = get_mlab_key(cell);
cell->combInfo.mlab_group = mlab_groups(key);
- cell->combInfo.comb_out = get_net_or_empty(cell, id_B1DATA);
+ cell->combInfo.comb_out = cell->getPort(id_B1DATA);
} else if (cell->type == id_MISTRAL_ALUT_ARITH) {
cell->combInfo.is_carry = true;
cell->combInfo.lut_input_count = 5;
@@ -292,14 +292,14 @@ void Arch::assign_comb_info(CellInfo *cell) const
{
int i = 0;
for (auto pin : arith_pins) {
- cell->combInfo.lut_in[i++] = get_net_or_empty(cell, pin);
+ cell->combInfo.lut_in[i++] = cell->getPort(pin);
}
}
- const NetInfo *ci = get_net_or_empty(cell, id_CI);
- const NetInfo *co = get_net_or_empty(cell, id_CO);
+ const NetInfo *ci = cell->getPort(id_CI);
+ const NetInfo *co = cell->getPort(id_CO);
- cell->combInfo.comb_out = get_net_or_empty(cell, id_SO);
+ cell->combInfo.comb_out = cell->getPort(id_SO);
cell->combInfo.carry_start = (ci == nullptr) || (ci->driver.cell == nullptr);
cell->combInfo.carry_end = (co == nullptr) || (co->users.empty());
@@ -308,10 +308,10 @@ void Arch::assign_comb_info(CellInfo *cell) const
const CellInfo *prev = ci->driver.cell;
if (prev != nullptr) {
for (int i = 0; i < 5; i++) {
- const NetInfo *a = get_net_or_empty(cell, arith_pins[i]);
+ const NetInfo *a = cell->getPort(arith_pins[i]);
if (a == nullptr)
continue;
- const NetInfo *b = get_net_or_empty(prev, arith_pins[i]);
+ const NetInfo *b = prev->getPort(arith_pins[i]);
if (a == b)
++cell->combInfo.chain_shared_input_count;
}
@@ -323,28 +323,28 @@ void Arch::assign_comb_info(CellInfo *cell) const
switch (cell->type.index) {
case ID_MISTRAL_ALUT6:
++cell->combInfo.lut_input_count;
- cell->combInfo.lut_in[5] = get_net_or_empty(cell, id_F);
+ cell->combInfo.lut_in[5] = cell->getPort(id_F);
[[fallthrough]];
case ID_MISTRAL_ALUT5:
++cell->combInfo.lut_input_count;
- cell->combInfo.lut_in[4] = get_net_or_empty(cell, id_E);
+ cell->combInfo.lut_in[4] = cell->getPort(id_E);
[[fallthrough]];
case ID_MISTRAL_ALUT4:
++cell->combInfo.lut_input_count;
- cell->combInfo.lut_in[3] = get_net_or_empty(cell, id_D);
+ cell->combInfo.lut_in[3] = cell->getPort(id_D);
[[fallthrough]];
case ID_MISTRAL_ALUT3:
++cell->combInfo.lut_input_count;
- cell->combInfo.lut_in[2] = get_net_or_empty(cell, id_C);
+ cell->combInfo.lut_in[2] = cell->getPort(id_C);
[[fallthrough]];
case ID_MISTRAL_ALUT2:
++cell->combInfo.lut_input_count;
- cell->combInfo.lut_in[1] = get_net_or_empty(cell, id_B);
+ cell->combInfo.lut_in[1] = cell->getPort(id_B);
[[fallthrough]];
case ID_MISTRAL_BUF: // used to route through to FFs etc
case ID_MISTRAL_NOT: // used for inverters that map to LUTs
++cell->combInfo.lut_input_count;
- cell->combInfo.lut_in[0] = get_net_or_empty(cell, id_A);
+ cell->combInfo.lut_in[0] = cell->getPort(id_A);
[[fallthrough]];
case ID_MISTRAL_CONST:
// MISTRAL_CONST is a nextpnr-inserted cell type for 0-input, constant-generating LUTs
@@ -375,8 +375,8 @@ void Arch::assign_ff_info(CellInfo *cell) const
cell->ffInfo.ctrlset.sload.inverted = false;
}
- cell->ffInfo.sdata = get_net_or_empty(cell, id_SDATA);
- cell->ffInfo.datain = get_net_or_empty(cell, id_DATAIN);
+ cell->ffInfo.sdata = cell->getPort(id_SDATA);
+ cell->ffInfo.datain = cell->getPort(id_DATAIN);
}
// Validity checking functions
@@ -883,7 +883,7 @@ void Arch::reassign_alm_inputs(uint32_t lab, uint8_t alm)
auto &bel_pins = luts[i]->pin_data[log].bel_pins;
bel_pins.clear();
- NetInfo *net = get_net_or_empty(luts[i], log);
+ NetInfo *net = luts[i]->getPort(log);
if (net == nullptr) {
// Disconnected inputs don't need to be allocated a pin, because the router won't be routing these
continue;
@@ -922,10 +922,10 @@ void Arch::reassign_alm_inputs(uint32_t lab, uint8_t alm)
rt_lut->addInput(id_A);
rt_lut->addOutput(id_Q);
// Disconnect the original data input to the FF, and connect it to the route-thru LUT instead
- NetInfo *datain = get_net_or_empty(ff, id_DATAIN);
- disconnect_port(getCtx(), ff, id_DATAIN);
- connect_port(getCtx(), datain, rt_lut, id_A);
- connect_ports(getCtx(), rt_lut, id_Q, ff, id_DATAIN);
+ NetInfo *datain = ff->getPort(id_DATAIN);
+ ff->disconnectPort(id_DATAIN);
+ rt_lut->connectPort(id_A, datain);
+ rt_lut->connectPorts(id_Q, ff, id_DATAIN);
// Assign route-thru LUT physical ports, input goes to the first half-specific input
rt_lut->pin_data[id_A].bel_pins.push_back(i ? id_D : id_C);
rt_lut->pin_data[id_Q].bel_pins.push_back(id_COMBOUT);
@@ -1050,7 +1050,7 @@ uint64_t Arch::compute_lut_mask(uint32_t lab, uint8_t alm)
else if (state == PIN_1)
index |= (1 << init_idx);
// Ignore if no associated physical pin
- if (get_net_or_empty(lut, log_pin) == nullptr || lut->pin_data.at(log_pin).bel_pins.empty())
+ if (lut->getPort(log_pin) == nullptr || lut->pin_data.at(log_pin).bel_pins.empty())
continue;
// ALM inputs appear to be inverted by default (TODO: check!)
// so only invert if an inverter has _not_ been folded into the pin
diff --git a/mistral/pack.cc b/mistral/pack.cc
index 4b434015..c4b3afe3 100644
--- a/mistral/pack.cc
+++ b/mistral/pack.cc
@@ -41,13 +41,13 @@ struct MistralPacker
vcc_drv->addOutput(id_Q);
gnd_net = ctx->createNet(ctx->id("$PACKER_GND_NET"));
vcc_net = ctx->createNet(ctx->id("$PACKER_VCC_NET"));
- connect_port(ctx, gnd_net, gnd_drv, id_Q);
- connect_port(ctx, vcc_net, vcc_drv, id_Q);
+ gnd_drv->connectPort(id_Q, gnd_net);
+ vcc_drv->connectPort(id_Q, vcc_net);
}
CellPinState get_pin_needed_muxval(CellInfo *cell, IdString port)
{
- NetInfo *net = get_net_or_empty(cell, port);
+ NetInfo *net = cell->getPort(port);
if (net == nullptr || net->driver.cell == nullptr) {
// Pin is disconnected
// If a mux value exists already, honour it
@@ -78,14 +78,14 @@ struct MistralPacker
void uninvert_port(CellInfo *cell, IdString port)
{
// Rewire a port so it is driven by the input to an inverter
- NetInfo *net = get_net_or_empty(cell, port);
+ NetInfo *net = cell->getPort(port);
NPNR_ASSERT(net != nullptr && net->driver.cell != nullptr && net->driver.cell->type == id_MISTRAL_NOT);
CellInfo *inv = net->driver.cell;
- disconnect_port(ctx, cell, port);
+ cell->disconnectPort(port);
- NetInfo *inv_a = get_net_or_empty(inv, id_A);
+ NetInfo *inv_a = inv->getPort(id_A);
if (inv_a != nullptr) {
- connect_port(ctx, inv_a, cell, port);
+ cell->connectPort(port, inv_a);
}
}
@@ -117,12 +117,12 @@ struct MistralPacker
// Pin is tied to a constant
// If there is a hard constant option; use it
if ((pin_style & int(req_mux)) == req_mux) {
- disconnect_port(ctx, cell, port_name);
+ cell->disconnectPort(port_name);
cell->pin_data[port_name].state = req_mux;
} else {
- disconnect_port(ctx, cell, port_name);
+ cell->disconnectPort(port_name);
// There is no hard constant, we need to connect it to the relevant soft-constant net
- connect_port(ctx, (req_mux == PIN_1) ? vcc_net : gnd_net, cell, port_name);
+ cell->connectPort(port_name, (req_mux == PIN_1) ? vcc_net : gnd_net);
}
}
}
@@ -138,7 +138,7 @@ struct MistralPacker
if (ci->type != id_MISTRAL_NOT && ci->type != id_GND && ci->type != id_VCC)
continue;
IdString port = (ci->type == id_MISTRAL_NOT) ? id_Q : id_Y;
- NetInfo *out = get_net_or_empty(ci, port);
+ NetInfo *out = ci->getPort(port);
if (out == nullptr) {
trim_cells.push_back(ci->name);
continue;
@@ -146,7 +146,7 @@ struct MistralPacker
if (!out->users.empty())
continue;
- disconnect_port(ctx, ci, id_A);
+ ci->disconnectPort(id_A);
trim_cells.push_back(ci->name);
trim_nets.push_back(out->name);
@@ -174,7 +174,7 @@ struct MistralPacker
continue;
if (ci->get_pin_state(id_SLOAD) != PIN_0)
continue;
- disconnect_port(ctx, ci, id_SDATA);
+ ci->disconnectPort(id_SDATA);
}
// Remove superfluous inverters and constant drivers
trim_design();
@@ -197,7 +197,7 @@ struct MistralPacker
if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_iobuf")) {
// Might have an input buffer (IB etc) connected to it
is_npnr_iob = true;
- NetInfo *o = get_net_or_empty(ci, id_O);
+ NetInfo *o = ci->getPort(id_O);
if (o == nullptr)
;
else if (o->users.size() > 1)
@@ -208,7 +208,7 @@ struct MistralPacker
if (ci->type == ctx->id("$nextpnr_obuf") || ci->type == ctx->id("$nextpnr_iobuf")) {
// Might have an output buffer (OB etc) connected to it
is_npnr_iob = true;
- NetInfo *i = get_net_or_empty(ci, id_I);
+ NetInfo *i = ci->getPort(id_I);
if (i != nullptr && i->driver.cell != nullptr) {
if (top_port.cell != nullptr)
log_error("Top level pin '%s' has multiple input/output buffers\n", ctx->nameOf(port.first));
@@ -245,8 +245,8 @@ struct MistralPacker
port.second.net = top_port.cell->ports.at(top_port.port).net;
}
// Now remove the nextpnr-inserted buffer
- disconnect_port(ctx, ci, id_I);
- disconnect_port(ctx, ci, id_O);
+ ci->disconnectPort(id_I);
+ ci->disconnectPort(id_O);
ctx->cells.erase(port.first);
}
}
@@ -290,14 +290,14 @@ struct MistralPacker
CellInfo *ci = cell.second.get();
if (ci->type != id_MISTRAL_ALUT_ARITH)
continue;
- const NetInfo *cin = get_net_or_empty(ci, id_CI);
+ const NetInfo *cin = ci->getPort(id_CI);
if (cin != nullptr && cin->driver.cell != nullptr)
continue; // not the start of a chain
std::vector<CellInfo *> chain;
CellInfo *cursor = ci;
while (true) {
chain.push_back(cursor);
- const NetInfo *co = get_net_or_empty(cursor, id_CO);
+ const NetInfo *co = cursor->getPort(id_CO);
if (co == nullptr || co->users.empty())
break;
if (co->users.size() > 1)
@@ -327,7 +327,7 @@ struct MistralPacker
for (int i = 0; i < int(chain.size()); i++) {
auto &c = chain.at(i);
log_info(" i=%d cell=%s dy=%d z=%d ci=%s co=%s\n", i, ctx->nameOf(c), c->constr_y, c->constr_z,
- ctx->nameOf(get_net_or_empty(c, id_CI)), ctx->nameOf(get_net_or_empty(c, id_CO)));
+ ctx->nameOf(c->getPort(id_CI)), ctx->nameOf(c->getPort(id_CO)));
}
}
}
@@ -338,7 +338,7 @@ struct MistralPacker
continue;
if (ci->cluster == ClusterId())
log_error("Failed to include arith cell '%s' in any chain (CI=%s)\n", ctx->nameOf(ci),
- ctx->nameOf(get_net_or_empty(ci, id_CI)));
+ ctx->nameOf(ci->getPort(id_CI)));
}
}
diff --git a/nexus/fasm.cc b/nexus/fasm.cc
index 4aaecdf4..c460e14b 100644
--- a/nexus/fasm.cc
+++ b/nexus/fasm.cc
@@ -421,7 +421,7 @@ struct NexusFasmWriter
BelId bel = cell->bel;
used_io.insert(bel);
push_bel(bel);
- const NetInfo *t = get_net_or_empty(cell, id_T);
+ const NetInfo *t = cell->getPort(id_T);
auto tmux = ctx->get_cell_pinmux(cell, id_T);
bool is_input = false, is_output = false;
if (tmux == PINMUX_0) {
@@ -444,7 +444,7 @@ struct NexusFasmWriter
used_io.insert(bel);
push_bel(bel);
push("SEIO18");
- const NetInfo *t = get_net_or_empty(cell, id_T);
+ const NetInfo *t = cell->getPort(id_T);
auto tmux = ctx->get_cell_pinmux(cell, id_T);
bool is_input = false, is_output = false;
if (tmux == PINMUX_0) {
@@ -481,7 +481,7 @@ struct NexusFasmWriter
bank.diff_used = true;
- const NetInfo *t = get_net_or_empty(cell, id_T);
+ const NetInfo *t = cell->getPort(id_T);
auto tmux = ctx->get_cell_pinmux(cell, id_T);
bool is_input = false, is_output = false;
if (tmux == PINMUX_0) {
@@ -843,7 +843,7 @@ struct NexusFasmWriter
if (!ci->attrs.count(id_IO_TYPE))
continue;
// VccO only concerns outputs
- const NetInfo *t = get_net_or_empty(ci, id_T);
+ const NetInfo *t = ci->getPort(id_T);
auto tmux = ctx->get_cell_pinmux(ci, id_T);
if (tmux == PINMUX_1 || (tmux != PINMUX_0 && t == nullptr))
continue;
diff --git a/nexus/pack.cc b/nexus/pack.cc
index 13522c78..5509d997 100644
--- a/nexus/pack.cc
+++ b/nexus/pack.cc
@@ -126,12 +126,12 @@ struct NexusPacker
for (auto pname : orig_port_names) {
if (rule.port_multixform.count(pname)) {
auto old_port = ci->ports.at(pname);
- disconnect_port(ctx, ci, pname);
+ ci->disconnectPort(pname);
ci->ports.erase(pname);
for (auto new_name : rule.port_multixform.at(pname)) {
ci->ports[new_name].name = new_name;
ci->ports[new_name].type = old_port.type;
- connect_port(ctx, old_port.net, ci, new_name);
+ ci->connectPort(new_name, old_port.net);
}
} else {
IdString new_name;
@@ -145,7 +145,7 @@ struct NexusPacker
new_name = ctx->id(stripped_name);
}
if (new_name != pname) {
- rename_port(ctx, ci, pname, new_name);
+ ci->renamePort(pname, new_name);
}
}
}
@@ -307,7 +307,7 @@ struct NexusPacker
CellInfo *ci = cell.second.get();
if (ci->type != type)
continue;
- NetInfo *z = get_net_or_empty(ci, id_Z);
+ NetInfo *z = ci->getPort(id_Z);
if (z == nullptr)
continue;
return z;
@@ -316,13 +316,13 @@ struct NexusPacker
NetInfo *new_net = ctx->createNet(ctx->id(stringf("$CONST_%s_NET_", type.c_str(ctx))));
CellInfo *new_cell = ctx->createCell(ctx->id(stringf("$CONST_%s_DRV_", type.c_str(ctx))), type);
new_cell->addOutput(id_Z);
- connect_port(ctx, new_net, new_cell, id_Z);
+ new_cell->connectPort(id_Z, new_net);
return new_net;
}
CellPinMux get_pin_needed_muxval(CellInfo *cell, IdString port)
{
- NetInfo *net = get_net_or_empty(cell, port);
+ NetInfo *net = cell->getPort(port);
if (net == nullptr || net->driver.cell == nullptr) {
// Pin is disconnected
// If a mux value exists already, honour it
@@ -353,14 +353,14 @@ struct NexusPacker
void uninvert_port(CellInfo *cell, IdString port)
{
// Rewire a port so it is driven by the input to an inverter
- NetInfo *net = get_net_or_empty(cell, port);
+ NetInfo *net = cell->getPort(port);
NPNR_ASSERT(net != nullptr && net->driver.cell != nullptr && net->driver.cell->type == id_INV);
CellInfo *inv = net->driver.cell;
- disconnect_port(ctx, cell, port);
+ cell->disconnectPort(port);
- NetInfo *inv_a = get_net_or_empty(inv, id_A);
+ NetInfo *inv_a = inv->getPort(id_A);
if (inv_a != nullptr) {
- connect_port(ctx, inv_a, cell, port);
+ cell->connectPort(port, inv_a);
}
}
@@ -373,7 +373,7 @@ struct NexusPacker
CellInfo *ci = cell.second.get();
if (ci->type != id_INV && ci->type != id_VLO && ci->type != id_VHI && ci->type != id_VCC_DRV)
continue;
- NetInfo *z = get_net_or_empty(ci, id_Z);
+ NetInfo *z = ci->getPort(id_Z);
if (z == nullptr) {
trim_cells.push_back(ci->name);
continue;
@@ -381,7 +381,7 @@ struct NexusPacker
if (!z->users.empty())
continue;
- disconnect_port(ctx, ci, id_A);
+ ci->disconnectPort(id_A);
trim_cells.push_back(ci->name);
trim_nets.push_back(z->name);
@@ -415,7 +415,7 @@ struct NexusPacker
for (IdString port : port_names) {
IdString new_name = ctx->id(remove_brackets(port.str(ctx)));
if (new_name != port)
- rename_port(ctx, cell, port, new_name);
+ cell->renamePort(port, new_name);
}
}
@@ -453,17 +453,17 @@ struct NexusPacker
if ((cell->type == id_OXIDE_COMB) && (req_mux == PINMUX_1)) {
// We need to add a connection to the dedicated Vcc resource that can feed these cell ports
- disconnect_port(ctx, cell, port_name);
- connect_port(ctx, dedi_vcc_net, cell, port_name);
+ cell->disconnectPort(port_name);
+ cell->connectPort(port_name, dedi_vcc_net);
continue;
}
- disconnect_port(ctx, cell, port_name);
+ cell->disconnectPort(port_name);
ctx->set_cell_pinmux(cell, port_name, req_mux);
} else if (port.second.net == nullptr) {
// If the port is disconnected; and there is no hard constant
// then we need to connect it to the relevant soft-constant net
- connect_port(ctx, (req_mux == PINMUX_1) ? vcc_net : gnd_net, cell, port_name);
+ cell->connectPort(port_name, (req_mux == PINMUX_1) ? vcc_net : gnd_net);
}
}
}
@@ -486,7 +486,7 @@ struct NexusPacker
if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_iobuf")) {
// Might have an input buffer (IB etc) connected to it
is_npnr_iob = true;
- NetInfo *o = get_net_or_empty(ci, id_O);
+ NetInfo *o = ci->getPort(id_O);
if (o == nullptr)
;
else if (o->users.size() > 1)
@@ -497,7 +497,7 @@ struct NexusPacker
if (ci->type == ctx->id("$nextpnr_obuf") || ci->type == ctx->id("$nextpnr_iobuf")) {
// Might have an output buffer (OB etc) connected to it
is_npnr_iob = true;
- NetInfo *i = get_net_or_empty(ci, id_I);
+ NetInfo *i = ci->getPort(id_I);
if (i != nullptr && i->driver.cell != nullptr) {
if (top_port.cell != nullptr)
log_error("Top level pin '%s' has multiple input/output buffers\n", ctx->nameOf(port.first));
@@ -534,8 +534,8 @@ struct NexusPacker
port.second.net = top_port.cell->ports.at(top_port.port).net;
}
// Now remove the nextpnr-inserted buffer
- disconnect_port(ctx, ci, id_I);
- disconnect_port(ctx, ci, id_O);
+ ci->disconnectPort(id_I);
+ ci->disconnectPort(id_O);
ctx->cells.erase(port.first);
}
}
@@ -635,13 +635,13 @@ struct NexusPacker
// For non-bidirectional IO, we also need to configure tristate and rename B
if (ci->type == id_IB) {
ctx->set_cell_pinmux(ci, id_T, PINMUX_1);
- rename_port(ctx, ci, id_I, id_B);
+ ci->renamePort(id_I, id_B);
} else if (ci->type == id_OB) {
ctx->set_cell_pinmux(ci, id_T, PINMUX_0);
- rename_port(ctx, ci, id_O, id_B);
+ ci->renamePort(id_O, id_B);
} else if (ci->type == id_OBZ) {
ctx->set_cell_pinmux(ci, id_T, PINMUX_SIG);
- rename_port(ctx, ci, id_O, id_B);
+ ci->renamePort(id_O, id_B);
}
// Get the IO bel
BelId bel = get_bel_attr(ci);
@@ -760,7 +760,7 @@ struct NexusPacker
if (cell->attrs.count(id_BEL))
return false;
- NetInfo *pin_net = get_net_or_empty(cell, pin);
+ NetInfo *pin_net = cell->getPort(pin);
if (pin_net == nullptr)
return false;
@@ -827,7 +827,7 @@ struct NexusPacker
buffer->addInput(i);
buffer->addOutput(o);
// Drive the buffered net with the buffer
- connect_port(ctx, buffered_net, buffer, o);
+ buffer->connectPort(o, buffered_net);
// Filter users
std::vector<PortRef> remaining_users;
@@ -843,7 +843,7 @@ struct NexusPacker
std::swap(net->users, remaining_users);
// Connect buffer input to original net
- connect_port(ctx, net, buffer, i);
+ buffer->connectPort(i, net);
return buffer;
}
@@ -936,56 +936,56 @@ struct NexusPacker
combs.push_back(
ctx->createCell(ctx->id(stringf("%s$lutram_comb[%d]$", ctx->nameOf(ci), i)), id_OXIDE_COMB));
// Rewiring - external WCK and WRE
- replace_port(ci, id_WCK, ramw, id_CLK);
- replace_port(ci, id_WRE, ramw, id_LSR);
+ ci->movePortTo(id_WCK, ramw, id_CLK);
+ ci->movePortTo(id_WRE, ramw, id_LSR);
// Internal WCK and WRE signals
ramw->addOutput(id_WCKO);
ramw->addOutput(id_WREO);
NetInfo *int_wck = ctx->createNet(ctx->id(stringf("%s$lutram_wck$", ctx->nameOf(ci))));
NetInfo *int_wre = ctx->createNet(ctx->id(stringf("%s$lutram_wre$", ctx->nameOf(ci))));
- connect_port(ctx, int_wck, ramw, id_WCKO);
- connect_port(ctx, int_wre, ramw, id_WREO);
+ ramw->connectPort(id_WCKO, int_wck);
+ ramw->connectPort(id_WREO, int_wre);
uint64_t initval = ctx->parse_lattice_param(ci, id_INITVAL, 64, 0).as_int64();
// Rewiring - buses
for (int i = 0; i < 4; i++) {
// Write address - external
- replace_port(ci, bus("WAD", i), ramw, ramw_wado[i]);
+ ci->movePortTo(bus("WAD", i), ramw, ramw_wado[i]);
// Write data - external
- replace_port(ci, bus("DI", i), ramw, ramw_wdo[i]);
+ ci->movePortTo(bus("DI", i), ramw, ramw_wdo[i]);
// Read data
- replace_port(ci, bus("DO", i), combs[i], id_F);
+ ci->movePortTo(bus("DO", i), combs[i], id_F);
// Read address
- NetInfo *rad = get_net_or_empty(ci, bus("RAD", i));
+ NetInfo *rad = ci->getPort(bus("RAD", i));
if (rad != nullptr) {
for (int j = 0; j < 4; j++) {
IdString port = (j % 2) ? comb1_rad[i] : comb0_rad[i];
combs[j]->addInput(port);
- connect_port(ctx, rad, combs[j], port);
+ combs[j]->connectPort(port, rad);
}
- disconnect_port(ctx, ci, bus("RAD", i));
+ ci->disconnectPort(bus("RAD", i));
}
// Write address - internal
NetInfo *int_wad = ctx->createNet(ctx->id(stringf("%s$lutram_wad[%d]$", ctx->nameOf(ci), i)));
ramw->addOutput(bus_flat("WADO", i));
- connect_port(ctx, int_wad, ramw, bus_flat("WADO", i));
+ ramw->connectPort(bus_flat("WADO", i), int_wad);
for (int j = 0; j < 4; j++) {
combs[j]->addInput(bus_flat("WAD", i));
- connect_port(ctx, int_wad, combs[j], bus_flat("WAD", i));
+ combs[j]->connectPort(bus_flat("WAD", i), int_wad);
}
// Write data - internal
NetInfo *int_wd = ctx->createNet(ctx->id(stringf("%s$lutram_wd[%d]$", ctx->nameOf(ci), i)));
ramw->addOutput(bus_flat("WDO", i));
- connect_port(ctx, int_wd, ramw, bus_flat("WDO", i));
+ ramw->connectPort(bus_flat("WDO", i), int_wd);
combs[i]->addInput(id_WDI);
- connect_port(ctx, int_wd, combs[i], id_WDI);
+ combs[i]->connectPort(id_WDI, int_wd);
// Write clock and enable - internal
combs[i]->addInput(id_WCK);
combs[i]->addInput(id_WRE);
- connect_port(ctx, int_wck, combs[i], id_WCK);
- connect_port(ctx, int_wre, combs[i], id_WRE);
+ combs[i]->connectPort(id_WCK, int_wck);
+ combs[i]->connectPort(id_WRE, int_wre);
// Remap init val
uint64_t split_init = 0;
for (int j = 0; j < 16; j++)
@@ -1178,7 +1178,7 @@ struct NexusPacker
base->params[param.first] = param.second;
}
for (auto &port : mergee->ports) {
- replace_port(mergee, port.first, base, port.first);
+ mergee->movePortTo(port.first, base, port.first);
}
ctx->cells.erase(mergee->name);
}
@@ -1191,13 +1191,13 @@ struct NexusPacker
if (ci->type != id_IOLOGIC)
continue;
CellInfo *iob = nullptr;
- NetInfo *di = get_net_or_empty(ci, id_DI);
+ NetInfo *di = ci->getPort(id_DI);
if (di != nullptr && di->driver.cell != nullptr)
iob = di->driver.cell;
- NetInfo *dout = get_net_or_empty(ci, id_DOUT);
+ NetInfo *dout = ci->getPort(id_DOUT);
if (dout != nullptr && dout->users.size() == 1)
iob = dout->users.at(0).cell;
- NetInfo *tout = get_net_or_empty(ci, id_TOUT);
+ NetInfo *tout = ci->getPort(id_TOUT);
if (tout != nullptr && tout->users.size() == 1)
iob = tout->users.at(0).cell;
if (iob == nullptr ||
@@ -1251,20 +1251,20 @@ struct NexusPacker
ctx->createCell(ctx->id(stringf("%s$widefn_comb[%d]$", ctx->nameOf(ci), i)), id_OXIDE_COMB));
for (int i = 0; i < 2; i++) {
- replace_port(ci, bus_flat("A", i), combs[i], id_A);
- replace_port(ci, bus_flat("B", i), combs[i], id_B);
- replace_port(ci, bus_flat("C", i), combs[i], id_C);
- replace_port(ci, bus_flat("D", i), combs[i], id_D);
+ ci->movePortTo(bus_flat("A", i), combs[i], id_A);
+ ci->movePortTo(bus_flat("B", i), combs[i], id_B);
+ ci->movePortTo(bus_flat("C", i), combs[i], id_C);
+ ci->movePortTo(bus_flat("D", i), combs[i], id_D);
}
- replace_port(ci, id_SEL, combs[0], id_SEL);
- replace_port(ci, id_Z, combs[0], id_OFX);
+ ci->movePortTo(id_SEL, combs[0], id_SEL);
+ ci->movePortTo(id_Z, combs[0], id_OFX);
NetInfo *f1 = ctx->createNet(ctx->id(stringf("%s$widefn_f1$", ctx->nameOf(ci))));
combs[0]->addInput(id_F1);
combs[1]->addOutput(id_F);
- connect_port(ctx, f1, combs[1], id_F);
- connect_port(ctx, f1, combs[0], id_F1);
+ combs[1]->connectPort(id_F, f1);
+ combs[0]->connectPort(id_F1, f1);
combs[0]->params[id_INIT] = ctx->parse_lattice_param(ci, id_INIT0, 16, 0);
combs[1]->params[id_INIT] = ctx->parse_lattice_param(ci, id_INIT1, 16, 0);
@@ -1290,7 +1290,7 @@ struct NexusPacker
CellInfo *ci = cell.second.get();
if (ci->type != id_CCU2)
continue;
- if (get_net_or_empty(ci, id_CIN) != nullptr)
+ if (ci->getPort(id_CIN) != nullptr)
continue;
roots.push_back(ci);
}
@@ -1309,16 +1309,16 @@ struct NexusPacker
// Rewire LUT ports
for (int i = 0; i < 2; i++) {
combs[i]->params[id_MODE] = std::string("CCU2");
- replace_port(ci, bus_flat("A", i), combs[i], id_A);
- replace_port(ci, bus_flat("B", i), combs[i], id_B);
- replace_port(ci, bus_flat("C", i), combs[i], id_C);
- replace_port(ci, bus_flat("D", i), combs[i], id_D);
- replace_port(ci, bus_flat("S", i), combs[i], id_F);
+ ci->movePortTo(bus_flat("A", i), combs[i], id_A);
+ ci->movePortTo(bus_flat("B", i), combs[i], id_B);
+ ci->movePortTo(bus_flat("C", i), combs[i], id_C);
+ ci->movePortTo(bus_flat("D", i), combs[i], id_D);
+ ci->movePortTo(bus_flat("S", i), combs[i], id_F);
}
// External carry chain
- replace_port(ci, id_CIN, combs[0], id_FCI);
- replace_port(ci, id_COUT, combs[1], id_FCO);
+ ci->movePortTo(id_CIN, combs[0], id_FCI);
+ ci->movePortTo(id_COUT, combs[1], id_FCO);
// Copy parameters
if (ci->params.count(id_INJECT))
@@ -1330,8 +1330,8 @@ struct NexusPacker
NetInfo *int_cy = ctx->createNet(ctx->id(stringf("%s$widefn_int_cy$", ctx->nameOf(ci))));
combs[0]->addOutput(id_FCO);
combs[1]->addInput(id_FCI);
- connect_port(ctx, int_cy, combs[0], id_FCO);
- connect_port(ctx, int_cy, combs[1], id_FCI);
+ combs[0]->connectPort(id_FCO, int_cy);
+ combs[1]->connectPort(id_FCI, int_cy);
// Relative constraints
for (int i = 0; i < 2; i++) {
@@ -1355,7 +1355,7 @@ struct NexusPacker
ctx->cells.erase(ci->name);
// Find next cell in chain, if it exists
- NetInfo *fco = get_net_or_empty(combs[1], id_FCO);
+ NetInfo *fco = combs[1]->getPort(id_FCO);
ci = nullptr;
if (fco != nullptr) {
if (fco->users.size() > 1)
@@ -1443,13 +1443,13 @@ struct NexusPacker
continue;
// Skip pins that are already in use
- if (get_net_or_empty(other_cell, bp.pin) != nullptr)
+ if (other_cell->getPort(bp.pin) != nullptr)
continue;
// Create the input if it doesn't exist
if (!other_cell->ports.count(bp.pin))
other_cell->addInput(bp.pin);
// Make the connection
- connect_ports(ctx, cell, port.first, other_cell, bp.pin);
+ cell->connectPorts(port.first, other_cell, bp.pin);
if (ctx->debug)
log_info(" found %s.%s\n", ctx->nameOf(other_cell), ctx->nameOf(bp.pin));
@@ -1729,31 +1729,31 @@ struct NexusPacker
if (mt.wide > 0) {
// Dot-product mode special case
- copy_bus(ctx, ci, ctx->id(stringf("B%d", (i * 9) / mt.wide)), (i * 9) % mt.wide, true, preadd9[i],
- id_B, 0, false, 9);
- copy_bus(ctx, ci, ctx->id(stringf("A%d", (i * 9) / mt.wide)), (i * 9) % mt.wide, true, mult9[i],
- id_A, 0, false, 9);
- copy_port(ctx, ci, id_CLK, mult9[i], id_CLK);
- copy_port(ctx, ci, (i > 1) ? id_CEA2A3 : id_CEA0A1, mult9[i], id_CEA);
- copy_port(ctx, ci, (i > 1) ? id_RSTA2A3 : id_RSTA0A1, mult9[i], id_RSTA);
- copy_port(ctx, ci, id_CLK, preadd9[i], id_CLK);
- copy_port(ctx, ci, (i > 1) ? id_CEB2B3 : id_CEB0B1, preadd9[i], id_CEB);
- copy_port(ctx, ci, (i > 1) ? id_RSTB2B3 : id_RSTB0B1, preadd9[i], id_RSTB);
+ ci->copyPortBusTo(ctx->id(stringf("B%d", (i * 9) / mt.wide)), (i * 9) % mt.wide, true, preadd9[i],
+ id_B, 0, false, 9);
+ ci->copyPortBusTo(ctx->id(stringf("A%d", (i * 9) / mt.wide)), (i * 9) % mt.wide, true, mult9[i],
+ id_A, 0, false, 9);
+ ci->copyPortTo(id_CLK, mult9[i], id_CLK);
+ ci->copyPortTo((i > 1) ? id_CEA2A3 : id_CEA0A1, mult9[i], id_CEA);
+ ci->copyPortTo((i > 1) ? id_RSTA2A3 : id_RSTA0A1, mult9[i], id_RSTA);
+ ci->copyPortTo(id_CLK, preadd9[i], id_CLK);
+ ci->copyPortTo((i > 1) ? id_CEB2B3 : id_CEB0B1, preadd9[i], id_CEB);
+ ci->copyPortTo((i > 1) ? id_RSTB2B3 : id_RSTB0B1, preadd9[i], id_RSTB);
// Copy register configuration
copy_param(ci, ctx->id(stringf("REGINPUTAB%d", i)), mult9[i], id_REGBYPSA1);
copy_param(ci, ctx->id(stringf("REGINPUTAB%d", i)), preadd9[i], id_REGBYPSBR0);
} else {
// B input split across pre-adders
- copy_bus(ctx, ci, id_B, b_start, true, preadd9[i], id_B, 0, false, 9);
+ ci->copyPortBusTo(id_B, b_start, true, preadd9[i], id_B, 0, false, 9);
// A input split across MULT9s
- copy_bus(ctx, ci, id_A, a_start, true, mult9[i], id_A, 0, false, 9);
+ ci->copyPortBusTo(id_A, a_start, true, mult9[i], id_A, 0, false, 9);
// Connect control set signals
- copy_port(ctx, ci, id_CLK, mult9[i], id_CLK);
- copy_port(ctx, ci, id_CEA, mult9[i], id_CEA);
- copy_port(ctx, ci, id_RSTA, mult9[i], id_RSTA);
- copy_port(ctx, ci, id_CLK, preadd9[i], id_CLK);
- copy_port(ctx, ci, id_CEB, preadd9[i], id_CEB);
- copy_port(ctx, ci, id_RSTB, preadd9[i], id_RSTB);
+ ci->copyPortTo(id_CLK, mult9[i], id_CLK);
+ ci->copyPortTo(id_CEA, mult9[i], id_CEA);
+ ci->copyPortTo(id_RSTA, mult9[i], id_RSTA);
+ ci->copyPortTo(id_CLK, preadd9[i], id_CLK);
+ ci->copyPortTo(id_CEB, preadd9[i], id_CEB);
+ ci->copyPortTo(id_RSTB, preadd9[i], id_RSTB);
// Copy register configuration
copy_param(ci, id_REGINPUTA, mult9[i], id_REGBYPSA1);
copy_param(ci, id_REGINPUTB, preadd9[i], id_REGBYPSBR0);
@@ -1761,12 +1761,12 @@ struct NexusPacker
// Connect and configure pre-adder if it isn't bypassed
if (mt.has_preadd) {
- copy_bus(ctx, ci, id_C, 9 * i, true, preadd9[i], id_C, 0, false, 9);
+ ci->copyPortBusTo(id_C, 9 * i, true, preadd9[i], id_C, 0, false, 9);
if (i == (mt.N9x9 - 1))
- copy_port(ctx, ci, id_SIGNEDC, preadd9[i], id_C9);
+ ci->copyPortTo(id_SIGNEDC, preadd9[i], id_C9);
copy_param(ci, id_REGINPUTC, preadd9[i], id_REGBYPSBL);
- copy_port(ctx, ci, id_CEC, preadd9[i], id_CECL);
- copy_port(ctx, ci, id_RSTC, preadd9[i], id_RSTCL);
+ ci->copyPortTo(id_CEC, preadd9[i], id_CECL);
+ ci->copyPortTo(id_RSTC, preadd9[i], id_RSTCL);
// Enable preadder
preadd9[i]->params[id_BYPASS_PREADD9] = std::string("USED");
preadd9[i]->params[id_OPC] = std::string("INPUT_C_AS_PREADDER_OPERAND");
@@ -1774,14 +1774,14 @@ struct NexusPacker
preadd9[i]->params[id_PREADDCAS_EN] = std::string("ENABLED");
} else if (mt.has_addsub) {
// Connect only for routeability reasons
- copy_bus(ctx, ci, id_C, 10 * i + ((i >= 4) ? 14 : 0), true, preadd9[i], id_C, 0, false, 10);
+ ci->copyPortBusTo(id_C, 10 * i + ((i >= 4) ? 14 : 0), true, preadd9[i], id_C, 0, false, 10);
}
// Connect up signedness for the most significant nonet
if (((b_start + 9) == mt.b_width) || (mt.wide > 0))
- copy_port(ctx, ci, mt.has_addsub ? id_SIGNED : id_SIGNEDB, preadd9[i], id_BSIGNED);
+ ci->copyPortTo(mt.has_addsub ? id_SIGNED : id_SIGNEDB, preadd9[i], id_BSIGNED);
if (((a_start + 9) == mt.a_width) || (mt.wide > 0))
- copy_port(ctx, ci, mt.has_addsub ? id_SIGNED : id_SIGNEDA, mult9[i], id_ASIGNED);
+ ci->copyPortTo(mt.has_addsub ? id_SIGNED : id_SIGNEDA, mult9[i], id_ASIGNED);
}
bool mult36_used = (mt.a_width >= 36) && (mt.b_width >= 36) && !(mt.wide > 0);
@@ -1800,11 +1800,11 @@ struct NexusPacker
for (int i = 0; i < Nreg18; i++) {
// Output split across reg18s
if (!mt.has_addsub)
- replace_bus(ctx, ci, id_Z, i * 18, true, reg18[i], id_PP, 0, false, 18);
+ ci->movePortBusTo(id_Z, i * 18, true, reg18[i], id_PP, 0, false, 18);
// Connect control set signals
- copy_port(ctx, ci, id_CLK, reg18[i], id_CLK);
- copy_port(ctx, ci, mt.has_addsub ? id_CEPIPE : id_CEOUT, reg18[i], id_CEP);
- copy_port(ctx, ci, mt.has_addsub ? id_RSTPIPE : id_RSTOUT, reg18[i], id_RSTP);
+ ci->copyPortTo(id_CLK, reg18[i], id_CLK);
+ ci->copyPortTo(mt.has_addsub ? id_CEPIPE : id_CEOUT, reg18[i], id_CEP);
+ ci->copyPortTo(mt.has_addsub ? id_RSTPIPE : id_RSTOUT, reg18[i], id_RSTP);
// Copy register configuration
copy_param(ci, mt.has_addsub ? id_REGPIPELINE : id_REGOUTPUT, reg18[i], id_REGBYPS);
}
@@ -1817,35 +1817,35 @@ struct NexusPacker
acc54[i] = create_dsp_cell(ci->name, id_ACC54_CORE, preadd9[0], (i * 4) + 2, 5);
for (int i = 0; i < Nacc54; i++) {
// C addsub input
- copy_bus(ctx, ci, id_C, 54 * i, true, acc54[i], id_CINPUT, 0, false, 54);
+ ci->copyPortBusTo(id_C, 54 * i, true, acc54[i], id_CINPUT, 0, false, 54);
// Output
- replace_bus(ctx, ci, id_Z, i * 54, true, acc54[i], id_SUM0, 0, false, 36);
- replace_bus(ctx, ci, id_Z, i * 54 + 36, true, acc54[i], id_SUM1, 0, false, 18);
+ ci->movePortBusTo(id_Z, i * 54, true, acc54[i], id_SUM0, 0, false, 36);
+ ci->movePortBusTo(id_Z, i * 54 + 36, true, acc54[i], id_SUM1, 0, false, 18);
// Control set
- copy_port(ctx, ci, id_CLK, acc54[i], id_CLK);
- copy_port(ctx, ci, id_RSTCTRL, acc54[i], id_RSTCTRL);
- copy_port(ctx, ci, id_CECTRL, acc54[i], id_CECTRL);
- copy_port(ctx, ci, id_RSTCIN, acc54[i], id_RSTCIN);
- copy_port(ctx, ci, id_CECIN, acc54[i], id_CECIN);
- copy_port(ctx, ci, id_RSTOUT, acc54[i], id_RSTO);
- copy_port(ctx, ci, id_CEOUT, acc54[i], id_CEO);
- copy_port(ctx, ci, id_RSTC, acc54[i], id_RSTC);
- copy_port(ctx, ci, id_CEC, acc54[i], id_CEC);
+ ci->copyPortTo(id_CLK, acc54[i], id_CLK);
+ ci->copyPortTo(id_RSTCTRL, acc54[i], id_RSTCTRL);
+ ci->copyPortTo(id_CECTRL, acc54[i], id_CECTRL);
+ ci->copyPortTo(id_RSTCIN, acc54[i], id_RSTCIN);
+ ci->copyPortTo(id_CECIN, acc54[i], id_CECIN);
+ ci->copyPortTo(id_RSTOUT, acc54[i], id_RSTO);
+ ci->copyPortTo(id_CEOUT, acc54[i], id_CEO);
+ ci->copyPortTo(id_RSTC, acc54[i], id_RSTC);
+ ci->copyPortTo(id_CEC, acc54[i], id_CEC);
// Add/acc control
if (i == 0)
- copy_port(ctx, ci, id_CIN, acc54[i], id_CIN);
+ ci->copyPortTo(id_CIN, acc54[i], id_CIN);
else
ctx->set_cell_pinmux(acc54[i], id_CIN, PINMUX_1);
if (i == (Nacc54 - 1))
- copy_port(ctx, ci, id_SIGNED, acc54[i], id_SIGNEDI);
+ ci->copyPortTo(id_SIGNED, acc54[i], id_SIGNEDI);
if (mt.wide > 0) {
- replace_bus(ctx, ci, id_ADDSUB, 0, true, acc54[i], id_ADDSUB, 0, false, 2);
- replace_bus(ctx, ci, id_ADDSUB, 2, true, acc54[i], id_M9ADDSUB, 0, false, 2);
+ ci->movePortBusTo(id_ADDSUB, 0, true, acc54[i], id_ADDSUB, 0, false, 2);
+ ci->movePortBusTo(id_ADDSUB, 2, true, acc54[i], id_M9ADDSUB, 0, false, 2);
} else {
- copy_port(ctx, ci, id_ADDSUB, acc54[i], id_ADDSUB0);
- copy_port(ctx, ci, id_ADDSUB, acc54[i], id_ADDSUB1);
+ ci->copyPortTo(id_ADDSUB, acc54[i], id_ADDSUB0);
+ ci->copyPortTo(id_ADDSUB, acc54[i], id_ADDSUB1);
}
- copy_port(ctx, ci, id_LOADC, acc54[i], id_LOAD);
+ ci->copyPortTo(id_LOADC, acc54[i], id_LOAD);
// Configuration
copy_param(ci, id_REGINPUTC, acc54[i], id_CREGBYPS1);
copy_param(ci, id_REGADDSUB, acc54[i], id_ADDSUBSIGNREGBYPS1);
@@ -1881,7 +1881,7 @@ struct NexusPacker
for (auto cell : to_remove) {
for (auto &port : cell->ports)
- disconnect_port(ctx, cell, port.first);
+ cell->disconnectPort(port.first);
ctx->cells.erase(cell->name);
}
}
@@ -2042,9 +2042,9 @@ struct NexusPacker
CellInfo *ci = cell.second.get();
if (ci->type == id_PLL_CORE) {
// Extra log to phys rules
- rename_port(ctx, ci, id_PLLPOWERDOWN_N, id_PLLPDN);
- rename_port(ctx, ci, id_LMMIWRRD_N, id_LMMIWRRDN);
- rename_port(ctx, ci, id_LMMIRESET_N, id_LMMIRESETN);
+ ci->renamePort(id_PLLPOWERDOWN_N, id_PLLPDN);
+ ci->renamePort(id_LMMIWRRD_N, id_LMMIWRRDN);
+ ci->renamePort(id_LMMIRESET_N, id_LMMIRESETN);
for (auto &defparam : pll_defaults)
if (!ci->params.count(defparam.first))
ci->params[defparam.first] = defparam.second;
@@ -2086,7 +2086,7 @@ struct NexusPacker
{
// Get the net
- NetInfo *net = get_net_or_empty(iob, port);
+ NetInfo *net = iob->getPort(port);
if (net == nullptr) {
return nullptr;
}
@@ -2099,8 +2099,8 @@ struct NexusPacker
// Get clock nets of IOLOGIC and the flip-flop
if (iol != nullptr) {
- NetInfo *iol_c = get_net_or_empty(iol, id_SCLKOUT);
- NetInfo *ff_c = get_net_or_empty(ff, id_CLK);
+ NetInfo *iol_c = iol->getPort(id_SCLKOUT);
+ NetInfo *ff_c = ff->getPort(id_CLK);
// If one of them is floating or it is not the same net then abort
if (iol_c == nullptr || ff_c == nullptr) {
@@ -2113,8 +2113,8 @@ struct NexusPacker
// Get reset nets of IOLOGIC and the flip-flop
if (iol != nullptr) {
- NetInfo *iol_r = get_net_or_empty(iol, id_LSROUT);
- NetInfo *ff_r = get_net_or_empty(ff, id_LSR);
+ NetInfo *iol_r = iol->getPort(id_LSROUT);
+ NetInfo *ff_r = ff->getPort(id_LSR);
// If one of them is floating or it is not the same net then abort.
// But both can be floating.
@@ -2155,17 +2155,17 @@ struct NexusPacker
bool isODDR = false;
CellInfo *iob = nullptr;
- NetInfo *di = get_net_or_empty(iol, id_DI);
+ NetInfo *di = iol->getPort(id_DI);
if (di != nullptr && di->driver.cell != nullptr) {
iob = di->driver.cell;
isIDDR = true;
}
- NetInfo *dout = get_net_or_empty(iol, id_DOUT);
+ NetInfo *dout = iol->getPort(id_DOUT);
if (dout != nullptr && dout->users.size() == 1) {
iob = dout->users.at(0).cell;
isODDR = true;
}
- NetInfo *tout = get_net_or_empty(iol, id_TOUT);
+ NetInfo *tout = iol->getPort(id_TOUT);
if (tout != nullptr && tout->users.size() == 1) {
iob = tout->users.at(0).cell;
isODDR = true; // FIXME: Not sure
@@ -2205,9 +2205,9 @@ struct NexusPacker
// same ned as SEIO33_CORE.I.
//
//
- NetInfo *iob_t = get_net_or_empty(iob, id_T);
+ NetInfo *iob_t = iob->getPort(id_T);
if (iob_t != nullptr && isODDR) {
- NetInfo *iol_t = get_net_or_empty(iol, id_TOUT);
+ NetInfo *iol_t = iol->getPort(id_TOUT);
// SIOLOGIC.TOUT is not driving SEIO33_CORE.T
if ((iol_t == nullptr) || (iol_t != nullptr && iol_t->users.empty()) ||
@@ -2216,7 +2216,7 @@ struct NexusPacker
// In this case if SIOLOGIC.TSDATA0 is not connected
// to the same net as SEIO33_CORE.T and is not
// floating then that configuration is illegal.
- NetInfo *iol_ti = get_net_or_empty(iol, id_TSDATA0);
+ NetInfo *iol_ti = iol->getPort(id_TSDATA0);
if (iol_ti != nullptr && (iol_ti->name != iob_t->name) && (iol_ti->name != gnd_net->name)) {
log_error("Cannot have %s.TSDATA0 and %s.T driven by different nets (%s vs. %s)\n",
ctx->nameOf(iol), ctx->nameOf(iob), ctx->nameOf(iol_ti), ctx->nameOf(iob_t));
@@ -2227,8 +2227,8 @@ struct NexusPacker
if (!iol->ports.count(id_TSDATA0)) {
iol->addInput(id_TSDATA0);
}
- disconnect_port(ctx, iol, id_TSDATA0);
- connect_port(ctx, iob_t, iol, id_TSDATA0);
+ iol->disconnectPort(id_TSDATA0);
+ iol->connectPort(id_TSDATA0, iob_t);
if (ctx->debug) {
log_info(" Reconnecting %s.TSDATA0 to %s\n", ctx->nameOf(iol), ctx->nameOf(iob_t));
@@ -2256,10 +2256,10 @@ struct NexusPacker
for (auto &it : tff_map) {
CellInfo *ff = ctx->cells.at(it.first).get();
- NetInfo *ff_d = get_net_or_empty(ff, id_M); // FIXME: id_D or id_M ?!
+ NetInfo *ff_d = ff->getPort(id_M); // FIXME: id_D or id_M ?!
NPNR_ASSERT(ff_d != nullptr);
- NetInfo *ff_q = get_net_or_empty(ff, id_Q);
+ NetInfo *ff_q = ff->getPort(id_Q);
NPNR_ASSERT(ff_q != nullptr);
for (auto &ios : it.second) {
@@ -2269,12 +2269,12 @@ struct NexusPacker
log_info(" Integrating %s into %s\n", ctx->nameOf(ff), ctx->nameOf(iol));
// Disconnect "old" T net
- disconnect_port(ctx, iol, id_TSDATA0);
- disconnect_port(ctx, iob, id_T);
+ iol->disconnectPort(id_TSDATA0);
+ iob->disconnectPort(id_T);
// Connect the "new" one
- connect_port(ctx, ff_d, iol, id_TSDATA0);
- connect_port(ctx, ff_d, iob, id_T);
+ iol->connectPort(id_TSDATA0, ff_d);
+ iob->connectPort(id_T, ff_d);
// Propagate parameters
iol->params[id_SRMODE] = ff->params.at(id_SRMODE);
@@ -2288,7 +2288,7 @@ struct NexusPacker
// Disconnect the flip-flop
for (auto &port : ff->ports) {
- disconnect_port(ctx, ff, port.first);
+ ff->disconnectPort(port.first);
}
// Check if the flip-flop can be removed
@@ -2316,9 +2316,9 @@ struct NexusPacker
ctrlset.clkmux = ctx->id(str_or_default(cell->params, id_CLKMUX, "CLK")).index;
ctrlset.cemux = ctx->id(str_or_default(cell->params, id_CEMUX, "CE")).index;
ctrlset.lsrmux = ctx->id(str_or_default(cell->params, id_LSRMUX, "LSR")).index;
- ctrlset.clk = get_net_or_empty(cell, id_CLK);
- ctrlset.ce = get_net_or_empty(cell, id_CE);
- ctrlset.lsr = get_net_or_empty(cell, id_LSR);
+ ctrlset.clk = cell->getPort(id_CLK);
+ ctrlset.ce = cell->getPort(id_CE);
+ ctrlset.lsr = cell->getPort(id_LSR);
return ctrlset;
}
@@ -2353,7 +2353,7 @@ struct NexusPacker
// Get input net
// At the packing stage all inputs go to M
- NetInfo *di = get_net_or_empty(ff, id_M);
+ NetInfo *di = ff->getPort(id_M);
if (di == nullptr || di->driver.cell == nullptr) {
continue;
}
@@ -2373,7 +2373,7 @@ struct NexusPacker
}
// The FF must not use M and DI at the same time
- if (get_net_or_empty(ff, id_DI)) {
+ if (ff->getPort(id_DI)) {
continue;
}
@@ -2445,7 +2445,7 @@ struct NexusPacker
}
// Reconnect M to DI
- rename_port(ctx, ff, id_M, id_DI);
+ ff->renamePort(id_M, id_DI);
ff->params[id_SEL] = std::string("DL");
// Store FF settings of the cluster
@@ -2528,8 +2528,8 @@ void Arch::assignCellInfo(CellInfo *cell)
cell->lutInfo.is_memory = str_or_default(cell->params, id_MODE, "LOGIC") == "DPRAM";
cell->lutInfo.is_carry = str_or_default(cell->params, id_MODE, "LOGIC") == "CCU2";
cell->lutInfo.mux2_used = port_used(cell, id_OFX);
- cell->lutInfo.f = get_net_or_empty(cell, id_F);
- cell->lutInfo.ofx = get_net_or_empty(cell, id_OFX);
+ cell->lutInfo.f = cell->getPort(id_F);
+ cell->lutInfo.ofx = cell->getPort(id_OFX);
if (cell->lutInfo.is_carry) {
cell->tmg_portmap[id_A] = id_A0;
cell->tmg_portmap[id_B] = id_B0;
@@ -2551,11 +2551,11 @@ void Arch::assignCellInfo(CellInfo *cell)
cell->ffInfo.ctrlset.clkmux = id(str_or_default(cell->params, id_CLKMUX, "CLK")).index;
cell->ffInfo.ctrlset.cemux = id(str_or_default(cell->params, id_CEMUX, "CE")).index;
cell->ffInfo.ctrlset.lsrmux = id(str_or_default(cell->params, id_LSRMUX, "LSR")).index;
- cell->ffInfo.ctrlset.clk = get_net_or_empty(cell, id_CLK);
- cell->ffInfo.ctrlset.ce = get_net_or_empty(cell, id_CE);
- cell->ffInfo.ctrlset.lsr = get_net_or_empty(cell, id_LSR);
- cell->ffInfo.di = get_net_or_empty(cell, id_DI);
- cell->ffInfo.m = get_net_or_empty(cell, id_M);
+ cell->ffInfo.ctrlset.clk = cell->getPort(id_CLK);
+ cell->ffInfo.ctrlset.ce = cell->getPort(id_CE);
+ cell->ffInfo.ctrlset.lsr = cell->getPort(id_LSR);
+ cell->ffInfo.di = cell->getPort(id_DI);
+ cell->ffInfo.m = cell->getPort(id_M);
cell->tmg_index = get_cell_timing_idx(id_OXIDE_FF, id("PPP:SYNC"));
} else if (cell->type == id_RAMW) {
cell->ffInfo.ctrlset.async = true;
@@ -2564,9 +2564,9 @@ void Arch::assignCellInfo(CellInfo *cell)
cell->ffInfo.ctrlset.clkmux = id(str_or_default(cell->params, id_CLKMUX, "CLK")).index;
cell->ffInfo.ctrlset.cemux = ID_CE;
cell->ffInfo.ctrlset.lsrmux = ID_INV;
- cell->ffInfo.ctrlset.clk = get_net_or_empty(cell, id_CLK);
+ cell->ffInfo.ctrlset.clk = cell->getPort(id_CLK);
cell->ffInfo.ctrlset.ce = nullptr;
- cell->ffInfo.ctrlset.lsr = get_net_or_empty(cell, id_LSR);
+ cell->ffInfo.ctrlset.lsr = cell->getPort(id_LSR);
cell->ffInfo.di = nullptr;
cell->ffInfo.m = nullptr;
cell->tmg_index = get_cell_timing_idx(id_RAMW);
diff --git a/nexus/post_place.cc b/nexus/post_place.cc
index f42c0f18..289f82b2 100644
--- a/nexus/post_place.cc
+++ b/nexus/post_place.cc
@@ -94,12 +94,12 @@ struct NexusPostPlaceOpt
if (ff->type != id_OXIDE_FF)
continue;
// Check M ('fabric') input net
- NetInfo *m = get_net_or_empty(ff, id_M);
+ NetInfo *m = ff->getPort(id_M);
if (m == nullptr)
continue;
// Ignore FFs that need both DI and M (PRLD mode)
- if (get_net_or_empty(ff, id_DI) != nullptr)
+ if (ff->getPort(id_DI) != nullptr)
continue;
const auto &drv = m->driver;
@@ -118,7 +118,7 @@ struct NexusPostPlaceOpt
if (dest_ff != ff->bel) {
// If dest_ff is already placed *and* using direct 'DI' input, don't touch it
CellInfo *dest_ff_cell = ctx->getBoundBelCell(dest_ff);
- if (dest_ff_cell != nullptr && get_net_or_empty(dest_ff_cell, id_DI) != nullptr)
+ if (dest_ff_cell != nullptr && dest_ff_cell->getPort(id_DI) != nullptr)
continue;
// Attempt the swap
bool swap_result = swap_cell_placement(ff, dest_ff);
@@ -126,7 +126,7 @@ struct NexusPostPlaceOpt
continue;
}
// Use direct interconnect
- rename_port(ctx, ff, id_M, id_DI);
+ ff->renamePort(id_M, id_DI);
ff->params[id_SEL] = std::string("DL");
++moves_made;
continue;