From 6a32aca4ac8705b637943c236cedd2f36422fb21 Mon Sep 17 00:00:00 2001 From: gatecat Date: Fri, 18 Feb 2022 10:52:37 +0000 Subject: refactor: New member functions to replace design_utils Signed-off-by: gatecat --- common/nextpnr_types.cc | 133 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) (limited to 'common/nextpnr_types.cc') 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 -- cgit v1.2.3