Add dnwell

This commit is contained in:
mrg 2021-05-25 13:25:48 -07:00
parent cc91cdf008
commit 6493d1a7f4
2 changed files with 162 additions and 24 deletions

View File

@ -1161,6 +1161,8 @@ class layout():
height=ur.y - ll.y, height=ur.y - ll.y,
width=ur.x - ll.x) width=ur.x - ll.x)
self.bbox = [self.bounding_box.ll(), self.bounding_box.ur()]
def add_enclosure(self, insts, layer="nwell", extend=0, leftx=None, rightx=None, topy=None, boty=None): def add_enclosure(self, insts, layer="nwell", extend=0, leftx=None, rightx=None, topy=None, boty=None):
""" """
Add a layer that surrounds the given instances. Useful Add a layer that surrounds the given instances. Useful
@ -1341,7 +1343,146 @@ class layout():
layer=layer, layer=layer,
offset=peri_pin_loc) offset=peri_pin_loc)
def add_power_ring(self, bbox): def add_dnwell(self, bbox=None, inflate=1):
""" Create a dnwell, along with nwell moat at border. """
if "dnwell" not in techlayer:
return
if not bbox:
bbox = [self.find_lowest_coords(),
self.find_highest_coords()]
# Find the corners
[ll, ur] = bbox
# Possibly inflate the bbox
nwell_offset = vector(self.nwell_width, self.nwell_width)
ll -= nwell_offset.scale(inflate, inflate)
ur += nwell_offset.scale(inflate, inflate)
# Other corners
ul = vector(ll.x, ur.y)
lr = vector(ur.x, ll.y)
# Add the dnwell
self.add_rect("dnwell",
offset=ll,
height=ur.y - ll.y,
width=ur.x - ll.x)
# Add the moat
self.add_path("nwell", [ll, lr, ur, ul, ll - vector(0, 0.5 * self.nwell_width)])
# Add the taps
layer_stack = self.active_stack
tap_spacing = 2
nwell_offset = vector(self.nwell_width, self.nwell_width)
loc = ll + nwell_offset.scale(tap_spacing, 0)
end_loc = lr - nwell_offset.scale(tap_spacing, 0)
while loc.x < end_loc.x:
self.add_via_center(layers=layer_stack,
offset=loc,
implant_type="n",
well_type="n")
self.add_via_stack_center(from_layer="li",
to_layer="m1",
offset=loc)
loc += nwell_offset.scale(tap_spacing, 0)
loc = ul + nwell_offset.scale(tap_spacing, 0)
end_loc = ur - nwell_offset.scale(tap_spacing, 0)
while loc.x < end_loc.x:
self.add_via_center(layers=layer_stack,
offset=loc,
implant_type="n",
well_type="n")
self.add_via_stack_center(from_layer="li",
to_layer="m2",
offset=loc)
loc += nwell_offset.scale(tap_spacing, 0)
loc = ll + nwell_offset.scale(0, tap_spacing)
end_loc = ul - nwell_offset.scale(0, tap_spacing)
while loc.y < end_loc.y:
self.add_via_center(layers=layer_stack,
offset=loc,
implant_type="n",
well_type="n")
self.add_via_stack_center(from_layer="li",
to_layer="m2",
offset=loc)
loc += nwell_offset.scale(0, tap_spacing)
loc = lr + nwell_offset.scale(0, tap_spacing)
end_loc = ur - nwell_offset.scale(0, tap_spacing)
while loc.y < end_loc.y:
self.add_via_center(layers=layer_stack,
offset=loc,
implant_type="n",
well_type="n")
self.add_via_stack_center(from_layer="li",
to_layer="m2",
offset=loc)
loc += nwell_offset.scale(0, tap_spacing)
# Add the gnd ring
self.add_ring([ll, ur])
def add_ring(self, bbox=None, width_mult=8, offset=0):
"""
Add a ring around the bbox
"""
# Ring size/space/pitch
wire_width = self.m2_width * width_mult
half_width = 0.5 * wire_width
wire_space = self.m2_space
wire_pitch = wire_width + wire_space
# Find the corners
if not bbox:
bbox = [self.find_lowest_coords(),
self.find_highest_coords()]
[ll, ur] = bbox
ul = vector(ll.x, ur.y)
lr = vector(ur.x, ll.y)
ll += vector(-offset * wire_pitch,
-offset * wire_pitch)
lr += vector(offset * wire_pitch,
-offset * wire_pitch)
ur += vector(offset * wire_pitch,
offset * wire_pitch)
ul += vector(-offset * wire_pitch,
offset * wire_pitch)
half_offset = vector(half_width, half_width)
self.add_path("m1", [ll - half_offset.scale(1, 0), lr + half_offset.scale(1, 0)], width=wire_width)
self.add_path("m1", [ul - half_offset.scale(1, 0), ur + half_offset.scale(1, 0)], width=wire_width)
self.add_path("m2", [ll - half_offset.scale(0, 1), ul + half_offset.scale(0, 1)], width=wire_width)
self.add_path("m2", [lr - half_offset.scale(0, 1), ur + half_offset.scale(0, 1)], width=wire_width)
# Find the number of vias for this pitch
supply_vias = 1
from sram_factory import factory
while True:
c = factory.create(module_type="contact",
layer_stack=self.m1_stack,
dimensions=(supply_vias, supply_vias))
if c.second_layer_width < wire_width and c.second_layer_height < wire_width:
supply_vias += 1
else:
supply_vias -= 1
break
via_points = [ll, lr, ur, ul]
for pt in via_points:
self.add_via_center(layers=self.m1_stack,
offset=pt,
size=(supply_vias,
supply_vias))
def add_power_ring(self):
""" """
Create vdd and gnd power rings around an area of the bounding box Create vdd and gnd power rings around an area of the bounding box
argument. Must have a supply_rail_width and supply_rail_pitch argument. Must have a supply_rail_width and supply_rail_pitch
@ -1350,7 +1491,7 @@ class layout():
modules.. modules..
""" """
[ll, ur] = bbox [ll, ur] = self.bbox
supply_rail_spacing = self.supply_rail_pitch - self.supply_rail_width supply_rail_spacing = self.supply_rail_pitch - self.supply_rail_width
height = (ur.y - ll.y) + 3 * self.supply_rail_pitch - supply_rail_spacing height = (ur.y - ll.y) + 3 * self.supply_rail_pitch - supply_rail_spacing

View File

@ -5,9 +5,9 @@
# (acting for and on behalf of Oklahoma State University) # (acting for and on behalf of Oklahoma State University)
# All rights reserved. # All rights reserved.
# #
import debug
import math import math
class vector3d(): class vector3d():
""" """
This is the vector3d class to represent a 3D coordinate. This is the vector3d class to represent a 3D coordinate.
@ -74,7 +74,6 @@ class vector3d():
""" """
return vector3d(self.x + other[0], self.y + other[1], self.z + other[2]) return vector3d(self.x + other[0], self.y + other[1], self.z + other[2])
def __radd__(self, other): def __radd__(self, other):
""" """
Override + function (right add) Override + function (right add)
@ -98,7 +97,6 @@ class vector3d():
""" """
return self._hash return self._hash
def __rsub__(self, other): def __rsub__(self, other):
""" """
Override - function (right) Override - function (right)
@ -178,7 +176,6 @@ class vector3d():
""" Return the euclidean distance between two values """ """ Return the euclidean distance between two values """
return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2) return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)
def adjacent(self, other): def adjacent(self, other):
""" Is the one grid adjacent in any planar direction to the other """ """ Is the one grid adjacent in any planar direction to the other """
if self == other + vector3d(1, 0, 0): if self == other + vector3d(1, 0, 0):