Thin-cell decoder changes.

Add hard decoder gates (nand, inv, pnan)
Add conditions for routing using LI layer in s8.
Generalize bus layers for decoders.
Move custom cells to own directory.
Fixed via directions, etc.
Add 4x16 hierarchical decoder and test case
This commit is contained in:
mrg
2020-05-29 10:36:07 -07:00
parent a305d788d7
commit 4a67f7dc71
49 changed files with 1991 additions and 552 deletions
+6 -2
View File
@@ -53,6 +53,10 @@ class contact(hierarchy_design.hierarchy_design):
first_dir = "H" if self.get_preferred_direction(layer_stack[0])=="V" else "V"
second_dir = "H" if self.get_preferred_direction(layer_stack[2])=="V" else "V"
self.directions = (first_dir, second_dir)
# Preferred directions
elif directions == "pref":
self.directions = (tech.preferred_directions[layer_stack[0]],
tech.preferred_directions[layer_stack[2]])
# User directions
elif directions:
self.directions = directions
@@ -149,7 +153,7 @@ class contact(hierarchy_design.hierarchy_design):
self.first_layer_vertical_enclosure = max(self.first_layer_enclosure,
(self.first_layer_minwidth - self.contact_array_height) / 2)
else:
debug.error("Invalid first layer direction.", -1)
debug.error("Invalid first layer direction: ".format(self.directions[0]), -1)
# In some technologies, the minimum width may be larger
# than the overlap requirement around the via, so
@@ -165,7 +169,7 @@ class contact(hierarchy_design.hierarchy_design):
self.second_layer_vertical_enclosure = max(self.second_layer_enclosure,
(self.second_layer_minwidth - self.contact_array_width) / 2)
else:
debug.error("Invalid second layer direction.", -1)
debug.error("Invalid secon layer direction: ".format(self.directions[1]), -1)
def create_contact_array(self):
""" Create the contact array at the origin"""
+13 -1
View File
@@ -86,8 +86,14 @@ class geometry:
elif mirror == "XY":
ll = ll.scale(-1, -1)
ur = ur.scale(-1, -1)
elif mirror == "" or mirror == "R0":
pass
else:
debug.error("Invalid mirroring: {}".format(mirror), -1)
if rotate == 90:
if rotate == 0:
pass
elif rotate == 90:
ll = ll.rotate_scale(-1, 1)
ur = ur.rotate_scale(-1, 1)
elif rotate == 180:
@@ -96,6 +102,8 @@ class geometry:
elif rotate == 270:
ll = ll.rotate_scale(1, -1)
ur = ur.rotate_scale(1, -1)
else:
debug.error("Invalid rotation: {}".format(rotate), -1)
self.boundary = [offset + ll, offset + ur]
self.normalize()
@@ -139,6 +147,10 @@ class geometry:
def cy(self):
""" Return the center y """
return 0.5 * (self.boundary[0].y + self.boundary[1].y)
def center(self):
""" Return the center coordinate """
return vector(self.cx(), self.cy())
class instance(geometry):
+31 -27
View File
@@ -244,25 +244,27 @@ class layout():
height))
return self.objs[-1]
def add_segment_center(self, layer, start, end):
def add_segment_center(self, layer, start, end, width=None):
"""
Add a min-width rectanglular segment using center
line on the start to end point
"""
minwidth_layer = drc["minwidth_{}".format(layer)]
if not width:
width = drc["minwidth_{}".format(layer)]
if start.x != end.x and start.y != end.y:
debug.error("Nonrectilinear center rect!", -1)
elif start.x != end.x:
offset = vector(0, 0.5 * minwidth_layer)
offset = vector(0, 0.5 * width)
return self.add_rect(layer,
start - offset,
end.x - start.x,
minwidth_layer)
width)
else:
offset = vector(0.5 * minwidth_layer, 0)
offset = vector(0.5 * width, 0)
return self.add_rect(layer,
start - offset,
minwidth_layer,
width,
end.y - start.y)
def get_pin(self, text):
@@ -322,7 +324,7 @@ class layout():
for pin_name in self.pin_map.keys():
self.copy_layout_pin(instance, pin_name, prefix + pin_name)
def add_layout_pin_segment_center(self, text, layer, start, end):
def add_layout_pin_segment_center(self, text, layer, start, end, width=None):
"""
Creates a path like pin with center-line convention
"""
@@ -331,27 +333,27 @@ class layout():
self.gds_write(file_name)
debug.error("Cannot have a non-manhatten layout pin: {}".format(file_name), -1)
minwidth_layer = drc["minwidth_{}".format(layer)]
if not width:
layer_width = drc["minwidth_{}".format(layer)]
else:
layer_width = width
# one of these will be zero
width = max(start.x, end.x) - min(start.x, end.x)
height = max(start.y, end.y) - min(start.y, end.y)
bbox_width = max(start.x, end.x) - min(start.x, end.x)
bbox_height = max(start.y, end.y) - min(start.y, end.y)
ll_offset = vector(min(start.x, end.x), min(start.y, end.y))
# Shift it down 1/2 a width in the 0 dimension
if height == 0:
ll_offset -= vector(0, 0.5 * minwidth_layer)
if width == 0:
ll_offset -= vector(0.5 * minwidth_layer, 0)
# This makes sure it is long enough, but also it is not 0 width!
height = max(minwidth_layer, height)
width = max(minwidth_layer, width)
if bbox_height == 0:
ll_offset -= vector(0, 0.5 * layer_width)
if bbox_width == 0:
ll_offset -= vector(0.5 * layer_width, 0)
return self.add_layout_pin(text,
layer,
ll_offset,
width,
height)
return self.add_layout_pin(text=text,
layer=layer,
offset=ll_offset,
width=bbox_width,
height=bbox_height)
def add_layout_pin_rect_center(self, text, layer, offset, width=None, height=None):
""" Creates a path like pin with center-line convention """
@@ -692,6 +694,8 @@ class layout():
boundary_layer = "stdc"
boundary = [self.find_lowest_coords(),
self.find_highest_coords()]
debug.check(boundary[0] and boundary[1], "No shapes to make a boundary.")
height = boundary[1][1] - boundary[0][1]
width = boundary[1][0] - boundary[0][0]
(layer_number, layer_purpose) = techlayer[boundary_layer]
@@ -1306,16 +1310,16 @@ class layout():
which vias are needed.
"""
via = self.add_via_stack_center(from_layer=start_layer,
to_layer=self.pwr_grid_layer,
size=size,
offset=loc,
directions=directions)
if start_layer == self.pwr_grid_layer:
self.add_layout_pin_rect_center(text=name,
layer=self.pwr_grid_layer,
offset=loc)
else:
via = self.add_via_stack_center(from_layer=start_layer,
to_layer=self.pwr_grid_layer,
size=size,
offset=loc,
directions=directions)
# Hack for min area
if OPTS.tech_name == "s8":
width = round_to_grid(sqrt(drc["minarea_m3"]))
+1
View File
@@ -208,6 +208,7 @@ class spice():
# parses line into ports and remove subckt
self.pins = subckt_line.split(" ")[2:]
else:
debug.info(4, "no spfile {0}".format(self.sp_file))
self.spice = []
# We don't define self.lvs and will use self.spice if dynamically created