2017-10-06 02:35:05 +02:00
|
|
|
import debug
|
|
|
|
|
from tech import GDS
|
2017-08-24 00:02:15 +02:00
|
|
|
from vector import vector
|
|
|
|
|
from tech import layer
|
|
|
|
|
|
|
|
|
|
class pin_layout:
|
|
|
|
|
"""
|
|
|
|
|
A class to represent a rectangular design pin. It is limited to a
|
|
|
|
|
single shape.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def __init__(self, name, rect, layer_name_num):
|
|
|
|
|
self.name = name
|
|
|
|
|
# repack the rect as a vector, just in case
|
|
|
|
|
if type(rect[0])==vector:
|
|
|
|
|
self.rect = rect
|
|
|
|
|
else:
|
|
|
|
|
self.rect = [vector(rect[0]),vector(rect[1])]
|
2017-10-07 00:30:15 +02:00
|
|
|
# snap the rect to the grid
|
|
|
|
|
self.rect = [x.snap_to_grid() for x in self.rect]
|
2017-08-24 00:02:15 +02:00
|
|
|
# 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 = layer.keys()[layer.values().index(layer_name_num)]
|
|
|
|
|
else:
|
|
|
|
|
self.layer=layer_name_num
|
|
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
|
""" override print function output """
|
|
|
|
|
return "({} layer={} ll={} ur={})".format(self.name,self.layer,self.rect[0],self.rect[1])
|
|
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
|
""" override print function output """
|
|
|
|
|
return "({} layer={} ll={} ur={})".format(self.name,self.layer,self.rect[0],self.rect[1])
|
|
|
|
|
|
2017-08-25 01:22:14 +02:00
|
|
|
def __eq__(self, other):
|
|
|
|
|
""" Check if these are the same pins for duplicate checks """
|
|
|
|
|
if isinstance(other, self.__class__):
|
2017-09-30 01:22:13 +02:00
|
|
|
return (self.name==other.name and self.layer==other.layer and self.rect == other.rect)
|
2017-08-25 01:22:14 +02:00
|
|
|
else:
|
|
|
|
|
return False
|
|
|
|
|
|
2017-12-12 23:53:19 +01:00
|
|
|
def overlaps(self, other):
|
|
|
|
|
""" Check if a shape overlaps with a rectangle """
|
|
|
|
|
ll = self.rect[0]
|
|
|
|
|
ur = self.rect[1]
|
|
|
|
|
oll = other.rect[0]
|
|
|
|
|
our = other.rect[1]
|
|
|
|
|
# Start assuming no overlaps
|
|
|
|
|
x_overlaps = False
|
|
|
|
|
y_overlaps = False
|
|
|
|
|
# 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):
|
|
|
|
|
x_overlaps = True
|
|
|
|
|
# check if other is within self x range
|
|
|
|
|
if (oll.x >= ll.x and oll.x <= ur.x) or (our.x >= ll.x and our.x <= ur.x):
|
|
|
|
|
x_overlaps = True
|
|
|
|
|
|
|
|
|
|
# check if self is within other y range
|
|
|
|
|
if (ll.y >= oll.y and ll.y <= our.y) or (ur.y >= oll.y and ur.y <= our.y):
|
|
|
|
|
y_overlaps = True
|
|
|
|
|
# check if other is within self y range
|
|
|
|
|
if (oll.y >= ll.y and oll.y <= ur.y) or (our.y >= ll.y and our.y <= ur.y):
|
|
|
|
|
y_overlaps = True
|
|
|
|
|
|
|
|
|
|
return x_overlaps and y_overlaps
|
2017-08-24 00:02:15 +02:00
|
|
|
def height(self):
|
|
|
|
|
""" Return height. Abs is for pre-normalized value."""
|
|
|
|
|
return abs(self.rect[1].y-self.rect[0].y)
|
|
|
|
|
|
|
|
|
|
def width(self):
|
|
|
|
|
""" Return width. Abs is for pre-normalized value."""
|
|
|
|
|
return abs(self.rect[1].x-self.rect[0].x)
|
|
|
|
|
|
|
|
|
|
def normalize(self):
|
|
|
|
|
""" Re-find the LL and UR points after a transform """
|
|
|
|
|
(first,second)=self.rect
|
|
|
|
|
ll = vector(min(first[0],second[0]),min(first[1],second[1]))
|
|
|
|
|
ur = vector(max(first[0],second[0]),max(first[1],second[1]))
|
|
|
|
|
self.rect=[ll,ur]
|
|
|
|
|
|
|
|
|
|
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. """
|
|
|
|
|
(ll,ur) = self.rect
|
|
|
|
|
if mirror=="MX":
|
|
|
|
|
ll=ll.scale(1,-1)
|
|
|
|
|
ur=ur.scale(1,-1)
|
|
|
|
|
elif mirror=="MY":
|
|
|
|
|
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:
|
|
|
|
|
ll=ll.rotate_scale(-1,1)
|
|
|
|
|
ur=ur.rotate_scale(-1,1)
|
|
|
|
|
elif rotate==180:
|
|
|
|
|
ll=ll.scale(-1,-1)
|
|
|
|
|
ur=ur.scale(-1,-1)
|
|
|
|
|
elif rotate==270:
|
|
|
|
|
ll=ll.rotate_scale(1,-1)
|
|
|
|
|
ur=ur.rotate_scale(1,-1)
|
|
|
|
|
|
|
|
|
|
self.rect=[offset+ll,offset+ur]
|
|
|
|
|
self.normalize()
|
|
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
|
|
|
|
|
def cx(self):
|
|
|
|
|
""" Center x """
|
|
|
|
|
return 0.5*(self.rect[0].x+self.rect[1].x)
|
|
|
|
|
|
|
|
|
|
def cy(self):
|
|
|
|
|
""" Center y """
|
|
|
|
|
return 0.5*(self.rect[0].y+self.rect[1].y)
|
|
|
|
|
|
|
|
|
|
# The four possible corners
|
|
|
|
|
def ll(self):
|
|
|
|
|
""" Lower left point """
|
|
|
|
|
return self.rect[0]
|
|
|
|
|
|
|
|
|
|
def ul(self):
|
|
|
|
|
""" Upper left point """
|
|
|
|
|
return vector(self.rect[0].x,self.rect[1].y)
|
|
|
|
|
|
2017-09-14 00:46:41 +02:00
|
|
|
def lr(self):
|
|
|
|
|
""" Lower right point """
|
2017-08-24 00:02:15 +02:00
|
|
|
return vector(self.rect[1].x,self.rect[0].y)
|
|
|
|
|
|
|
|
|
|
def ur(self):
|
|
|
|
|
""" Upper right point """
|
|
|
|
|
return self.rect[1]
|
|
|
|
|
|
|
|
|
|
# The possible y edge values
|
|
|
|
|
def uy(self):
|
|
|
|
|
""" Upper y value """
|
|
|
|
|
return self.rect[1].y
|
|
|
|
|
|
|
|
|
|
def by(self):
|
|
|
|
|
""" Bottom y value """
|
|
|
|
|
return self.rect[0].y
|
|
|
|
|
|
|
|
|
|
# The possible x edge values
|
|
|
|
|
|
|
|
|
|
def lx(self):
|
|
|
|
|
""" Left x value """
|
|
|
|
|
return self.rect[0].x
|
|
|
|
|
|
|
|
|
|
def rx(self):
|
|
|
|
|
""" Right x value """
|
|
|
|
|
return self.rect[1].x
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# The edge centers
|
|
|
|
|
def rc(self):
|
|
|
|
|
""" Right center point """
|
|
|
|
|
return vector(self.rect[1].x,0.5*(self.rect[0].y+self.rect[1].y))
|
|
|
|
|
|
|
|
|
|
def lc(self):
|
|
|
|
|
""" Left center point """
|
|
|
|
|
return vector(self.rect[0].x,0.5*(self.rect[0].y+self.rect[1].y))
|
|
|
|
|
|
|
|
|
|
def uc(self):
|
|
|
|
|
""" Upper center point """
|
|
|
|
|
return vector(0.5*(self.rect[0].x+self.rect[1].x),self.rect[1].y)
|
|
|
|
|
|
|
|
|
|
def bc(self):
|
|
|
|
|
""" Bottom center point """
|
|
|
|
|
return vector(0.5*(self.rect[0].x+self.rect[1].x),self.rect[0].y)
|
|
|
|
|
|
2017-10-06 02:35:05 +02:00
|
|
|
|
|
|
|
|
def gds_write_file(self, newLayout):
|
|
|
|
|
"""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,
|
|
|
|
|
offsetInMicrons=self.ll(),
|
|
|
|
|
width=self.width(),
|
|
|
|
|
height=self.height(),
|
|
|
|
|
center=False)
|
|
|
|
|
newLayout.addText(text=self.name,
|
|
|
|
|
layerNumber=layer[self.layer],
|
|
|
|
|
purposeNumber=0,
|
|
|
|
|
offsetInMicrons=self.ll(),
|
|
|
|
|
magnification=GDS["zoom"],
|
|
|
|
|
rotate=None)
|
|
|
|
|
|