Change to callable DRC rule. Use bottom coordinate for bus offsets.

This commit is contained in:
mrg 2020-04-15 15:29:55 -07:00
parent e95c97d7a5
commit 94eb2afa36
2 changed files with 38 additions and 47 deletions

View File

@ -46,7 +46,6 @@ class layout():
except ImportError: except ImportError:
self.pwr_grid_layer = "m3" self.pwr_grid_layer = "m3"
############################################################ ############################################################
# GDS layout # GDS layout
############################################################ ############################################################
@ -196,7 +195,7 @@ class layout():
self.insts.append(geometry.instance(name, mod, offset, mirror, rotate)) self.insts.append(geometry.instance(name, mod, offset, mirror, rotate))
debug.info(3, "adding instance {}".format(self.insts[-1])) debug.info(3, "adding instance {}".format(self.insts[-1]))
# This is commented out for runtime reasons # This is commented out for runtime reasons
#debug.info(4, "instance list: " + ",".join(x.name for x in self.insts)) # debug.info(4, "instance list: " + ",".join(x.name for x in self.insts))
return self.insts[-1] return self.insts[-1]
def get_inst(self, name): def get_inst(self, name):
@ -214,12 +213,14 @@ class layout():
width = drc["minwidth_{}".format(layer)] width = drc["minwidth_{}".format(layer)]
if not height: if not height:
height = drc["minwidth_{}".format(layer)] height = drc["minwidth_{}".format(layer)]
# negative layers indicate "unused" layers in a given technology
lpp = techlayer[layer] lpp = techlayer[layer]
if lpp[0] >= 0: if abs(offset[0]-5.16250)<0.01 and abs(offset[1]-8.70750)<0.01:
self.objs.append(geometry.rectangle(lpp, offset, width, height)) import pdb; pdb.set_trace()
self.objs.append(geometry.rectangle(lpp,
offset,
width,
height))
return self.objs[-1] return self.objs[-1]
return None
def add_rect_center(self, layer, offset, width=None, height=None): def add_rect_center(self, layer, offset, width=None, height=None):
""" """
@ -230,16 +231,13 @@ class layout():
width = drc["minwidth_{}".format(layer)] width = drc["minwidth_{}".format(layer)]
if not height: if not height:
height = drc["minwidth_{}".format(layer)] height = drc["minwidth_{}".format(layer)]
# negative layers indicate "unused" layers in a given technology
lpp = techlayer[layer] lpp = techlayer[layer]
corrected_offset = offset - vector(0.5 * width, 0.5 * height) corrected_offset = offset - vector(0.5 * width, 0.5 * height)
if lpp[0] >= 0:
self.objs.append(geometry.rectangle(lpp, self.objs.append(geometry.rectangle(lpp,
corrected_offset, corrected_offset,
width, width,
height)) height))
return self.objs[-1] return self.objs[-1]
return None
def add_segment_center(self, layer, start, end): def add_segment_center(self, layer, start, end):
""" """
@ -252,15 +250,15 @@ class layout():
elif start.x != end.x: elif start.x != end.x:
offset = vector(0, 0.5 * minwidth_layer) offset = vector(0, 0.5 * minwidth_layer)
return self.add_rect(layer, return self.add_rect(layer,
start-offset, start - offset,
end.x-start.x, end.x - start.x,
minwidth_layer) minwidth_layer)
else: else:
offset = vector(0.5 * minwidth_layer, 0) offset = vector(0.5 * minwidth_layer, 0)
return self.add_rect(layer, return self.add_rect(layer,
start-offset, start - offset,
minwidth_layer, minwidth_layer,
end.y-start.y) end.y - start.y)
def get_pin(self, text): def get_pin(self, text):
""" """
@ -268,14 +266,14 @@ class layout():
""" """
try: try:
if len(self.pin_map[text]) > 1: if len(self.pin_map[text]) > 1:
debug.error("Should use a pin iterator since more than one pin {}".format(text),-1) debug.error("Should use a pin iterator since more than one pin {}".format(text), -1)
# If we have one pin, return it and not the list. # If we have one pin, return it and not the list.
# Otherwise, should use get_pins() # Otherwise, should use get_pins()
any_pin = next(iter(self.pin_map[text])) any_pin = next(iter(self.pin_map[text]))
return any_pin return any_pin
except Exception: except Exception:
self.gds_write("missing_pin.gds") self.gds_write("missing_pin.gds")
debug.error("No pin found with name {0} on {1}. Saved as missing_pin.gds.".format(text,self.name),-1) debug.error("No pin found with name {0} on {1}. Saved as missing_pin.gds.".format(text, self.name), -1)
def get_pins(self, text): def get_pins(self, text):
""" """
@ -377,7 +375,7 @@ class layout():
height = drc["minwidth_{0}".format(layer)] height = drc["minwidth_{0}".format(layer)]
new_pin = pin_layout(text, new_pin = pin_layout(text,
[offset, offset+vector(width, height)], [offset, offset + vector(width, height)],
layer) layer)
try: try:
@ -413,22 +411,17 @@ class layout():
def add_label(self, text, layer, offset=[0, 0], zoom=-1): def add_label(self, text, layer, offset=[0, 0], zoom=-1):
"""Adds a text label on the given layer,offset, and zoom level""" """Adds a text label on the given layer,offset, and zoom level"""
# negative layers indicate "unused" layers in a given technology
debug.info(5, "add label " + str(text) + " " + layer + " " + str(offset)) debug.info(5, "add label " + str(text) + " " + layer + " " + str(offset))
lpp = techlayer[layer] lpp = techlayer[layer]
if lpp[0] >= 0:
self.objs.append(geometry.label(text, lpp, offset, zoom)) self.objs.append(geometry.label(text, lpp, offset, zoom))
return self.objs[-1] return self.objs[-1]
return None
def add_path(self, layer, coordinates, width=None): def add_path(self, layer, coordinates, width=None):
"""Connects a routing path on given layer,coordinates,width.""" """Connects a routing path on given layer,coordinates,width."""
debug.info(4, "add path " + str(layer) + " " + str(coordinates)) debug.info(4, "add path " + str(layer) + " " + str(coordinates))
import wire_path import wire_path
# NOTE: (UNTESTED) add_path(...) is currently not used # NOTE: (UNTESTED) add_path(...) is currently not used
# negative layers indicate "unused" layers in a given technology
# lpp = techlayer[layer] # lpp = techlayer[layer]
# if lpp[0] >= 0:
# self.objs.append(geometry.path(lpp, coordinates, width)) # self.objs.append(geometry.path(lpp, coordinates, width))
wire_path.wire_path(obj=self, wire_path.wire_path(obj=self,
@ -465,7 +458,7 @@ class layout():
from tech import preferred_directions from tech import preferred_directions
return preferred_directions[layer] return preferred_directions[layer]
def add_via(self, layers, offset, size=[1,1], directions=None, implant_type=None, well_type=None): def add_via(self, layers, offset, size=[1, 1], directions=None, implant_type=None, well_type=None):
""" Add a three layer via structure. """ """ Add a three layer via structure. """
if not directions: if not directions:
@ -487,7 +480,7 @@ class layout():
self.connect_inst([]) self.connect_inst([])
return inst return inst
def add_via_center(self, layers, offset, directions=None, size=[1,1], implant_type=None, well_type=None): def add_via_center(self, layers, offset, directions=None, size=[1, 1], implant_type=None, well_type=None):
""" """
Add a three layer via structure by the center coordinate Add a three layer via structure by the center coordinate
accounting for mirroring and rotation. accounting for mirroring and rotation.
@ -799,9 +792,7 @@ class layout():
self.add_rect(layer=layer, self.add_rect(layer=layer,
offset=line_offset, offset=line_offset,
height=length) height=length)
# Make this the center of the rail line_positions[names[i]] = line_offset + vector(half_minwidth, 0)
line_positions[names[i]] = line_offset + vector(half_minwidth,
0.5 * length)
else: else:
for i in range(len(names)): for i in range(len(names)):
line_offset = offset + vector(0, line_offset = offset + vector(0,
@ -953,14 +944,14 @@ class layout():
min_y = min([pin.center().y for pin in pins]) min_y = min([pin.center().y for pin in pins])
# if we are less than a pitch, just create a non-preferred layer jog # if we are less than a pitch, just create a non-preferred layer jog
if max_y-min_y <= pitch: if max_y - min_y <= pitch:
half_layer_width = 0.5 * drc["minwidth_{0}".format(self.horizontal_layer)] half_layer_width = 0.5 * drc["minwidth_{0}".format(self.horizontal_layer)]
# Add the vertical trunk on the horizontal layer! # Add the vertical trunk on the horizontal layer!
self.add_path(self.horizontal_layer, self.add_path(self.horizontal_layer,
[vector(trunk_offset.x, min_y - half_layer_width), [vector(trunk_offset.x, min_y - half_layer_width),
vector(trunk_offset.x,max_y + half_layer_width)]) vector(trunk_offset.x, max_y + half_layer_width)])
# Route each pin to the trunk # Route each pin to the trunk
for pin in pins: for pin in pins:
@ -1000,7 +991,7 @@ class layout():
# Remove the pin from all conflicts # Remove the pin from all conflicts
# FIXME: This is O(n^2), so maybe optimize it. # FIXME: This is O(n^2), so maybe optimize it.
for other_pin,conflicts in g.items(): for other_pin, conflicts in g.items():
if pin in conflicts: if pin in conflicts:
conflicts.remove(pin) conflicts.remove(pin)
g[other_pin]=conflicts g[other_pin]=conflicts
@ -1151,8 +1142,8 @@ class layout():
else: else:
self.bounding_box = self.add_rect(layer=boundary_layer, self.bounding_box = self.add_rect(layer=boundary_layer,
offset=ll, offset=ll,
height=ur.y-ll.y, height=ur.y - ll.y,
width=ur.x-ll.x) width=ur.x - ll.x)
def add_enclosure(self, insts, layer="nwell"): def add_enclosure(self, insts, layer="nwell"):
""" Add a layer that surrounds the given instances. Useful """ Add a layer that surrounds the given instances. Useful
@ -1171,8 +1162,8 @@ class layout():
self.add_rect(layer=layer, self.add_rect(layer=layer,
offset=vector(xmin, ymin), offset=vector(xmin, ymin),
width=xmax-xmin, width=xmax - xmin,
height=ymax-ymin) height=ymax - ymin)
def copy_power_pins(self, inst, name): def copy_power_pins(self, inst, name):
""" """
@ -1192,7 +1183,7 @@ class layout():
else: else:
debug.warning("{0} pins of {1} should be on {2} or metal1 for "\ debug.warning("{0} pins of {1} should be on {2} or metal1 for "\
"supply router." "supply router."
.format(name,inst.name,self.pwr_grid_layer)) .format(name, inst.name, self.pwr_grid_layer))
def add_power_pin(self, name, loc, size=[1, 1], vertical=False, start_layer="m1"): def add_power_pin(self, name, loc, size=[1, 1], vertical=False, start_layer="m1"):
""" """
@ -1244,8 +1235,8 @@ class layout():
[ll, ur] = bbox [ll, ur] = 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
width = (ur.x-ll.x) + 3 * self.supply_rail_pitch - supply_rail_spacing width = (ur.x - ll.x) + 3 * self.supply_rail_pitch - supply_rail_spacing
# LEFT vertical rails # LEFT vertical rails
offset = ll + vector(-2 * self.supply_rail_pitch, offset = ll + vector(-2 * self.supply_rail_pitch,

View File

@ -74,8 +74,8 @@ class wire(wire_path):
contact1 = getattr(contact, layer1 + "_via") contact1 = getattr(contact, layer1 + "_via")
max_contact = max(contact1.width, contact1.height) max_contact = max(contact1.width, contact1.height)
layer1_space = drc["{0}_to_{0}".format(layer1)] layer1_space = drc("{0}_to_{0}".format(layer1))
layer2_space = drc["{0}_to_{0}".format(layer2)] layer2_space = drc("{0}_to_{0}".format(layer2))
pitch = max_contact + max(layer1_space, layer2_space) pitch = max_contact + max(layer1_space, layer2_space)
return pitch return pitch