Add vdd and gnd rails around bank structure.

This commit is contained in:
Matt Guthaus 2018-03-04 17:53:22 -08:00
parent 8d9b79dfd8
commit 0f721a3d40
2 changed files with 220 additions and 102 deletions

View File

@ -80,6 +80,7 @@ class bank(design.design):
def route_layout(self): def route_layout(self):
""" Create routing amoung the modules """ """ Create routing amoung the modules """
self.route_power_ring(self.core_bbox)
self.create_central_bus() self.create_central_bus()
self.route_precharge_to_bitcell_array() self.route_precharge_to_bitcell_array()
self.route_sense_amp_to_trigate() self.route_sense_amp_to_trigate()
@ -129,10 +130,10 @@ class bank(design.design):
debug.check(self.num_rows*self.num_cols==self.word_size*self.num_words,"Invalid bank sizes.") debug.check(self.num_rows*self.num_cols==self.word_size*self.num_words,"Invalid bank sizes.")
debug.check(self.addr_size==self.col_addr_size + self.row_addr_size,"Invalid address break down.") debug.check(self.addr_size==self.col_addr_size + self.row_addr_size,"Invalid address break down.")
# Width for left gnd rail # Width for the vdd/gnd rails
self.vdd_rail_width = 5*self.m2_width self.supply_rail_width = 4*self.m2_width
self.gnd_rail_width = 5*self.m2_width self.supply_rail_pitch = self.supply_rail_width + 1.5*self.m2_space
# Number of control lines in the bus # Number of control lines in the bus
self.num_control_lines = 6 self.num_control_lines = 6
# The order of the control signals on the control bus: # The order of the control signals on the control bus:
@ -153,13 +154,12 @@ class bank(design.design):
self.m2_pitch = contact.m2m3.height + max(self.m2_space,self.m3_space) self.m2_pitch = contact.m2m3.height + max(self.m2_space,self.m3_space)
# Overall central bus gap. It includes all the column mux lines, # Overall central bus gap. It includes all the column mux lines,
# control lines, address flop to decoder lines and a GND power rail in M2 # control lines, and address flop to decoder lines
# 1.5 pitches on the right on the right of the control lines for vias (e.g. column mux addr lines) # 1.5 pitches on the right on the right of the control lines for vias (e.g. column mux addr lines)
self.start_of_right_central_bus = -self.m2_pitch * (self.num_control_lines + 1.5) self.start_of_right_central_bus = -self.m2_pitch * (self.num_control_lines + 1.5)
# one pitch on the right on the addr lines and one on the right of the gnd rail self.start_of_left_central_bus = self.start_of_right_central_bus - self.m2_pitch*(self.num_addr_lines)
self.start_of_left_central_bus = self.start_of_right_central_bus - self.m2_pitch*(self.num_addr_lines+2) - self.gnd_rail_width # add a pitch on each side
# add a pitch on each end and around the gnd rail self.overall_central_bus_width = self.m2_pitch * (self.num_control_lines + self.num_addr_lines + 3)
self.overall_central_bus_width = self.m2_pitch * (self.num_control_lines + self.num_addr_lines + 5) + self.gnd_rail_width
@ -390,7 +390,7 @@ class bank(design.design):
self.connect_inst(temp) self.connect_inst(temp)
def add_msf_address(self): def add_msf_address(self):
""" Adding address Flip-flops """ """ Adding address wires """
# A gap between the hierarchical decoder and addr flops # A gap between the hierarchical decoder and addr flops
gap = max(drc["pwell_to_nwell"], 2*self.m2_pitch) gap = max(drc["pwell_to_nwell"], 2*self.m2_pitch)
@ -469,7 +469,7 @@ class bank(design.design):
self.add_mod(self.nand2) self.add_mod(self.nand2)
# left of gnd rail is the "bus start" # left of gnd rail is the "bus start"
bus_start = self.gnd_x_offset - self.m2_space bus_start = self.start_of_right_central_bus - self.m2_space
xoffset_nand = bus_start - self.nand2.width - self.inv4x.width - drc["pwell_to_nwell"] xoffset_nand = bus_start - self.nand2.width - self.inv4x.width - drc["pwell_to_nwell"]
xoffset_nor = bus_start - self.nor2.width - self.inv4x.width - drc["pwell_to_nwell"] xoffset_nor = bus_start - self.nor2.width - self.inv4x.width - drc["pwell_to_nwell"]
xoffset_inv = bus_start - self.inv4x.width xoffset_inv = bus_start - self.inv4x.width
@ -617,17 +617,21 @@ class bank(design.design):
# Add vdd/gnd supply rails # Add vdd/gnd supply rails
gnd_pos = inv_inst.get_pin("gnd").cy() gnd_pin = inv_inst.get_pin("gnd")
left_gnd_pos = vector(xoffset_bank_sel_inv, gnd_pos) left_gnd_pos = vector(self.left_gnd_x_center, gnd_pos.cy())
right_gnd_pos = vector(self.gnd_x_offset + 0.5*contact.m1m2.height, gnd_pos) self.add_path("metal1",[left_gnd_pos, gnd_pos.rc()])
self.add_path("metal1",[left_gnd_pos, right_gnd_pos])
self.add_via_center(layers=("metal1", "via1", "metal2"), self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=right_gnd_pos, offset=left_gnd_pos,
rotate=90) size = (1,3),
rotate=90)
vdd_pin = inv_inst.get_pin("vdd") vdd_pin = inv_inst.get_pin("vdd")
left_vdd_pos = vector(self.left_vdd_x_offset,vdd_pin.cy()) left_vdd_pos = vector(self.left_vdd_x_center, vdd_pin.cy())
self.add_path("metal1",[left_vdd_pos,vdd_pin.rc()]) self.add_path("metal1",[left_vdd_pos, vdd_pin.rc()])
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=left_vdd_pos,
size = (1,3),
rotate=90)
@ -647,43 +651,129 @@ class bank(design.design):
self.decoder_min_point = addr_min_point self.decoder_min_point = addr_min_point
if self.num_banks>1: if self.num_banks>1:
# The control gating logic is below the decoder
# Min of the control gating logic and tri gate.
self.min_point = min(self.decoder_min_point - self.num_control_lines * self.bitcell.height, tri_gate_min_point) self.min_point = min(self.decoder_min_point - self.num_control_lines * self.bitcell.height, tri_gate_min_point)
else: else:
# Just the min of the decoder logic logic and tri gate.
self.min_point = min(self.decoder_min_point, addr_min_point, tri_gate_min_point) self.min_point = min(self.decoder_min_point, addr_min_point, tri_gate_min_point)
# The max point is always the top of the precharge bitlines # The max point is always the top of the precharge bitlines
self.max_point = self.precharge_array_inst.uy() # Add a vdd and gnd power rail above the array
self.max_point = self.precharge_array_inst.uy() + 3*self.m1_width
# Create the core bbox for the power rings
ur = vector(self.bitcell_array_inst.ur().x + 3*self.m1_width, self.max_point)
ll = vector(min(self.msf_address_inst.ll().x, self.row_decoder_inst.ll().x), self.min_point)
self.core_bbox = [ll, ur]
# Compute the vertical rail positions for later use
self.right_gnd_x_offset = ur.x
self.right_vdd_x_offset = self.right_gnd_x_offset + self.supply_rail_pitch
self.left_vdd_x_offset = ll.x - self.supply_rail_pitch
self.left_gnd_x_offset = self.left_vdd_x_offset - self.supply_rail_pitch
# Add a vdd and gnd power rail below the array
self.min_point -= 2*self.supply_rail_pitch
# Add a vdd and gnd power rail above the array
self.max_point += self.supply_rail_pitch + self.supply_rail_width
self.height = self.max_point - self.min_point self.height = self.max_point - self.min_point
self.width = self.right_vdd_x_offset - self.left_gnd_x_offset + self.supply_rail_width
# Add an extra gap between the bitcell and the rail def route_power_ring(self, bbox):
self.right_vdd_x_offset = self.bitcell_array_inst.ur().x + 3 * self.m1_width """ Create vdd and gnd power rings around an area of the bounding box argument.. """
offset = vector(self.right_vdd_x_offset, self.min_point)
self.add_layout_pin(text="vdd",
layer="metal1",
offset=offset,
width=self.vdd_rail_width,
height=self.height)
# from the edge of the decoder is another 2 times minwidth metal1 [ll, ur] = bbox
self.left_vdd_x_offset = min(self.msf_address_inst.ll().x, self.row_decoder_inst.ll().x) - self.vdd_rail_width - 2*self.m1_width
offset = vector(self.left_vdd_x_offset, self.min_point)
self.add_layout_pin(text="vdd",
layer="metal1",
offset=offset,
width=self.vdd_rail_width,
height=self.height)
self.gnd_x_offset = self.start_of_right_central_bus - self.gnd_rail_width - self.m2_pitch # LEFT vertical rails
offset = vector(self.gnd_x_offset, self.min_point) offset = ll.scale(1,0) + vector(-2*self.supply_rail_pitch, self.min_point)
self.add_layout_pin(text="gnd", left_gnd_pin=self.add_layout_pin(text="gnd",
layer="metal2", layer="metal2",
offset=offset, offset=offset,
width=self.gnd_rail_width, width=self.supply_rail_width,
height=self.height) height=self.height)
self.width = self.right_vdd_x_offset - self.left_vdd_x_offset + self.vdd_rail_width
offset = ll.scale(1,0) + vector(-1*self.supply_rail_pitch, self.min_point)
left_vdd_pin=self.add_layout_pin(text="vdd",
layer="metal2",
offset=offset,
width=self.supply_rail_width,
height=self.height)
# RIGHT vertical rails
offset = ur.scale(1,0) + vector(0,self.min_point)
right_gnd_pin = self.add_layout_pin(text="gnd",
layer="metal2",
offset=offset,
width=self.supply_rail_width,
height=self.height)
offset = ur.scale(1,0) + vector(self.supply_rail_pitch,self.min_point)
right_vdd_pin=self.add_layout_pin(text="vdd",
layer="metal2",
offset=offset,
width=self.supply_rail_width,
height=self.height)
# 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="metal1",
offset=offset,
width=self.width,
height=self.supply_rail_width)
offset = ll + vector(-2*self.supply_rail_pitch, -1*self.supply_rail_pitch)
bottom_vdd_pin=self.add_layout_pin(text="vdd",
layer="metal1",
offset=offset,
width=self.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="metal1",
offset=offset,
width=self.width,
height=self.supply_rail_width)
offset = vector(ll.x, ur.y) + vector(-2*self.supply_rail_pitch, self.supply_rail_pitch)
top_vdd_pin=self.add_layout_pin(text="vdd",
layer="metal1",
offset=offset,
width=self.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.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()
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)]
for pt in via_points:
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=pt,
size = (3,3))
def create_central_bus(self): def create_central_bus(self):
""" Create the address, supply, and control signal central bus lines. """ """ Create the address, supply, and control signal central bus lines. """
@ -829,29 +919,26 @@ class bank(design.design):
for gnd_pin in self.row_decoder_inst.get_pins("gnd"): for gnd_pin in self.row_decoder_inst.get_pins("gnd"):
if gnd_pin.uy()>0: if gnd_pin.uy()>0:
continue continue
decoder_gnd_position = gnd_pin.rc() gnd_position = gnd_pin.rc()
via_position = decoder_gnd_position + vector(0.5*contact.m1m2.height+self.m2_space,0) left_rail_position = vector(self.left_gnd_x_center, gnd_position.y)
gnd_rail_position = vector(self.gnd_x_offset, decoder_gnd_position.y) self.add_path("metal1", [left_rail_position, gnd_position])
self.add_path("metal1", [decoder_gnd_position, via_position]) self.add_via_center(layers=("metal1", "via1", "metal2"),
self.add_path("metal3", [via_position, gnd_rail_position]) offset=left_rail_position,
self.add_via_center(layers=("metal1","via1","metal2"), size = (1,3),
offset=via_position,
rotate=90) rotate=90)
self.add_via_center(layers=("metal2","via2","metal3"),
offset=via_position,
rotate=90)
self.add_via_center(layers=("metal2","via2","metal3"),
offset=gnd_rail_position,
rotate=270)
# route the vdd rails # route the vdd rails
for vdd_pin in self.row_decoder_inst.get_pins("vdd"): for vdd_pin in self.row_decoder_inst.get_pins("vdd"):
if vdd_pin.uy()>0: if vdd_pin.uy()>0:
continue continue
y_offset = vdd_pin.rc().y vdd_y_pos = vdd_pin.cy()
left_rail_position = vector(self.left_vdd_x_offset, y_offset) left_rail_position = vector(self.left_vdd_x_center, vdd_y_pos)
right_rail_position = vector(self.row_decoder_inst.ur().x, y_offset) right_rail_position = vector(self.row_decoder_inst.ur().x, vdd_y_pos)
self.add_path("metal1", [left_rail_position, right_rail_position]) self.add_path("metal1", [left_rail_position, right_rail_position])
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=left_rail_position,
size = (1,3),
rotate=90)
def route_wordline_driver(self): def route_wordline_driver(self):
@ -876,20 +963,28 @@ class bank(design.design):
# route the gnd rails, add contact to rail as well # route the gnd rails, add contact to rail as well
for gnd_pin in self.wordline_driver_inst.get_pins("gnd"): for gnd_pin in self.wordline_driver_inst.get_pins("gnd"):
driver_gnd_pos = gnd_pin.rc() gnd_pos = gnd_pin.rc()
right_rail_pos = vector(self.bitcell_array_inst.ll().x, driver_gnd_pos.y) left_rail_pos = vector(self.left_gnd_x_center, gnd_pos.y)
self.add_path("metal1", [driver_gnd_pos, right_rail_pos]) self.add_path("metal1", [left_rail_pos, gnd_pos])
gnd_rail_pos = vector(self.gnd_x_offset, driver_gnd_pos.y + 0.5*contact.m1m2.width) self.add_via_center(layers=("metal1", "via1", "metal2"),
self.add_via(layers=("metal1","via1","metal2"), offset=left_rail_pos,
offset=gnd_rail_pos, size = (1,3),
rotate=270) rotate=90)
# route the vdd rails # route the vdd rails
for vdd_pin in self.wordline_driver_inst.get_pins("vdd"): for vdd_pin in self.wordline_driver_inst.get_pins("vdd"):
y_offset = vdd_pin.rc().y vdd_pos = vdd_pin.rc()
left_rail_pos = vector(self.left_vdd_x_offset, y_offset) left_rail_pos = vector(self.left_vdd_x_center, vdd_pos.y)
right_rail_pos = vector(self.right_vdd_x_offset+self.vdd_rail_width, y_offset) right_rail_pos = vector(self.right_vdd_x_center, vdd_pos.y)
self.add_path("metal1", [left_rail_pos, right_rail_pos]) self.add_path("metal1", [left_rail_pos, right_rail_pos])
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=left_rail_pos,
size = (1,3),
rotate=90)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=right_rail_pos,
size = (1,3),
rotate=90)
@ -928,20 +1023,21 @@ class bank(design.design):
# route the gnd rails, add contact to rail as well # route the gnd rails, add contact to rail as well
for gnd_pin in self.col_decoder_inst.get_pins("gnd"): for gnd_pin in self.col_decoder_inst.get_pins("gnd"):
driver_gnd_pos = gnd_pin.rc() left_rail_pos = vector(self.left_gnd_x_offset, gnd_pin.cy())
right_rail_pos = vector(self.gnd_x_offset, driver_gnd_pos.y) self.add_path("metal1", [left_rail_pos, gnd_pin.rc()])
self.add_path("metal1", [driver_gnd_pos, right_rail_pos]) self.add_via_center(layers=("metal1", "via1", "metal2"),
gnd_rail_pos = vector(self.gnd_x_offset, driver_gnd_pos.y + 0.5*contact.m1m2.width) offset=left_rail_pos,
self.add_via(layers=("metal1","via1","metal2"), size = (1,3),
offset=gnd_rail_pos, rotate=90)
rotate=270)
# route the vdd rails # route the vdd rails
for vdd_pin in self.col_decoder_inst.get_pins("vdd"): for vdd_pin in self.col_decoder_inst.get_pins("vdd"):
y_offset = vdd_pin.rc().y left_rail_pos = vector(self.left_vdd_x_center, vdd_pin.cy())
left_rail_pos = vector(self.left_vdd_x_offset, y_offset) self.add_path("metal1", [left_rail_pos, vdd_pin.rc()])
right_rail_pos = vector(self.gnd_x_offset, y_offset) self.add_via_center(layers=("metal1", "via1", "metal2"),
self.add_path("metal1", [left_rail_pos, right_rail_pos]) offset=left_rail_pos,
size = (1,3),
rotate=90)
# The connection between last address flops to the input # The connection between last address flops to the input
# of the column_mux line decoder # of the column_mux line decoder
@ -1001,11 +1097,11 @@ class bank(design.design):
if pin.layer=="metal3": if pin.layer=="metal3":
msf_din_pos=pin.ll() msf_din_pos=pin.ll()
break break
address_pos = vector(self.left_vdd_x_offset, msf_din_pos.y) address_pos = vector(self.left_gnd_x_offset, msf_din_pos.y)
self.add_layout_pin(text="ADDR[{}]".format(i), self.add_layout_pin(text="ADDR[{}]".format(i),
layer="metal3", layer="metal3",
offset=address_pos, offset=address_pos,
width=msf_din_pos.x - self.left_vdd_x_offset) width=msf_din_pos.x - address_pos.x)
for i in range(self.row_addr_size): for i in range(self.row_addr_size):
@ -1025,17 +1121,17 @@ class bank(design.design):
for gnd_pin in self.msf_address_inst.get_pins("gnd"): for gnd_pin in self.msf_address_inst.get_pins("gnd"):
if gnd_pin.layer != "metal2": if gnd_pin.layer != "metal2":
continue continue
gnd_via = gnd_pin.lr() + vector(contact.m1m2.height,0) gnd_via = gnd_pin.ll() + vector(contact.m1m2.height,0)
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via(layers=("metal1", "via1", "metal2"),
offset=gnd_via, offset=gnd_via,
rotate=90) rotate=90)
gnd_offset = gnd_pin.rc() gnd_offset = gnd_pin.lc()
rail_offset = vector(self.gnd_x_offset+contact.m1m2.height,gnd_offset.y) rail_offset = vector(self.left_gnd_x_center, gnd_offset.y)
self.add_path("metal1",[gnd_offset,rail_offset]) self.add_path("metal1",[gnd_offset,rail_offset])
rail_via = rail_offset - vector(0,0.5*self.m2_width) self.add_via_center(layers=("metal1", "via1", "metal2"),
self.add_via(layers=("metal1", "via1", "metal2"), offset=rail_offset,
offset=rail_via, size = (1,3),
rotate=90) rotate=90)
# Connect address FF vdd # Connect address FF vdd
for vdd_pin in self.msf_address_inst.get_pins("vdd"): for vdd_pin in self.msf_address_inst.get_pins("vdd"):
@ -1043,8 +1139,12 @@ class bank(design.design):
continue continue
vdd_offset = vdd_pin.bc() vdd_offset = vdd_pin.bc()
mid = vector(vdd_offset.x, vdd_offset.y - self.m1_pitch) mid = vector(vdd_offset.x, vdd_offset.y - self.m1_pitch)
rail_offset = vector(self.left_vdd_x_offset, mid.y) rail_offset = vector(self.left_vdd_x_center, mid.y)
self.add_path("metal1", [vdd_offset,mid,rail_offset]) self.add_path("metal1", [vdd_offset,mid,rail_offset])
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=rail_offset,
size = (1,3),
rotate=90)
def add_lvs_correspondence_points(self): def add_lvs_correspondence_points(self):
""" This adds some points for easier debugging if LVS goes wrong. """ This adds some points for easier debugging if LVS goes wrong.
@ -1143,8 +1243,13 @@ class bank(design.design):
for vdd_pin in inst.get_pins("vdd"): for vdd_pin in inst.get_pins("vdd"):
self.add_rect(layer="metal1", self.add_rect(layer="metal1",
offset=vdd_pin.ll(), offset=vdd_pin.ll(),
width=self.right_vdd_x_offset - vdd_pin.lx(), width=self.right_vdd_x_center,
height=self.m1_width) height=vdd_pin.height())
via_position = vector(self.right_vdd_x_center, vdd_pin.cy())
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=via_position,
size = (1,3),
rotate=90)
def route_gnd_supply(self): def route_gnd_supply(self):
@ -1156,12 +1261,13 @@ class bank(design.design):
continue continue
# route to the right hand side of the big rail to reduce via overlaps # route to the right hand side of the big rail to reduce via overlaps
pin_pos = gnd_pin.lc() pin_pos = gnd_pin.lc()
gnd_offset = vector(self.gnd_x_offset+self.gnd_rail_width, pin_pos.y) gnd_offset = vector(self.right_gnd_x_offset + self.supply_rail_width, pin_pos.y)
self.add_path("metal1", [gnd_offset, pin_pos]) self.add_path("metal1", [pin_pos, gnd_offset])
contact_offset = gnd_offset - vector(0,0.5*self.m2_width) via_position = vector(self.right_gnd_x_center, gnd_pin.cy())
self.add_via(layers=("metal1", "via1", "metal2"), self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=contact_offset, offset=via_position,
rotate=90) size = (1,3),
rotate=90)
def add_control_pins(self): def add_control_pins(self):
""" Add the control signal input pins """ """ Add the control signal input pins """

View File

@ -685,7 +685,7 @@ class sram(design.design):
""" Create rails at bottom. Connect veritcal rails to top and bottom. """ """ Create rails at bottom. Connect veritcal rails to top and bottom. """
self.add_layout_pin(text="gnd", self.add_layout_pin(text="gnd",
layer="metal3", layer="metal1",
offset=vector(0,0), offset=vector(0,0),
height=self.power_rail_width, height=self.power_rail_width,
width=self.width) width=self.width)
@ -703,10 +703,22 @@ class sram(design.design):
for vdd_pin in vdd_pins: for vdd_pin in vdd_pins:
vdd_pos = vdd_pin.ul() vdd_pos = vdd_pin.ul()
# Route to bottom # Route to bottom
self.add_rect(layer="metal1", self.add_rect(layer="metal2",
offset=vector(vdd_pos.x,self.power_rail_pitch), offset=vector(vdd_pos.x,self.power_rail_pitch),
height=self.horz_control_bus_positions["vdd"].y-self.power_rail_pitch, height=self.horz_control_bus_positions["vdd"].y-self.power_rail_pitch,
width=vdd_pin.width()) width=vdd_pin.width())
# Add vias at top
rail_pos = vector(vdd_pin.ur().x,self.horz_control_bus_positions["vdd"].y)
self.add_via(layers=("metal1","via1","metal2"),
offset=rail_pos - vector(0,0.5*self.m1_width),
rotate=90,
size=[1,3])
# Add vias at bottom
rail_pos = vector(vdd_pin.lr().x,self.power_rail_pitch)
self.add_via(layers=("metal1","via1","metal2"),
offset=rail_pos,
rotate=90,
size=[2,3])
gnd_pins = self.bank_inst[i].get_pins("gnd") gnd_pins = self.bank_inst[i].get_pins("gnd")
for gnd_pin in gnd_pins: for gnd_pin in gnd_pins: