6from ._synth_ops_gen
import *
7from .._mlir_libs._circt._synth
import _LongestPathAnalysis, _LongestPathCollection, _LongestPathDataflowPath, _LongestPathHistory, _LongestPathObject
9from dataclasses
import dataclass
10from typing
import Any, Dict, List, Union, Optional
20 Represents a single element in a hierarchical instance path.
21 In hardware design, modules are instantiated hierarchically. This class
22 represents one level in that hierarchy, containing both the module type
23 and the specific instance name.
25 instance_name: The name of this specific instance
26 module_name: The type/name of the module being instantiated
28 _instance: hw.InstanceOp
45 Represents a signal or port object in the dataflow graph.
46 This class encapsulates a specific signal within the hardware hierarchy,
47 including its location in the instance hierarchy, signal name, and bit position
48 for multi-bit signals.
50 instance_path: Hierarchical path to the module containing this object
51 name: The signal/port name within the module
52 bit_pos: Bit position for multi-bit signals (0 for single-bit)
55 _object: _LongestPathObject
61 Generate a human-readable string representation of this object.
62 Format: "module1:instance1/module2:instance2 signal_name[bit_pos]"
64 path =
"/".join(f
"{elem.module_name}:{elem.instance_name}"
66 return f
"{path} {self.name}[{self.bit_pos}]"
69 return f
"Object({self.instance_path}, {self.name}, {self.bit_pos})"
73 """Get the hierarchical instance path to this object."""
74 operations = self.
_object.instance_path
76 return [
Instance(op)
for op
in operations]
80 """Get the name of this signal/port."""
85 """Get the bit position for multi-bit signals."""
89 def value(self) -> Optional[Value]:
90 """Get the MLIR value associated with this object, if any."""
95 """Check if this object represents an output port."""
96 return self.
value is None
102 Represents a debug point in the timing path history.
103 Debug points are intermediate points along a timing path that provide
104 insight into the delay accumulation and signal propagation through
105 the circuit. Each point captures the state at a specific location.
107 object: The signal/object at this debug point
108 delay: Accumulated delay up to this point (in timing units)
109 comment: Optional descriptive comment about this point
120 Represents a complete dataflow path from end point to start point.
121 A dataflow path captures the complete timing path through a circuit,
122 from an output point (end-point) back to an input point (start-point), including
123 all intermediate debug points and the total delay.
125 end_point: The output signal/object where this path ends
126 path: The OpenPath containing the detailed path information
127 root: The root module name for this analysis
130 _path: _LongestPathDataflowPath
134 """Get the total delay of this path in timing units."""
135 return self.
_path.delay
139 """Get the input signal/object where this path begins."""
144 """Get the output signal/object where this path ends."""
149 """Get the history of debug points along this path."""
154 """Get the root module name for this analysis."""
155 return self.
_path.root.attributes[
"sym_name"].value
163 Convert this path to FlameGraph format for visualization.
164 FlameGraphs are a visualization technique that shows call stacks or
165 in this case, timing paths through the circuit hierarchy. Each line
166 represents a segment of the path with its associated delay.
167 The format is: "hierarchy_path delay_increment"
168 where hierarchy_path uses semicolons to separate hierarchy levels.
170 String in FlameGraph format showing the timing path progression
173 prefix = f
"top:{self.root}"
181 current_hierarchy = start_point_hierarchy
185 for debug_point
in self.
history[::-1]:
188 if history_hierarchy:
190 delay_increment = debug_point.delay - current_delay
191 trace.append(f
"{current_hierarchy} {delay_increment}")
194 current_hierarchy = history_hierarchy
195 current_delay = debug_point.delay
198 if current_delay != self.
delay:
199 final_delay = self.
delay - current_delay
200 trace.append(f
"{end_point_hierarchy} {final_delay}")
202 return "\n".join(trace)
206 Build a hierarchical string representation of an Object for FlameGraph format.
207 This method constructs a semicolon-separated hierarchy string that represents
208 the full path from the top-level module down to the specific signal. This
209 format is compatible with FlameGraph visualization tools.
211 obj: Object to represent in the hierarchy
212 prefix: Top-level prefix (typically "top:module_name")
214 Hierarchical string in format: "top:root;module1:inst1;module2:inst2;signal[bit]"
219 for elem
in obj.instance_path:
220 parts.append(f
"{elem.instance_name}:{elem.module_name}")
223 signal_part = obj.name
224 signal_part += f
"[{obj.bit_pos}]"
225 parts.append(signal_part)
227 return ";".join(parts)
237 A collection of timing paths sorted by delay (longest first).
238 This class provides a Python wrapper around the C++ LongestPathCollection,
239 offering convenient access to timing paths with caching for performance.
240 The paths are pre-sorted by delay in descending order.
242 collection: The underlying C++ collection object
243 length: Number of paths in the collection
248 Initialize the collection wrapper.
250 collection: The underlying C++ LongestPathCollection object
260 """Get the number of paths in the collection."""
264 self, index: Union[slice,
265 int]) -> Union[DataflowPath, List[DataflowPath]]:
267 Get a specific path from the collection by index.
268 Supports both integer and slice indexing. Integer indices can be negative.
271 index: Integer index or slice object to access paths
274 DataflowPath or list of DataflowPaths for slice access
277 IndexError: If index is out of range
279 if isinstance(index, slice):
280 return [self[i]
for i
in range(*index.indices(len(self)))]
285 if index < 0
or index >= self.
length:
286 raise IndexError(
"Index out of range")
296 """Get the path with the maximum delay (first element since sorted)."""
301 Get the path at the specified position in the delay-sorted collection.
302 Since paths are sorted by delay in descending order, higher ratios
303 correspond to paths with higher delays (closer to the critical path).
305 ratio: Position ratio between 0.0 and 1.0
306 (e.g., 1.0 = longest delay path, 0.0 = shortest delay path,
307 0.95 = path among the top 5% slowest paths)
309 DataflowPath at the specified position ratio
311 assert ratio >= 0.0
and ratio <= 1.0,
"Ratio must be between 0.0 and 1.0"
312 index = int(len(self) * (1 - ratio))
316 """Print a statistical summary of path delays in the collection."""
317 print(f
"Total paths: {len(self)}")
318 print(f
"Max delay: {self.longest_path.delay}")
319 print(f
"Min delay: {self[-1].delay}")
320 print(f
"50th percentile delay: {self.get_by_delay_ratio(0.5).delay}")
321 print(f
"90th percentile delay: {self.get_by_delay_ratio(0.9).delay}")
322 print(f
"95th percentile delay: {self.get_by_delay_ratio(0.95).delay}")
323 print(f
"99th percentile delay: {self.get_by_delay_ratio(0.99).delay}")
324 print(f
"99.9th percentile delay: {self.get_by_delay_ratio(0.999).delay}")
326 def merge(self, src:
"LongestPathCollection"):
328 Merge another collection into this one.
330 src: The collection to merge into this one
338 Drop all paths except the longest path per end point or start point.
340 per_end_point: Whether to keep only the longest path per end point
341 (True) or per start point (False)
355 Main interface for performing longest path analysis on Synth dialect.
356 This class provides a Python wrapper around the C++ LongestPathAnalysis,
357 enabling timing analysis of Synth dialect. It can identify critical timing
358 paths and provide detailed path information.
360 analysis: The underlying C++ analysis object
365 collect_debug_info: bool =
True,
366 keep_only_max_delay_paths: bool =
False,
367 lazy_computation: bool =
False,
368 top_module_name: str =
""):
370 Initialize the longest path analysis for a given module.
372 module: The MLIR module to analyze
373 collect_debug_info: Whether to include debug points in the analysis.
374 Debug points provide additional information about the path,
375 but increase analysis time and memory usage.
376 keep_only_max_delay_paths: Keep only maximum-delay paths in collections.
377 lazy_computation: Enable lazy (on-demand) computation.
379 self.
analysis = synth._LongestPathAnalysis(module, collect_debug_info,
380 keep_only_max_delay_paths,
387 elaborate_paths: bool =
True) -> LongestPathCollection:
389 Perform longest path analysis and return all timing paths to the
390 specified value and bit position.
392 value: The value to analyze
393 bit_pos: The bit position to analyze
394 elaborate_paths: Whether to elaborate the paths with detailed information
396 LongestPathCollection containing all paths sorted by delay
403 elaborate_paths: bool =
True) -> LongestPathCollection:
405 Get internal paths within the module.
407 Internal paths are paths that start and end at sequential elements
408 (registers/flip-flops), forming complete paths through combinational
409 logic. These paths may cross module boundaries but both endpoints are
410 sequential elements, not ports.
413 module_name: Name of the module to analyze
414 elaborate_paths: Whether to include full hierarchical instance information
417 LongestPathCollection containing all internal paths sorted by delay
423 self, module_name: str) -> LongestPathCollection:
425 Get external paths from module input ports to internal sequential elements.
427 These are input-to-register paths that start at module input ports and end
428 at internal sequential elements (registers/flip-flops).
431 module_name: Name of the module to analyze
434 LongestPathCollection containing input-to-internal paths sorted by delay
440 self, module_name: str) -> LongestPathCollection:
442 Get external paths from internal sequential elements to module output ports.
444 These are register-to-output paths that start at internal sequential elements
445 (registers/flip-flops) and end at module output ports.
448 module_name: Name of the module to analyze
451 LongestPathCollection containing internal-to-output paths sorted by delay
458 elaborate_paths: bool =
True) -> LongestPathCollection:
460 Get all paths in the module (internal and external paths combined).
463 module_name: Name of the module to analyze
464 elaborate_paths: Whether to include full hierarchical instance information
465 (only applies to internal paths)
468 LongestPathCollection containing all paths sorted by delay
479 Represents the history of a timing path, including intermediate debug points.
480 This class provides a Python wrapper around the C++ LongestPathHistory,
481 enabling iteration over the path's history and access to debug points.
483 history: The underlying C++ history object
485 history: _LongestPathHistory
488 """Iterate over the debug points in the history."""
static void print(TypedAttr val, llvm::raw_ostream &os)
List[DebugPoint] history(self)
_LongestPathDataflowPath _path
str _build_hierarchy_string(self, Object obj, str prefix="")
__init__(self, hw.InstanceOp instance)
LongestPathCollection get_paths_from_internal_to_output_ports(self, str module_name)
LongestPathCollection get_paths_from_input_ports_to_internal(self, str module_name)
LongestPathCollection get_paths(self, value, int bit_pos, bool elaborate_paths=True)
LongestPathCollection get_all_paths(self, str module_name, bool elaborate_paths=True)
LongestPathCollection get_internal_paths(self, str module_name, bool elaborate_paths=True)
__init__(self, module, bool collect_debug_info=True, bool keep_only_max_delay_paths=False, bool lazy_computation=False, str top_module_name="")
merge(self, "LongestPathCollection" src)
Union[DataflowPath, List[DataflowPath]] __getitem__(self, Union[slice, int] index)
DataflowPath longest_path(self)
DataflowPath get_by_delay_ratio(self, float ratio)
drop_non_critical_paths(self, bool per_end_point=True)
__init__(self, collection)
_LongestPathHistory history
Optional[Value] value(self)
bool is_output_port(self)
List[Instance] instance_path(self)
_LongestPathObject _object