mirror of https://github.com/VLSIDA/OpenRAM.git
118 lines
4.4 KiB
Python
118 lines
4.4 KiB
Python
# See LICENSE for licensing information.
|
|
#
|
|
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
|
# All rights reserved.
|
|
#
|
|
from .bbox import bbox
|
|
|
|
|
|
class bbox_node:
|
|
"""
|
|
This class represents a node in the bbox tree structure. Bbox trees are
|
|
binary trees we use to partition the shapes in the routing region so that
|
|
we can detect overlaps faster in a binary search-like manner.
|
|
"""
|
|
|
|
def __init__(self, bbox, left=None, right=None):
|
|
|
|
self.bbox = bbox
|
|
self.is_leaf = not left and not right
|
|
self.left = left
|
|
self.right = right
|
|
|
|
|
|
def iterate_point(self, point, check_done=False):
|
|
""" Iterate over shapes in the tree that overlap the given point. """
|
|
|
|
px, py = point.x, point.y
|
|
# Return this shape if it's a leaf
|
|
if self.is_leaf:
|
|
ll, ur = self.bbox.rect
|
|
if check_done or (ll.x <= px and px <= ur.x and ll.y <= py and py <= ur.y):
|
|
yield self.bbox.shape
|
|
else:
|
|
# Check the left child
|
|
if self.left:
|
|
ll, ur = self.left.bbox.rect
|
|
if ll.x <= px and px <= ur.x and ll.y <= py and py <= ur.y:
|
|
yield from self.left.iterate_point(point, True)
|
|
# Check the right child
|
|
if self.right:
|
|
ll, ur = self.right.bbox.rect
|
|
if ll.x <= px and px <= ur.x and ll.y <= py and py <= ur.y:
|
|
yield from self.right.iterate_point(point, True)
|
|
|
|
|
|
def iterate_shape(self, shape, check_done=False):
|
|
""" Iterate over shapes in the tree that overlap the given shape. """
|
|
|
|
sll, sur = shape.rect
|
|
# Return this shape if it's a leaf
|
|
if self.is_leaf:
|
|
ll, ur = self.bbox.rect
|
|
if check_done or (ll.x <= sur.x and sll.x <= ur.x and ll.y <= sur.y and sll.y <= ur.y):
|
|
yield self.bbox.shape
|
|
else:
|
|
# Check the left child
|
|
if self.left:
|
|
ll, ur = self.left.bbox.rect
|
|
if ll.x <= sur.x and sll.x <= ur.x and ll.y <= sur.y and sll.y <= ur.y:
|
|
yield from self.left.iterate_shape(shape, True)
|
|
# Check the right child
|
|
if self.right:
|
|
ll, ur = self.right.bbox.rect
|
|
if ll.x <= sur.x and sll.x <= ur.x and ll.y <= sur.y and sll.y <= ur.y:
|
|
yield from self.right.iterate_shape(shape, True)
|
|
|
|
|
|
def get_costs(self, bbox):
|
|
""" Return the costs of bbox nodes after merging the given bbox. """
|
|
|
|
# Find the new areas for all possible cases
|
|
self_merge = bbox.merge(self.bbox)
|
|
left_merge = bbox.merge(self.left.bbox)
|
|
right_merge = bbox.merge(self.right.bbox)
|
|
|
|
# Add the change in areas as cost
|
|
self_cost = self_merge.area()
|
|
left_cost = self_merge.area() - self.bbox.area()
|
|
left_cost += left_merge.area() - self.left.bbox.area()
|
|
right_cost = self_merge.area() - self.bbox.area()
|
|
right_cost += right_merge.area() - self.right.bbox.area()
|
|
|
|
# Add the overlaps in areas as cost
|
|
self_overlap = self.bbox.overlap(bbox)
|
|
left_overlap = left_merge.overlap(self.right.bbox)
|
|
right_overlap = right_merge.overlap(self.left.bbox)
|
|
if self_overlap:
|
|
self_cost += self_overlap.area()
|
|
if left_overlap:
|
|
left_cost += left_overlap.area()
|
|
if right_overlap:
|
|
right_cost += right_overlap.area()
|
|
|
|
return self_cost, left_cost, right_cost
|
|
|
|
|
|
def insert(self, bbox):
|
|
""" Insert a bbox to the bbox tree. """
|
|
|
|
if self.is_leaf:
|
|
# Put the current bbox to the left child
|
|
self.left = bbox_node(self.bbox)
|
|
# Put the new bbox to the right child
|
|
self.right = bbox_node(bbox)
|
|
else:
|
|
# Calculate the costs of adding the new bbox
|
|
self_cost, left_cost, right_cost = self.get_costs(bbox)
|
|
if self_cost < left_cost and self_cost < right_cost: # Add here
|
|
self.left = bbox_node(self.bbox, left=self.left, right=self.right)
|
|
self.right = bbox_node(bbox)
|
|
elif left_cost < right_cost: # Add to the left
|
|
self.left.insert(bbox)
|
|
else: # Add to the right
|
|
self.right.insert(bbox)
|
|
# Update the current bbox
|
|
self.bbox = self.left.bbox.merge(self.right.bbox)
|
|
self.is_leaf = False
|