2023-05-05 05:51:30 +02:00
|
|
|
# See LICENSE for licensing information.
|
|
|
|
|
#
|
|
|
|
|
# Copyright (c) 2016-2023 Regents of the University of California, Santa Cruz
|
|
|
|
|
# All rights reserved.
|
|
|
|
|
#
|
2023-05-09 22:23:01 +02:00
|
|
|
from openram.base.vector3d import vector3d
|
2023-06-15 20:08:13 +02:00
|
|
|
from openram.tech import drc
|
2023-05-09 22:23:01 +02:00
|
|
|
|
2023-05-05 05:51:30 +02:00
|
|
|
|
2023-07-13 21:07:55 +02:00
|
|
|
class graph_node:
|
|
|
|
|
""" This class represents a node on the graph. """
|
2023-05-05 05:51:30 +02:00
|
|
|
|
2023-05-09 22:23:01 +02:00
|
|
|
# This is used to assign unique ids to nodes
|
|
|
|
|
next_id = 0
|
|
|
|
|
|
2023-05-22 22:08:21 +02:00
|
|
|
def __init__(self, center):
|
2023-05-09 22:23:01 +02:00
|
|
|
|
2023-07-13 21:07:55 +02:00
|
|
|
self.id = graph_node.next_id
|
|
|
|
|
graph_node.next_id += 1
|
2023-05-22 22:08:21 +02:00
|
|
|
if isinstance(center, vector3d):
|
2023-05-09 22:23:01 +02:00
|
|
|
self.center = center
|
|
|
|
|
else:
|
|
|
|
|
self.center = vector3d(center)
|
2023-05-05 05:51:30 +02:00
|
|
|
self.neighbors = []
|
|
|
|
|
|
|
|
|
|
|
2023-05-29 21:43:43 +02:00
|
|
|
def add_neighbor(self, other):
|
2023-05-05 05:51:30 +02:00
|
|
|
""" Connect two nodes. """
|
|
|
|
|
|
2023-05-29 21:43:43 +02:00
|
|
|
if other not in self.neighbors:
|
|
|
|
|
self.neighbors.append(other)
|
|
|
|
|
other.neighbors.append(self)
|
2023-05-05 05:51:30 +02:00
|
|
|
|
|
|
|
|
|
2023-05-29 21:43:43 +02:00
|
|
|
def remove_neighbor(self, other):
|
2023-05-05 05:51:30 +02:00
|
|
|
""" Disconnect two nodes. """
|
|
|
|
|
|
2023-05-29 21:43:43 +02:00
|
|
|
if other in self.neighbors:
|
|
|
|
|
self.neighbors.remove(other)
|
|
|
|
|
other.neighbors.remove(self)
|
2023-05-09 22:23:01 +02:00
|
|
|
|
|
|
|
|
|
2023-05-30 06:49:00 +02:00
|
|
|
def remove_all_neighbors(self):
|
|
|
|
|
""" Disconnect all current neighbors. """
|
|
|
|
|
|
|
|
|
|
for neighbor in self.neighbors:
|
|
|
|
|
self.neighbors.remove(neighbor)
|
|
|
|
|
neighbor.neighbors.remove(self)
|
|
|
|
|
|
|
|
|
|
|
2023-06-15 20:08:13 +02:00
|
|
|
def get_direction(self, b):
|
|
|
|
|
""" Return the direction of path from a to b. """
|
|
|
|
|
|
|
|
|
|
horiz = self.center.x == b.center.x
|
|
|
|
|
vert = self.center.y == b.center.y
|
|
|
|
|
return (horiz, vert)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_edge_cost(self, other, prev_node=None):
|
2023-05-23 03:16:49 +02:00
|
|
|
""" Get the cost of going from this node to the other node. """
|
|
|
|
|
|
|
|
|
|
if other in self.neighbors:
|
|
|
|
|
is_vertical = self.center.x == other.center.x
|
|
|
|
|
layer_dist = self.center.distance(other.center)
|
2023-07-30 06:48:33 +02:00
|
|
|
# Double the cost if the edge is in non-preferred direction
|
2023-05-23 03:16:49 +02:00
|
|
|
if is_vertical != bool(self.center.z):
|
|
|
|
|
layer_dist *= 2
|
2023-07-30 06:48:33 +02:00
|
|
|
# Add a constant wire cost to prevent dog-legs
|
|
|
|
|
if prev_node and self.get_direction(prev_node) != self.get_direction(other):
|
|
|
|
|
layer_dist += drc["grid"]
|
|
|
|
|
via_dist = abs(self.center.z - other.center.z)
|
2023-05-23 03:16:49 +02:00
|
|
|
return layer_dist + via_dist
|
2023-05-22 22:08:21 +02:00
|
|
|
return float("inf")
|