Skip to content

Commit

Permalink
Rework replica_bitcell_array supplies
Browse files Browse the repository at this point in the history
Uses layer and direction preferences in tech file.
Places straps on left/right or top/bottom.
  • Loading branch information
mguthaus committed Apr 19, 2022
1 parent 5e546ee commit 64f2f90
Show file tree
Hide file tree
Showing 11 changed files with 210 additions and 61 deletions.
10 changes: 10 additions & 0 deletions compiler/base/custom_cell_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,16 @@ def __init__(self, port_order, port_types, port_map=None, storage_nets=["Q", "Q_

self.storage_nets = storage_nets

self.wl_layer = "m1"
self.wl_dir = "H"
self.bl_layer = "m2"
self.bl_dir = "V"

self.vdd_layer = "m1"
self.vdd_dir = "H"
self.gnd_layer = "m1"
self.gnd_dir = "H"


class cell_properties():
"""
Expand Down
17 changes: 8 additions & 9 deletions compiler/base/hierarchy_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -673,9 +673,9 @@ def route_vertical_pins(self, name, insts=None, layer=None, xside="cx", yside="c
bot_pos = vector(x, bot_y)

if num_pins==2:
self.add_layout_pin_rect_ends(name=name,
layer=pin_layer,
start=top_pos,
self.add_layout_pin_rect_ends(name=name,
layer=pin_layer,
start=top_pos,
end=bot_pos,
width=via_width)
else:
Expand All @@ -689,10 +689,10 @@ def route_vertical_pins(self, name, insts=None, layer=None, xside="cx", yside="c
def add_layout_pin_rect_ends(self, name, layer, start, end, width=None):

# This adds pins on the end connected by a segment
top_rect = self.add_layout_pin_rect_center(text=name,
top_rect = self.add_layout_pin_rect_center(text=name,
layer=layer,
offset=start)
bot_rect = self.add_layout_pin_rect_center(text=name,
bot_rect = self.add_layout_pin_rect_center(text=name,
layer=layer,
offset=end)
# This is made to not overlap with the pin above
Expand Down Expand Up @@ -773,9 +773,9 @@ def route_horizontal_pins(self, name, insts=None, layer=None, xside="cx", yside=
right_pos = vector(right_x, y)

if num_pins==2:
self.add_layout_pin_rect_ends(name=name,
layer=pin_layer,
start=left_pos,
self.add_layout_pin_rect_ends(name=name,
layer=pin_layer,
start=left_pos,
end=right_pos,
width=via_height)
else:
Expand Down Expand Up @@ -812,7 +812,6 @@ def add_layout_end_pin_segment_center(self, text, layer, start, end):
end=end_pin.bc())
else:
debug.error("Cannot have a point pin.", -1)


def add_layout_pin_segment_center(self, text, layer, start, end, width=None):
"""
Expand Down
2 changes: 1 addition & 1 deletion compiler/modules/col_cap_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,4 @@ def add_layout_pins(self):
inst = self.cell_inst[row, col]
for pin_name in ["vdd", "gnd"]:
for pin in inst.get_pins(pin_name):
self.copy_power_pin(pin)
self.copy_layout_pin(inst, pin_name)
9 changes: 9 additions & 0 deletions compiler/modules/dff_buf_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,15 @@ def get_dout_bar_name(self, row, col):
return dout_bar_name

def route_supplies(self):
for row in range(self.rows):
vdd0_pin=self.dff_insts[row, 0].get_pin("vdd")
vddn_pin=self.dff_insts[row, self.columns - 1].get_pin("vdd")
self.add_path(vdd0_pin.layer, [vdd0_pin.lc(), vddn_pin.rc()], width=vdd0_pin.height())

gnd0_pin=self.dff_insts[row, 0].get_pin("gnd")
gndn_pin=self.dff_insts[row, self.columns - 1].get_pin("gnd")
self.add_path(gnd0_pin.layer, [gnd0_pin.lc(), gndn_pin.rc()], width=gnd0_pin.height())

if OPTS.experimental_power and self.rows > 1:
# Vertical straps on ends if multiple rows
left_dff_insts = [self.dff_insts[x, 0] for x in range(self.rows)]
Expand Down
201 changes: 155 additions & 46 deletions compiler/modules/replica_bitcell_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

import debug
from bitcell_base_array import bitcell_base_array
from tech import drc, spice, cell_properties
from tech import drc, spice, preferred_directions
from tech import cell_properties as props
from vector import vector
from globals import OPTS
from sram_factory import factory
Expand Down Expand Up @@ -309,7 +310,7 @@ def create_layout(self):
# row-based or column based power and ground lines.
self.vertical_pitch = getattr(self, "{}_pitch".format(self.supply_stack[0]))
self.horizontal_pitch = getattr(self, "{}_pitch".format(self.supply_stack[2]))
self.unused_offset = vector(2 * self.horizontal_pitch, 2 * self.vertical_pitch)
self.unused_offset = vector(0.25, 0.25)

# This is a bitcell x bitcell offset to scale
self.bitcell_offset = vector(self.cell.width, self.cell.height)
Expand Down Expand Up @@ -461,38 +462,67 @@ def add_layout_pins(self):

def route_supplies(self):

bitcell = getattr(props, "bitcell_{}port".format(OPTS.num_ports))

wl_layer = bitcell.wl_layer
wl_dir = bitcell.wl_dir

bl_layer = bitcell.bl_layer
bl_dir = bitcell.bl_dir

vdd_layer = bitcell.vdd_layer
vdd_dir = bitcell.vdd_dir

gnd_layer = bitcell.gnd_layer
gnd_dir = bitcell.gnd_dir

# vdd/gnd are only connected in the perimeter cells
# replica column should only have a vdd/gnd in the dummy cell on top/bottom
supply_insts = self.dummy_col_insts + self.dummy_row_insts

vdd_leftx = 0
vdd_rightx = 0
gnd_leftx = 0
gnd_rightx = 0
# For the wordlines
top_bot_mult = 1
left_right_mult = 1

vdd_locs = []
gnd_locs = []
# 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)
left_right_mult = 3

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)
top_bot_mult = 3

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"):
(vdd_leftx, vdd_rightx) = self.connect_pin(pin, 2.5)
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"):
(gnd_leftx, gnd_rightx) = self.connect_pin(pin)


self.add_layout_end_pin_segment_center(text="vdd",
layer=self.supply_stack[2],
start=vector(vdd_leftx, 0),
end=vector(vdd_leftx, self.height))
self.add_layout_end_pin_segment_center(text="vdd",
layer=self.supply_stack[2],
start=vector(vdd_rightx, 0),
end=vector(vdd_rightx, self.height))
self.add_layout_end_pin_segment_center(text="gnd",
layer=self.supply_stack[2],
start=vector(gnd_leftx, 0),
end=vector(gnd_leftx, self.height))
self.add_layout_end_pin_segment_center(text="gnd",
layer=self.supply_stack[2],
start=vector(gnd_rightx, 0),
end=vector(gnd_rightx, self.height))
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)


def route_unused_wordlines(self):
Expand All @@ -501,41 +531,120 @@ def route_unused_wordlines(self):
for inst in self.dummy_row_insts:
for wl_name in self.col_cap_top.get_wordline_names():
pin = inst.get_pin(wl_name)
self.connect_pin(pin)
self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x)
self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x)

# Ground the unused replica wordlines
for (names, inst) in zip(self.rbl_wordline_names, self.dummy_row_replica_insts):
for (wl_name, pin_name) in zip(names, self.dummy_row.get_wordline_names()):
if wl_name in self.gnd_wordline_names:
pin = inst.get_pin(pin_name)
self.connect_pin(pin)

self.connect_side_pin(pin, "left", self.left_gnd_locs[0].x)
self.connect_side_pin(pin, "right", self.right_gnd_locs[0].x)

def connect_pin(self, pin, offset_multiple=1):
def route_side_pin(self, name, side, offset_multiple=1):
"""
Routes a vertical or horizontal pin on the side of the bbox.
The multiple specifies how many track offsets to be away from the side assuming
(0,0) (self.width, self.height)
"""
if side in ["left", "right"]:
return self.route_vertical_side_pin(name, side, offset_multiple)
elif side in ["top", "bottom", "bot"]:
return self.route_horizontal_side_pin(name, side, offset_multiple)
else:
debug.error("Invalid side {}".format(side), -1)

pin_layer = pin.layer
def route_vertical_side_pin(self, name, side, offset_multiple=1):
"""
Routes a vertical pin on the side of the bbox.
"""
if side == "left":
bot_loc = vector(-offset_multiple * self.vertical_pitch, 0)
top_loc = vector(-offset_multiple * self.vertical_pitch, self.height)
elif side == "right":
bot_loc = vector(self.width + offset_multiple * self.vertical_pitch, 0)
top_loc = vector(self.width + offset_multiple * self.vertical_pitch, self.height)

layer = self.supply_stack[2]
self.add_path(layer, [bot_loc, top_loc])

self.add_layout_pin_rect_center(text=name,
layer=layer,
offset=top_loc)
self.add_layout_pin_rect_center(text=name,
layer=layer,
offset=bot_loc)

return (bot_loc, top_loc)

def route_horizontal_side_pin(self, name, side, offset_multiple=1):
"""
Routes a horizontal pin on the side of the bbox.
"""
if side in ["bottom", "bot"]:
left_loc = vector(0, -offset_multiple * self.horizontal_pitch)
right_loc = vector(self.width, -offset_multiple * self.horizontal_pitch)
elif side == "top":
left_loc = vector(0, self.height + offset_multiple * self.horizontal_pitch)
right_loc = vector(self.width, self.height + offset_multiple * self.horizontal_pitch)

layer = self.supply_stack[0]
self.add_path(layer, [left_loc, right_loc])

self.add_layout_pin_rect_center(text=name,
layer=layer,
offset=left_loc)
self.add_layout_pin_rect_center(text=name,
layer=layer,
offset=right_loc)

return (left_loc, right_loc)

def connect_side_pin(self, pin, side, offset):
"""
Used to connect horizontal layers of pins to the left/right straps
locs provides the offsets of the pin strip end points.
"""
if side in ["left", "right"]:
self.connect_vertical_side_pin(pin, side, offset)
elif side in ["top", "bottom", "bot"]:
self.connect_horizontal_side_pin(pin, side, offset)
else:
debug.error("Invalid side {}".format(side), -1)

left_pin_loc = vector(self.dummy_col_insts[0].lx(), pin.cy())
right_pin_loc = vector(self.dummy_col_insts[1].rx(), pin.cy())
def connect_horizontal_side_pin(self, pin, side, yoffset):
"""
Used to connect vertical layers of pins to the top/bottom horizontal straps
"""
cell_loc = pin.center()
pin_loc = vector(cell_loc.x, yoffset)

# Place the pins a track outside of the array
left_loc = left_pin_loc - vector(offset_multiple * self.horizontal_pitch, 0)
right_loc = right_pin_loc + vector(offset_multiple * self.horizontal_pitch, 0)
self.add_via_stack_center(offset=left_loc,
from_layer=pin_layer,
to_layer=self.supply_stack[2],
directions=("H", "H"))
self.add_via_stack_center(offset=right_loc,
from_layer=pin_layer,
to_layer=self.supply_stack[2],
directions=("H", "H"))
self.add_via_stack_center(offset=pin_loc,
from_layer=pin.layer,
to_layer=self.supply_stack[0],
directions=("V", "V"))

# Add a path to connect to the array
self.add_path(pin_layer, [left_loc, right_loc])
self.add_path(pin.layer, [cell_loc, pin_loc])


return (left_loc.x, right_loc.x)
def connect_vertical_side_pin(self, pin, side, xoffset):
"""
Used to connect vertical layers of pins to the top/bottom vertical straps
"""
cell_loc = pin.center()
pin_loc = vector(xoffset, cell_loc.y)

# Place the pins a track outside of the array
self.add_via_stack_center(offset=pin_loc,
from_layer=pin.layer,
to_layer=self.supply_stack[2],
directions=("H", "H"))

# Add a path to connect to the array
self.add_path(pin.layer, [cell_loc, pin_loc])

def analytical_power(self, corner, load):
"""Power of Bitcell array and bitline in nW."""
Expand Down
7 changes: 5 additions & 2 deletions compiler/modules/row_cap_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,13 @@ def add_layout_pins(self):
width=self.width,
height=wl_pin.height())

# Add vdd/gnd via stacks
for row in range(1, self.row_size - 1):
for col in range(self.column_size):
inst = self.cell_inst[row, col]
for pin_name in ["vdd", "gnd"]:
for pin in inst.get_pins(pin_name):
self.copy_power_pin(pin)
self.add_layout_pin(text=pin_name,
layer=pin.layer,
offset=pin.ll(),
width=pin.width(),
height=pin.height())
3 changes: 1 addition & 2 deletions compiler/openram.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,8 @@


from sram import sram
s = sram(name=OPTS.output_name,
s = sram(name=OPTS.output_name,
sram_config=c)


# Output the files for the resulting SRAM
s.save()
Expand Down
2 changes: 2 additions & 0 deletions compiler/tests/configs/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@
nominal_corner_only = True
check_lvsdrc = True

route_supplies = False

output_name = "sram"
1 change: 0 additions & 1 deletion technology/freepdk45/tech/tech.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
# Custom cell properties
###################################################
cell_properties = cell_properties()
cell_properties.bitcell_power_pin_directions = ("V", "V")

###################################################
# Custom cell properties
Expand Down
2 changes: 2 additions & 0 deletions technology/scn4m_subm/tech/tech.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
# Custom cell properties
###################################################
cell_properties = cell_properties()
cell_properties.bitcell_1port.gnd_layer = "m2"
cell_properties.bitcell_1port.gnd_dir = "V"

###################################################
# Custom cell properties
Expand Down
Loading

0 comments on commit 64f2f90

Please sign in to comment.