PEP8 formatting

This commit is contained in:
Matthew Guthaus 2019-11-07 16:48:37 +00:00
parent 0dea153919
commit 32f1cde897
1 changed files with 120 additions and 107 deletions

View File

@ -11,6 +11,7 @@ from vector import vector
from tech import layer from tech import layer
import math import math
class pin_layout: class pin_layout:
""" """
A class to represent a rectangular design pin. It is limited to a A class to represent a rectangular design pin. It is limited to a
@ -20,40 +21,45 @@ class pin_layout:
def __init__(self, name, rect, layer_name_pp): def __init__(self, name, rect, layer_name_pp):
self.name = name self.name = name
# repack the rect as a vector, just in case # repack the rect as a vector, just in case
if type(rect[0])==vector: if type(rect[0]) == vector:
self.rect = rect self.rect = rect
else: else:
self.rect = [vector(rect[0]),vector(rect[1])] self.rect = [vector(rect[0]), vector(rect[1])]
# snap the rect to the grid # snap the rect to the grid
self.rect = [x.snap_to_grid() for x in self.rect] self.rect = [x.snap_to_grid() for x in self.rect]
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
# else it is required to be a lpp # else it is required to be a lpp
else: else:
for (layer_name, lpp) in layer.items(): 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]): if layer_name_pp[0] == lpp[0] and (not layer_name_pp[1] or layer_name_pp[1]==lpp[1]):
self.layer=layer_name self.layer = layer_name
break break
else: else:
debug.error("Couldn't find layer {}".format(layer_name_pp),-1) debug.error("Couldn't find layer {}".format(layer_name_pp), -1)
self.lpp = layer[self.layer] self.lpp = layer[self.layer]
def __str__(self): def __str__(self):
""" override print function output """ """ override print function output """
return "({} layer={} ll={} ur={})".format(self.name,self.layer,self.rect[0],self.rect[1]) return "({} layer={} ll={} ur={})".format(self.name,
self.layer,
self.rect[0],
self.rect[1])
def __repr__(self): def __repr__(self):
""" """
override repr function output (don't include override repr function output (don't include
name since pin shapes could have same shape but diff name e.g. blockage vs A) name since pin shapes could have same shape but diff name e.g. blockage vs A)
""" """
return "(layer={} ll={} ur={})".format(self.layer,self.rect[0],self.rect[1]) return "(layer={} ll={} ur={})".format(self.layer,
self.rect[0],
self.rect[1])
def __hash__(self): def __hash__(self):
""" Implement the hash function for sets etc. """ """ Implement the hash function for sets etc. """
@ -72,15 +78,15 @@ class pin_layout:
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__):
return (self.layer==other.layer and self.rect == other.rect) return (self.layer == other.layer and self.rect == other.rect)
else: else:
return False return False
def bbox(self, pin_list): def bbox(self, pin_list):
""" """
Given a list of layout pins, create a bounding box layout. Given a list of layout pins, create a bounding box layout.
""" """
(ll, ur) = self.rect (ll, ur) = self.rect
min_x = ll.x min_x = ll.x
max_x = ur.x max_x = ur.x
min_y = ll.y min_y = ll.y
@ -92,17 +98,17 @@ class pin_layout:
min_y = min(min_y, pin.ll().y) min_y = min(min_y, pin.ll().y)
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 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)
and return the new rectangle. and return the new rectangle.
""" """
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
@ -111,20 +117,20 @@ class pin_layout:
def intersection(self, other): def intersection(self, other):
""" Check if a shape overlaps with a rectangle """ """ Check if a shape overlaps with a rectangle """
(ll,ur) = self.rect (ll, ur) = self.rect
(oll,our) = other.rect (oll, our) = other.rect
min_x = max(ll.x, oll.x) min_x = max(ll.x, oll.x)
max_x = min(ll.x, oll.x) max_x = min(ll.x, oll.x)
min_y = max(ll.y, oll.y) min_y = max(ll.y, oll.y)
max_y = min(ll.y, oll.y) max_y = min(ll.y, oll.y)
return [vector(min_x,min_y),vector(max_x,max_y)] return [vector(min_x, min_y), vector(max_x, max_y)]
def xoverlaps(self, other): def xoverlaps(self, other):
""" Check if shape has x overlap """ """ Check if shape has x overlap """
(ll,ur) = self.rect (ll, ur) = self.rect
(oll,our) = other.rect (oll, our) = other.rect
x_overlaps = False x_overlaps = False
# check if self is within other x range # check if self is within other x range
if (ll.x >= oll.x and ll.x <= our.x) or (ur.x >= oll.x and ur.x <= our.x): if (ll.x >= oll.x and ll.x <= our.x) or (ur.x >= oll.x and ur.x <= our.x):
@ -137,8 +143,8 @@ class pin_layout:
def yoverlaps(self, other): def yoverlaps(self, other):
""" Check if shape has x overlap """ """ Check if shape has x overlap """
(ll,ur) = self.rect (ll, ur) = self.rect
(oll,our) = other.rect (oll, our) = other.rect
y_overlaps = False y_overlaps = False
# check if self is within other y range # check if self is within other y range
@ -152,15 +158,15 @@ class pin_layout:
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
(oll,our) = other.rect (oll, our) = other.rect
return (oll.x >= ll.x and our.x <= ur.x) return (oll.x >= ll.x and our.x <= ur.x)
def ycontains(self, other): def ycontains(self, other):
""" Check if shape contains the y overlap """ """ Check if shape contains the y overlap """
(ll,ur) = self.rect (ll, ur) = self.rect
(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)
@ -189,7 +195,6 @@ class pin_layout:
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
@ -215,40 +220,45 @@ class pin_layout:
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.rect (first, second) = self.rect
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 to get the absolute pin location. """
We must then re-find the ll and ur. The master is the cell instance. """ Transform with offset, mirror and rotation
(ll,ur) = self.rect to get the absolute pin location.
if mirror=="MX": We must then re-find the ll and ur.
ll=ll.scale(1,-1) The master is the cell instance.
ur=ur.scale(1,-1) """
elif mirror=="MY": (ll, ur) = self.rect
ll=ll.scale(-1,1) if mirror == "MX":
ur=ur.scale(-1,1) ll = ll.scale(1, -1)
elif mirror=="XY": ur = ur.scale(1, -1)
ll=ll.scale(-1,-1) elif mirror == "MY":
ur=ur.scale(-1,-1) ll = ll.scale(-1, 1)
ur = ur.scale(-1, 1)
elif mirror == "XY":
ll = ll.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)
elif rotate==180: elif rotate == 180:
ll=ll.scale(-1,-1) ll = ll.scale(-1, -1)
ur=ur.scale(-1,-1) ur = ur.scale(-1, -1)
elif rotate==270: elif rotate == 270:
ll=ll.rotate_scale(1,-1) ll = ll.rotate_scale(1, -1)
ur=ur.rotate_scale(1,-1) ur = ur.rotate_scale(1, -1)
self.rect=[offset+ll,offset+ur] self.rect = [offset + ll, offset + ur]
self.normalize() self.normalize()
def center(self): def center(self):
return vector(0.5*(self.rect[0].x+self.rect[1].x),0.5*(self.rect[0].y+self.rect[1].y)) return vector(0.5*(self.rect[0].x+self.rect[1].x),
0.5*(self.rect[0].y+self.rect[1].y))
def cx(self): def cx(self):
""" Center x """ """ Center x """
@ -265,17 +275,17 @@ class pin_layout:
def ul(self): def ul(self):
""" Upper left point """ """ Upper left point """
return vector(self.rect[0].x,self.rect[1].y) return vector(self.rect[0].x, self.rect[1].y)
def lr(self): def lr(self):
""" Lower right point """ """ Lower right point """
return vector(self.rect[1].x,self.rect[0].y) return vector(self.rect[1].x, self.rect[0].y)
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 """
return self.rect[1].y return self.rect[1].y
@ -294,30 +304,33 @@ class pin_layout:
""" 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 """
return vector(self.rect[1].x,0.5*(self.rect[0].y+self.rect[1].y)) return vector(self.rect[1].x,
0.5*(self.rect[0].y+self.rect[1].y))
def lc(self): def lc(self):
""" Left center point """ """ Left center point """
return vector(self.rect[0].x,0.5*(self.rect[0].y+self.rect[1].y)) return vector(self.rect[0].x,
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),self.rect[1].y) return vector(0.5*(self.rect[0].x+self.rect[1].x),
self.rect[1].y)
def bc(self): def bc(self):
""" Bottom center point """ """ Bottom center point """
return vector(0.5*(self.rect[0].x+self.rect[1].x),self.rect[0].y) return vector(0.5*(self.rect[0].x+self.rect[1].x),
self.rect[0].y)
def gds_write_file(self, newLayout): def gds_write_file(self, newLayout):
"""Writes the pin shape and label to GDS""" """Writes the pin shape and label to GDS"""
debug.info(4, "writing pin (" + str(self.layer) + "):" debug.info(4, "writing pin (" + str(self.layer) + "):"
+ str(self.width()) + "x" + str(self.height()) + " @ " + str(self.ll())) + str(self.width()) + "x"
(layer_num,purpose) = layer[self.layer] + str(self.height()) + " @ " + str(self.ll()))
(layer_num, purpose) = layer[self.layer]
newLayout.addBox(layerNumber=layer_num, newLayout.addBox(layerNumber=layer_num,
purposeNumber=purpose, purposeNumber=purpose,
offsetInMicrons=self.ll(), offsetInMicrons=self.ll(),
@ -325,37 +338,37 @@ class pin_layout:
height=self.height(), height=self.height(),
center=False) center=False)
# Add the tet in the middle of the pin. # Add the tet in the middle of the pin.
# This fixes some pin label offsetting when GDS gets imported into Magic. # This fixes some pin label offsetting when GDS gets
# imported into Magic.
newLayout.addText(text=self.name, newLayout.addText(text=self.name,
layerNumber=layer_num, layerNumber=layer_num,
purposeNumber=purpose, purposeNumber=purpose,
offsetInMicrons=self.center(), offsetInMicrons=self.center(),
magnification=GDS["zoom"], magnification=GDS["zoom"],
rotate=None) rotate=None)
def compute_overlap(self, other): def compute_overlap(self, other):
""" Calculate the rectangular overlap of two rectangles. """ """ Calculate the rectangular overlap of two rectangles. """
(r1_ll,r1_ur) = self.rect (r1_ll, r1_ur) = self.rect
(r2_ll,r2_ur) = other.rect (r2_ll, r2_ur) = other.rect
#ov_ur = vector(min(r1_ur.x,r2_ur.x),min(r1_ur.y,r2_ur.y)) # ov_ur = vector(min(r1_ur.x,r2_ur.x),min(r1_ur.y,r2_ur.y))
#ov_ll = vector(max(r1_ll.x,r2_ll.x),max(r1_ll.y,r2_ll.y)) # ov_ll = vector(max(r1_ll.x,r2_ll.x),max(r1_ll.y,r2_ll.y))
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:
return [0,0] return [0, 0]
def distance(self, other): def distance(self, other):
""" """
Calculate the distance to another pin layout. Calculate the distance to another pin layout.
""" """
(r1_ll,r1_ur) = self.rect (r1_ll, r1_ur) = self.rect
(r2_ll,r2_ur) = other.rect (r2_ll, r2_ur) = other.rect
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)
@ -376,7 +389,7 @@ class pin_layout:
elif left: elif left:
return r1_ll.x - r2_ur.x return r1_ll.x - r2_ur.x
elif right: elif right:
return r2_ll.x - r1.ur.x return r2_ll.x - r1_ur.x
elif bottom: elif bottom:
return r1_ll.y - r2_ur.y return r1_ll.y - r2_ur.y
elif top: elif top:
@ -385,9 +398,8 @@ class pin_layout:
# 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
""" """
@ -399,21 +411,21 @@ class pin_layout:
intersections = self.compute_overlap_segment(other) intersections = self.compute_overlap_segment(other)
# This is the common case where two pairs of edges overlap # This is the common case where two pairs of edges overlap
# at two points, so just find the distance between those two points # at two points, so just find the distance between those two points
if len(intersections)==2: if len(intersections) == 2:
(p1,p2) = intersections (p1, p2) = intersections
return math.sqrt(pow(p1[0]-p2[0],2) + pow(p1[1]-p2[1],2)) return math.sqrt(pow(p1[0]-p2[0], 2) + pow(p1[1]-p2[1], 2))
else: else:
# 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
(if any) (if any)
""" """
(r1_ll,r1_ur) = self.rect (r1_ll, r1_ur) = self.rect
(r2_ll,r2_ur) = other.rect (r2_ll, r2_ur) = other.rect
# The other corners besides ll and ur # The other corners besides ll and ur
r1_ul = vector(r1_ll.x, r1_ur.y) r1_ul = vector(r1_ll.x, r1_ur.y)
@ -422,6 +434,7 @@ 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)
@ -431,14 +444,14 @@ class pin_layout:
# 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 = []
for (p,q) in pairwise(r2_cw_points): for (p, q) in pairwise(r2_cw_points):
r2_edges.append([p,q]) r2_edges.append([p, q])
# There are 4 edges on each rectangle # There are 4 edges on each rectangle
# so just brute force check intersection of each # so just brute force check intersection of each
@ -460,18 +473,18 @@ class pin_layout:
q.x >= min(p.x, r.x) and \ q.x >= min(p.x, r.x) and \
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
Return the a segment if they overlap. Return the a segment if they overlap.
Return None if they don't. Return None if they don't.
""" """
(a,b) = s1 (a, b) = s1
(c,d) = s2 (c, d) = s2
# Line AB represented as a1x + b1y = c1 # Line AB represented as a1x + b1y = c1
a1 = b.y - a.y a1 = b.y - a.y
b1 = a.x - b.x b1 = a.x - b.x
@ -484,11 +497,11 @@ class pin_layout:
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