From c1fedda575517f5fbc35ec36c0665811e2680a8f Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 30 Jun 2020 15:07:34 -0700 Subject: [PATCH] Modifications for min area metal. Made add_via_stack_center iterative instead of recursive. Removed add_via_stack (non-center) since it isn't used. Add min area metal during iterative via insertion. --- compiler/base/hierarchy_layout.py | 126 ++++++++++++++---------------- compiler/pgates/pwrite_driver.py | 24 +++--- 2 files changed, 69 insertions(+), 81 deletions(-) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index c57de915..a5272ba5 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -13,6 +13,7 @@ from tech import drc, GDS from tech import layer as techlayer from tech import layer_indices from tech import layer_stacks +from tech import preferred_directions import os from globals import OPTS from vector import vector @@ -521,7 +522,6 @@ class layout(): def get_preferred_direction(self, layer): """ Return the preferred routing directions """ - from tech import preferred_directions return preferred_directions[layer] def add_via(self, layers, offset, size=[1, 1], directions=None, implant_type=None, well_type=None): @@ -567,24 +567,6 @@ class layout(): self.connect_inst([]) return inst - def add_via_stack(self, offset, from_layer, to_layer, - directions=None, - size=[1, 1], - implant_type=None, - well_type=None): - """ - Punch a stack of vias from a start layer to a target layer. - """ - return self.__add_via_stack_internal(offset=offset, - directions=directions, - from_layer=from_layer, - to_layer=to_layer, - via_func=self.add_via, - last_via=None, - size=size, - implant_type=implant_type, - well_type=well_type) - def add_via_stack_center(self, offset, from_layer, @@ -594,24 +576,7 @@ class layout(): implant_type=None, well_type=None): """ - Punch a stack of vias from a start layer to a target layer by the center - coordinate accounting for mirroring and rotation. - """ - return self.__add_via_stack_internal(offset=offset, - directions=directions, - from_layer=from_layer, - to_layer=to_layer, - via_func=self.add_via_center, - last_via=None, - size=size, - implant_type=implant_type, - well_type=well_type) - - def __add_via_stack_internal(self, offset, directions, from_layer, to_layer, - via_func, last_via, size, implant_type=None, well_type=None): - """ - Punch a stack of vias from a start layer to a target layer. Here we - figure out whether to punch it up or down the stack. + Punch a stack of vias from a start layer to a target layer by the center. """ if from_layer == to_layer: @@ -619,38 +584,65 @@ class layout(): # a metal enclosure. This helps with center-line path routing. self.add_rect_center(layer=from_layer, offset=offset) - return last_via + return None - from_id = layer_indices[from_layer] - to_id = layer_indices[to_layer] + via = None + cur_layer = from_layer + while cur_layer != to_layer: + from_id = layer_indices[cur_layer] + to_id = layer_indices[to_layer] - if from_id < to_id: # grow the stack up - search_id = 0 - next_id = 2 - else: # grow the stack down - search_id = 2 - next_id = 0 + if from_id < to_id: # grow the stack up + search_id = 0 + next_id = 2 + else: # grow the stack down + search_id = 2 + next_id = 0 - curr_stack = next(filter(lambda stack: stack[search_id] == from_layer, layer_stacks), None) - if curr_stack is None: - raise ValueError("Cannot create via from '{0}' to '{1}'." - "Layer '{0}' not defined".format(from_layer, to_layer)) + curr_stack = next(filter(lambda stack: stack[search_id] == cur_layer, layer_stacks), None) + + via = self.add_via_center(layers=curr_stack, + size=size, + offset=offset, + directions=directions, + implant_type=implant_type, + well_type=well_type) + + if cur_layer != from_layer: + self.add_min_area_rect_center(cur_layer, + offset, + via.mod.first_layer_width, + via.mod.first_layer_height) + + cur_layer = curr_stack[next_id] - via = via_func(layers=curr_stack, - size=size, - offset=offset, - directions=directions, - implant_type=implant_type, - well_type=well_type) - - via = self.__add_via_stack_internal(offset=offset, - directions=directions, - from_layer=curr_stack[next_id], - to_layer=to_layer, - via_func=via_func, - last_via=via, - size=size) return via + + def add_min_area_rect_center(self, + layer, + offset, + width=None, + height=None): + """ + Add a minimum area retcangle at the given point. + Either width or height should be fixed. + """ + + min_area = drc("minarea_{}".format(layer)) + if min_area == 0: + return + + min_width = drc("minwidth_{}".format(layer)) + + if preferred_directions[layer] == "V": + height = max(min_area / width, min_width) + else: + width = max(min_area / height, min_width) + + self.add_rect_center(layer=layer, + offset=offset, + width=width, + height=height) def add_ptx(self, offset, mirror="R0", rotate=0, width=1, mults=1, tx_type="nmos"): """Adds a ptx module to the design.""" @@ -1181,12 +1173,8 @@ class layout(): self.add_path(layer, [pin_loc, peri_pin_loc]) - self.add_via_stack_center(from_layer=layer, - to_layer="m4", - offset=peri_pin_loc) - self.add_layout_pin_rect_center(text=name, - layer="m4", + layer=layer, offset=peri_pin_loc) def add_power_ring(self, bbox): diff --git a/compiler/pgates/pwrite_driver.py b/compiler/pgates/pwrite_driver.py index da5eacdc..87db7b20 100644 --- a/compiler/pgates/pwrite_driver.py +++ b/compiler/pgates/pwrite_driver.py @@ -160,11 +160,11 @@ class pwrite_driver(design.design): track_xoff = self.get_m2_track(1) din_loc = self.din_inst.get_pin("A").center() - self.add_via_stack("m1", "m2", din_loc) + self.add_via_stack_center("m1", "m2", din_loc) din_track = vector(track_xoff,din_loc.y) br_in = self.br_inst.get_pin("in").center() - self.add_via_stack("m1", "m2", br_in) + self.add_via_stack_center("m1", "m2", br_in) br_track = vector(track_xoff,br_in.y) din_in = vector(track_xoff,0) @@ -181,11 +181,11 @@ class pwrite_driver(design.design): track_xoff = self.get_m4_track(self.din_bar_track) din_bar_in = self.din_inst.get_pin("Z").center() - self.add_via_stack("m1", "m3", din_bar_in) + self.add_via_stack_center("m1", "m3", din_bar_in) din_bar_track = vector(track_xoff,din_bar_in.y) bl_in = self.bl_inst.get_pin("in").center() - self.add_via_stack("m1", "m3", bl_in) + self.add_via_stack_center("m1", "m3", bl_in) bl_track = vector(track_xoff,bl_in.y) din_in = vector(track_xoff,0) @@ -204,15 +204,15 @@ class pwrite_driver(design.design): # This M2 pitch is a hack since the A and Z pins align horizontally en_bar_loc = self.en_inst.get_pin("Z").uc() en_bar_track = vector(track_xoff, en_bar_loc.y) - self.add_via_stack("m1", "m3", en_bar_loc) + self.add_via_stack_center("m1", "m3", en_bar_loc) # This is a U route to the right down then left bl_en_loc = self.bl_inst.get_pin("en_bar").center() bl_en_track = vector(track_xoff, bl_en_loc.y) - self.add_via_stack("m1", "m3", bl_en_loc) + self.add_via_stack_center("m1", "m3", bl_en_loc) br_en_loc = self.br_inst.get_pin("en_bar").center() br_en_track = vector(track_xoff, bl_en_loc.y) - self.add_via_stack("m1", "m3", br_en_loc) + self.add_via_stack_center("m1", "m3", br_en_loc) # L shape @@ -237,21 +237,21 @@ class pwrite_driver(design.design): en_loc = self.en_inst.get_pin("A").center() en_rail = vector(en_loc.x, vdd_yloc) - self.add_via_stack("m1", "m2", en_loc) + self.add_via_stack_center("m1", "m2", en_loc) self.add_path("m2", [en_loc, en_rail]) - self.add_via_stack("m2", "m3", en_rail) + self.add_via_stack_center("m2", "m3", en_rail) # Start point in the track on the pin rail en_track = vector(track_xoff, vdd_yloc) - self.add_via_stack("m3", "m4", en_track) + self.add_via_stack_center("m3", "m4", en_track) # This is a U route to the right down then left bl_en_loc = self.bl_inst.get_pin("en").center() bl_en_track = vector(track_xoff, bl_en_loc.y) - self.add_via_stack("m1", "m3", bl_en_loc) + self.add_via_stack_center("m1", "m3", bl_en_loc) br_en_loc = self.br_inst.get_pin("en").center() br_en_track = vector(track_xoff, bl_en_loc.y) - self.add_via_stack("m1", "m3", br_en_loc) + self.add_via_stack_center("m1", "m3", br_en_loc) # U shape self.add_wire(self.m3_stack,