Moving wide metal spacing to routing grid level

This commit is contained in:
Matt Guthaus 2018-10-15 09:59:16 -07:00
parent 1c426aad29
commit d855d4f1a6
4 changed files with 49 additions and 32 deletions

View File

@ -16,7 +16,7 @@ class design_rules():
def __call__(self, name, *args): def __call__(self, name, *args):
rule = self.rules[name] rule = self.rules[name]
if callable(rule): if callable(rule):
return rule(args) return rule(*args)
else: else:
return rule return rule

View File

@ -1,3 +1,4 @@
import debug
class drc_lut(): class drc_lut():
""" """
@ -6,8 +7,8 @@ class drc_lut():
It searches through backwards until all of the key values are It searches through backwards until all of the key values are
met and returns the rule value. met and returns the rule value.
For exampe, the key values can be width and length, For exampe, the key values can be width and length,
and it would return the rule for a wire of a given width and length. and it would return the rule for a wire of at least a given width and length.
A key can be not compared by passing a None. A dimension can be ignored by passing inf.
""" """
def __init__(self, table): def __init__(self, table):
self.table = table self.table = table
@ -16,20 +17,24 @@ class drc_lut():
""" """
Lookup a given tuple in the table. Lookup a given tuple in the table.
""" """
if len(*key)==0: if len(key)==0:
key_size = len(list(self.table.keys())[0]) first_key = list(sorted(self.table.keys()))[0]
key = tuple(0 for i in range(key_size)) return self.table[first_key]
for table_key in sorted(self.table.keys(), reverse=True): for table_key in sorted(self.table.keys(), reverse=True):
if self.match(key, table_key): if self.match(key, table_key):
return self.table[table_key] return self.table[table_key]
def match(self, t1, t2): def match(self, key1, key2):
""" """
Determine if t1>t2 for each tuple pair. Determine if key1>=key2 for all tuple pairs.
(i.e. return false if key1<key2 for any pair.)
""" """
# If any one pair is less than, return False # If any one pair is less than, return False
for i in range(len(t1)): debug.check(len(key1)==len(key2),"Comparing invalid key lengths.")
if t1[i] < t2[i]: for k1,k2 in zip(key1,key2):
if k1 < k2:
return False return False
return True return True

View File

@ -483,10 +483,10 @@ class router:
else: else:
debug.error("Invalid zindex for track", -1) debug.error("Invalid zindex for track", -1)
width = drc("minwidth_{0}".format(layer_name), width, length) min_width = drc("minwidth_{0}".format(layer_name), width, length)
spacing = drc(str(layer_name)+"_to_"+str(layer_name), width, length) min_spacing = drc(str(layer_name)+"_to_"+str(layer_name), width, length)
return (width,spacing) return (min_width,min_spacing)
def convert_pin_coord_to_tracks(self, pin, coord): def convert_pin_coord_to_tracks(self, pin, coord):
""" """
@ -1112,8 +1112,8 @@ class router:
ll = path[0][0] ll = path[0][0]
ur = path[-1][-1] ur = path[-1][-1]
z = ll.z z = ll.z
pin = self.add_enclosure(ll, ur, z, name) pin = self.add_enclosure(ll, ur, z, name)
print(ll, ur, ll.z, "->",pin)
self.cell.add_layout_pin(text=name, self.cell.add_layout_pin(text=name,
layer=pin.layer, layer=pin.layer,
offset=pin.ll(), offset=pin.ll(),
@ -1133,20 +1133,11 @@ class router:
(abs_ll,unused) = self.convert_track_to_shape(ll) (abs_ll,unused) = self.convert_track_to_shape(ll)
(unused,abs_ur) = self.convert_track_to_shape(ur) (unused,abs_ur) = self.convert_track_to_shape(ur)
# Get the layer information
x_distance = abs(abs_ll.x-abs_ur.x)
y_distance = abs(abs_ll.y-abs_ur.y)
shape_width = min(x_distance, y_distance)
shape_length = max(x_distance, y_distance)
# Get the DRC rule for the grid dimensions # Get the DRC rule for the grid dimensions
(width, space) = self.get_layer_width_space(zindex, shape_width, shape_length) (width, space) = self.get_layer_width_space(zindex)
layer = self.get_layer(zindex) layer = self.get_layer(zindex)
# Compute the shape offsets with correct spacing pin = pin_layout(name, [abs_ll, abs_ur], layer)
new_ll = abs_ll + vector(0.5*space, 0.5*space)
new_ur = abs_ur - vector(0.5*space, 0.5*space)
pin = pin_layout(name, [new_ll, new_ur], layer)
return pin return pin

View File

@ -69,7 +69,7 @@ class supply_router(router):
# Determine the rail locations # Determine the rail locations
self.route_supply_rails(self.vdd_name,1) self.route_supply_rails(self.vdd_name,1)
#self.write_debug_gds("pre_pin_debug.gds",stop_program=True) self.write_debug_gds("pre_pin_debug.gds",stop_program=True)
# Route the supply pins to the supply rails # Route the supply pins to the supply rails
self.route_pins_to_rails(gnd_name) self.route_pins_to_rails(gnd_name)
@ -132,16 +132,27 @@ class supply_router(router):
self.add_wavepath(name, wave_path) self.add_wavepath(name, wave_path)
def compute_supply_rails(self, name, start_offset):
def route_supply_rails(self, name, supply_number):
""" """
Route the horizontal and vertical supply rails across the entire design. Compute the unblocked locations for the horizontal and vertical supply rails.
Must be done with lower left at 0,0 Go in a raster order from bottom to the top (for horizontal) and left to right
(for vertical). Start with an initial start_offset in x and y direction.
""" """
start_offset = supply_number*self.rail_track_width
max_yoffset = self.rg.ur.y max_yoffset = self.rg.ur.y
max_xoffset = self.rg.ur.x max_xoffset = self.rg.ur.x
step_offset = 2*self.rail_track_width max_length = max(max_yoffset,max_xoffset)
# Convert the number of tracks to dimensions to get the design rule spacing
rail_width = self.track_width*self.rail_track_width
(horizontal_width, horizontal_space) = self.get_layer_width_space(0, rail_width, max_length)
(vertical_width, vertical_space) = self.get_layer_width_space(1, rail_width, max_length)
width = max(horizontal_width, vertical_width)
space = max(horizontal_space, vertical_space)
# This is the supply rail pitch in terms of routing grids
# The 2* is to alternate the two supplies
step_offset = 2*math.ceil((width+space)/self.track_width)
# Horizontal supply rails # Horizontal supply rails
for offset in range(start_offset, max_yoffset, step_offset): for offset in range(start_offset, max_yoffset, step_offset):
@ -161,6 +172,16 @@ class supply_router(router):
while wave and wave[0].y < max_yoffset: while wave and wave[0].y < max_yoffset:
wave = self.find_supply_rail(name, wave, direction.NORTH) wave = self.find_supply_rail(name, wave, direction.NORTH)
def route_supply_rails(self, name, supply_number):
"""
Route the horizontal and vertical supply rails across the entire design.
Must be done with lower left at 0,0
"""
# Compute the grid locations of the supply rails
start_offset = supply_number*self.rail_track_width
self.compute_supply_rails(name, start_offset)
# Add the supply rail vias (and prune disconnected rails) # Add the supply rail vias (and prune disconnected rails)
self.connect_supply_rails(name) self.connect_supply_rails(name)