Skip to content

Commit e8e0ee8

Browse files
authored
Fix wirelength_analyzer when terminating at a comb cell (e.g. LUT) (#50)
* Fix wirelength_analyzer when terminating at a comb cell (e.g. LUT) An example of this occurring is the case when the LUT outputs to a hierarchical (out of context) port Signed-off-by: Eddie Hung <[email protected]> * Update doc Signed-off-by: Eddie Hung <[email protected]> * Fix warning to output cell and cleanup Signed-off-by: Eddie Hung <[email protected]> --------- Signed-off-by: Eddie Hung <[email protected]>
1 parent da8f1a1 commit e8e0ee8

File tree

1 file changed

+29
-24
lines changed

1 file changed

+29
-24
lines changed

wirelength_analyzer/wa.py

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -421,47 +421,52 @@ def find_longest_path(self):
421421
self.tstart()
422422
lp = nx.dag_longest_path(self.G, weight='wirelength')
423423

424-
# The final edge in the path returned by Networkx's longest path
425-
# algorithm always has a non-zero weight. This means that, the final
426-
# node in the longest path may be an ancestor to subsequent edges as
427-
# as long as these subsequent edges have zero weight. In the context
428-
# of the wirelength analyzer this means that the terminal cell in the
429-
# longest path reported by Networkx may be a combinatorial driver for
430-
# subsequent routeSegments that do not appear in the reported path. To
431-
# avoid this scenario we perform a Depth First Search from the final
432-
# node in the Networkx longest path, stopping at the first cell/bel
433-
# that is not a combinatorial driver of any subsequent routeSegments
434-
435-
def search_for_first_valid_sink(source, path=()):
424+
# NetworkX's longest path algorithm will return the longest path by
425+
# wirelength, but it is not necessarily a path that terminates in a
426+
# timing endpoint (e.g. a FF).
427+
# Consider the example where the tail of such a longest path consists
428+
# of a LUT followed by an intra-site connection to a FF.
429+
# NetworkX will return a path that terminates at the LUT, since the
430+
# intra-site connection to the FF incurs no additional wirelength.
431+
# Rather than present this truncated path to the user, attempt to
432+
# extend this longest path to include connections to downstream cells.
433+
434+
def search_for_first_valid_sink(source, path=[]):
436435
"""
437436
Run a Depth First Search from the provided source returning the
438437
first path found to a cell that is not a combinatorial driver for
439438
any further routeSegments.
440439
441440
Args:
442441
source: the source node to begin searching from
443-
path: an empty tuple that will containt the path found
442+
path: the current list of nodes leading to source
444443
Returns:
445-
a tuple of nodes (starting at the source node) forming a path
446-
if a valid path can be found.
444+
a list of nodes (starting at the source node) forming a path
445+
to the first sink, empty list if one cannot be found.
447446
"""
448447
out_edges = self.G.out_edges(source)
449-
path = (*path, source)
448+
path = path + [source]
450449
if len(out_edges) == 0:
451450
source_seg = self.G.nodes[source]['segment']
452451
if source_seg.which() == 'belPin':
453-
if self.placements.get((source_seg.belPin.site, source_seg.belPin.bel)) is not None:
452+
if (source_seg.belPin.site, source_seg.belPin.bel) in self.placements:
454453
return path
455-
return None
456-
return None
454+
return []
457455
for oe in out_edges:
458456
ret = search_for_first_valid_sink(oe[1], path)
459-
if ret is not None:
457+
if ret:
460458
return ret
461-
return None
462-
463-
tail = search_for_first_valid_sink(lp[-1])
464-
lp = lp + list(tail)[1:]
459+
return []
460+
461+
last = lp[-1]
462+
tail = search_for_first_valid_sink(last)
463+
if tail:
464+
lp = lp + tail[1:]
465+
else:
466+
seg = self.G.nodes[last]['segment']
467+
cell = self.placements[(seg.belPin.site, seg.belPin.bel)]
468+
sl = self.phys.strList
469+
warnings.warn("No valid sink found from cell " + sl[cell.cellName] + "; assuming that it drives a hierarchical port.")
465470
return lp
466471

467472
def expand_edge(self, source, sink):

0 commit comments

Comments
 (0)