aboutsummaryrefslogtreecommitdiffstats
path: root/common/nextpnr_types.cc
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2022-02-18 10:52:37 +0000
committergatecat <gatecat@ds0.me>2022-02-18 11:13:18 +0000
commit6a32aca4ac8705b637943c236cedd2f36422fb21 (patch)
tree28483964fb3c92bc104ab6162d1c9196651ced26 /common/nextpnr_types.cc
parent61d1db16be2c68cf6ae8b4d2ff3266b5c7086ad2 (diff)
downloadnextpnr-6a32aca4ac8705b637943c236cedd2f36422fb21.tar.gz
nextpnr-6a32aca4ac8705b637943c236cedd2f36422fb21.tar.bz2
nextpnr-6a32aca4ac8705b637943c236cedd2f36422fb21.zip
refactor: New member functions to replace design_utils
Signed-off-by: gatecat <gatecat@ds0.me>
Diffstat (limited to 'common/nextpnr_types.cc')
-rw-r--r--common/nextpnr_types.cc133
1 files changed, 133 insertions, 0 deletions
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