From d855d4f1a650d41946f2ef00645602877bdae2cd Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 15 Oct 2018 09:59:16 -0700 Subject: [PATCH] Moving wide metal spacing to routing grid level --- compiler/drc/design_rules.py | 2 +- compiler/drc/drc_lut.py | 23 +++++++++++++-------- compiler/router/router.py | 21 ++++++------------- compiler/router/supply_router.py | 35 +++++++++++++++++++++++++------- 4 files changed, 49 insertions(+), 32 deletions(-) diff --git a/compiler/drc/design_rules.py b/compiler/drc/design_rules.py index 465f14ed..4bc2eaa6 100644 --- a/compiler/drc/design_rules.py +++ b/compiler/drc/design_rules.py @@ -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 diff --git a/compiler/drc/drc_lut.py b/compiler/drc/drc_lut.py index e6bb8004..07e482c8 100644 --- a/compiler/drc/drc_lut.py +++ b/compiler/drc/drc_lut.py @@ -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",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 diff --git a/compiler/router/supply_router.py b/compiler/router/supply_router.py index 880f0c51..f0b1d7d1 100644 --- a/compiler/router/supply_router.py +++ b/compiler/router/supply_router.py @@ -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)