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):
rule = self.rules[name]
if callable(rule):
return rule(args)
return rule(*args)
else:
return rule

View File

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

View File

@ -483,10 +483,10 @@ class router:
else:
debug.error("Invalid zindex for track", -1)
width = drc("minwidth_{0}".format(layer_name), width, length)
spacing = drc(str(layer_name)+"_to_"+str(layer_name), width, length)
min_width = drc("minwidth_{0}".format(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):
"""
@ -1112,8 +1112,8 @@ class router:
ll = path[0][0]
ur = path[-1][-1]
z = ll.z
pin = self.add_enclosure(ll, ur, z, name)
print(ll, ur, ll.z, "->",pin)
self.cell.add_layout_pin(text=name,
layer=pin.layer,
offset=pin.ll(),
@ -1133,20 +1133,11 @@ class router:
(abs_ll,unused) = self.convert_track_to_shape(ll)
(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
(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)
# Compute the shape offsets with correct spacing
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)
pin = pin_layout(name, [abs_ll, abs_ur], layer)
return pin

View File

@ -69,7 +69,7 @@ class supply_router(router):
# Determine the rail locations
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
self.route_pins_to_rails(gnd_name)
@ -132,16 +132,27 @@ class supply_router(router):
self.add_wavepath(name, wave_path)
def route_supply_rails(self, name, supply_number):
def compute_supply_rails(self, name, start_offset):
"""
Route the horizontal and vertical supply rails across the entire design.
Must be done with lower left at 0,0
Compute the unblocked locations for the horizontal and vertical supply rails.
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_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
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:
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)
self.connect_supply_rails(name)