From 4cf0f8e799b8307931d252becf7fd088b1b22ad9 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 2 Oct 2025 16:45:41 +0200 Subject: [PATCH] sdc: keep_hiearchy --- passes/cmds/sdc.cc | 70 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/passes/cmds/sdc.cc b/passes/cmds/sdc.cc index 9a2a5b1ed..c3cd0ed0a 100644 --- a/passes/cmds/sdc.cc +++ b/passes/cmds/sdc.cc @@ -97,6 +97,7 @@ struct SdcObjects { Graph, } value_mode; using CellPin = std::pair; + Design* design; std::vector> design_ports; std::vector> design_cells; std::vector> design_pins; @@ -158,7 +159,7 @@ struct SdcObjects { } } } - SdcObjects(Design* design) { + SdcObjects(Design* design) : design(design) { Module* top = design->top_module(); if (!top) log_error("Top module couldn't be determined. Check 'top' attribute usage"); @@ -250,6 +251,47 @@ struct SdcObjects { } log("\n"); } + + class KeepHierarchyWorker { + std::unordered_set tracked_modules = {}; + Design* design = nullptr; + bool mark(Module* mod) { + for (auto* cell : mod->cells()) { + if (auto* submod = design->module(cell->type)) + if (mark(submod)) + return true; + } + + if (tracked_modules.count(mod)) + return true; + + return false; + } + public: + KeepHierarchyWorker(SdcObjects* objects, Design* d) : design(d) { + for (auto [ref, _] : objects->constrained_ports) { + tracked_modules.insert(ref.second->module); + } + for (auto& [_, cell] : objects->constrained_cells) { + tracked_modules.insert(cell->module); + } + for (auto& [ref, _] : objects->constrained_pins) { + tracked_modules.insert(ref.second.first->module); + } + for (auto& [ref, _] : objects->constrained_nets) { + tracked_modules.insert(ref.second->module); + } + log_debug("keep_hierarchy tracked modules:\n"); + for (auto* mod : tracked_modules) + log_debug("%s", mod->name); + } + bool mark() { + return mark(design->top_module()); + } + }; + void keep_hierarchy() { + (void)KeepHierarchyWorker(this, design).mark(); + } }; // TODO vectors @@ -448,10 +490,11 @@ void dump_sdc_graph(const std::vector& graph, const std::vector> sdc_calls = gather_nested_calls(interp); std::vector graph = build_graph(sdc_calls); - dump_sdc_graph(graph, node_ownership(graph)); + if (dump_mode) + dump_sdc_graph(graph, node_ownership(graph)); } // patterns -> (pattern-object-bit)s @@ -743,9 +786,21 @@ struct SdcPass : public Pass { void execute(std::vector args, RTLIL::Design *design) override { log_header(design, "Executing SDC pass.\n"); size_t argidx; + bool graph_mode = false; + bool dump_mode = false; + bool keep_hierarchy_mode = false; std::vector opensta_stubs_paths; for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-stubs" && argidx+1 < args.size()) { + if (args[argidx] == "-graph") { + graph_mode = true; + continue; + } else if (args[argidx] == "-dump") { + dump_mode = true; + continue; + } else if (args[argidx] == "-keep_hierarchy") { + keep_hierarchy_mode = true; + continue; + } else if (args[argidx] == "-stubs" && argidx+1 < args.size()) { opensta_stubs_paths.push_back(args[++argidx]); continue; } @@ -767,8 +822,11 @@ struct SdcPass : public Pass { log_cmd_error("SDC interpreter returned an error in OpenSTA stub file %s: %s\n", path.c_str(), Tcl_GetStringResult(interp)); if (Tcl_EvalFile(interp, sdc_path.c_str()) != TCL_OK) log_cmd_error("SDC interpreter returned an error: %s\n", Tcl_GetStringResult(interp)); - sdc.objects->dump(); - inspect_globals(interp); + if (dump_mode) + sdc.objects->dump(); + if (keep_hierarchy_mode) + sdc.objects->keep_hierarchy(); + inspect_globals(interp, graph_mode); Tcl_Release(interp); } } SdcPass;