Add separate layer and purpose pairs to tech layers.

This commit is contained in:
Matt Guthaus
2019-10-25 10:03:25 -07:00
parent 31825d9d77
commit 38213d998f
10 changed files with 160 additions and 155 deletions
+12 -9
View File
@@ -266,11 +266,12 @@ class instance(geometry):
class path(geometry):
"""Represents a Path"""
def __init__(self, layerNumber, coordinates, path_width):
def __init__(self, lpp, coordinates, path_width):
"""Initializes a path for the specified layer"""
geometry.__init__(self)
self.name = "path"
self.layerNumber = layerNumber
self.layerNumber = lpp[0]
self.layerPurpose = lpp[1]
self.coordinates = map(lambda x: [x[0], x[1]], coordinates)
self.coordinates = vector(self.coordinates).snap_to_grid()
self.path_width = path_width
@@ -283,7 +284,7 @@ class path(geometry):
"""Writes the path to GDS"""
debug.info(4, "writing path (" + str(self.layerNumber) + "): " + self.coordinates)
new_layout.addPath(layerNumber=self.layerNumber,
purposeNumber=0,
purposeNumber=self.layerPurpose,
coordinates=self.coordinates,
width=self.path_width)
@@ -303,12 +304,13 @@ class path(geometry):
class label(geometry):
"""Represents a text label"""
def __init__(self, text, layerNumber, offset, zoom=-1):
def __init__(self, text, lpp, offset, zoom=-1):
"""Initializes a text label for specified layer"""
geometry.__init__(self)
self.name = "label"
self.text = text
self.layerNumber = layerNumber
self.layerNumber = lpp[0]
self.layerPurpose = lpp[1]
self.offset = vector(offset).snap_to_grid()
if zoom<0:
@@ -325,7 +327,7 @@ class label(geometry):
debug.info(4, "writing label (" + str(self.layerNumber) + "): " + self.text)
new_layout.addText(text=self.text,
layerNumber=self.layerNumber,
purposeNumber=0,
purposeNumber=self.layerPurpose,
offsetInMicrons=self.offset,
magnification=self.zoom,
rotate=None)
@@ -346,11 +348,12 @@ class label(geometry):
class rectangle(geometry):
"""Represents a rectangular shape"""
def __init__(self, layerNumber, offset, width, height):
def __init__(self, lpp, offset, width, height):
"""Initializes a rectangular shape for specified layer"""
geometry.__init__(self)
self.name = "rect"
self.layerNumber = layerNumber
self.layerNumber = lpp[0]
self.layerPurpose = lpp[1]
self.offset = vector(offset).snap_to_grid()
self.size = vector(width, height).snap_to_grid()
self.width = round_to_grid(self.size.x)
@@ -374,7 +377,7 @@ class rectangle(geometry):
debug.info(4, "writing rectangle (" + str(self.layerNumber) + "):"
+ str(self.width) + "x" + str(self.height) + " @ " + str(self.offset))
new_layout.addBox(layerNumber=self.layerNumber,
purposeNumber=0,
purposeNumber=self.layerPurpose,
offsetInMicrons=self.offset,
width=self.width,
height=self.height,
+13 -13
View File
@@ -150,9 +150,9 @@ class layout():
if not height:
height=drc["minwidth_{}".format(layer)]
# negative layers indicate "unused" layers in a given technology
layer_num = techlayer[layer]
if layer_num >= 0:
self.objs.append(geometry.rectangle(layer_num, offset, width, height))
lpp = techlayer[layer]
if lpp[0] >= 0:
self.objs.append(geometry.rectangle(lpp, offset, width, height))
return self.objs[-1]
return None
@@ -165,10 +165,10 @@ class layout():
if not height:
height=drc["minwidth_{}".format(layer)]
# negative layers indicate "unused" layers in a given technology
layer_num = techlayer[layer]
lpp = techlayer[layer]
corrected_offset = offset - vector(0.5*width,0.5*height)
if layer_num >= 0:
self.objs.append(geometry.rectangle(layer_num, corrected_offset, width, height))
if lpp[0] >= 0:
self.objs.append(geometry.rectangle(lpp, corrected_offset, width, height))
return self.objs[-1]
return None
@@ -334,9 +334,9 @@ class layout():
"""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))
layer_num = techlayer[layer]
if layer_num >= 0:
self.objs.append(geometry.label(text, layer_num, offset, zoom))
lpp = techlayer[layer]
if lpp[0] >= 0:
self.objs.append(geometry.label(text, lpp, offset, zoom))
return self.objs[-1]
return None
@@ -347,9 +347,9 @@ class layout():
import wire_path
# NOTE: (UNTESTED) add_path(...) is currently not used
# negative layers indicate "unused" layers in a given technology
#layer_num = techlayer[layer]
#if layer_num >= 0:
# self.objs.append(geometry.path(layer_num, coordinates, width))
#lpp = techlayer[layer]
#if lpp[0] >= 0:
# self.objs.append(geometry.path(lpp, coordinates, width))
wire_path.wire_path(obj=self,
layer=layer,
@@ -539,7 +539,7 @@ class layout():
Do not write the pins since they aren't obstructions.
"""
if type(layer)==str:
layer_num = techlayer[layer]
layer_num = techlayer[layer][0]
else:
layer_num = layer
+18 -10
View File
@@ -17,7 +17,7 @@ class pin_layout:
single shape.
"""
def __init__(self, name, rect, layer_name_num):
def __init__(self, name, rect, layer_name_pp):
self.name = name
# repack the rect as a vector, just in case
if type(rect[0])==vector:
@@ -30,12 +30,19 @@ class pin_layout:
debug.check(self.width()>0,"Zero width pin.")
debug.check(self.height()>0,"Zero height pin.")
# if it's a layer number look up the layer name. this assumes a unique layer number.
if type(layer_name_num)==int:
self.layer = list(layer.keys())[list(layer.values()).index(layer_name_num)]
# if it's a string, use the name
if type(layer_name_pp)==str:
self.layer=layer_name_pp
# else it is required to be a lpp
else:
self.layer=layer_name_num
self.layer_num = layer[self.layer]
for (layer_name, lpp) in layer.items():
if layer_name_pp[0]==lpp[0] and (layer_name_pp[1]==None or layer_name_pp[1]==lpp[1]):
self.layer=layer_name
break
else:
debug.error("Couldn't find layer {}".format(layer_name_pp),-1)
self.lpp = layer[self.layer]
def __str__(self):
""" override print function output """
@@ -310,8 +317,9 @@ class pin_layout:
"""Writes the pin shape and label to GDS"""
debug.info(4, "writing pin (" + str(self.layer) + "):"
+ str(self.width()) + "x" + str(self.height()) + " @ " + str(self.ll()))
newLayout.addBox(layerNumber=layer[self.layer],
purposeNumber=0,
(layer_num,purpose) = layer[self.layer]
newLayout.addBox(layerNumber=layer_num,
purposeNumber=purpose,
offsetInMicrons=self.ll(),
width=self.width(),
height=self.height(),
@@ -319,8 +327,8 @@ class pin_layout:
# Add the tet in the middle of the pin.
# This fixes some pin label offsetting when GDS gets imported into Magic.
newLayout.addText(text=self.name,
layerNumber=layer[self.layer],
purposeNumber=0,
layerNumber=layer_num,
purposeNumber=purpose,
offsetInMicrons=self.center(),
magnification=GDS["zoom"],
rotate=None)
+9 -9
View File
@@ -45,7 +45,7 @@ def pin_center(boundary):
"""
return [0.5 * (boundary[0] + boundary[2]), 0.5 * (boundary[1] + boundary[3])]
def auto_measure_libcell(pin_list, name, units, layer):
def auto_measure_libcell(pin_list, name, units, lpp):
"""
Open a GDS file and find the pins in pin_list as text on a given layer.
Return these as a set of properties including the cell width/height too.
@@ -56,19 +56,19 @@ def auto_measure_libcell(pin_list, name, units, layer):
reader.loadFromFile(cell_gds)
cell = {}
measure_result = cell_vlsi.getLayoutBorder(layer)
measure_result = cell_vlsi.getLayoutBorder(lpp[0])
if measure_result == None:
measure_result = cell_vlsi.measureSize(name)
[cell["width"], cell["height"]] = measure_result
for pin in pin_list:
(name,layer,boundary)=cell_vlsi.getPinShapeByLabel(str(pin))
(name,lpp,boundary)=cell_vlsi.getPinShapeByLabel(str(pin))
cell[str(pin)] = pin_center(boundary)
return cell
def get_gds_size(name, gds_filename, units, layer):
def get_gds_size(name, gds_filename, units, lpp):
"""
Open a GDS file and return the size from either the
bounding box or a border layer.
@@ -79,20 +79,20 @@ def get_gds_size(name, gds_filename, units, layer):
reader.loadFromFile(gds_filename)
cell = {}
measure_result = cell_vlsi.getLayoutBorder(layer)
measure_result = cell_vlsi.getLayoutBorder(lpp)
if measure_result == None:
debug.info(2,"Layout border failed. Trying to measure size for {}".format(name))
measure_result = cell_vlsi.measureSize(name)
# returns width,height
return measure_result
def get_libcell_size(name, units, layer):
def get_libcell_size(name, units, lpp):
"""
Open a GDS file and return the library cell size from either the
bounding box or a border layer.
"""
cell_gds = OPTS.openram_tech + "gds_lib/" + str(name) + ".gds"
return(get_gds_size(name, cell_gds, units, layer))
return(get_gds_size(name, cell_gds, units, lpp))
def get_gds_pins(pin_names, name, gds_filename, units):
@@ -109,10 +109,10 @@ def get_gds_pins(pin_names, name, gds_filename, units):
cell[str(pin_name)]=[]
pin_list=cell_vlsi.getPinShape(str(pin_name))
for pin_shape in pin_list:
(layer,boundary)=pin_shape
(lpp,boundary)=pin_shape
rect=[vector(boundary[0],boundary[1]),vector(boundary[2],boundary[3])]
# this is a list because other cells/designs may have must-connect pins
cell[str(pin_name)].append(pin_layout(pin_name, rect, layer))
cell[str(pin_name)].append(pin_layout(pin_name, rect, lpp))
return cell
def get_libcell_pins(pin_list, name, units):