From 59a29e5f420a2d4ad598aa1ac81fa62cc96f138e Mon Sep 17 00:00:00 2001 From: gatecat Date: Thu, 16 May 2024 14:27:54 +0200 Subject: [PATCH] nexus: Use a toposort when preplacing clock primitives Signed-off-by: gatecat --- nexus/pack.cc | 50 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/nexus/pack.cc b/nexus/pack.cc index 9991d49d..75ceb309 100644 --- a/nexus/pack.cc +++ b/nexus/pack.cc @@ -916,19 +916,47 @@ struct NexusPacker { // Keep running until we reach a fixed point log_info("Placing globals...\n"); - bool did_something = true; - while (did_something) { - did_something = false; - for (auto &cell : ctx->cells) { - CellInfo *ci = cell.second.get(); - if (ci->type == id_OSC_CORE) - did_something |= preplace_singleton(ci); - else if (ci->type == id_DCC) - did_something |= preplace_prim(ci, id_CLKI, false); - else if (ci->type == id_PLL_CORE) - did_something |= preplace_prim(ci, id_REFCK, false); + TopoSort sorter; + auto is_glb_cell = [&](const CellInfo *cell) { + return cell->type.in(id_OSC_CORE, id_DCC, id_PLL_CORE, id_DCS); + }; + + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); + if (is_glb_cell(ci)) { + sorter.node(ci->name); + + auto do_pin = [&](IdString pin) { + NetInfo *net = ci->getPort(pin); + if (!net || !net->driver.cell || !is_glb_cell(net->driver.cell)) + return; + sorter.edge(net->driver.cell->name, ci->name); + }; + + if (ci->type == id_PLL_CORE) { + do_pin(id_REFCK); + } else if (ci->type == id_DCC) { + do_pin(id_CLKI); + } else if (ci->type == id_DCS) { + do_pin(id_CLK0); + do_pin(id_CLK1); + } } } + + sorter.sort(); + + for (IdString cell_name : sorter.sorted) { + CellInfo *ci = ctx->cells.at(cell_name).get(); + if (ci->type == id_OSC_CORE) + preplace_singleton(ci); + else if (ci->type == id_DCC) + preplace_prim(ci, id_CLKI, false); + else if (ci->type == id_PLL_CORE) + preplace_prim(ci, id_REFCK, false); + else if (ci->type == id_DCS) + preplace_prim(ci, id_CLK0, false); + } } // Get a bus port name