diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 8c595254..31ec17d7 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -2157,6 +2157,13 @@ class layout(): # Add the gnd ring self.add_ring([ll, ur]) + def reset_coordinates(self): + ll=vector(min([x.lx() for x in self.insts]),min([y.by() for y in self.insts])) + + self.translate_all(ll) + self.width = max([x.rx() for x in self.insts]) - min([x.lx() for x in self.insts]) + self.height = max([x.uy() for x in self.insts]) - min([y.by() for y in self.insts]) + def add_ring(self, bbox=None, width_mult=8, offset=0): """ Add a ring around the bbox @@ -2209,7 +2216,7 @@ class layout(): size=(supply_vias, supply_vias)) - def add_power_ring(self): + def add_power_ring(self, h_layer="m2", v_layer="m1"): """ Create vdd and gnd power rings around an area of the bounding box argument. Must have a supply_rail_width and supply_rail_pitch @@ -2217,42 +2224,42 @@ class layout(): left/right/top/bottom vdd/gnd center offsets for use in other modules.. """ - [ll, ur] = self.bbox - supply_rail_spacing = self.supply_rail_pitch - self.supply_rail_width + supply_rail_spacing = self.supply_rail_pitch height = (ur.y - ll.y) + 3 * self.supply_rail_pitch - supply_rail_spacing 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) - left_gnd_pin = self.add_layout_pin(text="gnd", - layer="m2", + 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) + height=height + 2 * supply_rail_spacing) offset = ll + vector(-1 * self.supply_rail_pitch, -1 * self.supply_rail_pitch) - left_vdd_pin = self.add_layout_pin(text="vdd", - layer="m2", + self.left_vdd_pin = self.add_layout_pin(text="vdd", + layer=v_layer, offset=offset, width=self.supply_rail_width, height=height) - # RIGHT vertical rails - offset = vector(ur.x, ll.y) + vector(0, -2 * self.supply_rail_pitch) - right_gnd_pin = self.add_layout_pin(text="gnd", - layer="m2", + # 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) + height=height + 2* supply_rail_spacing) - offset = vector(ur.x, ll.y) + vector(self.supply_rail_pitch, + offset = vector(ur.x, ll.y) + vector(1 * self.supply_rail_pitch - self.supply_rail_width, -1 * self.supply_rail_pitch) - right_vdd_pin = self.add_layout_pin(text="vdd", - layer="m2", + self.right_vdd_pin = self.add_layout_pin(text="vdd", + layer=v_layer, offset=offset, width=self.supply_rail_width, height=height) @@ -2260,47 +2267,47 @@ class layout(): # BOTTOM horizontal rails offset = ll + vector(-2 * self.supply_rail_pitch, -2 * self.supply_rail_pitch) - bottom_gnd_pin = self.add_layout_pin(text="gnd", - layer="m1", + self.bottom_gnd_pin = self.add_layout_pin(text="gnd", + layer=h_layer, offset=offset, - width=width, + width=width + 2 * supply_rail_spacing, height=self.supply_rail_width) offset = ll + vector(-1 * self.supply_rail_pitch, -1 * self.supply_rail_pitch) - bottom_vdd_pin = self.add_layout_pin(text="vdd", - layer="m1", + self.bottom_vdd_pin = self.add_layout_pin(text="vdd", + layer=h_layer, offset=offset, width=width, height=self.supply_rail_width) # TOP horizontal rails offset = vector(ll.x, ur.y) + vector(-2 * self.supply_rail_pitch, - 0) - top_gnd_pin = self.add_layout_pin(text="gnd", - layer="m1", + 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, + width=width + 2 * supply_rail_spacing, height=self.supply_rail_width) - offset = vector(ll.x, ur.y) + vector(-1 * self.supply_rail_pitch, - self.supply_rail_pitch) - top_vdd_pin = self.add_layout_pin(text="vdd", - layer="m1", + 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 = left_gnd_pin.cx() - self.left_vdd_x_center = left_vdd_pin.cx() - self.right_gnd_x_center = right_gnd_pin.cx() - self.right_vdd_x_center = right_vdd_pin.cx() + 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 = bottom_gnd_pin.cy() - self.bottom_vdd_y_center = bottom_vdd_pin.cy() - self.top_gnd_y_center = top_gnd_pin.cy() - self.top_vdd_y_center = top_vdd_pin.cy() + 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 diff --git a/compiler/modules/capped_replica_bitcell_array.py b/compiler/modules/capped_replica_bitcell_array.py index df74b8b9..30d6e2c5 100644 --- a/compiler/modules/capped_replica_bitcell_array.py +++ b/compiler/modules/capped_replica_bitcell_array.py @@ -203,28 +203,29 @@ class capped_replica_bitcell_array(bitcell_base_array): self.replica_bitcell_array_inst.place(offset=0) self.add_end_caps() - - ll=vector(min([x.lx() for x in self.insts]),min([y.by() for y in self.insts])) + ll = vector(-1 * self.dummy_col_insts[0].width, -1 * self.dummy_row_insts[0].height) self.translate_all(ll) - self.width = max([x.rx() for x in self.insts]) - min([x.lx() for x in self.insts]) - self.height = max([x.uy() for x in self.insts]) - min([y.by() for y in self.insts]) + self.capped_rba_width = self.dummy_col_insts[0].width + self.dummy_row_insts[0].width + self.dummy_col_insts[1].width + self.capped_rba_height = self.dummy_col_insts[0].height + self.route_power_ring(self.supply_stack[2], self.supply_stack[0]) self.route_supplies() self.route_unused_wordlines() - self.width = max([x.rx() for x in self.insts]) - min([x.lx() for x in self.insts]) - self.height = max([x.uy() for x in self.insts]) - min([y.by() for y in self.insts]) - ll=vector(min([x.lx() for x in self.insts]),min([y.by() for y in self.insts])) - - self.translate_all(ll) - + self.reset_coordinates() self.add_layout_pins() self.add_boundary() - self.DRC_LVS() + + + 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) def get_main_array_top(self): return self.replica_bitcell_array_inst.by() + self.replica_bitcell_array.get_main_array_top() @@ -288,13 +289,13 @@ class capped_replica_bitcell_array(bitcell_base_array): if "wl" in pin_name: # wordlines pin_offset = pin.ll().scale(0, 1) - pin_width = self.width + pin_width = self.capped_rba_width pin_height = pin.height() else: # bitlines pin_offset = pin.ll().scale(1, 0) pin_width = pin.width() - pin_height = self.height + pin_height = self.capped_rba_height self.add_layout_pin(text=pin_name, layer=pin.layer, @@ -309,55 +310,79 @@ class capped_replica_bitcell_array(bitcell_base_array): else: bitcell = getattr(props, "bitcell_{}port".format(OPTS.num_ports)) - vdd_dir = bitcell.vdd_dir - gnd_dir = bitcell.gnd_dir - + #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 + #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])) - # For the wordlines - top_bot_mult = 1 - left_right_mult = 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])) - # There are always vertical pins for the WLs on the left/right if we have unused wordlines - self.left_gnd_locs = self.route_side_pin("gnd", "left", left_right_mult) - self.right_gnd_locs = self.route_side_pin("gnd", "right", left_right_mult) - # This needs to be big enough so that they aren't in the same supply routing grid - left_right_mult = 4 + 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])) - if gnd_dir == "V": - self.top_gnd_locs = self.route_side_pin("gnd", "top", top_bot_mult) - self.bot_gnd_locs = self.route_side_pin("gnd", "bot", top_bot_mult) - # This needs to be big enough so that they aren't in the same supply routing grid - top_bot_mult = 4 - - if vdd_dir == "V": - self.top_vdd_locs = self.route_side_pin("vdd", "top", top_bot_mult) - self.bot_vdd_locs = self.route_side_pin("vdd", "bot", top_bot_mult) - elif vdd_dir == "H": - self.left_vdd_locs = self.route_side_pin("vdd", "left", left_right_mult) - self.right_vdd_locs = self.route_side_pin("vdd", "right", left_right_mult) - else: - debug.error("Invalid vdd direction {}".format(vdd_dir), -1) - - for inst in supply_insts: - for pin in inst.get_pins("vdd"): - if vdd_dir == "V": - self.connect_side_pin(pin, "top", self.top_vdd_locs[0].y) - self.connect_side_pin(pin, "bot", self.bot_vdd_locs[0].y) - elif vdd_dir == "H": - self.connect_side_pin(pin, "left", self.left_vdd_locs[0].x) - self.connect_side_pin(pin, "right", self.right_vdd_locs[0].x) - - for inst in supply_insts: - for pin in inst.get_pins("gnd"): - if gnd_dir == "V": - self.connect_side_pin(pin, "top", self.top_gnd_locs[0].y) - self.connect_side_pin(pin, "bot", self.bot_gnd_locs[0].y) - elif gnd_dir == "H": - self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x) - self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x) + 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])) def route_unused_wordlines(self): """ Connect the unused RBL and dummy wordlines to gnd