Merge branch 's8_update' into dev

Add lpp to addText(), remove reference to specific technology in gdsMill
This commit is contained in:
Joey Kunzler 2020-02-24 14:02:18 -08:00
commit 4c9b3c5864
4 changed files with 130 additions and 135 deletions

View File

@ -51,7 +51,7 @@ class geometry:
y = item[0] * math.sin(angle) + item[1] * mirr * math.cos(angle) + offset[1] y = item[0] * math.sin(angle) + item[1] * mirr * math.cos(angle) + offset[1]
coordinate += [[x, y]] coordinate += [[x, y]]
return coordinate return coordinate
def normalize(self): def normalize(self):
""" Re-find the LL and UR points after a transform """ """ Re-find the LL and UR points after a transform """
(first, second) = self.boundary (first, second) = self.boundary
@ -64,14 +64,14 @@ class geometry:
def update_boundary(self): def update_boundary(self):
""" Update the boundary with a new placement. """ """ Update the boundary with a new placement. """
self.compute_boundary(self.offset, self.mirror, self.rotate) self.compute_boundary(self.offset, self.mirror, self.rotate)
def compute_boundary(self, offset=vector(0, 0), mirror="", rotate=0): def compute_boundary(self, offset=vector(0, 0), mirror="", rotate=0):
""" Transform with offset, mirror and rotation to get the absolute pin location. """ Transform with offset, mirror and rotation to get the absolute pin location.
We must then re-find the ll and ur. The master is the cell instance. """ We must then re-find the ll and ur. The master is the cell instance. """
if OPTS.netlist_only: if OPTS.netlist_only:
self.boundary = [vector(0,0), vector(0,0)] self.boundary = [vector(0,0), vector(0,0)]
return return
(ll, ur) = [vector(0, 0), vector(self.width, self.height)] (ll, ur) = [vector(0, 0), vector(self.width, self.height)]
if mirror == "MX": if mirror == "MX":
@ -83,7 +83,7 @@ class geometry:
elif mirror == "XY": elif mirror == "XY":
ll = ll.scale(-1, -1) ll = ll.scale(-1, -1)
ur = ur.scale(-1, -1) ur = ur.scale(-1, -1)
if rotate == 90: if rotate == 90:
ll = ll.rotate_scale(-1, 1) ll = ll.rotate_scale(-1, 1)
ur = ur.rotate_scale(-1, 1) ur = ur.rotate_scale(-1, 1)
@ -96,19 +96,19 @@ class geometry:
self.boundary = [offset + ll, offset + ur] self.boundary = [offset + ll, offset + ur]
self.normalize() self.normalize()
def ll(self): def ll(self):
""" Return the lower left corner """ """ Return the lower left corner """
return self.boundary[0] return self.boundary[0]
def ur(self): def ur(self):
""" Return the upper right corner """ """ Return the upper right corner """
return self.boundary[1] return self.boundary[1]
def lr(self): def lr(self):
""" Return the lower right corner """ """ Return the lower right corner """
return vector(self.boundary[1].x, self.boundary[0].y) return vector(self.boundary[1].x, self.boundary[0].y)
def ul(self): def ul(self):
""" Return the upper left corner """ """ Return the upper left corner """
return vector(self.boundary[0].x, self.boundary[1].y) return vector(self.boundary[0].x, self.boundary[1].y)
@ -132,12 +132,12 @@ class geometry:
def cx(self): def cx(self):
""" Return the center x """ """ Return the center x """
return 0.5 * (self.boundary[0].x + self.boundary[1].x) return 0.5 * (self.boundary[0].x + self.boundary[1].x)
def cy(self): def cy(self):
""" Return the center y """ """ Return the center y """
return 0.5 * (self.boundary[0].y + self.boundary[1].y) return 0.5 * (self.boundary[0].y + self.boundary[1].y)
class instance(geometry): class instance(geometry):
""" """
An instance of an instance/module with a specified location and An instance of an instance/module with a specified location and
@ -148,7 +148,7 @@ class instance(geometry):
geometry.__init__(self) geometry.__init__(self)
debug.check(mirror not in ["R90", "R180", "R270"], debug.check(mirror not in ["R90", "R180", "R270"],
"Please use rotation and not mirroring during instantiation.") "Please use rotation and not mirroring during instantiation.")
self.name = name self.name = name
self.mod = mod self.mod = mod
self.gds = mod.gds self.gds = mod.gds
@ -166,7 +166,7 @@ class instance(geometry):
self.width = round_to_grid(mod.width) self.width = round_to_grid(mod.width)
self.height = round_to_grid(mod.height) self.height = round_to_grid(mod.height)
self.compute_boundary(offset, mirror, rotate) self.compute_boundary(offset, mirror, rotate)
debug.info(4, "creating instance: " + self.name) debug.info(4, "creating instance: " + self.name)
def get_blockages(self, lpp, top=False): def get_blockages(self, lpp, top=False):
@ -202,11 +202,11 @@ class instance(geometry):
new_blockages.append(self.transform_coords(b,self.offset, mirr, angle)) new_blockages.append(self.transform_coords(b,self.offset, mirr, angle))
return new_blockages return new_blockages
def gds_write_file(self, new_layout): def gds_write_file(self, new_layout):
"""Recursively writes all the sub-modules in this instance""" """Recursively writes all the sub-modules in this instance"""
debug.info(4, "writing instance: " + self.name) debug.info(4, "writing instance: " + self.name)
# make sure to write out my module/structure # make sure to write out my module/structure
# (it will only be written the first time though) # (it will only be written the first time though)
self.mod.gds_write_file(self.gds) self.mod.gds_write_file(self.gds)
# now write an instance of my module/structure # now write an instance of my module/structure
@ -215,7 +215,7 @@ class instance(geometry):
offsetInMicrons=self.offset, offsetInMicrons=self.offset,
mirror=self.mirror, mirror=self.mirror,
rotate=self.rotate) rotate=self.rotate)
def place(self, offset, mirror="R0", rotate=0): def place(self, offset, mirror="R0", rotate=0):
""" This updates the placement of an instance. """ """ This updates the placement of an instance. """
# Update the placement of an already added instance # Update the placement of an already added instance
@ -224,8 +224,8 @@ class instance(geometry):
self.rotate = rotate self.rotate = rotate
self.update_boundary() self.update_boundary()
debug.info(3, "placing instance {}".format(self)) debug.info(3, "placing instance {}".format(self))
def get_pin(self,name,index=-1): def get_pin(self,name,index=-1):
""" Return an absolute pin that is offset and transformed based on """ Return an absolute pin that is offset and transformed based on
this instance location. Index will return one of several pins.""" this instance location. Index will return one of several pins."""
@ -243,20 +243,20 @@ class instance(geometry):
def get_num_pins(self, name): def get_num_pins(self, name):
""" Return the number of pins of a given name """ """ Return the number of pins of a given name """
return len(self.mod.get_pins(name)) return len(self.mod.get_pins(name))
def get_pins(self,name): def get_pins(self,name):
""" Return an absolute pin that is offset and transformed based on """ Return an absolute pin that is offset and transformed based on
this instance location. """ this instance location. """
import copy import copy
pin = copy.deepcopy(self.mod.get_pins(name)) pin = copy.deepcopy(self.mod.get_pins(name))
new_pins = [] new_pins = []
for p in pin: for p in pin:
p.transform(self.offset,self.mirror,self.rotate) p.transform(self.offset,self.mirror,self.rotate)
new_pins.append(p) new_pins.append(p)
return new_pins return new_pins
def __str__(self): def __str__(self):
""" override print function output """ """ override print function output """
return "( inst: " + self.name + " @" + str(self.offset) + " mod=" + self.mod.name + " " + self.mirror + " R=" + str(self.rotate) + ")" return "( inst: " + self.name + " @" + str(self.offset) + " mod=" + self.mod.name + " " + self.mirror + " R=" + str(self.rotate) + ")"
@ -293,7 +293,7 @@ class path(geometry):
def get_blockages(self, layer): def get_blockages(self, layer):
""" Fail since we don't support paths yet. """ """ Fail since we don't support paths yet. """
assert(0) assert(0)
def __str__(self): def __str__(self):
""" override print function output """ """ override print function output """
return "path: layer=" + self.layerNumber + " w=" + self.width return "path: layer=" + self.layerNumber + " w=" + self.width
@ -329,6 +329,7 @@ class label(geometry):
debug.info(4, "writing label (" + str(self.layerNumber) + "): " + self.text) debug.info(4, "writing label (" + str(self.layerNumber) + "): " + self.text)
new_layout.addText(text=self.text, new_layout.addText(text=self.text,
layerNumber=self.layerNumber, layerNumber=self.layerNumber,
purposeNumber=self.layerPurpose,
offsetInMicrons=self.offset, offsetInMicrons=self.offset,
magnification=self.zoom, magnification=self.zoom,
rotate=None) rotate=None)
@ -336,7 +337,7 @@ class label(geometry):
def get_blockages(self, layer): def get_blockages(self, layer):
""" Returns an empty list since text cannot be blockages. """ """ Returns an empty list since text cannot be blockages. """
return [] return []
def __str__(self): def __str__(self):
""" override print function output """ """ override print function output """
return "label: " + self.text + " layer=" + str(self.layerNumber) return "label: " + self.text + " layer=" + str(self.layerNumber)
@ -345,7 +346,7 @@ class label(geometry):
""" override print function output """ """ override print function output """
return "( label: " + self.text + " @" + str(self.offset) + " layer=" + str(self.layerNumber) + " )" return "( label: " + self.text + " @" + str(self.offset) + " layer=" + str(self.layerNumber) + " )"
class rectangle(geometry): class rectangle(geometry):
"""Represents a rectangular shape""" """Represents a rectangular shape"""
@ -363,7 +364,7 @@ class rectangle(geometry):
debug.info(4, "creating rectangle (" + str(self.layerNumber) + "): " debug.info(4, "creating rectangle (" + str(self.layerNumber) + "): "
+ str(self.width) + "x" + str(self.height) + " @ " + str(self.offset)) + str(self.width) + "x" + str(self.height) + " @ " + str(self.offset))
def get_blockages(self, layer): def get_blockages(self, layer):
""" Returns a list of one rectangle if it is on this layer""" """ Returns a list of one rectangle if it is on this layer"""
if self.layerNumber == layer: if self.layerNumber == layer:

View File

@ -30,7 +30,7 @@ class pin_layout:
debug.check(self.width() > 0, "Zero width pin.") debug.check(self.width() > 0, "Zero width pin.")
debug.check(self.height() > 0, "Zero height pin.") debug.check(self.height() > 0, "Zero height pin.")
# if it's a string, use the name # if it's a string, use the name
if type(layer_name_pp) == str: if type(layer_name_pp) == str:
self._layer = layer_name_pp self._layer = layer_name_pp
@ -93,17 +93,17 @@ class pin_layout:
is a major speedup, if pin_layout is used as a key for dicts. is a major speedup, if pin_layout is used as a key for dicts.
""" """
return self._hash return self._hash
def __lt__(self, other): def __lt__(self, other):
""" Provide a function for ordering items by the ll point """ """ Provide a function for ordering items by the ll point """
(ll, ur) = self.rect (ll, ur) = self.rect
(oll, our) = other.rect (oll, our) = other.rect
if ll.x < oll.x and ll.y < oll.y: if ll.x < oll.x and ll.y < oll.y:
return True return True
return False return False
def __eq__(self, other): def __eq__(self, other):
""" Check if these are the same pins for duplicate checks """ """ Check if these are the same pins for duplicate checks """
if isinstance(other, self.__class__): if isinstance(other, self.__class__):
@ -128,14 +128,14 @@ class pin_layout:
max_y = max(max_y, pin.ur().y) max_y = max(max_y, pin.ur().y)
self.rect = [vector(min_x, min_y), vector(max_x, max_y)] self.rect = [vector(min_x, min_y), vector(max_x, max_y)]
def fix_minarea(self): def fix_minarea(self):
""" """
Try to fix minimum area rule. Try to fix minimum area rule.
""" """
min_area = drc("{}_minarea".format(self.layer)) min_area = drc("{}_minarea".format(self.layer))
pass pass
def inflate(self, spacing=None): def inflate(self, spacing=None):
""" """
Inflate the rectangle by the spacing (or other rule) Inflate the rectangle by the spacing (or other rule)
@ -143,12 +143,12 @@ class pin_layout:
""" """
if not spacing: if not spacing:
spacing = 0.5*drc("{0}_to_{0}".format(self.layer)) spacing = 0.5*drc("{0}_to_{0}".format(self.layer))
(ll, ur) = self.rect (ll, ur) = self.rect
spacing = vector(spacing, spacing) spacing = vector(spacing, spacing)
newll = ll - spacing newll = ll - spacing
newur = ur + spacing newur = ur + spacing
return (newll, newur) return (newll, newur)
def intersection(self, other): def intersection(self, other):
@ -191,7 +191,7 @@ class pin_layout:
y_overlaps = True y_overlaps = True
return y_overlaps return y_overlaps
def xcontains(self, other): def xcontains(self, other):
""" Check if shape contains the x overlap """ """ Check if shape contains the x overlap """
(ll, ur) = self.rect (ll, ur) = self.rect
@ -205,13 +205,13 @@ class pin_layout:
(oll, our) = other.rect (oll, our) = other.rect
return (oll.y >= ll.y and our.y <= ur.y) return (oll.y >= ll.y and our.y <= ur.y)
def contains(self, other): def contains(self, other):
""" Check if a shape contains another rectangle """ """ Check if a shape contains another rectangle """
# If it is the same shape entirely, it is contained! # If it is the same shape entirely, it is contained!
if self == other: if self == other:
return True return True
# Can only overlap on the same layer # Can only overlap on the same layer
if not self.same_lpp(self.lpp, other.lpp): if not self.same_lpp(self.lpp, other.lpp):
return False return False
@ -230,13 +230,13 @@ class pin_layout:
if shape.contains(self): if shape.contains(self):
return True return True
return False return False
def overlaps(self, other): def overlaps(self, other):
""" Check if a shape overlaps with a rectangle """ """ Check if a shape overlaps with a rectangle """
# Can only overlap on the same layer # Can only overlap on the same layer
if not self.same_lpp(self.lpp, other.lpp): if not self.same_lpp(self.lpp, other.lpp):
return False return False
x_overlaps = self.xoverlaps(other) x_overlaps = self.xoverlaps(other)
y_overlaps = self.yoverlaps(other) y_overlaps = self.yoverlaps(other)
@ -245,11 +245,11 @@ class pin_layout:
def area(self): def area(self):
""" Return the area. """ """ Return the area. """
return self.height()*self.width() return self.height()*self.width()
def height(self): def height(self):
""" Return height. Abs is for pre-normalized value.""" """ Return height. Abs is for pre-normalized value."""
return abs(self.rect[1].y-self.rect[0].y) return abs(self.rect[1].y-self.rect[0].y)
def width(self): def width(self):
""" Return width. Abs is for pre-normalized value.""" """ Return width. Abs is for pre-normalized value."""
return abs(self.rect[1].x-self.rect[0].x) return abs(self.rect[1].x-self.rect[0].x)
@ -260,7 +260,7 @@ class pin_layout:
ll = vector(min(first[0], second[0]), min(first[1], second[1])) ll = vector(min(first[0], second[0]), min(first[1], second[1]))
ur = vector(max(first[0], second[0]), max(first[1], second[1])) ur = vector(max(first[0], second[0]), max(first[1], second[1]))
self.rect=[ll, ur] self.rect=[ll, ur]
def transform(self, offset, mirror, rotate): def transform(self, offset, mirror, rotate):
""" """
Transform with offset, mirror and rotation Transform with offset, mirror and rotation
@ -278,7 +278,7 @@ class pin_layout:
elif mirror == "XY": elif mirror == "XY":
ll = ll.scale(-1, -1) ll = ll.scale(-1, -1)
ur = ur.scale(-1, -1) ur = ur.scale(-1, -1)
if rotate == 90: if rotate == 90:
ll = ll.rotate_scale(-1, 1) ll = ll.rotate_scale(-1, 1)
ur = ur.rotate_scale(-1, 1) ur = ur.rotate_scale(-1, 1)
@ -303,7 +303,7 @@ class pin_layout:
def cy(self): def cy(self):
""" Center y """ """ Center y """
return 0.5*(self.rect[0].y+self.rect[1].y) return 0.5*(self.rect[0].y+self.rect[1].y)
# The four possible corners # The four possible corners
def ll(self): def ll(self):
""" Lower left point """ """ Lower left point """
@ -320,7 +320,7 @@ class pin_layout:
def ur(self): def ur(self):
""" Upper right point """ """ Upper right point """
return self.rect[1] return self.rect[1]
# The possible y edge values # The possible y edge values
def uy(self): def uy(self):
""" Upper y value """ """ Upper y value """
@ -331,15 +331,15 @@ class pin_layout:
return self.rect[0].y return self.rect[0].y
# The possible x edge values # The possible x edge values
def lx(self): def lx(self):
""" Left x value """ """ Left x value """
return self.rect[0].x return self.rect[0].x
def rx(self): def rx(self):
""" Right x value """ """ Right x value """
return self.rect[1].x return self.rect[1].x
# The edge centers # The edge centers
def rc(self): def rc(self):
""" Right center point """ """ Right center point """
@ -350,7 +350,7 @@ class pin_layout:
""" Left center point """ """ Left center point """
return vector(self.rect[0].x, return vector(self.rect[0].x,
0.5*(self.rect[0].y+self.rect[1].y)) 0.5*(self.rect[0].y+self.rect[1].y))
def uc(self): def uc(self):
""" Upper center point """ """ Upper center point """
return vector(0.5*(self.rect[0].x+self.rect[1].x), return vector(0.5*(self.rect[0].x+self.rect[1].x),
@ -378,6 +378,7 @@ class pin_layout:
# imported into Magic. # imported into Magic.
newLayout.addText(text=self.name, newLayout.addText(text=self.name,
layerNumber=layer_num, layerNumber=layer_num,
purposeNumber=purpose,
offsetInMicrons=self.center(), offsetInMicrons=self.center(),
magnification=GDS["zoom"], magnification=GDS["zoom"],
rotate=None) rotate=None)
@ -392,7 +393,7 @@ class pin_layout:
dy = min(r1_ur.y, r2_ur.y) - max(r1_ll.y, r2_ll.y) dy = min(r1_ur.y, r2_ur.y) - max(r1_ll.y, r2_ll.y)
dx = min(r1_ur.x, r2_ur.x) - max(r1_ll.x, r2_ll.x) dx = min(r1_ur.x, r2_ur.x) - max(r1_ll.x, r2_ll.x)
if dx >= 0 and dy >= 0: if dx >= 0 and dy >= 0:
return [dx, dy] return [dx, dy]
else: else:
@ -407,7 +408,7 @@ class pin_layout:
def dist(x1, y1, x2, y2): def dist(x1, y1, x2, y2):
return math.sqrt((x2-x1)**2 + (y2-y1)**2) return math.sqrt((x2-x1)**2 + (y2-y1)**2)
left = r2_ur.x < r1_ll.x left = r2_ur.x < r1_ll.x
right = r1_ur.x < r2_ll.x right = r1_ur.x < r2_ll.x
bottom = r2_ur.y < r1_ll.y bottom = r2_ur.y < r1_ll.y
@ -432,7 +433,7 @@ class pin_layout:
else: else:
# rectangles intersect # rectangles intersect
return 0 return 0
def overlap_length(self, other): def overlap_length(self, other):
""" """
Calculate the intersection segment and determine its length Calculate the intersection segment and determine its length
@ -453,7 +454,7 @@ class pin_layout:
# This is where we had a corner intersection or none # This is where we had a corner intersection or none
return 0 return 0
def compute_overlap_segment(self, other): def compute_overlap_segment(self, other):
""" """
Calculate the intersection segment of two rectangles Calculate the intersection segment of two rectangles
@ -469,19 +470,19 @@ class pin_layout:
r2_lr = vector(r2_ur.x, r2_ll.y) r2_lr = vector(r2_ur.x, r2_ll.y)
from itertools import tee from itertools import tee
def pairwise(iterable): def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..." "s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable) a, b = tee(iterable)
next(b, None) next(b, None)
return zip(a, b) return zip(a, b)
# R1 edges CW # R1 edges CW
r1_cw_points = [r1_ll, r1_ul, r1_ur, r1_lr, r1_ll] r1_cw_points = [r1_ll, r1_ul, r1_ur, r1_lr, r1_ll]
r1_edges = [] r1_edges = []
for (p, q) in pairwise(r1_cw_points): for (p, q) in pairwise(r1_cw_points):
r1_edges.append([p, q]) r1_edges.append([p, q])
# R2 edges CW # R2 edges CW
r2_cw_points = [r2_ll, r2_ul, r2_ur, r2_lr, r2_ll] r2_cw_points = [r2_ll, r2_ul, r2_ur, r2_lr, r2_ll]
r2_edges = [] r2_edges = []
@ -509,9 +510,9 @@ class pin_layout:
q.y <= max(p.y, r.y) and \ q.y <= max(p.y, r.y) and \
q.y >= min(p.y, r.y): q.y >= min(p.y, r.y):
return True return True
return False return False
def segment_intersection(self, s1, s2): def segment_intersection(self, s1, s2):
""" """
Determine the intersection point of two segments Determine the intersection point of two segments
@ -524,22 +525,22 @@ class pin_layout:
a1 = b.y - a.y a1 = b.y - a.y
b1 = a.x - b.x b1 = a.x - b.x
c1 = a1*a.x + b1*a.y c1 = a1*a.x + b1*a.y
# Line CD represented as a2x + b2y = c2 # Line CD represented as a2x + b2y = c2
a2 = d.y - c.y a2 = d.y - c.y
b2 = c.x - d.x b2 = c.x - d.x
c2 = a2*c.x + b2*c.y c2 = a2*c.x + b2*c.y
determinant = a1*b2 - a2*b1 determinant = a1*b2 - a2*b1
if determinant != 0: if determinant != 0:
x = (b2*c1 - b1*c2)/determinant x = (b2*c1 - b1*c2)/determinant
y = (a1*c2 - a2*c1)/determinant y = (a1*c2 - a2*c1)/determinant
r = vector(x, y).snap_to_grid() r = vector(x, y).snap_to_grid()
if self.on_segment(a, r, b) and self.on_segment(c, r, d): if self.on_segment(a, r, b) and self.on_segment(c, r, d):
return r return r
return None return None
def same_lpp(self, lpp1, lpp2): def same_lpp(self, lpp1, lpp2):
@ -549,5 +550,5 @@ class pin_layout:
""" """
if lpp1[1] == None or lpp2[1] == None: if lpp1[1] == None or lpp2[1] == None:
return lpp1[0] == lpp2[0] return lpp1[0] == lpp2[0]
return lpp1[0] == lpp2[0] and lpp1[1] == lpp2[1] return lpp1[0] == lpp2[0] and lpp1[1] == lpp2[1]

View File

@ -1,12 +1,5 @@
import math import math
from globals import OPTS
# default purpose layer is used for addText() in vlsiLayout.py
if OPTS.tech_name == "s8":
purposeLayer=20
else:
purposeLayer=0
class GdsStructure: class GdsStructure:
"""Class represent a GDS Structure Object""" """Class represent a GDS Structure Object"""
def __init__(self): def __init__(self):
@ -147,7 +140,7 @@ class GdsText:
self.elementFlags="" self.elementFlags=""
self.plex="" self.plex=""
self.drawingLayer="" self.drawingLayer=""
self.purposeLayer=purposeLayer self.purposeLayer=0
self.transFlags=[0,0,0] self.transFlags=[0,0,0]
self.magFactor="" self.magFactor=""
self.rotateAngle="" self.rotateAngle=""

View File

@ -35,7 +35,7 @@ class VlsiLayout:
modDate.hour, modDate.hour,
modDate.minute, modDate.minute,
modDate.second) modDate.second)
self.info = dict() #information gathered from the GDSII header self.info = dict() #information gathered from the GDSII header
self.info['units']=self.units self.info['units']=self.units
self.info['dates']=(modDate.year, self.info['dates']=(modDate.year,
@ -52,12 +52,12 @@ class VlsiLayout:
modDate.second) modDate.second)
self.info['libraryName']=libraryName self.info['libraryName']=libraryName
self.info['gdsVersion']=gdsVersion self.info['gdsVersion']=gdsVersion
self.xyTree = [] #This will contain a list of all structure names self.xyTree = [] #This will contain a list of all structure names
#expanded to include srefs / arefs separately. #expanded to include srefs / arefs separately.
#each structure will have an X,Y,offset, and rotate associated #each structure will have an X,Y,offset, and rotate associated
#with it. Populate via traverseTheHierarchy method. #with it. Populate via traverseTheHierarchy method.
#temp variables used in delegate functions #temp variables used in delegate functions
self.tempCoordinates=None self.tempCoordinates=None
self.tempPassFail = True self.tempPassFail = True
@ -73,14 +73,14 @@ class VlsiLayout:
if(rotateAngle): if(rotateAngle):
angle = math.radians(float(rotateAngle)) angle = math.radians(float(rotateAngle))
coordinatesRotate = [] #this will hold the rotated values coordinatesRotate = [] #this will hold the rotated values
for coordinate in coordinatesToRotate: for coordinate in coordinatesToRotate:
# This is the CCW rotation matrix # This is the CCW rotation matrix
newX = coordinate[0]*math.cos(angle) - coordinate[1]*math.sin(angle) newX = coordinate[0]*math.cos(angle) - coordinate[1]*math.sin(angle)
newY = coordinate[0]*math.sin(angle) + coordinate[1]*math.cos(angle) newY = coordinate[0]*math.sin(angle) + coordinate[1]*math.cos(angle)
coordinatesRotate.extend((newX,newY)) coordinatesRotate.extend((newX,newY))
return coordinatesRotate return coordinatesRotate
def rename(self,newName): def rename(self,newName):
#take the root structure and copy it to a new structure with the new name #take the root structure and copy it to a new structure with the new name
self.structures[newName] = self.structures[self.rootStructureName] self.structures[newName] = self.structures[self.rootStructureName]
@ -129,8 +129,8 @@ class VlsiLayout:
modDate.hour, modDate.hour,
modDate.minute, modDate.minute,
modDate.second) modDate.second)
#repopulate the 2d map so drawing occurs correctly #repopulate the 2d map so drawing occurs correctly
self.prepareForWrite() self.prepareForWrite()
@ -155,15 +155,15 @@ class VlsiLayout:
debug.check(len(structureNames)==1,"Multiple possible root structures in the layout: {}".format(str(structureNames))) debug.check(len(structureNames)==1,"Multiple possible root structures in the layout: {}".format(str(structureNames)))
self.rootStructureName = structureNames[0] self.rootStructureName = structureNames[0]
def traverseTheHierarchy(self, startingStructureName=None, delegateFunction = None, def traverseTheHierarchy(self, startingStructureName=None, delegateFunction = None,
transformPath = [], rotateAngle = 0, transFlags = [0,0,0], coordinates = (0,0)): transformPath = [], rotateAngle = 0, transFlags = [0,0,0], coordinates = (0,0)):
#since this is a recursive function, must deal with the default #since this is a recursive function, must deal with the default
#parameters explicitly #parameters explicitly
if startingStructureName == None: if startingStructureName == None:
startingStructureName = self.rootStructureName startingStructureName = self.rootStructureName
#set up the rotation matrix #set up the rotation matrix
if(rotateAngle == None or rotateAngle == ""): if(rotateAngle == None or rotateAngle == ""):
angle = 0 angle = 0
else: else:
@ -193,10 +193,10 @@ class VlsiLayout:
try: try:
if(len(self.structures[startingStructureName].srefs)>0): #does this structure reference any others? if(len(self.structures[startingStructureName].srefs)>0): #does this structure reference any others?
#if so, go through each and call this function again #if so, go through each and call this function again
#if not, return back to the caller (caller can be this function) #if not, return back to the caller (caller can be this function)
for sref in self.structures[startingStructureName].srefs: for sref in self.structures[startingStructureName].srefs:
#here, we are going to modify the sref coordinates based on the parent objects rotation #here, we are going to modify the sref coordinates based on the parent objects rotation
self.traverseTheHierarchy(startingStructureName = sref.sName, self.traverseTheHierarchy(startingStructureName = sref.sName,
delegateFunction = delegateFunction, delegateFunction = delegateFunction,
transformPath = transformPath, transformPath = transformPath,
rotateAngle = sref.rotateAngle, rotateAngle = sref.rotateAngle,
@ -204,12 +204,12 @@ class VlsiLayout:
coordinates = sref.coordinates) coordinates = sref.coordinates)
except KeyError: except KeyError:
debug.error("Could not find structure {} in GDS file.".format(startingStructureName),-1) debug.error("Could not find structure {} in GDS file.".format(startingStructureName),-1)
#MUST HANDLE AREFs HERE AS WELL #MUST HANDLE AREFs HERE AS WELL
#when we return, drop the last transform from the transformPath #when we return, drop the last transform from the transformPath
del transformPath[-1] del transformPath[-1]
return return
def initialize(self): def initialize(self):
self.deduceHierarchy() self.deduceHierarchy()
# self.traverseTheHierarchy() # self.traverseTheHierarchy()
@ -217,17 +217,17 @@ class VlsiLayout:
for layerNumber in self.layerNumbersInUse: for layerNumber in self.layerNumbersInUse:
self.processLabelPins((layerNumber, None)) self.processLabelPins((layerNumber, None))
def populateCoordinateMap(self): def populateCoordinateMap(self):
def addToXyTree(startingStructureName = None,transformPath = None): def addToXyTree(startingStructureName = None,transformPath = None):
uVector = np.array([[1.0],[0.0],[0.0]]) #start with normal basis vectors uVector = np.array([[1.0],[0.0],[0.0]]) #start with normal basis vectors
vVector = np.array([[0.0],[1.0],[0.0]]) vVector = np.array([[0.0],[1.0],[0.0]])
origin = np.array([[0.0],[0.0],[1.0]]) #and an origin (Z component is 1.0 to indicate position instead of vector) origin = np.array([[0.0],[0.0],[1.0]]) #and an origin (Z component is 1.0 to indicate position instead of vector)
#make a copy of all the transforms and reverse it #make a copy of all the transforms and reverse it
reverseTransformPath = transformPath[:] reverseTransformPath = transformPath[:]
if len(reverseTransformPath) > 1: if len(reverseTransformPath) > 1:
reverseTransformPath.reverse() reverseTransformPath.reverse()
#now go through each transform and apply them to our basis and origin in succession #now go through each transform and apply them to our basis and origin in succession
for transform in reverseTransformPath: for transform in reverseTransformPath:
origin = np.dot(transform[0], origin) #rotate origin = np.dot(transform[0], origin) #rotate
@ -237,20 +237,20 @@ class VlsiLayout:
uVector = np.dot(transform[1], uVector) #scale uVector = np.dot(transform[1], uVector) #scale
vVector = np.dot(transform[1], vVector) #scale vVector = np.dot(transform[1], vVector) #scale
origin = np.dot(transform[2], origin) #translate origin = np.dot(transform[2], origin) #translate
#we don't need to do a translation on the basis vectors #we don't need to do a translation on the basis vectors
#uVector = transform[2] * uVector #translate #uVector = transform[2] * uVector #translate
#vVector = transform[2] * vVector #translate #vVector = transform[2] * vVector #translate
#populate the xyTree with each structureName and coordinate space #populate the xyTree with each structureName and coordinate space
self.xyTree.append((startingStructureName,origin,uVector,vVector)) self.xyTree.append((startingStructureName,origin,uVector,vVector))
self.traverseTheHierarchy(delegateFunction = addToXyTree) self.traverseTheHierarchy(delegateFunction = addToXyTree)
def microns(self, userUnits): def microns(self, userUnits):
"""Utility function to convert user units to microns""" """Utility function to convert user units to microns"""
userUnit = self.units[1]/self.units[0] userUnit = self.units[1]/self.units[0]
userUnitsPerMicron = userUnit / userunit userUnitsPerMicron = userUnit / userunit
layoutUnitsPerMicron = userUnitsPerMicron / self.units[0] layoutUnitsPerMicron = userUnitsPerMicron / self.units[0]
return userUnits / layoutUnitsPerMicron return userUnits / layoutUnitsPerMicron
def userUnits(self, microns): def userUnits(self, microns):
"""Utility function to convert microns to user units""" """Utility function to convert microns to user units"""
userUnit = self.units[1]/self.units[0] userUnit = self.units[1]/self.units[0]
@ -270,7 +270,7 @@ class VlsiLayout:
if self.debug: if self.debug:
debug.info(0,"DEBUG: GdsMill vlsiLayout: changeRoot: %s "%newRoot) debug.info(0,"DEBUG: GdsMill vlsiLayout: changeRoot: %s "%newRoot)
# Determine if newRoot exists # Determine if newRoot exists
# layoutToAdd (default) or nameOfLayout # layoutToAdd (default) or nameOfLayout
if (newRoot == 0 | ((newRoot not in self.structures) & ~create)): if (newRoot == 0 | ((newRoot not in self.structures) & ~create)):
@ -282,19 +282,19 @@ class VlsiLayout:
self.rootStructureName = newRoot self.rootStructureName = newRoot
def addInstance(self,layoutToAdd,nameOfLayout=0,offsetInMicrons=(0,0),mirror=None,rotate=None): def addInstance(self,layoutToAdd,nameOfLayout=0,offsetInMicrons=(0,0),mirror=None,rotate=None):
""" """
Method to insert one layout into another at a particular offset. Method to insert one layout into another at a particular offset.
""" """
offsetInLayoutUnits = (self.userUnits(offsetInMicrons[0]),self.userUnits(offsetInMicrons[1])) offsetInLayoutUnits = (self.userUnits(offsetInMicrons[0]),self.userUnits(offsetInMicrons[1]))
if self.debug: if self.debug:
debug.info(0,"DEBUG: GdsMill vlsiLayout: addInstance: type {0}, nameOfLayout {1}".format(type(layoutToAdd),nameOfLayout)) debug.info(0,"DEBUG: GdsMill vlsiLayout: addInstance: type {0}, nameOfLayout {1}".format(type(layoutToAdd),nameOfLayout))
debug.info(0,"DEBUG: name={0} offset={1} mirror={2} rotate={3}".format(layoutToAdd.rootStructureName,offsetInMicrons, mirror, rotate)) debug.info(0,"DEBUG: name={0} offset={1} mirror={2} rotate={3}".format(layoutToAdd.rootStructureName,offsetInMicrons, mirror, rotate))
# Determine if we are instantiating the root design of # Determine if we are instantiating the root design of
# layoutToAdd (default) or nameOfLayout # layoutToAdd (default) or nameOfLayout
if nameOfLayout == 0: if nameOfLayout == 0:
StructureFound = True StructureFound = True
@ -303,7 +303,7 @@ class VlsiLayout:
StructureName = nameOfLayout #layoutToAdd StructureName = nameOfLayout #layoutToAdd
StructureFound = False StructureFound = False
for structure in layoutToAdd.structures: for structure in layoutToAdd.structures:
if StructureName in structure: if StructureName in structure:
if self.debug: if self.debug:
debug.info(1,"DEBUG: Structure %s Found"%StructureName) debug.info(1,"DEBUG: Structure %s Found"%StructureName)
StructureFound = True StructureFound = True
@ -311,7 +311,7 @@ class VlsiLayout:
debug.check(StructureFound,"Could not find layout to instantiate {}".format(StructureName)) debug.check(StructureFound,"Could not find layout to instantiate {}".format(StructureName))
# If layoutToAdd is a unique object (not this), then copy hierarchy, # If layoutToAdd is a unique object (not this), then copy hierarchy,
# otherwise, if it is a text name of an internal structure, use it. # otherwise, if it is a text name of an internal structure, use it.
if layoutToAdd != self: if layoutToAdd != self:
@ -330,7 +330,7 @@ class VlsiLayout:
layoutToAddSref.coordinates = offsetInLayoutUnits layoutToAddSref.coordinates = offsetInLayoutUnits
if mirror or rotate: if mirror or rotate:
layoutToAddSref.transFlags = [0,0,0] layoutToAddSref.transFlags = [0,0,0]
# transFlags = (mirror around x-axis, magnification, rotation) # transFlags = (mirror around x-axis, magnification, rotation)
# If magnification or rotation is true, it is the flags are then # If magnification or rotation is true, it is the flags are then
@ -356,7 +356,7 @@ class VlsiLayout:
#add the sref to the root structure #add the sref to the root structure
self.structures[self.rootStructureName].srefs.append(layoutToAddSref) self.structures[self.rootStructureName].srefs.append(layoutToAddSref)
def addBox(self,layerNumber=0, purposeNumber=0, offsetInMicrons=(0,0), width=1.0, height=1.0,center=False): def addBox(self,layerNumber=0, purposeNumber=0, offsetInMicrons=(0,0), width=1.0, height=1.0,center=False):
""" """
Method to add a box to a layout Method to add a box to a layout
@ -373,7 +373,7 @@ class VlsiLayout:
(offsetInLayoutUnits[0],offsetInLayoutUnits[1]+heightInLayoutUnits), (offsetInLayoutUnits[0],offsetInLayoutUnits[1]+heightInLayoutUnits),
offsetInLayoutUnits] offsetInLayoutUnits]
else: else:
startPoint = (offsetInLayoutUnits[0]-widthInLayoutUnits/2.0, offsetInLayoutUnits[1]-heightInLayoutUnits/2.0) startPoint = (offsetInLayoutUnits[0]-widthInLayoutUnits/2.0, offsetInLayoutUnits[1]-heightInLayoutUnits/2.0)
coordinates=[startPoint, coordinates=[startPoint,
(startPoint[0]+widthInLayoutUnits,startPoint[1]), (startPoint[0]+widthInLayoutUnits,startPoint[1]),
(startPoint[0]+widthInLayoutUnits,startPoint[1]+heightInLayoutUnits), (startPoint[0]+widthInLayoutUnits,startPoint[1]+heightInLayoutUnits),
@ -386,7 +386,7 @@ class VlsiLayout:
boundaryToAdd.purposeLayer = purposeNumber boundaryToAdd.purposeLayer = purposeNumber
#add the sref to the root structure #add the sref to the root structure
self.structures[self.rootStructureName].boundaries.append(boundaryToAdd) self.structures[self.rootStructureName].boundaries.append(boundaryToAdd)
def addPath(self, layerNumber=0, purposeNumber=0, coordinates=[(0,0)], width=1.0): def addPath(self, layerNumber=0, purposeNumber=0, coordinates=[(0,0)], width=1.0):
""" """
Method to add a path to a layout Method to add a path to a layout
@ -405,11 +405,12 @@ class VlsiLayout:
pathToAdd.coordinates = layoutUnitCoordinates pathToAdd.coordinates = layoutUnitCoordinates
#add the sref to the root structure #add the sref to the root structure
self.structures[self.rootStructureName].paths.append(pathToAdd) self.structures[self.rootStructureName].paths.append(pathToAdd)
def addText(self, text, layerNumber=0, offsetInMicrons=(0,0), magnification=0.1, rotate = None): def addText(self, text, layerNumber=0, purposeNumber=0, offsetInMicrons=(0,0), magnification=0.1, rotate = None):
offsetInLayoutUnits = (self.userUnits(offsetInMicrons[0]),self.userUnits(offsetInMicrons[1])) offsetInLayoutUnits = (self.userUnits(offsetInMicrons[0]),self.userUnits(offsetInMicrons[1]))
textToAdd = GdsText() textToAdd = GdsText()
textToAdd.drawingLayer = layerNumber textToAdd.drawingLayer = layerNumber
textToAdd.purposeLayer = purposeNumber
textToAdd.coordinates = [offsetInLayoutUnits] textToAdd.coordinates = [offsetInLayoutUnits]
textToAdd.transFlags = [0,0,0] textToAdd.transFlags = [0,0,0]
textToAdd.textString = self.padText(text) textToAdd.textString = self.padText(text)
@ -438,7 +439,7 @@ class VlsiLayout:
return 1 return 1
else: else:
return 0 return 0
def intersectionPoint(self,startPoint1,endPoint1,startPoint2,endPoint2): def intersectionPoint(self,startPoint1,endPoint1,startPoint2,endPoint2):
if((endPoint1[0]-startPoint1[0])!=0 and (endPoint2[0]-startPoint2[0])!=0): if((endPoint1[0]-startPoint1[0])!=0 and (endPoint2[0]-startPoint2[0])!=0):
pSlope = (endPoint1[1]-startPoint1[1])/(endPoint1[0]-startPoint1[0]) pSlope = (endPoint1[1]-startPoint1[1])/(endPoint1[0]-startPoint1[0])
@ -458,7 +459,7 @@ class VlsiLayout:
newY = None newY = None
elif((endPoint1[0]-startPoint1[0])==0 and (endPoint2[0]-startPoint2[0])!=0): elif((endPoint1[0]-startPoint1[0])==0 and (endPoint2[0]-startPoint2[0])!=0):
qSlope = (endPoint2[1]-startPoint2[1])/(endPoint2[0]-startPoint2[0]) qSlope = (endPoint2[1]-startPoint2[1])/(endPoint2[0]-startPoint2[0])
qIntercept = startPoint2[1]-qSlope*startPoint2[0] qIntercept = startPoint2[1]-qSlope*startPoint2[0]
newX=endPoint1[0] newX=endPoint1[0]
newY=qSlope*newX+qIntercept newY=qSlope*newX+qIntercept
elif((endPoint1[0]-startPoint1[0])!=0 and (endPoint2[0]-startPoint2[0])==0): elif((endPoint1[0]-startPoint1[0])!=0 and (endPoint2[0]-startPoint2[0])==0):
@ -467,14 +468,14 @@ class VlsiLayout:
newX=endPoint2[0] newX=endPoint2[0]
newY=pSlope*newX+pIntercept newY=pSlope*newX+pIntercept
return (newX,newY) return (newX,newY)
def isCollinear(self,testPoint,point1,point2): def isCollinear(self,testPoint,point1,point2):
slope1 = (testPoint[1]-point1[1])/(testPoint[0]-point1[0]) slope1 = (testPoint[1]-point1[1])/(testPoint[0]-point1[0])
slope2 = (point2[1]-point1[1])/(point2[0]-point1[0]) slope2 = (point2[1]-point1[1])/(point2[0]-point1[0])
if slope1 == slope2: if slope1 == slope2:
return True return True
return False return False
def doShapesIntersect(self,shape1Coordinates, shape2Coordinates): def doShapesIntersect(self,shape1Coordinates, shape2Coordinates):
""" """
Utility function to determine if 2 arbitrary shapes intersect. Utility function to determine if 2 arbitrary shapes intersect.
@ -491,7 +492,7 @@ class VlsiLayout:
if(self.isBounded(intersect,startPoint1,endPoint1) and self.isBounded(intersect,startPoint2,endPoint2)): if(self.isBounded(intersect,startPoint1,endPoint1) and self.isBounded(intersect,startPoint2,endPoint2)):
return True #these shapes overlap! return True #these shapes overlap!
return False #these shapes are ok return False #these shapes are ok
def isPointInsideOfBox(self,pointCoordinates,boxCoordinates): def isPointInsideOfBox(self,pointCoordinates,boxCoordinates):
""" """
Check if a point is contained in the shape Check if a point is contained in the shape
@ -516,7 +517,7 @@ class VlsiLayout:
pointCoordinates[1]<bottomBound): pointCoordinates[1]<bottomBound):
return False return False
return True return True
def isShapeInsideOfBox(self,shapeCoordinates, boxCoordinates): def isShapeInsideOfBox(self,shapeCoordinates, boxCoordinates):
""" """
Go through every point in the shape to test if they are all inside the box. Go through every point in the shape to test if they are all inside the box.
@ -525,8 +526,8 @@ class VlsiLayout:
if not self.isPointInsideOfBox(point,boxCoordinates): if not self.isPointInsideOfBox(point,boxCoordinates):
return False return False
return True return True
def fillAreaDensity(self, layerToFill = 0, offsetInMicrons = (0,0), coverageWidth = 100.0, coverageHeight = 100.0, minSpacing = 0.22, blockSize = 1.0): def fillAreaDensity(self, layerToFill = 0, offsetInMicrons = (0,0), coverageWidth = 100.0, coverageHeight = 100.0, minSpacing = 0.22, blockSize = 1.0):
effectiveBlock = blockSize+minSpacing effectiveBlock = blockSize+minSpacing
widthInBlocks = int(coverageWidth/effectiveBlock) widthInBlocks = int(coverageWidth/effectiveBlock)
@ -545,7 +546,7 @@ class VlsiLayout:
shiftedBoundaryCoordinates.append((shapeCoordinate[0]+coordinates[0],shapeCoordinate[1]+coordinates[1])) shiftedBoundaryCoordinates.append((shapeCoordinate[0]+coordinates[0],shapeCoordinate[1]+coordinates[1]))
joint = self.doShapesIntersect(self.tempCoordinates, shiftedBoundaryCoordinates) joint = self.doShapesIntersect(self.tempCoordinates, shiftedBoundaryCoordinates)
if joint: if joint:
self.tempPassFail = False self.tempPassFail = False
common = self.isShapeInsideOfBox(shiftedBoundaryCoordinates,self.tempCoordinates) common = self.isShapeInsideOfBox(shiftedBoundaryCoordinates,self.tempCoordinates)
if common: if common:
self.tempPassFail = False self.tempPassFail = False
@ -558,11 +559,11 @@ class VlsiLayout:
shiftedBoundaryCoordinates.append((shapeCoordinate[0]+coordinates[0],shapeCoordinate[1]+coordinates[1])) shiftedBoundaryCoordinates.append((shapeCoordinate[0]+coordinates[0],shapeCoordinate[1]+coordinates[1]))
joint = self.doShapesIntersect(self.tempCoordinates, shiftedBoundaryCoordinates) joint = self.doShapesIntersect(self.tempCoordinates, shiftedBoundaryCoordinates)
if joint: if joint:
self.tempPassFail = False self.tempPassFail = False
common = self.isShapeInsideOfBox(shiftedBoundaryCoordinates,self.tempCoordinates) common = self.isShapeInsideOfBox(shiftedBoundaryCoordinates,self.tempCoordinates)
if common: if common:
self.tempPassFail = False self.tempPassFail = False
for yIndex in range(0,heightInBlocks): for yIndex in range(0,heightInBlocks):
for xIndex in range(0,widthInBlocks): for xIndex in range(0,widthInBlocks):
percentDone = (float((yIndex*heightInBlocks)+xIndex) / (heightInBlocks*widthInBlocks))*100 percentDone = (float((yIndex*heightInBlocks)+xIndex) / (heightInBlocks*widthInBlocks))*100
@ -581,7 +582,7 @@ class VlsiLayout:
passFailRecord.append(self.tempPassFail) passFailRecord.append(self.tempPassFail)
print("Percent Complete:"+str(percentDone)) print("Percent Complete:"+str(percentDone))
passFailIndex=0 passFailIndex=0
for yIndex in range(0,heightInBlocks): for yIndex in range(0,heightInBlocks):
for xIndex in range(0,widthInBlocks): for xIndex in range(0,widthInBlocks):
@ -632,7 +633,7 @@ class VlsiLayout:
self.units[0]*cellBoundary[1]], self.units[0]*cellBoundary[1]],
[self.units[0]*cellBoundary[2], [self.units[0]*cellBoundary[2],
self.units[0]*cellBoundary[3]]] self.units[0]*cellBoundary[3]]]
def measureSizeInStructure(self, structure, cellBoundary): def measureSizeInStructure(self, structure, cellBoundary):
(structureName, structureOrigin, (structureName, structureOrigin,
structureuVector, structurevVector) = structure structureuVector, structurevVector) = structure
@ -645,7 +646,7 @@ class VlsiLayout:
thisBoundary[2]+structureOrigin[0],thisBoundary[3]+structureOrigin[1]] thisBoundary[2]+structureOrigin[0],thisBoundary[3]+structureOrigin[1]]
cellBoundary=self.updateBoundary(thisBoundary,cellBoundary) cellBoundary=self.updateBoundary(thisBoundary,cellBoundary)
return cellBoundary return cellBoundary
def updateBoundary(self,thisBoundary,cellBoundary): def updateBoundary(self,thisBoundary,cellBoundary):
[left_bott_X,left_bott_Y,right_top_X,right_top_Y]=thisBoundary [left_bott_X,left_bott_Y,right_top_X,right_top_Y]=thisBoundary
# If any are None # If any are None
@ -672,7 +673,7 @@ class VlsiLayout:
lpp): lpp):
text_list.append(Text) text_list.append(Text)
return text_list return text_list
def getPinShape(self, pin_name): def getPinShape(self, pin_name):
""" """
Search for a pin label and return the largest enclosing rectangle Search for a pin label and return the largest enclosing rectangle
@ -693,7 +694,7 @@ class VlsiLayout:
max_pins.append(max_pin) max_pins.append(max_pin)
return max_pins return max_pins
def getAllPinShapes(self, pin_name): def getAllPinShapes(self, pin_name):
""" """
@ -716,7 +717,7 @@ class VlsiLayout:
""" """
# Get the labels on a layer in the root level # Get the labels on a layer in the root level
labels = self.getTexts(lpp) labels = self.getTexts(lpp)
# Get all of the shapes on the layer at all levels # Get all of the shapes on the layer at all levels
# and transform them to the current level # and transform them to the current level
shapes = self.getAllShapes(lpp) shapes = self.getAllShapes(lpp)
@ -730,7 +731,7 @@ class VlsiLayout:
pin_shapes.append((lpp, boundary)) pin_shapes.append((lpp, boundary))
label_text = label.textString label_text = label.textString
# Remove the padding if it exists # Remove the padding if it exists
if label_text[-1] == "\x00": if label_text[-1] == "\x00":
label_text = label_text[0:-1] label_text = label_text[0:-1]
@ -740,7 +741,7 @@ class VlsiLayout:
except KeyError: except KeyError:
self.pins[label_text] = [] self.pins[label_text] = []
self.pins[label_text].append(pin_shapes) self.pins[label_text].append(pin_shapes)
def getBlockages(self, lpp): def getBlockages(self, lpp):
""" """
Return all blockages on a given layer in Return all blockages on a given layer in
@ -755,7 +756,7 @@ class VlsiLayout:
for i in range(0, len(boundary), 2): for i in range(0, len(boundary), 2):
vectors.append((boundary[i], boundary[i+1])) vectors.append((boundary[i], boundary[i+1]))
blockages.append(vectors) blockages.append(vectors)
return blockages return blockages
def getAllShapes(self, lpp): def getAllShapes(self, lpp):
@ -870,7 +871,7 @@ class VlsiLayout:
""" """
Rotate a coordinate in space. Rotate a coordinate in space.
""" """
# MRG: 9/3/18 Incorrect matrix multiplication! # MRG: 9/3/18 Incorrect matrix multiplication!
# This is fixed to be: # This is fixed to be:
# |u[0] v[0]| |x| |x'| # |u[0] v[0]| |x| |x'|
# |u[1] v[1]|x|y|=|y'| # |u[1] v[1]|x|y|=|y'|
@ -892,7 +893,7 @@ class VlsiLayout:
else: else:
return False return False
def sameLPP(lpp1, lpp2): def sameLPP(lpp1, lpp2):
""" """
Check if the layers and purposes are the same. Check if the layers and purposes are the same.
@ -900,14 +901,13 @@ def sameLPP(lpp1, lpp2):
""" """
if lpp1[1] == None or lpp2[1] == None: if lpp1[1] == None or lpp2[1] == None:
return lpp1[0] == lpp2[0] return lpp1[0] == lpp2[0]
return lpp1[0] == lpp2[0] and lpp1[1] == lpp2[1] return lpp1[0] == lpp2[0] and lpp1[1] == lpp2[1]
def boundaryArea(A): def boundaryArea(A):
""" """
Returns boundary area for sorting. Returns boundary area for sorting.
""" """
area_A=(A[2]-A[0])*(A[3]-A[1]) area_A=(A[2]-A[0])*(A[3]-A[1])
return area_A return area_A