mirror of
https://github.com/VLSIDA/OpenRAM.git
synced 2026-08-29 01:24:39 +02:00
Rewrite blockage routines in router. Clean up GdsMill code.
This commit is contained in:
@@ -89,7 +89,7 @@ class astar_grid(grid.grid):
|
||||
self.counter+=1
|
||||
|
||||
|
||||
def astar_route(self,detour_scale):
|
||||
def route(self,detour_scale):
|
||||
"""
|
||||
This does the A* maze routing with preferred direction routing.
|
||||
"""
|
||||
|
||||
@@ -36,6 +36,9 @@ class grid:
|
||||
def add_blockage_shape(self,ll,ur,z):
|
||||
debug.info(3,"Adding blockage ll={0} ur={1} z={2}".format(str(ll),str(ur),z))
|
||||
|
||||
if ll[0]<42 and ll[0]>38 and ll[1]<3 and ll[1]>0:
|
||||
debug.info(0,"Adding blockage ll={0} ur={1} z={2}".format(str(ll),str(ur),z))
|
||||
|
||||
block_list = []
|
||||
for x in range(int(ll[0]),int(ur[0])+1):
|
||||
for y in range(int(ll[1]),int(ur[1])+1):
|
||||
|
||||
+118
-41
@@ -27,8 +27,7 @@ class router:
|
||||
self.top_name = self.layout.rootStructureName
|
||||
|
||||
self.pins = {}
|
||||
# the list of all blockage shapes
|
||||
self.blockages = []
|
||||
self.blockages=[]
|
||||
# all the paths we've routed so far (to supplement the blockages)
|
||||
self.paths = []
|
||||
|
||||
@@ -101,9 +100,9 @@ class router:
|
||||
This doesn't consider whether the obstacles will be pins or not. They get reset later
|
||||
if they are not actually a blockage.
|
||||
"""
|
||||
for layer in self.layers:
|
||||
self.get_blockages(self.top_name)
|
||||
|
||||
#for layer in [self.vert_layer_number,self.horiz_layer_number]:
|
||||
# self.get_blockages(layer)
|
||||
self.get_blockages(self.horiz_layer_number)
|
||||
|
||||
def clear_pins(self):
|
||||
"""
|
||||
@@ -207,38 +206,50 @@ class router:
|
||||
self.rg.add_blockage_shape(ll,ur,zlayer)
|
||||
|
||||
|
||||
def get_blockages(self, sref, mirr = 1, angle = math.radians(float(0)), xyShift = (0, 0)):
|
||||
def get_blockages(self, layer_num):
|
||||
"""
|
||||
Recursive find boundaries as blockages to the routing grid.
|
||||
Recurses for each Structure in GDS.
|
||||
"""
|
||||
for boundary in self.layout.structures[sref].boundaries:
|
||||
coord_trans = self.translate_coordinates(boundary.coordinates, mirr, angle, xyShift)
|
||||
shape_coords = self.min_max_coord(coord_trans)
|
||||
shape = self.convert_shape_to_units(shape_coords)
|
||||
|
||||
# only consider the two layers that we are routing on
|
||||
if boundary.drawingLayer in [self.vert_layer_number,self.horiz_layer_number]:
|
||||
# store the blockages as pin layouts so they are easy to compare etc.
|
||||
self.blockages.append(pin_layout("blockage",shape,boundary.drawingLayer))
|
||||
shapes = self.layout.getAllShapesInStructureList(layer_num)
|
||||
|
||||
for boundary in shapes:
|
||||
rect = [vector(boundary[0],boundary[1]),vector(boundary[2],boundary[3])]
|
||||
new_pin = pin_layout("blockage",rect,layer_num)
|
||||
self.blockages.append(new_pin)
|
||||
|
||||
|
||||
# for boundary in self.layout.structures[sref].boundaries:
|
||||
# coord_trans = self.translate_coordinates(boundary.coordinates, mirr, angle, xyShift)
|
||||
# shape_coords = self.min_max_coord(coord_trans)
|
||||
# shape = self.convert_shape_to_units(shape_coords)
|
||||
|
||||
# # only consider the two layers that we are routing on
|
||||
# if boundary.drawingLayer in [self.vert_layer_number,self.horiz_layer_number]:
|
||||
# # store the blockages as pin layouts so they are easy to compare etc.
|
||||
# new_pin = pin_layout("blockage",shape,boundary.drawingLayer)
|
||||
# # avoid repeated blockage pins
|
||||
# if new_pin not in self.blockages:
|
||||
# self.blockages.append(new_pin)
|
||||
|
||||
|
||||
# recurse given the mirror, angle, etc.
|
||||
for cur_sref in self.layout.structures[sref].srefs:
|
||||
sMirr = 1
|
||||
if cur_sref.transFlags[0] == True:
|
||||
sMirr = -1
|
||||
sAngle = math.radians(float(0))
|
||||
if cur_sref.rotateAngle:
|
||||
sAngle = math.radians(float(cur_sref.rotateAngle))
|
||||
sAngle += angle
|
||||
x = cur_sref.coordinates[0]
|
||||
y = cur_sref.coordinates[1]
|
||||
newX = (x)*math.cos(angle) - mirr*(y)*math.sin(angle) + xyShift[0]
|
||||
newY = (x)*math.sin(angle) + mirr*(y)*math.cos(angle) + xyShift[1]
|
||||
sxyShift = (newX, newY)
|
||||
# # recurse given the mirror, angle, etc.
|
||||
# for cur_sref in self.layout.structures[sref].srefs:
|
||||
# sMirr = 1
|
||||
# if cur_sref.transFlags[0] == True:
|
||||
# sMirr = -1
|
||||
# sAngle = math.radians(float(0))
|
||||
# if cur_sref.rotateAngle:
|
||||
# sAngle = math.radians(float(cur_sref.rotateAngle))
|
||||
# sAngle += angle
|
||||
# x = cur_sref.coordinates[0]
|
||||
# y = cur_sref.coordinates[1]
|
||||
# newX = (x)*math.cos(angle) - mirr*(y)*math.sin(angle) + xyShift[0]
|
||||
# newY = (x)*math.sin(angle) + mirr*(y)*math.cos(angle) + xyShift[1]
|
||||
# sxyShift = (newX, newY)
|
||||
|
||||
self.get_blockages(cur_sref.sName, sMirr, sAngle, sxyShift)
|
||||
# self.get_blockages(cur_sref.sName, sMirr, sAngle, sxyShift)
|
||||
|
||||
|
||||
def convert_point_to_units(self,p):
|
||||
"""
|
||||
@@ -248,21 +259,25 @@ class router:
|
||||
pt=pt.scale(self.track_widths[0],self.track_widths[1],1)
|
||||
return pt
|
||||
|
||||
def convert_blockage_to_tracks(self,shape,round_bigger=False):
|
||||
def convert_blockage_to_tracks(self,shape):
|
||||
"""
|
||||
Convert a rectangular blockage shape into track units.
|
||||
"""
|
||||
[ll,ur] = shape
|
||||
ll = snap_to_grid(ll)
|
||||
ur = snap_to_grid(ur)
|
||||
(ll,ur) = shape
|
||||
# ll = snap_to_grid(ll)
|
||||
# ur = snap_to_grid(ur)
|
||||
|
||||
# to scale coordinates to tracks
|
||||
#debug.info(1,"Converting [ {0} , {1} ]".format(ll,ur))
|
||||
debug.info(3,"Converting [ {0} , {1} ]".format(ll,ur))
|
||||
old_ll = ll
|
||||
old_ur = ur
|
||||
ll=ll.scale(self.track_factor)
|
||||
ur=ur.scale(self.track_factor)
|
||||
ll = ll.floor() if round_bigger else ll.round()
|
||||
ur = ur.ceil() if round_bigger else ur.round()
|
||||
#debug.info(1,"Converted [ {0} , {1} ]".format(ll,ur))
|
||||
ll = ll.floor()
|
||||
ur = ur.ceil()
|
||||
if ll[0]<45 and ll[0]>35 and ll[1]<10 and ll[1]>0:
|
||||
debug.info(0,"Converting [ {0} , {1} ]".format(old_ll,old_ur))
|
||||
debug.info(0,"Converted [ {0} , {1} ]".format(ll,ur))
|
||||
return [ll,ur]
|
||||
|
||||
def convert_pin_to_tracks(self, pin):
|
||||
@@ -271,9 +286,9 @@ class router:
|
||||
If no on-grid pins are found, it searches for the nearest off-grid pin(s).
|
||||
If a pin has insufficent overlap, it returns the blockage list to avoid it.
|
||||
"""
|
||||
[ll,ur] = pin.rect
|
||||
ll = snap_to_grid(ll)
|
||||
ur = snap_to_grid(ur)
|
||||
(ll,ur) = pin.rect
|
||||
#ll = snap_to_grid(ll)
|
||||
#ur = snap_to_grid(ur)
|
||||
|
||||
#debug.info(1,"Converting [ {0} , {1} ]".format(ll,ur))
|
||||
|
||||
@@ -401,6 +416,68 @@ class router:
|
||||
self.write_debug_gds()
|
||||
debug.check(found_pin,"Unable to find pin on grid.")
|
||||
|
||||
def write_debug_gds(self):
|
||||
"""
|
||||
Write out a GDS file with the routing grid and search information annotated on it.
|
||||
"""
|
||||
# Only add the debug info to the gds file if we have any debugging on.
|
||||
# This is because we may reroute a wire with detours and don't want the debug information.
|
||||
if OPTS.debug_level==0: return
|
||||
|
||||
self.add_router_info()
|
||||
debug.error("Writing debug_route.gds")
|
||||
self.cell.gds_write("debug_route.gds")
|
||||
|
||||
def add_router_info(self):
|
||||
"""
|
||||
Write the routing grid and router cost, blockage, pins on
|
||||
the boundary layer for debugging purposes. This can only be
|
||||
called once or the labels will overlap.
|
||||
"""
|
||||
debug.info(0,"Adding router info")
|
||||
grid_keys=self.rg.map.keys()
|
||||
partial_track=vector(0,self.track_width/6.0)
|
||||
for g in grid_keys:
|
||||
continue # for now...
|
||||
shape = self.convert_full_track_to_shape(g)
|
||||
self.cell.add_rect(layer="boundary",
|
||||
offset=shape[0],
|
||||
width=shape[1].x-shape[0].x,
|
||||
height=shape[1].y-shape[0].y)
|
||||
# These are the on grid pins
|
||||
#rect = self.convert_track_to_pin(g)
|
||||
#self.cell.add_rect(layer="boundary",
|
||||
# offset=rect[0],
|
||||
# width=rect[1].x-rect[0].x,
|
||||
# height=rect[1].y-rect[0].y)
|
||||
|
||||
t=self.rg.map[g].get_type()
|
||||
|
||||
# midpoint offset
|
||||
off=vector((shape[1].x+shape[0].x)/2,
|
||||
(shape[1].y+shape[0].y)/2)
|
||||
if g[2]==1:
|
||||
# Upper layer is upper right label
|
||||
type_off=off+partial_track
|
||||
else:
|
||||
# Lower layer is lower left label
|
||||
type_off=off-partial_track
|
||||
if t!=None:
|
||||
self.cell.add_label(text=str(t),
|
||||
layer="text",
|
||||
offset=type_off)
|
||||
self.cell.add_label(text="{0},{1}".format(g[0],g[1]),
|
||||
layer="text",
|
||||
offset=shape[0],
|
||||
zoom=0.05)
|
||||
|
||||
for blockage in self.blockages:
|
||||
self.cell.add_rect(layer="boundary",
|
||||
offset=blockage.ll(),
|
||||
width=blockage.width(),
|
||||
height=blockage.height())
|
||||
|
||||
|
||||
# FIXME: This should be replaced with vector.snap_to_grid at some point
|
||||
|
||||
def snap_to_grid(offset):
|
||||
|
||||
@@ -26,7 +26,7 @@ class signal_router(router):
|
||||
|
||||
def create_routing_grid(self):
|
||||
"""
|
||||
Create a routing grid that spans given area. Wires cannot exist outside region.
|
||||
Create a sprase routing grid with A* expansion functions.
|
||||
"""
|
||||
# We will add a halo around the boundary
|
||||
# of this many tracks
|
||||
@@ -44,6 +44,8 @@ class signal_router(router):
|
||||
This is used to speed up the routing when there is not much detouring needed.
|
||||
"""
|
||||
self.cell = cell
|
||||
self.source_pin_name = src
|
||||
self.target_pin_name = dest
|
||||
|
||||
# Clear the pins if we have previously routed
|
||||
if (hasattr(self,'rg')):
|
||||
@@ -73,7 +75,7 @@ class signal_router(router):
|
||||
|
||||
|
||||
# returns the path in tracks
|
||||
(path,cost) = self.rg.astar_route(detour_scale)
|
||||
(path,cost) = self.rg.route(detour_scale)
|
||||
if path:
|
||||
debug.info(1,"Found path: cost={0} ".format(cost))
|
||||
debug.info(2,str(path))
|
||||
@@ -158,59 +160,3 @@ class signal_router(router):
|
||||
|
||||
|
||||
|
||||
|
||||
def write_debug_gds(self):
|
||||
"""
|
||||
Write out a GDS file with the routing grid and search information annotated on it.
|
||||
"""
|
||||
# Only add the debug info to the gds file if we have any debugging on.
|
||||
# This is because we may reroute a wire with detours and don't want the debug information.
|
||||
if OPTS.debug_level==0: return
|
||||
|
||||
self.add_router_info()
|
||||
pin_names = list(self.pins.keys())
|
||||
debug.error("Writing debug_route.gds from {0} to {1}".format(self.source_pin_name,self.target_pin_name))
|
||||
self.cell.gds_write("debug_route.gds")
|
||||
|
||||
def add_router_info(self):
|
||||
"""
|
||||
Write the routing grid and router cost, blockage, pins on
|
||||
the boundary layer for debugging purposes. This can only be
|
||||
called once or the labels will overlap.
|
||||
"""
|
||||
debug.info(0,"Adding router info for {0} to {1}".format(self.source_pin_name,self.target_pin_name))
|
||||
grid_keys=self.rg.map.keys()
|
||||
partial_track=vector(0,self.track_width/6.0)
|
||||
for g in grid_keys:
|
||||
shape = self.convert_full_track_to_shape(g)
|
||||
self.cell.add_rect(layer="boundary",
|
||||
offset=shape[0],
|
||||
width=shape[1].x-shape[0].x,
|
||||
height=shape[1].y-shape[0].y)
|
||||
# These are the on grid pins
|
||||
#rect = self.convert_track_to_pin(g)
|
||||
#self.cell.add_rect(layer="boundary",
|
||||
# offset=rect[0],
|
||||
# width=rect[1].x-rect[0].x,
|
||||
# height=rect[1].y-rect[0].y)
|
||||
|
||||
t=self.rg.map[g].get_type()
|
||||
|
||||
# midpoint offset
|
||||
off=vector((shape[1].x+shape[0].x)/2,
|
||||
(shape[1].y+shape[0].y)/2)
|
||||
if g[2]==1:
|
||||
# Upper layer is upper right label
|
||||
type_off=off+partial_track
|
||||
else:
|
||||
# Lower layer is lower left label
|
||||
type_off=off-partial_track
|
||||
if t!=None:
|
||||
self.cell.add_label(text=str(t),
|
||||
layer="text",
|
||||
offset=type_off)
|
||||
self.cell.add_label(text="{0},{1}".format(g[0],g[1]),
|
||||
layer="text",
|
||||
offset=shape[0],
|
||||
zoom=0.05)
|
||||
|
||||
|
||||
@@ -66,24 +66,22 @@ class supply_router(router):
|
||||
# Add blockages from previous routes
|
||||
self.add_path_blockages()
|
||||
|
||||
# Now add the src/tgt if they are not blocked by other shapes
|
||||
self.add_pin(vdd_name,True)
|
||||
#self.add_pin()
|
||||
|
||||
# source pin will be a specific layout pin
|
||||
# target pin will be the rails only
|
||||
|
||||
# returns the path in tracks
|
||||
(path,cost) = self.rg.route(detour_scale)
|
||||
if path:
|
||||
debug.info(1,"Found path: cost={0} ".format(cost))
|
||||
debug.info(2,str(path))
|
||||
self.add_route(path)
|
||||
return True
|
||||
else:
|
||||
self.write_debug_gds()
|
||||
# clean up so we can try a reroute
|
||||
self.clear_pins()
|
||||
# (path,cost) = self.rg.route(detour_scale)
|
||||
# if path:
|
||||
# debug.info(1,"Found path: cost={0} ".format(cost))
|
||||
# debug.info(2,str(path))
|
||||
# self.add_route(path)
|
||||
# return True
|
||||
# else:
|
||||
# self.write_debug_gds()
|
||||
# # clean up so we can try a reroute
|
||||
# self.clear_pins()
|
||||
|
||||
|
||||
self.write_debug_gds()
|
||||
return False
|
||||
|
||||
|
||||
@@ -114,6 +112,17 @@ class supply_router(router):
|
||||
self.cell.add_route(self.layers,abs_path)
|
||||
|
||||
|
||||
def create_routing_grid(self):
|
||||
"""
|
||||
Create a sprase routing grid with A* expansion functions.
|
||||
"""
|
||||
# We will add a halo around the boundary
|
||||
# of this many tracks
|
||||
size = self.ur - self.ll
|
||||
debug.info(1,"Size: {0} x {1}".format(size.x,size.y))
|
||||
|
||||
import supply_grid
|
||||
self.rg = supply_grid.supply_grid()
|
||||
|
||||
|
||||
##########################
|
||||
@@ -135,6 +144,3 @@ class supply_router(router):
|
||||
""" Create alternating vdd/gnd lines horizontally """
|
||||
pass
|
||||
|
||||
def route(self):
|
||||
#self.create_grid()
|
||||
pass
|
||||
|
||||
@@ -38,7 +38,7 @@ class no_blockages_test(openram_test):
|
||||
self.connect_inst([])
|
||||
|
||||
r=router(gds_file)
|
||||
layer_stack =("metal3","via1","metal2")
|
||||
layer_stack =("metal3","via2","metal2")
|
||||
self.assertTrue(r.route(self,layer_stack))
|
||||
|
||||
r=routing("10_supply_grid_test_{0}".format(OPTS.tech_name))
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user