mirror of https://github.com/VLSIDA/OpenRAM.git
updata io_pin_placer
This commit is contained in:
parent
ee6be23cfa
commit
61f5ff6ec4
|
|
@ -13,9 +13,6 @@ from .router import router
|
||||||
import re
|
import re
|
||||||
|
|
||||||
class io_pin_placer(router):
|
class io_pin_placer(router):
|
||||||
"""
|
|
||||||
This is the signal escape router that uses the Hanan grid graph method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, layers, design, bbox=None):
|
def __init__(self, layers, design, bbox=None):
|
||||||
|
|
||||||
|
|
@ -30,6 +27,9 @@ class io_pin_placer(router):
|
||||||
self.io_pins_added_right = []
|
self.io_pins_added_right = []
|
||||||
self.io_pins_added_up = []
|
self.io_pins_added_up = []
|
||||||
self.io_pins_added_down = []
|
self.io_pins_added_down = []
|
||||||
|
|
||||||
|
# fake_pins, use for rename
|
||||||
|
self.io_pins_fake =[]
|
||||||
|
|
||||||
|
|
||||||
def get_closest_edge(self, point):
|
def get_closest_edge(self, point):
|
||||||
|
|
@ -51,8 +51,162 @@ class io_pin_placer(router):
|
||||||
if min_diff == ur_diff_x:
|
if min_diff == ur_diff_x:
|
||||||
return "right", True
|
return "right", True
|
||||||
return "top", False
|
return "top", False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def initial_position(self, pins): # pins is list []
|
||||||
|
""" Set the IO pin center at the perimeter """
|
||||||
|
pattern_clk = r'^clk'
|
||||||
|
pattern_addr0 = r'^addr0'
|
||||||
|
pattern_addr1 = r'^addr1'
|
||||||
|
pattern_dout0 = r'^dout0'
|
||||||
|
pattern_dout1 = r'^dout1'
|
||||||
|
pattern_din = r'^din'
|
||||||
|
pattern_wmask = r'^wmask'
|
||||||
|
pattern_spare_wen = r'^spare_wen'
|
||||||
|
pattern_web = r'^web'
|
||||||
|
pattern_csb = r'^csb'
|
||||||
|
for pin in pins:
|
||||||
|
c = pin.center()
|
||||||
|
# Find the closest edge
|
||||||
|
edge, vertical = self.get_closest_edge(c)
|
||||||
|
if re.match(pattern_clk, pin.name):# clk, should be placed at horizontal edge
|
||||||
|
if edge == "bottom" or edge == "left":
|
||||||
|
edge = "bottom"
|
||||||
|
elif edge == "top" or edge == "right":
|
||||||
|
edge = "top"
|
||||||
|
self.store_position(pin, edge, vertical)
|
||||||
|
if re.match(pattern_addr0, pin.name): # all the addr0[] should be placed at left edge
|
||||||
|
if edge == "top" or edge == "left":
|
||||||
|
edge = "left"
|
||||||
|
vertical = True
|
||||||
|
elif edge == "bottom": # but for big sram, addr0[] may have pins at bottom, which is allowed
|
||||||
|
vertical = False
|
||||||
|
self.store_position(pin, edge, vertical)
|
||||||
|
if re.match(pattern_addr1, pin.name): # all the addr1[] should be placed at right edge
|
||||||
|
if edge == "bottom" or edge == "right":
|
||||||
|
edge = "right"
|
||||||
|
vertical = True
|
||||||
|
elif edge == "top": # but for big sram, addr1[] may have pins at top, which is allowed
|
||||||
|
vertical = False
|
||||||
|
self.store_position(pin, edge, vertical)
|
||||||
|
if re.match(pattern_din, pin.name): # din
|
||||||
|
self.store_position(pin, edge, vertical)
|
||||||
|
if re.match(pattern_wmask, pin.name): # wmask
|
||||||
|
self.store_position(pin, edge, vertical)
|
||||||
|
if re.match(pattern_spare_wen, pin.name): # spare_wen
|
||||||
|
self.store_position(pin, edge, vertical)
|
||||||
|
if re.match(pattern_csb, pin.name):# csb
|
||||||
|
self.store_position(pin, edge, vertical)
|
||||||
|
if re.match(pattern_web, pin.name): # web
|
||||||
|
self.store_position(pin, edge, vertical)
|
||||||
|
# special handle the dout pins, if r/rw ports
|
||||||
|
for pin in pins:
|
||||||
|
if re.match(pattern_dout0, pin.name):
|
||||||
|
edge = "bottom"
|
||||||
|
vertical = False
|
||||||
|
self.store_dout_position(pin, edge, vertical)
|
||||||
|
if re.match(pattern_dout1, pin.name):
|
||||||
|
edge = "top"
|
||||||
|
vertical = False
|
||||||
|
self.store_dout_position(pin, edge, vertical)
|
||||||
|
|
||||||
|
|
||||||
|
def check_overlap(self, pin_position, edge):
|
||||||
|
""" Return the suggested position to aviod overlap """
|
||||||
|
ll, ur = self.bbox
|
||||||
|
c = pin_position # original source pin center
|
||||||
|
offset = 0.95 + 0.19 # FIX: this is the magic number to overcome the ovetflow problem at the boundary, may need a method
|
||||||
|
add_distance = 0
|
||||||
|
|
||||||
|
if edge == "bottom":
|
||||||
|
fake_center = vector(c.x, ll.y - self.track_wire * 2 + offset)
|
||||||
|
pin_to_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_down)
|
||||||
|
via_to_close = False
|
||||||
|
# if cannot direct place below the source pin, need move towards right, and ensure the min. distance between vias
|
||||||
|
while pin_to_close or via_to_close:
|
||||||
|
debug.warning("overlap, changing position")
|
||||||
|
add_distance = add_distance + 0.1
|
||||||
|
fake_center = vector(c.x + add_distance, ll.y - self.track_wire * 2 + offset)
|
||||||
|
pin_to_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_down)
|
||||||
|
via_to_close = abs(fake_center.x - c.x) < 0.6
|
||||||
|
if edge == "top":
|
||||||
|
fake_center = vector(c.x, ur.y + self.track_wire * 2 - offset)
|
||||||
|
pin_to_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_up)
|
||||||
|
via_to_close = False
|
||||||
|
# if cannot direct place below the source pin, need move towards right, and ensure the min. distance between vias
|
||||||
|
while pin_to_close or via_to_close:
|
||||||
|
debug.warning("overlap, changing position")
|
||||||
|
add_distance = add_distance + 0.1
|
||||||
|
fake_center = vector(c.x + add_distance, ur.y + self.track_wire * 2 - offset)
|
||||||
|
pin_to_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_up)
|
||||||
|
via_to_close = abs(fake_center.x - c.x) < 0.6
|
||||||
|
|
||||||
|
return fake_center
|
||||||
|
|
||||||
|
|
||||||
|
def store_dout_position(self, pin, edge, vertical):
|
||||||
|
pin_position = pin.center()
|
||||||
|
pin_position = self.check_overlap(pin_position, edge)
|
||||||
|
# store the center position, rect, layer of fake pin, here make sure the pin in the gds will be big enough
|
||||||
|
layer = self.get_layer(int(not vertical))
|
||||||
|
half_wire_vector = vector([self.half_wire] * 2)
|
||||||
|
nll = pin_position - half_wire_vector - half_wire_vector
|
||||||
|
nur = pin_position + half_wire_vector + half_wire_vector
|
||||||
|
rect = [nll, nur]
|
||||||
|
#fake_pin = [pin.name() + "_" + "fake", pin_position, rect, layer]
|
||||||
|
fake_pin = graph_shape(name=pin.name + "_" + "fake",
|
||||||
|
rect=rect,
|
||||||
|
layer_name_pp=layer)
|
||||||
|
|
||||||
|
if edge == "left":
|
||||||
|
self.io_pins_added_left.append(fake_pin)
|
||||||
|
elif edge == "bottom":
|
||||||
|
self.io_pins_added_down.append(fake_pin)
|
||||||
|
elif edge == "right":
|
||||||
|
self.io_pins_added_right.append(fake_pin)
|
||||||
|
elif edge == "top":
|
||||||
|
self.io_pins_added_up.append(fake_pin)
|
||||||
|
|
||||||
|
self.io_pins_fake.append(fake_pin)
|
||||||
|
debug.warning("pin added: {0}".format(fake_pin))
|
||||||
|
|
||||||
|
|
||||||
|
def store_position(self, pin, edge, vertical): # also need to store the source pin
|
||||||
|
ll, ur = self.bbox
|
||||||
|
c = pin.center()
|
||||||
|
offset = 0.95 + 0.19 # FIX: this is the magic number to overcome the ovetflow problem at the boundary, may need a method
|
||||||
|
if edge == "left":
|
||||||
|
fake_center = vector(ll.x - self.track_wire * 2 + offset, c.y)
|
||||||
|
if edge == "bottom":
|
||||||
|
fake_center = vector(c.x, ll.y - self.track_wire * 2 + offset)
|
||||||
|
if edge == "right":
|
||||||
|
fake_center = vector(ur.x + self.track_wire * 2 - offset, c.y)
|
||||||
|
if edge == "top":
|
||||||
|
fake_center = vector(c.x, ur.y + self.track_wire * 2 - offset)
|
||||||
|
# store the center position, rect, layer of fake pin, here make sure the pin in the gds will be big enough
|
||||||
|
layer = self.get_layer(int(not vertical))
|
||||||
|
half_wire_vector = vector([self.half_wire] * 2)
|
||||||
|
nll = fake_center - half_wire_vector - half_wire_vector
|
||||||
|
nur = fake_center + half_wire_vector + half_wire_vector
|
||||||
|
rect = [nll, nur]
|
||||||
|
#fake_pin = [pin.name() + "_" + "fake", fake_center, rect, layer]
|
||||||
|
fake_pin = graph_shape(name=pin.name + "_" + "fake",
|
||||||
|
rect=rect,
|
||||||
|
layer_name_pp=layer)
|
||||||
|
|
||||||
|
if edge == "left":
|
||||||
|
self.io_pins_added_left.append(fake_pin)
|
||||||
|
elif edge == "bottom":
|
||||||
|
self.io_pins_added_down.append(fake_pin)
|
||||||
|
elif edge == "right":
|
||||||
|
self.io_pins_added_right.append(fake_pin)
|
||||||
|
elif edge == "top":
|
||||||
|
self.io_pins_added_up.append(fake_pin)
|
||||||
|
|
||||||
|
self.io_pins_fake.append(fake_pin)
|
||||||
|
debug.warning("pin added: {0}".format(fake_pin))
|
||||||
|
|
||||||
|
|
||||||
def create_fake_pin(self, pin):
|
def create_fake_pin(self, pin):
|
||||||
""" Create a fake pin on the perimeter orthogonal to the given pin. """
|
""" Create a fake pin on the perimeter orthogonal to the given pin. """
|
||||||
|
|
||||||
|
|
@ -63,51 +217,70 @@ class io_pin_placer(router):
|
||||||
print(pin.name)
|
print(pin.name)
|
||||||
# Find the closest edge
|
# Find the closest edge
|
||||||
edge, vertical = self.get_closest_edge(c)
|
edge, vertical = self.get_closest_edge(c)
|
||||||
|
# Relocate the pin position of addr/dout
|
||||||
|
pattern_addr = r'^addr'
|
||||||
|
pattern_dout = r'^dout'
|
||||||
|
if re.match(pattern_addr, pin.name):# all the addr[] should be placed at vertical edge
|
||||||
|
if edge == "top" or edge == "left":
|
||||||
|
edge = "left"
|
||||||
|
vertical = True
|
||||||
|
elif edge == "bottom" or edge == "right":
|
||||||
|
edge = "right"
|
||||||
|
vertical = True
|
||||||
|
|
||||||
|
if re.match(pattern_dout, pin.name):# all the dout[] should be placed at horizontal edge
|
||||||
|
if edge == "bottom" or edge == "right":
|
||||||
|
edge = "bottom"
|
||||||
|
vertical = False
|
||||||
|
elif edge == "top" or edge == "left":
|
||||||
|
edge = "top"
|
||||||
|
vertical = False
|
||||||
|
|
||||||
offset = 0.95 + 0.19 # FIX: this is the magic number to overcome the ovetflow problem at the boundary, may need a method
|
offset = 0.95 + 0.19 # FIX: this is the magic number to overcome the ovetflow problem at the boundary, may need a method
|
||||||
add_distance = 0
|
add_distance = 0
|
||||||
# Keep the fake pin out of the SRAM layout are so that they won't be
|
# Keep the fake pin out of the SRAM layout are so that they won't be
|
||||||
# blocked by previous signals if they're on the same orthogonal line
|
# blocked by previous signals if they're on the same orthogonal line
|
||||||
if edge == "left":
|
if edge == "left":
|
||||||
fake_center = vector(ll.x - self.track_wire * 2 + offset, c.y)
|
fake_center = vector(ll.x - self.track_wire * 2 + offset, c.y)
|
||||||
is_too_close = any(abs(pin_added.center().y - fake_center.y) < (0.8 + self.half_wire * 4)for pin_added in self.io_pins_added_left)
|
is_too_close = any(abs(pin_added.center().y - fake_center.y) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_left)
|
||||||
while is_too_close:
|
while is_too_close:
|
||||||
debug.warning("overlap, changing position")
|
debug.warning("overlap, changing position")
|
||||||
add_distance = add_distance + 0.8 + self.half_wire * 4
|
add_distance = add_distance + 0.1#+ 0.4 + self.half_wire * 4
|
||||||
fake_center = vector(ll.x - self.track_wire * 2 + offset, c.y + add_distance)
|
fake_center = vector(ll.x - self.track_wire * 2 + offset, c.y + add_distance)
|
||||||
is_too_close = any(abs(pin_added.center().y - fake_center.y) < (0.8 + self.half_wire * 4)for pin_added in self.io_pins_added_left)
|
is_too_close = any(abs(pin_added.center().y - fake_center.y) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_left)
|
||||||
|
|
||||||
if edge == "bottom":
|
if edge == "bottom":
|
||||||
fake_center = vector(c.x, ll.y - self.track_wire * 2 + offset)
|
fake_center = vector(c.x, ll.y - self.track_wire * 2 + offset)
|
||||||
is_too_close = any(abs(pin_added.center().x - fake_center.x) < (0.8 + self.half_wire * 4)for pin_added in self.io_pins_added_down)
|
is_too_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_down)
|
||||||
while is_too_close:
|
while is_too_close:
|
||||||
debug.warning("overlap, changing position")
|
debug.warning("overlap, changing position")
|
||||||
add_distance = add_distance + 0.8 + self.half_wire * 4
|
add_distance = add_distance + 0.1#0.4 + self.half_wire * 4
|
||||||
fake_center = vector(c.x + add_distance, ll.y - self.track_wire * 2 + offset)
|
fake_center = vector(c.x + add_distance, ll.y - self.track_wire * 2 + offset)
|
||||||
is_too_close = any(abs(pin_added.center().x - fake_center.x) < (0.8 + self.half_wire * 4)for pin_added in self.io_pins_added_down)
|
is_too_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_down)
|
||||||
|
|
||||||
if edge == "right":
|
if edge == "right":
|
||||||
fake_center = vector(ur.x + self.track_wire * 2 - offset, c.y)
|
fake_center = vector(ur.x + self.track_wire * 2 - offset, c.y)
|
||||||
is_too_close = any(abs(pin_added.center().y - fake_center.y) < (0.8 + self.half_wire * 4)for pin_added in self.io_pins_added_right)
|
is_too_close = any(abs(pin_added.center().y - fake_center.y) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_right)
|
||||||
while is_too_close:
|
while is_too_close:
|
||||||
debug.warning("overlap, changing position")
|
debug.warning("overlap, changing position")
|
||||||
add_distance = add_distance + 0.8 + self.half_wire * 4
|
add_distance = add_distance + 0.1#0.4 + self.half_wire * 4
|
||||||
fake_center = vector(ur.x + self.track_wire * 2 - offset, c.y + add_distance)
|
fake_center = vector(ur.x + self.track_wire * 2 - offset, c.y + add_distance)
|
||||||
# debug
|
# debug
|
||||||
for pin_added in self.io_pins_added_right:
|
for pin_added in self.io_pins_added_right:
|
||||||
dis = abs(pin_added.center().y - fake_center.y)
|
dis = abs(pin_added.center().y - fake_center.y)
|
||||||
debug.warning("current position is {0}".format(fake_center))
|
debug.warning("current position is {0}".format(fake_center))
|
||||||
debug.warning("distance from {0} is {1}".format(pin_added, dis))
|
debug.warning("distance from {0} is {1}".format(pin_added, dis))
|
||||||
debug.warning("must disrance is {0}".format(0.8 + self.half_wire * 4))
|
debug.warning("must disrance is {0}".format(0.4 + self.half_wire * 4))
|
||||||
is_too_close = any(abs(pin_added.center().y - fake_center.y) < (0.8 + self.half_wire * 4)for pin_added in self.io_pins_added_right)
|
is_too_close = any(abs(pin_added.center().y - fake_center.y) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_right)
|
||||||
|
|
||||||
if edge == "top":
|
if edge == "top":
|
||||||
fake_center = vector(c.x, ur.y + self.track_wire * 2 - offset)
|
fake_center = vector(c.x, ur.y + self.track_wire * 2 - offset)
|
||||||
is_too_close = any(abs(pin_added.center().x - fake_center.x) < (0.8 + self.half_wire * 4)for pin_added in self.io_pins_added_up)
|
is_too_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_up)
|
||||||
while is_too_close:
|
while is_too_close:
|
||||||
debug.warning("overlap, changing position")
|
debug.warning("overlap, changing position")
|
||||||
add_distance = add_distance + 0.8 + self.half_wire * 4
|
add_distance = add_distance + 0.1#0.4 + self.half_wire * 4
|
||||||
fake_center = vector(c.x + add_distance, ur.y + self.track_wire * 2 - offset)
|
fake_center = vector(c.x + add_distance, ur.y + self.track_wire * 2 - offset)
|
||||||
is_too_close = any(abs(pin_added.center().x - fake_center.x) < (0.8 + self.half_wire * 4)for pin_added in self.io_pins_added_up)
|
is_too_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_up)
|
||||||
|
|
||||||
# Create the fake pin shape, here make sure the pin in the gds will be big enough
|
# Create the fake pin shape, here make sure the pin in the gds will be big enough
|
||||||
layer = self.get_layer(int(not vertical))
|
layer = self.get_layer(int(not vertical))
|
||||||
|
|
@ -133,11 +306,11 @@ class io_pin_placer(router):
|
||||||
self.io_pins_added_up.append(pin)
|
self.io_pins_added_up.append(pin)
|
||||||
debug.warning("pin added: {0}".format(pin))
|
debug.warning("pin added: {0}".format(pin))
|
||||||
|
|
||||||
return pin
|
return pin, vertical, add_distance
|
||||||
|
|
||||||
|
|
||||||
def add_io_pins(self, pin_names):
|
def add_io_pins(self, pin_names):
|
||||||
""" Add IO pins on the edges without routing them. """
|
""" Add IO pins on the edges WITHOUT routing them. """
|
||||||
debug.info(1, "Adding IO pins on the perimeter...")
|
debug.info(1, "Adding IO pins on the perimeter...")
|
||||||
|
|
||||||
# Prepare GDS reader (if necessary for pin/blockage identification)
|
# Prepare GDS reader (if necessary for pin/blockage identification)
|
||||||
|
|
@ -147,16 +320,188 @@ class io_pin_placer(router):
|
||||||
for name in pin_names:
|
for name in pin_names:
|
||||||
self.find_pins(name)# this will add the pins to the self.pins
|
self.find_pins(name)# this will add the pins to the self.pins
|
||||||
|
|
||||||
# Replace layout pins with those on the perimeter
|
# inital position
|
||||||
|
pin_list = []
|
||||||
for name in self.pins:
|
for name in self.pins:
|
||||||
pin = next(iter(self.pins[name]))
|
pin = next(iter(self.pins[name]))
|
||||||
fake_pin = self.create_fake_pin(pin)
|
pin_list.append(pin)
|
||||||
self.design.replace_layout_pin(name, fake_pin) # if do not have replace_layout_pin, final gds won't have io pins
|
|
||||||
|
self.initial_position(pin_list)
|
||||||
|
|
||||||
|
# Change IO pin names, which means "internal name" will be used, and internal io pins will not have label such as "dout0[0]"
|
||||||
|
self.replace_layout_pins(pin_names)
|
||||||
|
|
||||||
|
|
||||||
|
def add_io_pins_connected(self, pin_names):
|
||||||
|
""" Add IO pins on the edges WITH routing them. """
|
||||||
|
debug.info(1, "Adding IO pins on the perimeter...")
|
||||||
|
|
||||||
|
# Prepare GDS reader (if necessary for pin/blockage identification)
|
||||||
|
self.prepare_gds_reader()
|
||||||
|
|
||||||
|
# Find pins to be added (without routing)
|
||||||
|
for name in pin_names:
|
||||||
|
self.find_pins(name)# this will add the pins to the self.pins
|
||||||
|
debug.warning("the pins in pin_name -> {0}".format(name))
|
||||||
|
|
||||||
|
# inital position
|
||||||
|
pin_list = []
|
||||||
|
for name in self.pins:
|
||||||
|
pin = next(iter(self.pins[name]))
|
||||||
|
pin_list.append(pin)
|
||||||
|
debug.warning("the pins in self.pins -> {0}".format(name))
|
||||||
|
|
||||||
|
self.initial_position(pin_list)
|
||||||
|
|
||||||
|
# add fake io pins at the perimeter, which will be used for routing
|
||||||
|
for fake_pin in self.io_pins_fake:
|
||||||
|
self.design.add_layout_pin(text=fake_pin.name,
|
||||||
|
layer=fake_pin.layer,
|
||||||
|
offset=fake_pin.ll(),
|
||||||
|
width=fake_pin.width(),
|
||||||
|
height=fake_pin.height())
|
||||||
|
|
||||||
|
# connect the source_pin and io_pin(target)
|
||||||
|
self.connect_pins(pin_names)
|
||||||
|
|
||||||
|
# remove the fake pin before change the name, in order to avoid possible problem
|
||||||
|
for fake_pin in self.io_pins_fake:
|
||||||
|
self.remove_io_pins(fake_pin.name)
|
||||||
|
|
||||||
|
# Change IO pin names, which means "internal name" will be used, and internal io pins will not have label such as "dout0[0]"
|
||||||
|
self.replace_layout_pins(pin_names)
|
||||||
|
|
||||||
|
|
||||||
|
def connect_pins(self, pin_names): # pin_names should be a list
|
||||||
|
""" Add IO pins on the edges, and connect them to the internal one, not-graph like process """
|
||||||
|
debug.info(1, "connecting to io pins...")
|
||||||
|
pattern_dout = r'^dout'
|
||||||
|
for pin_name in pin_names:
|
||||||
|
# get pin pairs ready
|
||||||
|
source_pin = next(iter(self.pins[pin_name]))
|
||||||
|
for fake_pin in self.io_pins_fake:
|
||||||
|
if pin_name + "_" + "fake" == fake_pin.name:
|
||||||
|
target_pin = fake_pin
|
||||||
|
break
|
||||||
|
# special hanlde dout pins
|
||||||
|
if re.match(pattern_dout, pin_name):
|
||||||
|
number_str = re.findall(r'\[(\d+)\]', pin_name)
|
||||||
|
if number_str:
|
||||||
|
number = int(number_str[0])
|
||||||
|
if number % 2 == 0:
|
||||||
|
is_up = True
|
||||||
|
else:
|
||||||
|
is_up = False
|
||||||
|
point_list = self.decide_point(source_pin, target_pin, is_up)
|
||||||
|
self.add_wire(point_list)
|
||||||
|
# other pins
|
||||||
|
else:
|
||||||
|
debug.warning("source{0}".format(source_pin.center()))
|
||||||
|
debug.warning("target{0}".format(target_pin.center()))
|
||||||
|
point_list = self.decide_point(source_pin, target_pin)
|
||||||
|
debug.warning("point_list->{0}".format(point_list))
|
||||||
|
self.add_wire(point_list)
|
||||||
|
|
||||||
|
|
||||||
|
def add_wire(self, point_list):
|
||||||
|
if len(point_list) == 2:
|
||||||
|
# direct connect
|
||||||
|
self.add_line(point_list[0], point_list[1])
|
||||||
|
elif len(point_list) == 4:
|
||||||
|
# intermediate points
|
||||||
|
self.add_line(point_list[0], point_list[1])
|
||||||
|
self.add_via(point_list[1])
|
||||||
|
self.add_line(point_list[1], point_list[2])
|
||||||
|
self.add_via(point_list[2])
|
||||||
|
self.add_line(point_list[2], point_list[3])
|
||||||
|
|
||||||
|
|
||||||
|
def add_line(self, point_1, point_2):
|
||||||
|
if round(point_1.y, 3) == round(point_2.y, 3):
|
||||||
|
# horizontal m3
|
||||||
|
self.design.add_path(self.get_layer(False), [point_1, point_2])
|
||||||
|
else:
|
||||||
|
# vertical m4
|
||||||
|
self.design.add_path(self.get_layer(True), [point_1, point_2])
|
||||||
|
|
||||||
|
|
||||||
|
def add_via(self, point):
|
||||||
|
# currently only m3-m4 vias are supported in this method
|
||||||
|
# usd in order to make "z" shape routing only
|
||||||
|
self.design.add_via_stack_center(from_layer=self.get_layer(False),
|
||||||
|
to_layer=self.get_layer(True),
|
||||||
|
offset=point)
|
||||||
|
|
||||||
|
|
||||||
|
def add_start_via(self, point):
|
||||||
|
# currently only m3-m4 vias are supported in this method
|
||||||
|
# used in source_pin only
|
||||||
|
self.design.add_via_stack_center(from_layer=self.get_layer(False),
|
||||||
|
to_layer=self.get_layer(True),
|
||||||
|
offset=point)
|
||||||
|
|
||||||
|
|
||||||
|
def decide_point(self, source_pin, target_pin, is_up=False):
|
||||||
|
ll, ur = self.bbox
|
||||||
|
offset = 0.95 + 0.19 # FIX: this is the magic number to overcome the ovetflow problem at the boundary, may need a method
|
||||||
|
# internal -> left
|
||||||
|
if round(target_pin.center().x, 3) == round(ll.x - self.track_wire * 2 + offset, 3):
|
||||||
|
# direct connect possible
|
||||||
|
return [source_pin.rc(), target_pin.lc()] # FIX: not sure if shape overlap in met3 allowed, but seems OK
|
||||||
|
# internal -> right
|
||||||
|
if round(target_pin.center().x, 3) == round(ur.x + self.track_wire * 2 - offset, 3):
|
||||||
|
# direct connect possible
|
||||||
|
return [source_pin.lc(), target_pin.rc()]
|
||||||
|
# internal -> top, need to add start_via m3->m4
|
||||||
|
if round(target_pin.center().y, 3) == round(ur.y + self.track_wire * 2 - offset, 3):
|
||||||
|
self.add_start_via(source_pin.center())
|
||||||
|
if round(target_pin.center().x, 3) == round(source_pin.center().x, 3):
|
||||||
|
# direct connect possible
|
||||||
|
return [source_pin.bc(), target_pin.uc()]
|
||||||
|
else:
|
||||||
|
# need intermediate point
|
||||||
|
via_basic_y = self.design.bank.height + 3 # 3 is magic number, make sure out of bank area
|
||||||
|
is_up = not is_up# Be attention, for channel at the top, the is_up should be inverted! Otherwise will cause overlap!
|
||||||
|
if is_up:
|
||||||
|
via_basic_y = via_basic_y + 0.5
|
||||||
|
else:
|
||||||
|
via_basic_y = via_basic_y - 0.5
|
||||||
|
point_1 = vector(source_pin.center().x, via_basic_y)
|
||||||
|
point_2 = vector(target_pin.center().x, via_basic_y)
|
||||||
|
return [source_pin.bc(), point_1, point_2, target_pin.uc()]
|
||||||
|
# internal -> bottom, need to add start_via m3->m4
|
||||||
|
if round(target_pin.center().y, 3) == round(ll.y - self.track_wire * 2 + offset, 3):
|
||||||
|
self.add_start_via(source_pin.center())
|
||||||
|
if round(target_pin.center().x, 3) == round(source_pin.center().x, 3):
|
||||||
|
# direct connect possible
|
||||||
|
return [source_pin.uc(), target_pin.bc()]
|
||||||
|
else:
|
||||||
|
# need intermediate point
|
||||||
|
via_basic_y = ll.y + 21 # 21 is magic number, make sure out of dff area
|
||||||
|
if is_up:
|
||||||
|
via_basic_y = via_basic_y + 0.5
|
||||||
|
else:
|
||||||
|
via_basic_y = via_basic_y - 0.5
|
||||||
|
point_1 = vector(source_pin.center().x, via_basic_y)
|
||||||
|
point_2 = vector(target_pin.center().x, via_basic_y)
|
||||||
|
return [source_pin.uc(), point_1, point_2, target_pin.bc()]
|
||||||
|
|
||||||
|
|
||||||
def remove_io_pins(self, pin_name):
|
def remove_io_pins(self, pin_name):
|
||||||
# remove io pin in gds, so we could reroute
|
# remove io pin in gds, so we could reroute
|
||||||
self.design.remove_layout_pin(pin_name)
|
self.design.remove_layout_pin(pin_name)
|
||||||
|
|
||||||
|
|
||||||
|
def replace_layout_pins(self, pin_names):
|
||||||
|
""" Change the IO pin names with new ones around the perimeter. """
|
||||||
|
for pin_name in pin_names:
|
||||||
|
perimeter_pin_name = pin_name + "_" + "fake"
|
||||||
|
for pin in self.io_pins_fake:
|
||||||
|
if pin.name == perimeter_pin_name:
|
||||||
|
perimeter_pin = pin
|
||||||
|
self.design.replace_layout_pin(pin_name, perimeter_pin)
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue