aboutsummaryrefslogtreecommitdiffstats
path: root/ice40/arch.cc
diff options
context:
space:
mode:
authorSergiusz Bazanski <q3k@q3k.org>2018-07-23 22:13:10 +0100
committerSergiusz Bazanski <q3k@q3k.org>2018-07-24 02:55:40 +0100
commite6c7b1446580c92e9581593c78dd21753b409606 (patch)
tree700900c07ea9b4934123cb56a99d433a2f0b5ea2 /ice40/arch.cc
parent69233385f875d01a36e36924d3099175e7544b4e (diff)
downloadnextpnr-e6c7b1446580c92e9581593c78dd21753b409606.tar.gz
nextpnr-e6c7b1446580c92e9581593c78dd21753b409606.tar.bz2
nextpnr-e6c7b1446580c92e9581593c78dd21753b409606.zip
ice40: Refactor PLL/LOCK LUT splicing out into Arch::
Diffstat (limited to 'ice40/arch.cc')
-rw-r--r--ice40/arch.cc50
1 files changed, 50 insertions, 0 deletions
diff --git a/ice40/arch.cc b/ice40/arch.cc
index d6ef800d..6679217a 100644
--- a/ice40/arch.cc
+++ b/ice40/arch.cc
@@ -2,6 +2,7 @@
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com>
+ * Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -805,4 +806,53 @@ void Arch::assignCellInfo(CellInfo *cell)
}
}
+std::unique_ptr<CellInfo> Arch::spliceLUT(CellInfo *ci, IdString portId, bool onlyNonLUTs)
+{
+ auto port = ci->ports[portId];
+
+ NPNR_ASSERT(port.net != nullptr);
+
+
+ // Create pass-through LUT.
+ std::unique_ptr<CellInfo> pt =
+ create_ice_cell(getCtx(), id("ICESTORM_LC"), ci->name.str(this) + "$nextpnr_ice40_pack_pll_lc");
+ pt->params[id("LUT_INIT")] = "255"; // output is always I3
+
+ // Create LUT output net.
+ std::unique_ptr<NetInfo> out_net = std::unique_ptr<NetInfo>(new NetInfo);
+ out_net->name = id(ci->name.str(this) + "$nextnr_ice40_pack_pll_net");
+ out_net->driver.cell = pt.get();
+ out_net->driver.port = id("O");
+ pt->ports.at(id("O")).net = out_net.get();
+
+ // New users of the original cell's port
+ std::vector<PortRef> new_users;
+ for (const auto &user : port.net->users) {
+ if (onlyNonLUTs && user.cell->type == id("ICESTORM_LC")) {
+ new_users.push_back(user);
+ continue;
+ }
+ // Rewrite pointer into net in user.
+ user.cell->ports[user.port].net = out_net.get();
+ // Add user to net.
+ PortRef pr;
+ pr.cell = user.cell;
+ pr.port = user.port;
+ out_net->users.push_back(pr);
+ }
+
+ // Add LUT to new users.
+ PortRef pr;
+ pr.cell = pt.get();
+ pr.port = id("I3");
+ new_users.push_back(pr);
+ pt->ports.at(id("I3")).net = port.net;
+
+ // Replace users of the original net.
+ port.net->users = new_users;
+
+ nets[out_net->name] = std::move(out_net);
+ return pt;
+}
+
NEXTPNR_NAMESPACE_END