diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 31ec17d7..9d9bb131 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -2216,7 +2216,7 @@ class layout(): size=(supply_vias, supply_vias)) - def add_power_ring(self, h_layer="m2", v_layer="m1"): + def add_power_ring(self, h_layer="m2", v_layer="m1", top=True, bottom=True, left=True, right=True): """ Create vdd and gnd power rings around an area of the bounding box argument. Must have a supply_rail_width and supply_rail_pitch @@ -2231,111 +2231,113 @@ class layout(): width = (ur.x - ll.x) + 3 * self.supply_rail_pitch - supply_rail_spacing # LEFT vertical rails - offset = ll + vector(-2*self.supply_rail_pitch, - -2*self.supply_rail_pitch) - self.left_gnd_pin = self.add_layout_pin(text="gnd", - layer=v_layer, - offset=offset, - width=self.supply_rail_width, - height=height + 2 * supply_rail_spacing) + if left: + offset = ll + vector(-2*self.supply_rail_pitch, + -2*self.supply_rail_pitch) + self.left_gnd_pin = self.add_layout_pin(text="gnd", + layer=v_layer, + offset=offset, + width=self.supply_rail_width, + height=height + 2 * supply_rail_spacing) - offset = ll + vector(-1 * self.supply_rail_pitch, - -1 * self.supply_rail_pitch) - self.left_vdd_pin = self.add_layout_pin(text="vdd", - layer=v_layer, - offset=offset, - width=self.supply_rail_width, - height=height) + offset = ll + vector(-1 * self.supply_rail_pitch, + -1 * self.supply_rail_pitch) + self.left_vdd_pin = self.add_layout_pin(text="vdd", + layer=v_layer, + offset=offset, + width=self.supply_rail_width, + height=height) - # RIGHT vertical railsteac a 460 - offset = vector(ur.x, ll.y) + vector(2 * self.supply_rail_pitch - self.supply_rail_width, - -2 * self.supply_rail_pitch) - self.right_gnd_pin = self.add_layout_pin(text="gnd", - layer=v_layer, - offset=offset, - width=self.supply_rail_width, - height=height + 2* supply_rail_spacing) + if right: + # RIGHT vertical railsteac a 460 + offset = vector(ur.x, ll.y) + vector(2 * self.supply_rail_pitch - self.supply_rail_width, + -2 * self.supply_rail_pitch) + self.right_gnd_pin = self.add_layout_pin(text="gnd", + layer=v_layer, + offset=offset, + width=self.supply_rail_width, + height=height + 2* supply_rail_spacing) - offset = vector(ur.x, ll.y) + vector(1 * self.supply_rail_pitch - self.supply_rail_width, - -1 * self.supply_rail_pitch) - self.right_vdd_pin = self.add_layout_pin(text="vdd", - layer=v_layer, - offset=offset, - width=self.supply_rail_width, - height=height) + offset = vector(ur.x, ll.y) + vector(1 * self.supply_rail_pitch - self.supply_rail_width, + -1 * self.supply_rail_pitch) + self.right_vdd_pin = self.add_layout_pin(text="vdd", + layer=v_layer, + offset=offset, + width=self.supply_rail_width, + height=height) - # BOTTOM horizontal rails - offset = ll + vector(-2 * self.supply_rail_pitch, - -2 * self.supply_rail_pitch) - self.bottom_gnd_pin = self.add_layout_pin(text="gnd", - layer=h_layer, - offset=offset, - width=width + 2 * supply_rail_spacing, - height=self.supply_rail_width) + if bottom: + # BOTTOM horizontal rails + offset = ll + vector(-2 * self.supply_rail_pitch, + -2 * self.supply_rail_pitch) + self.bottom_gnd_pin = self.add_layout_pin(text="gnd", + layer=h_layer, + offset=offset, + width=width + 2 * supply_rail_spacing, + height=self.supply_rail_width) - offset = ll + vector(-1 * self.supply_rail_pitch, - -1 * self.supply_rail_pitch) - self.bottom_vdd_pin = self.add_layout_pin(text="vdd", - layer=h_layer, - offset=offset, - width=width, - height=self.supply_rail_width) + offset = ll + vector(-1 * self.supply_rail_pitch, + -1 * self.supply_rail_pitch) + self.bottom_vdd_pin = self.add_layout_pin(text="vdd", + layer=h_layer, + offset=offset, + width=width, + height=self.supply_rail_width) + if top: + # TOP horizontal rails + offset = vector(ll.x, ur.y) + vector(-2 * self.supply_rail_pitch, + 2 * self.supply_rail_pitch - self.supply_rail_width) + self.top_gnd_pin = self.add_layout_pin(text="gnd", + layer=h_layer, + offset=offset, + width=width + 2 * supply_rail_spacing, + height=self.supply_rail_width) - # TOP horizontal rails - offset = vector(ll.x, ur.y) + vector(-2 * self.supply_rail_pitch, - 2 * self.supply_rail_pitch - self.supply_rail_width) - self.top_gnd_pin = self.add_layout_pin(text="gnd", - layer=h_layer, - offset=offset, - width=width + 2 * supply_rail_spacing, - height=self.supply_rail_width) - - offset = vector(ll.x, ur.y) + vector(-1 * self.supply_rail_pitch, - 1 * self.supply_rail_pitch - self.supply_rail_width) - self.top_vdd_pin = self.add_layout_pin(text="vdd", - layer=h_layer, - offset=offset, - width=width, - height=self.supply_rail_width) + offset = vector(ll.x, ur.y) + vector(-1 * self.supply_rail_pitch, + 1 * self.supply_rail_pitch - self.supply_rail_width) + self.top_vdd_pin = self.add_layout_pin(text="vdd", + layer=h_layer, + offset=offset, + width=width, + height=self.supply_rail_width) # Remember these for connecting things in the design - self.left_gnd_x_center = self.left_gnd_pin.cx() - self.left_vdd_x_center = self.left_vdd_pin.cx() - self.right_gnd_x_center = self.right_gnd_pin.cx() - self.right_vdd_x_center = self.right_vdd_pin.cx() - - self.bottom_gnd_y_center = self.bottom_gnd_pin.cy() - self.bottom_vdd_y_center = self.bottom_vdd_pin.cy() - self.top_gnd_y_center = self.top_gnd_pin.cy() - self.top_vdd_y_center = self.top_vdd_pin.cy() - - # Find the number of vias for this pitch - self.supply_vias = 1 - while True: - c = factory.create(module_type="contact", - layer_stack=self.m1_stack, - dimensions=(self.supply_vias, self.supply_vias)) - if c.second_layer_width < self.supply_rail_width and c.second_layer_height < self.supply_rail_width: - self.supply_vias += 1 - else: - self.supply_vias -= 1 - break - - via_points = [vector(self.left_gnd_x_center, self.bottom_gnd_y_center), - vector(self.left_gnd_x_center, self.top_gnd_y_center), - vector(self.right_gnd_x_center, self.bottom_gnd_y_center), - vector(self.right_gnd_x_center, self.top_gnd_y_center), - vector(self.left_vdd_x_center, self.bottom_vdd_y_center), - vector(self.left_vdd_x_center, self.top_vdd_y_center), - vector(self.right_vdd_x_center, self.bottom_vdd_y_center), - vector(self.right_vdd_x_center, self.top_vdd_y_center)] + if left: + self.left_gnd_x_center = self.left_gnd_pin.cx() + self.left_vdd_x_center = self.left_vdd_pin.cx() + if right: + self.right_gnd_x_center = self.right_gnd_pin.cx() + self.right_vdd_x_center = self.right_vdd_pin.cx() + if bottom: + self.bottom_gnd_y_center = self.bottom_gnd_pin.cy() + self.bottom_vdd_y_center = self.bottom_vdd_pin.cy() + if top: + self.top_gnd_y_center = self.top_gnd_pin.cy() + self.top_vdd_y_center = self.top_vdd_pin.cy() + via_points = [] + if left and bottom: + via_points.append((self.left_gnd_x_center, self.bottom_gnd_y_center)) + if left and top: + via_points.append(vector(self.left_gnd_x_center, self.top_gnd_y_center)) + if right and bottom: + via_points.append(vector(self.right_gnd_x_center, self.bottom_gnd_y_center)) + if right and top: + via_points.append(vector(self.right_gnd_x_center, self.top_gnd_y_center)) + if left and bottom: + via_points.append(vector(self.left_vdd_x_center, self.bottom_vdd_y_center)) + if left and top: + via_points.append(vector(self.left_vdd_x_center, self.top_vdd_y_center)) + if right and bottom: + via_points.append(vector(self.right_vdd_x_center, self.bottom_vdd_y_center)) + if right and top: + via_points.append((self.right_vdd_x_center, self.top_vdd_y_center)) + for pt in via_points: - self.add_via_center(layers=self.m1_stack, - offset=pt, - size=(self.supply_vias, - self.supply_vias)) - + self.add_via_stack_center(offset=pt, + from_layer=h_layer, + to_layer=v_layer, + min_area=True) def pdf_write(self, pdf_name): """ Display the layout to a PDF file. diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index 30d6e2c5..db7a1547 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -224,8 +224,8 @@ class capped_replica_bitcell_array(bitcell_base_array): def route_power_ring(self, v_layer, h_layer): self.bbox = (vector(0,0), vector(self.capped_rba_width, self.capped_rba_height)) self.supply_rail_width = drc["minwidth_m1"] - self.supply_rail_pitch = 3 * self.supply_rail_width - self.add_power_ring(v_layer, h_layer) + self.supply_rail_pitch = 6 * self.supply_rail_width + self.add_power_ring(v_layer=v_layer, h_layer=h_layer) def get_main_array_top(self): return self.replica_bitcell_array_inst.by() + self.replica_bitcell_array.get_main_array_top() @@ -309,80 +309,83 @@ class capped_replica_bitcell_array(bitcell_base_array): bitcell = factory.create(module_type="pbitcell") else: bitcell = getattr(props, "bitcell_{}port".format(OPTS.num_ports)) + top = True + bottom = True + left = False + right = False + + if top: + inst = self.dummy_row_insts[1] + if "vdd" in inst.mod.pins: + array_pins = inst.get_pins("vdd") + for array_pin in array_pins: + supply_pin = self.top_vdd_pin + self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])]) + self.add_via_stack_center(from_layer = array_pin.layer, + to_layer = supply_pin.layer, + offset = vector(array_pin.center()[0], supply_pin.center()[1])) - #vdd_dir = bitcell.vdd_dir - #gnd_dir = bitcell.gnd_dir - - # vdd/gnd are only connected in the perimeter cells - #supply_insts = self.dummy_col_insts + self.dummy_row_insts - inst = self.dummy_row_insts[1] - if "vdd" in inst.mod.pins: - array_pins = inst.get_pins("vdd") - for array_pin in array_pins: - supply_pin = self.top_vdd_pin - self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])]) - self.add_via_stack_center(from_layer = array_pin.layer, - to_layer = supply_pin.layer, - offset = vector(array_pin.center()[0], supply_pin.center()[1])) + array_pins = inst.get_pins("gnd") + for array_pin in array_pins: + supply_pin = self.top_gnd_pin + self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])]) + self.add_via_stack_center(from_layer = array_pin.layer, + to_layer = supply_pin.layer, + offset = vector(array_pin.center()[0], supply_pin.center()[1])) + if bottom: + inst = self.dummy_row_insts[0] + if "vdd" in inst.mod.pins: + array_pins = inst.get_pins("vdd") + for array_pin in array_pins: + supply_pin = self.bottom_vdd_pin + self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])]) + self.add_via_stack_center(from_layer = array_pin.layer, + to_layer = supply_pin.layer, + offset = vector(array_pin.center()[0], supply_pin.center()[1])) - array_pins = inst.get_pins("gnd") - for array_pin in array_pins: - supply_pin = self.top_gnd_pin - self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])]) - self.add_via_stack_center(from_layer = array_pin.layer, - to_layer = supply_pin.layer, - offset = vector(array_pin.center()[0], supply_pin.center()[1])) - inst = self.dummy_row_insts[0] - if "vdd" in inst.mod.pins: - array_pins = inst.get_pins("vdd") - for array_pin in array_pins: - supply_pin = self.bottom_vdd_pin - self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])]) - self.add_via_stack_center(from_layer = array_pin.layer, - to_layer = supply_pin.layer, - offset = vector(array_pin.center()[0], supply_pin.center()[1])) + array_pins = inst.get_pins("gnd") + for array_pin in array_pins: + supply_pin = self.bottom_gnd_pin + self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])]) + self.add_via_stack_center(from_layer = array_pin.layer, + to_layer = supply_pin.layer, + offset = vector(array_pin.center()[0], supply_pin.center()[1])) + if left: + inst = self.dummy_col_insts[0] + if "vdd" in inst.mod.pins: + array_pins = inst.get_pins("vdd") + for array_pin in array_pins: + supply_pin = self.left_vdd_pin + self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])]) + self.add_via_stack_center(from_layer = array_pin.layer, + to_layer = supply_pin.layer, + offset = vector(supply_pin.center()[0], array_pin.center()[1])) - array_pins = inst.get_pins("gnd") - for array_pin in array_pins: - supply_pin = self.bottom_gnd_pin - self.add_path(array_pin.layer, [array_pin.center(), vector(array_pin.center()[0], supply_pin.center()[1])]) - self.add_via_stack_center(from_layer = array_pin.layer, - to_layer = supply_pin.layer, - offset = vector(array_pin.center()[0], supply_pin.center()[1])) - inst = self.dummy_col_insts[0] - if "vdd" in inst.mod.pins: - array_pins = inst.get_pins("vdd") - for array_pin in array_pins: - supply_pin = self.left_vdd_pin - self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])]) - self.add_via_stack_center(from_layer = array_pin.layer, - to_layer = supply_pin.layer, - offset = vector(supply_pin.center()[0], array_pin.center()[1])) + array_pins = inst.get_pins("gnd") + for array_pin in array_pins: + supply_pin = self.left_gnd_pin + self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])]) + self.add_via_stack_center(from_layer = array_pin.layer, + to_layer = supply_pin.layer, + offset = vector(supply_pin.center()[0], array_pin.center()[1])) + if right: + inst = self.dummy_col_insts[1] + if "vdd" in inst.mod.pins: + array_pins = inst.get_pins("vdd") + for array_pin in array_pins: + supply_pin = self.right_vdd_pin + self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])]) + self.add_via_stack_center(from_layer = array_pin.layer, + to_layer = supply_pin.layer, + offset = vector(supply_pin.center()[0], array_pin.center()[1])) - array_pins = inst.get_pins("gnd") - for array_pin in array_pins: - supply_pin = self.left_gnd_pin - self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])]) - self.add_via_stack_center(from_layer = array_pin.layer, - to_layer = supply_pin.layer, - offset = vector(supply_pin.center()[0], array_pin.center()[1])) - inst = self.dummy_col_insts[1] - if "vdd" in inst.mod.pins: - array_pins = inst.get_pins("vdd") - for array_pin in array_pins: - supply_pin = self.right_vdd_pin - self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])]) - self.add_via_stack_center(from_layer = array_pin.layer, - to_layer = supply_pin.layer, - offset = vector(supply_pin.center()[0], array_pin.center()[1])) - - array_pins = inst.get_pins("gnd") - for array_pin in array_pins: - supply_pin = self.right_gnd_pin - self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])]) - self.add_via_stack_center(from_layer = array_pin.layer, - to_layer = supply_pin.layer, - offset = vector(supply_pin.center()[0], array_pin.center()[1])) + array_pins = inst.get_pins("gnd") + for array_pin in array_pins: + supply_pin = self.right_gnd_pin + self.add_path(array_pin.layer, [array_pin.center(), vector(supply_pin.center()[0], array_pin.center()[1])]) + self.add_via_stack_center(from_layer = array_pin.layer, + to_layer = supply_pin.layer, + offset = vector(supply_pin.center()[0], array_pin.center()[1])) def route_unused_wordlines(self): """ Connect the unused RBL and dummy wordlines to gnd diff --git a/compiler/modules/col_cap_array.py b/compiler/modules/col_cap_array.py index 9f9a64da..5291340e 100644 --- a/compiler/modules/col_cap_array.py +++ b/compiler/modules/col_cap_array.py @@ -17,7 +17,7 @@ class col_cap_array(bitcell_base_array): self.mirror = mirror self.location = location - self.no_instances = True + #self.no_instances = True self.create_netlist() if not OPTS.netlist_only: self.create_layout() diff --git a/compiler/modules/row_cap_array.py b/compiler/modules/row_cap_array.py index 4febdde3..e35e260a 100644 --- a/compiler/modules/row_cap_array.py +++ b/compiler/modules/row_cap_array.py @@ -16,7 +16,7 @@ class row_cap_array(bitcell_base_array): super().__init__(rows=rows, cols=cols, column_offset=column_offset, name=name) self.mirror = mirror self.location = location - self.no_instances = True + #self.no_instances = True self.create_netlist() if not OPTS.netlist_only: self.create_layout() diff --git a/technology/sky130/custom/sky130_col_cap_array.py b/technology/sky130/custom/sky130_col_cap_array.py index 70ca69a3..017e50ce 100644 --- a/technology/sky130/custom/sky130_col_cap_array.py +++ b/technology/sky130/custom/sky130_col_cap_array.py @@ -68,6 +68,7 @@ class sky130_col_cap_array(col_cap_array, sky130_bitcell_base_array): bitcell_pins.append("gnd") # gnd bitcell_pins.append("vdd") # vpb bitcell_pins.append("gnd") # vnb + bitcell_pins.append("gnd")# poly gate for parasitic tx #bitcell_pins.extend([x for x in self.all_wordline_names if x.endswith("_{0}".format(row))]) return bitcell_pins diff --git a/technology/sky130/tech/tech.py b/technology/sky130/tech/tech.py index 51a4b8d7..07ffa69e 100755 --- a/technology/sky130/tech/tech.py +++ b/technology/sky130/tech/tech.py @@ -114,14 +114,15 @@ cell_properties.bitcell_2port.vdd_dir = "H" cell_properties.bitcell_2port.gnd_layer = "m2" cell_properties.bitcell_2port.gnd_dir = "H" -cell_properties.col_cap_1port_bitcell = d.cell(['bl', 'br', 'vdd', 'gnd', 'vpb', 'vnb'], - ['INPUT', 'INPUT','POWER', 'GROUND', 'BIAS', 'BIAS'], +cell_properties.col_cap_1port_bitcell = d.cell(['bl', 'br', 'vdd', 'gnd', 'vpb', 'vnb', 'gate'], + ['INPUT', 'INPUT','POWER', 'GROUND', 'BIAS', 'BIAS', 'INPUT'], {'bl': 'bl', 'br': 'br', 'vdd': 'vdd', 'gnd': 'gnd', 'vnb': 'vnb', - 'vpb': 'vpb'}) + 'vpb': 'vpb', + 'gate': 'gate'}) cell_properties.col_cap_1port_bitcell.boundary_layer = "mem" cell_properties.col_cap_1port_strap_power = d.cell(['vdd', 'vpb', 'vnb'],