mirror of https://github.com/VLSIDA/OpenRAM.git
Moving wide metal spacing to routing grid level
This commit is contained in:
parent
1c426aad29
commit
d855d4f1a6
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
"""
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
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
|
|
||||||
"""
|
|
||||||
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)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue