Skip to content

Commit bbe2444

Browse files
authored
[Synth][LongestPathAnalysis] Remove hack for passing top module name through IR attribute (#9006)
This removes a hack `synth.longest-path-analysis-top` which was put to IR in order to pass a top name to analysis. The top module name is now passed explicitly as a parameter to the LongestPathAnalysis constructor and related APIs instead of being stored as an IR attribute.
1 parent f104898 commit bbe2444

File tree

13 files changed

+45
-49
lines changed

13 files changed

+45
-49
lines changed

include/circt-c/Dialect/Synth.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ DEFINE_C_API_STRUCT(SynthLongestPathCollection, void);
5151
// Create a LongestPathAnalysis for the given module
5252
MLIR_CAPI_EXPORTED SynthLongestPathAnalysis synthLongestPathAnalysisCreate(
5353
MlirOperation module, bool collectDebugInfo, bool keepOnlyMaxDelayPaths,
54-
bool lazyComputation);
54+
bool lazyComputation, MlirStringRef topModuleName);
5555

5656
// Destroy a LongestPathAnalysis
5757
MLIR_CAPI_EXPORTED void

include/circt/Dialect/Synth/Analysis/LongestPathAnalysis.h

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,18 @@ struct LongestPathAnalysisOptions {
206206
/// are needed rather than complete path enumeration.
207207
bool keepOnlyMaxDelayPaths = false;
208208

209+
/// Name of the top module for the analysis.
210+
/// If empty, the top module is inferred from the instance graph.
211+
StringAttr topModuleName = {};
212+
209213
/// Construct analysis options with the specified settings.
210214
LongestPathAnalysisOptions(bool collectDebugInfo = false,
211215
bool lazyComputation = false,
212-
bool keepOnlyMaxDelayPaths = false)
216+
bool keepOnlyMaxDelayPaths = false,
217+
StringAttr topModuleName = {})
213218
: collectDebugInfo(collectDebugInfo), lazyComputation(lazyComputation),
214-
keepOnlyMaxDelayPaths(keepOnlyMaxDelayPaths) {}
219+
keepOnlyMaxDelayPaths(keepOnlyMaxDelayPaths),
220+
topModuleName(topModuleName) {}
215221
};
216222

217223
// This analysis finds the longest paths in the dataflow graph across modules.
@@ -282,16 +288,6 @@ class LongestPathAnalysis {
282288
// Return the top nodes that were used for the analysis.
283289
llvm::ArrayRef<hw::HWModuleOp> getTopModules() const;
284290

285-
// This is the name of the attribute that can be attached to the module
286-
// to specify the top module for the analysis. This is optional, if not
287-
// specified, the analysis will infer the top module from the instance graph.
288-
// However it's recommended to specify it, as the entire module tends to
289-
// contain testbench or verification modules, which may have expensive paths
290-
// that are not of interest.
291-
static StringRef getTopModuleNameAttrName() {
292-
return "synth.longest-path-analysis-top";
293-
}
294-
295291
MLIRContext *getContext() const { return ctx; }
296292

297293
protected:

include/circt/Dialect/Synth/Transforms/SynthPasses.td

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,10 @@ def PrintLongestPathAnalysis
116116
Option<"showTopKPercent", "show-top-k-percent", "int", "5",
117117
"The size of the longest paths to show.">,
118118
Option<"emitJSON", "emit-json", "bool", "false",
119-
"Output analysis results in JSON format">];
119+
"Output analysis results in JSON format">,
120+
Option<"topModuleName", "top-module-name", "std::string", "",
121+
"Name of the top module to analyze (empty for automatic "
122+
"inference from instance graph)">];
120123
}
121124

122125
class ExternalSolverPass<string name> : Pass<name, "hw::HWModuleOp"> {

integration_test/Bindings/Python/dialects/synth.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ def build_top(module):
141141
analysis = LongestPathAnalysis(test_child,
142142
collect_debug_info=True,
143143
keep_only_max_delay_paths=True,
144-
lazy_computation=True)
144+
lazy_computation=True,
145+
top_module_name="test_child")
145146
c1 = analysis.get_paths(result0, 0)
146147
c2 = analysis.get_paths(result1, 0)
147148
# CHECK-NEXT: len(c1) = 1

lib/Bindings/Python/SynthModule.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,15 @@ void circt::python::populateDialectSynthSubmodule(nb::module_ &m) {
3333
"__init__",
3434
[](SynthLongestPathAnalysis *self, MlirOperation module,
3535
bool collectDebugInfo, bool keepOnlyMaxDelayPaths,
36-
bool lazyComputation) {
36+
bool lazyComputation, const std::string &topModuleName) {
3737
new (self) SynthLongestPathAnalysis(synthLongestPathAnalysisCreate(
3838
module, collectDebugInfo, keepOnlyMaxDelayPaths,
39-
lazyComputation));
39+
lazyComputation,
40+
mlirStringRefCreateFromCString(topModuleName.c_str())));
4041
},
4142
nb::arg("module"), nb::arg("collect_debug_info") = false,
4243
nb::arg("keep_only_max_delay_paths") = false,
43-
nb::arg("lazy_computation") = false)
44+
nb::arg("lazy_computation") = false, nb::arg("top_module_name") = "")
4445
.def("__del__",
4546
[](SynthLongestPathAnalysis &self) {
4647
synthLongestPathAnalysisDestroy(self);

lib/Bindings/Python/dialects/synth.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,8 @@ def __init__(self,
352352
module,
353353
collect_debug_info: bool = True,
354354
keep_only_max_delay_paths: bool = False,
355-
lazy_computation: bool = False):
355+
lazy_computation: bool = False,
356+
top_module_name: str = ""):
356357
"""
357358
Initialize the longest path analysis for a given module.
358359
Args:
@@ -365,7 +366,8 @@ def __init__(self,
365366
"""
366367
self.analysis = synth._LongestPathAnalysis(module, collect_debug_info,
367368
keep_only_max_delay_paths,
368-
lazy_computation)
369+
lazy_computation,
370+
top_module_name)
369371

370372
def get_paths(self,
371373
value,

lib/CAPI/Dialect/Synth.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,17 +80,19 @@ SynthLongestPathObject wrap(const DataflowPath::OutputPort *object) {
8080

8181
SynthLongestPathAnalysis
8282
synthLongestPathAnalysisCreate(MlirOperation module, bool collectDebugInfo,
83-
bool keepOnlyMaxDelayPaths,
84-
bool lazyComputation) {
83+
bool keepOnlyMaxDelayPaths, bool lazyComputation,
84+
MlirStringRef topModuleName) {
8585
auto *op = unwrap(module);
8686
auto *wrapper = new LongestPathAnalysisWrapper();
8787
wrapper->analysisManager =
8888
std::make_unique<mlir::ModuleAnalysisManager>(op, nullptr);
8989
mlir::AnalysisManager am = *wrapper->analysisManager;
90+
auto topModuleNameAttr =
91+
StringAttr::get(op->getContext(), unwrap(topModuleName));
9092
wrapper->analysis = std::make_unique<LongestPathAnalysis>(
9193
op, am,
9294
LongestPathAnalysisOptions(collectDebugInfo, lazyComputation,
93-
keepOnlyMaxDelayPaths));
95+
keepOnlyMaxDelayPaths, topModuleNameAttr));
9496
return wrap(wrapper);
9597
}
9698

lib/Dialect/Synth/Analysis/LongestPathAnalysis.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,7 @@ class Context {
485485
bool doLazyComputation() const { return option.lazyComputation; }
486486
bool doKeepOnlyMaxDelayPaths() const { return option.keepOnlyMaxDelayPaths; }
487487
bool isLocalScope() const { return instanceGraph == nullptr; }
488+
StringAttr getTopModuleName() const { return option.topModuleName; }
488489

489490
private:
490491
bool isRunningParallel() const { return !doLazyComputation(); }
@@ -1752,14 +1753,12 @@ LongestPathAnalysis::Impl::initializeAndRun(hw::HWModuleOp module) {
17521753

17531754
LogicalResult
17541755
LongestPathAnalysis::Impl::initializeAndRun(mlir::ModuleOp module) {
1755-
auto topNameAttr =
1756-
module->getAttrOfType<FlatSymbolRefAttr>(getTopModuleNameAttrName());
1757-
1756+
auto topNameAttr = ctx.getTopModuleName();
17581757
topModules.clear();
17591758
llvm::SetVector<Operation *> visited;
17601759
auto *instanceGraph = ctx.instanceGraph;
1761-
if (topNameAttr) {
1762-
auto *topNode = instanceGraph->lookup(topNameAttr.getAttr());
1760+
if (topNameAttr && topNameAttr.getValue() != "") {
1761+
auto *topNode = instanceGraph->lookupOrNull(topNameAttr);
17631762
if (!topNode || !topNode->getModule() ||
17641763
!isa<hw::HWModuleOp>(topNode->getModule())) {
17651764
module.emitError() << "top module not found in instance graph "

lib/Dialect/Synth/Analysis/PrintLongestPathAnalysis.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ void PrintLongestPathAnalysisPass::runOnOperation() {
280280
/*collectDebugInfo=*/showTopKPercent.getValue() > 0,
281281
/*lazyComputation=*/false,
282282
/*keepOnlyMaxDelayPaths=*/
283-
!test));
283+
!test, StringAttr::get(&getContext(), topModuleName.getValue())));
284284

285285
igraph::InstancePathCache pathCache(
286286
getAnalysis<circt::igraph::InstanceGraph>());

test/CAPI/support.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ void testInstancePath(void) {
5555
// for testing purposes without needing to expose additional InstancePathCache
5656
// APIs.
5757

58+
MlirStringRef moduleName = mlirStringRefCreateFromCString("top");
5859
SynthLongestPathAnalysis analysis =
59-
synthLongestPathAnalysisCreate(moduleOp, true, false, false);
60+
synthLongestPathAnalysisCreate(moduleOp, true, false, false, moduleName);
6061

61-
MlirStringRef moduleName = mlirStringRefCreateFromCString("top");
6262
SynthLongestPathCollection collection =
6363
synthLongestPathAnalysisGetAllPaths(analysis, moduleName, true);
6464

0 commit comments

Comments
 (0)