aboutsummaryrefslogtreecommitdiffstats
path: root/ice40/pack.cc
diff options
context:
space:
mode:
authorDavid Shah <davey1576@gmail.com>2018-06-13 10:50:05 +0200
committerDavid Shah <davey1576@gmail.com>2018-06-13 10:50:05 +0200
commita76f5c5678980c8b2e958252a68ba03676d63229 (patch)
treea9f32a39a91164b36ca55d567baf177bbaece1cc /ice40/pack.cc
parentddf549b117987c1e52412b58531c48a6050b51d1 (diff)
downloadnextpnr-a76f5c5678980c8b2e958252a68ba03676d63229.tar.gz
nextpnr-a76f5c5678980c8b2e958252a68ba03676d63229.tar.bz2
nextpnr-a76f5c5678980c8b2e958252a68ba03676d63229.zip
Remove IO buffers when fed by SB_IO
Signed-off-by: David Shah <davey1576@gmail.com>
Diffstat (limited to 'ice40/pack.cc')
-rw-r--r--ice40/pack.cc59
1 files changed, 59 insertions, 0 deletions
diff --git a/ice40/pack.cc b/ice40/pack.cc
index 8f770a07..73ba0e3d 100644
--- a/ice40/pack.cc
+++ b/ice40/pack.cc
@@ -134,10 +134,69 @@ static void pack_constants(Design *design)
}
}
+static bool is_nextpnr_iob(CellInfo *cell)
+{
+ return cell->type == "$nextpnr_ibuf" || cell->type == "$nextpnr_obuf" ||
+ cell->type == "$nextpnr_iobuf";
+}
+
+// Pack IO buffers
+static void pack_io(Design *design)
+{
+ std::unordered_set<IdString> packed_cells;
+ std::vector<CellInfo *> new_cells;
+
+ for (auto cell : design->cells) {
+ CellInfo *ci = cell.second;
+ if (is_nextpnr_iob(ci)) {
+ if (ci->type == "$nextpnr_ibuf" || ci->type == "$nextpnr_iobuf") {
+ CellInfo *sb = net_only_drives(ci->ports.at("O").net, is_sb_io,
+ "PACKAGE_PIN", true, ci);
+ if (sb != nullptr) {
+ // Trivial case, SB_IO used. Just destroy the net and the
+ // iobuf
+ packed_cells.insert(ci->name);
+ log_info("%s feeds SB_IO %s, removing %s %s.\n",
+ ci->name.c_str(), sb->name.c_str(),
+ ci->type.c_str(), ci->name.c_str());
+ NetInfo *net = sb->ports.at("PACKAGE_PIN").net;
+ if (net != nullptr) {
+ design->nets.erase(net->name);
+ sb->ports.at("PACKAGE_PIN").net = nullptr;
+ }
+ }
+ } else if (ci->type == "$nextpnr_obuf") {
+ CellInfo *sb = net_only_drives(ci->ports.at("I").net, is_sb_io,
+ "PACKAGE_PIN", true, ci);
+ if (sb != nullptr) {
+ // Trivial case, SB_IO used. Just destroy the net and the
+ // iobuf
+ packed_cells.insert(ci->name);
+ log_info("%s feeds SB_IO %s, removing %s %s.\n",
+ ci->name.c_str(), sb->name.c_str(),
+ ci->type.c_str(), ci->name.c_str());
+ NetInfo *net = sb->ports.at("PACKAGE_PIN").net;
+ if (net != nullptr) {
+ design->nets.erase(net->name);
+ sb->ports.at("PACKAGE_PIN").net = nullptr;
+ }
+ }
+ }
+ }
+ }
+ for (auto pcell : packed_cells) {
+ design->cells.erase(pcell);
+ }
+ for (auto ncell : new_cells) {
+ design->cells[ncell->name] = ncell;
+ }
+}
+
// Main pack function
void pack_design(Design *design)
{
pack_constants(design);
+ pack_io(design);
pack_lut_lutffs(design);
pack_nonlut_ffs(design);
}