diff options
author | Sergiusz Bazanski <q3k@q3k.org> | 2018-07-23 22:13:10 +0100 |
---|---|---|
committer | Sergiusz Bazanski <q3k@q3k.org> | 2018-07-24 02:55:40 +0100 |
commit | e6c7b1446580c92e9581593c78dd21753b409606 (patch) | |
tree | 700900c07ea9b4934123cb56a99d433a2f0b5ea2 /ice40/arch.cc | |
parent | 69233385f875d01a36e36924d3099175e7544b4e (diff) | |
download | nextpnr-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.cc | 50 |
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 |