mirror of https://github.com/VLSIDA/OpenRAM.git
Change to callable DRC rule. Use bottom coordinate for bus offsets.
This commit is contained in:
parent
e95c97d7a5
commit
94eb2afa36
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue