diff options
author | David Shah <davey1576@gmail.com> | 2018-06-13 15:10:42 +0200 |
---|---|---|
committer | David Shah <davey1576@gmail.com> | 2018-06-13 15:10:42 +0200 |
commit | 14b5e46b5df76973dccd26bb07dc12c26e5d6efc (patch) | |
tree | dfdef863b1e195fc0dd660663ca9d0088081f723 | |
parent | d80e60cce210b58c036003f6812eb876c632d19e (diff) | |
download | nextpnr-14b5e46b5df76973dccd26bb07dc12c26e5d6efc.tar.gz nextpnr-14b5e46b5df76973dccd26bb07dc12c26e5d6efc.tar.bz2 nextpnr-14b5e46b5df76973dccd26bb07dc12c26e5d6efc.zip |
ice40: Promote one clock to a global buffer
Signed-off-by: David Shah <davey1576@gmail.com>
-rw-r--r-- | ice40/cells.cc | 8 | ||||
-rw-r--r-- | ice40/cells.h | 6 | ||||
-rw-r--r-- | ice40/pack.cc | 48 |
3 files changed, 61 insertions, 1 deletions
diff --git a/ice40/cells.cc b/ice40/cells.cc index b038db68..604baccb 100644 --- a/ice40/cells.cc +++ b/ice40/cells.cc @@ -79,7 +79,9 @@ CellInfo *create_ice_cell(Design *design, IdString type, IdString name) add_port(new_cell, "D_IN_0", PORT_OUT); add_port(new_cell, "D_IN_1", PORT_OUT); - + } else if (type == "SB_GB") { + add_port(new_cell, "USER_SIGNAL_TO_GLOBAL_BUFFER", PORT_IN); + add_port(new_cell, "GLOBAL_BUFFER_OUTPUT", PORT_OUT); } else { log_error("unable to create iCE40 cell of type %s", type.c_str()); } @@ -164,4 +166,8 @@ void nxio_to_sb(CellInfo *nxio, CellInfo *sbio) } } +bool is_global_net(NetInfo *net) { + return bool(net_driven_by(net, is_gbuf, "GLOBAL_BUFFER_OUTPUT")); +} + NEXTPNR_NAMESPACE_END diff --git a/ice40/cells.h b/ice40/cells.h index 3cf0b718..660c7265 100644 --- a/ice40/cells.h +++ b/ice40/cells.h @@ -50,6 +50,9 @@ inline bool is_ff(const CellInfo *cell) // Return true if a cell is a SB_IO inline bool is_sb_io(const CellInfo *cell) { return cell->type == "SB_IO"; } +// Return true if a cell is a global buffer +inline bool is_gbuf(const CellInfo *cell) {return cell->type == "SB_GB"; } + // Convert a SB_LUT primitive to (part of) an ICESTORM_LC, swapping ports // as needed. Set no_dff if a DFF is not being used, so that the output // can be reconnected @@ -64,6 +67,9 @@ void dff_to_lc(CellInfo *dff, CellInfo *lc, bool pass_thru_lut = false); // Convert a nextpnr IO buffer to a SB_IO void nxio_to_sb(CellInfo *nxio, CellInfo *sbio); +// Return true if a net is a global net +bool is_global_net(NetInfo *net); + NEXTPNR_NAMESPACE_END #endif diff --git a/ice40/pack.cc b/ice40/pack.cc index 49c95ad6..e8876283 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -222,10 +222,58 @@ static void pack_io(Design *design) } } +// Simple global promoter (clock only) +static void promote_globals(Design *design) +{ + std::unordered_map<IdString, int> clock_count; + for (auto net : design->nets) { + NetInfo *ni = net.second; + if (ni->driver.cell != nullptr && !is_global_net(ni)) { + clock_count[net.first] = 0; + for (auto user : ni->users) { + if (user.cell != nullptr && is_ff(user.cell) && user.port == "C") + clock_count[net.first]++; + } + } + } + auto global_clock = std::max_element(clock_count.begin(), clock_count.end(), []( + const std::pair<IdString, int> &a, const std::pair<IdString, int> &b) { + return a.second < b.second; + }); + if (global_clock->second > 0) { + NetInfo *clknet = design->nets[global_clock->first]; + CellInfo *gb = create_ice_cell(design, "SB_GB"); + gb->ports["USER_SIGNAL_TO_GLOBAL_BUFFER"].net = clknet; + PortRef pr; + pr.cell = gb; + pr.port = "USER_SIGNAL_TO_GLOBAL_BUFFER"; + clknet->users.push_back(pr); + + pr.cell = gb; + pr.port = "GLOBAL_BUFFER_OUTPUT"; + NetInfo *glbnet = new NetInfo(); + glbnet->name = clknet->name.str() + "_glb"; + glbnet->driver = pr; + design->nets[glbnet->name] = glbnet; + std::vector<PortRef> keep_users; + for (auto user : clknet->users) { + if (user.cell != nullptr && is_ff(user.cell) && user.port == "C") { + user.cell->ports[user.port].net = glbnet; + glbnet->users.push_back(user); + } else { + keep_users.push_back(user); + } + } + clknet->users = keep_users; + design->cells[gb->name] = gb; + } +} + // Main pack function void pack_design(Design *design) { pack_constants(design); + promote_globals(design); pack_io(design); pack_lut_lutffs(design); pack_nonlut_ffs(design); |