Added functionality to express polygons in LEF files.

This commit is contained in:
jsowash 2019-06-25 09:20:00 -07:00
parent d22d7de195
commit 3bd69d2759
3 changed files with 91 additions and 51 deletions

View File

@ -165,7 +165,7 @@ class instance(geometry):
debug.info(4, "creating instance: " + self.name) debug.info(4, "creating instance: " + self.name)
def get_blockages(self, layer, top=False): def get_blockages(self, layer, top=False):
""" Retrieve rectangular blockages of all modules in this instance. """ Retrieve blockages of all modules in this instance.
Apply the transform of the instance placement to give absolute blockages.""" Apply the transform of the instance placement to give absolute blockages."""
angle = math.radians(float(self.rotate)) angle = math.radians(float(self.rotate))
mirr = 1 mirr = 1
@ -186,11 +186,11 @@ class instance(geometry):
new_blockages = [] new_blockages = []
if self.mod.is_library_cell: if self.mod.is_library_cell:
# Writes library cell blockages as shapes instead of a large metal blockage
blockages = [] blockages = []
blockages = self.mod.gds.getBlockages(layer) blockages = self.mod.gds.getBlockages(layer)
for b in blockages: for b in blockages:
new_blockages.append(self.transform_coords(b,self.offset, mirr, angle)) new_blockages.append(self.transform_coords(b,self.offset, mirr, angle))
print(new_blockages)
else: else:
blockages = self.mod.get_blockages(layer) blockages = self.mod.get_blockages(layer)
for b in blockages: for b in blockages:

View File

@ -12,6 +12,7 @@ import math
import debug import debug
import datetime import datetime
from collections import defaultdict from collections import defaultdict
import pdb
class lef: class lef:
""" """
@ -84,7 +85,7 @@ class lef:
pin_list = self.get_pins(name) pin_list = self.get_pins(name)
for pin in pin_list: for pin in pin_list:
self.lef.write("{0}LAYER {1} ;\n".format(self.indent,pin.layer)) self.lef.write("{0}LAYER {1} ;\n".format(self.indent,pin.layer))
self.lef_write_rect(pin.rect) self.lef_write_shape(pin.rect)
# End the PORT # End the PORT
self.indent = self.indent[:-3] self.indent = self.indent[:-3]
@ -100,15 +101,29 @@ class lef:
for layer in self.lef_layers: for layer in self.lef_layers:
self.lef.write("{0}LAYER {1} ;\n".format(self.indent,layer)) self.lef.write("{0}LAYER {1} ;\n".format(self.indent,layer))
self.indent += " " self.indent += " "
# pdb.set_trace()
blockages = self.get_blockages(layer,True) blockages = self.get_blockages(layer,True)
for b in blockages: for b in blockages:
self.lef_write_rect(b) # if len(b) > 2:
# print(b)
self.lef_write_shape(b)
self.indent = self.indent[:-3] self.indent = self.indent[:-3]
self.lef.write("{0}END\n".format(self.indent)) self.lef.write("{0}END\n".format(self.indent))
def lef_write_rect(self, rect): def lef_write_shape(self, rect):
""" Write a LEF rectangle """ if len(rect) == 2:
self.lef.write("{0}RECT ".format(self.indent)) """ Write a LEF rectangle """
for item in rect: self.lef.write("{0}RECT ".format(self.indent))
self.lef.write(" {0} {1}".format(round(item[0],self.round_grid), round(item[1],self.round_grid))) for item in rect:
self.lef.write(" ;\n") # print(rect)
self.lef.write(" {0} {1}".format(round(item[0],self.round_grid), round(item[1],self.round_grid)))
self.lef.write(" ;\n")
else:
""" Write a LEF polygon """
self.lef.write("{0}POLYGON ".format(self.indent))
for item in rect:
self.lef.write(" {0} {1}".format(round(item[0],self.round_grid), round(item[1],self.round_grid)))
# for i in range(0,len(rect)):
# self.lef.write(" {0} {1}".format(round(rect[i][0],self.round_grid), round(rect[i][1],self.round_grid)))
self.lef.write(" ;\n")

View File

@ -3,7 +3,6 @@ from datetime import *
#from mpmath import matrix #from mpmath import matrix
#from numpy import matrix #from numpy import matrix
from vector import vector from vector import vector
from pin_layout import pin_layout
import numpy as np import numpy as np
#import gdsPrimitives #import gdsPrimitives
import debug import debug
@ -727,12 +726,26 @@ class VlsiLayout:
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,layer):
"""
Return all blockages on a given layer in [llx, lly, urx, ury] format and
user units.
"""
blockages = []
shapes = self.getAllShapes(layer)
for boundary in shapes:
vectors = []
for i in range(0,len(boundary),2):
vectors.append(vector(boundary[i],boundary[i+1]))
blockages.append(vectors)
return blockages
def getAllShapes(self,layer): def getAllShapes(self,layer):
""" """
Return all shapes on a given layer in [llx, lly, urx, ury] format and Return all shapes on a given layer in [llx, lly, urx, ury] format and user units for rectangles
user units. and [coordinate 1, coordinate 2,...] format and user units for polygons.
""" """
boundaries = set() boundaries = set()
for TreeUnit in self.xyTree: for TreeUnit in self.xyTree:
@ -742,55 +755,67 @@ class VlsiLayout:
# Convert to user units # Convert to user units
user_boundaries = [] user_boundaries = []
for boundary in boundaries: for boundary in boundaries:
user_boundaries.append([boundary[0]*self.units[0],boundary[1]*self.units[0], boundaries_list = []
boundary[2]*self.units[0],boundary[3]*self.units[0]]) for i in range(0,len(boundary)):
boundaries_list.append(boundary[i]*self.units[0])
user_boundaries.append(boundaries_list)
return user_boundaries return user_boundaries
def getBlockages(self,layer):
blockages = []
shapes = self.getAllShapes(layer)
for boundary in shapes:
ll = vector(boundary[0],boundary[1])
ur = vector(boundary[2],boundary[3])
rect = [ll,ur]
new_pin = rect
blockages.append(new_pin)
return blockages
def getShapesInStructure(self,layer,structure): def getShapesInStructure(self,layer,structure):
""" """
Go through all the shapes in a structure and return the list of shapes in Go through all the shapes in a structure and return the list of shapes in
the form [llx, lly, urx, ury] the form [llx, lly, urx, ury] for rectangles and [coordinate 1, coordinate 2,...] for polygons.
""" """
(structureName,structureOrigin,structureuVector,structurevVector)=structure (structureName,structureOrigin,structureuVector,structurevVector)=structure
#print(structureName,"u",structureuVector.transpose(),"v",structurevVector.transpose(),"o",structureOrigin.transpose()) #print(structureName,"u",structureuVector.transpose(),"v",structurevVector.transpose(),"o",structureOrigin.transpose())
boundaries = [] boundaries = []
for boundary in self.structures[str(structureName)].boundaries: for boundary in self.structures[str(structureName)].boundaries:
# FIXME: Right now, this only supports rectangular shapes!
# We should trigger an error but some FreePDK45 library cells contain paths.
# These get saved fine, but we cannot parse them as blockages...
#debug.check(len(boundary.coordinates)==5,"Non-rectangular shapes are not supported.")
if len(boundary.coordinates)!=5:
continue
if layer==boundary.drawingLayer: if layer==boundary.drawingLayer:
left_bottom=boundary.coordinates[0] if len(boundary.coordinates)!=5:
right_top=boundary.coordinates[2] # if shape is a polygon (used in DFF)
# Rectangle is [leftx, bottomy, rightx, topy]. boundaryPolygon = []
boundaryRect=[left_bottom[0],left_bottom[1],right_top[0],right_top[1]] # Polygon is a list of coordinates going ccw
# perform the rotation for coord in range(0,len(boundary.coordinates)):
boundaryRect=self.transformRectangle(boundaryRect,structureuVector,structurevVector) boundaryPolygon.append(boundary.coordinates[coord][0])
# add the offset and make it a tuple boundaryPolygon.append(boundary.coordinates[coord][1])
boundaryRect=(boundaryRect[0]+structureOrigin[0].item(),boundaryRect[1]+structureOrigin[1].item(), # perform the rotation
boundaryRect[2]+structureOrigin[0].item(),boundaryRect[3]+structureOrigin[1].item()) boundaryPolygon=self.transformPolygon(boundaryPolygon,structureuVector,structurevVector)
boundaries.append(boundaryRect) # add the offset
polygon = []
for i in range(0,len(boundaryPolygon),2):
polygon.append(boundaryPolygon[i]+structureOrigin[0].item())
polygon.append(boundaryPolygon[i+1]+structureOrigin[1].item())
# make it a tuple
polygon = tuple(polygon)
boundaries.append(polygon)
else:
# else shape is a rectangle
left_bottom=boundary.coordinates[0]
right_top=boundary.coordinates[2]
# Rectangle is [leftx, bottomy, rightx, topy].
boundaryRect=[left_bottom[0],left_bottom[1],right_top[0],right_top[1]]
# perform the rotation
boundaryRect=self.transformRectangle(boundaryRect,structureuVector,structurevVector)
# add the offset and make it a tuple
boundaryRect=(boundaryRect[0]+structureOrigin[0].item(),boundaryRect[1]+structureOrigin[1].item(),
boundaryRect[2]+structureOrigin[0].item(),boundaryRect[3]+structureOrigin[1].item())
boundaries.append(boundaryRect)
return boundaries return boundaries
def transformPolygon(self,originalPolygon,uVector,vVector):
"""
Transforms the coordinates of a polygon in space.
"""
polygon = []
newPolygon = []
for i in range(0,len(originalPolygon),2):
polygon.append(self.transformCoordinate([originalPolygon[i],originalPolygon[i+1]],uVector,vVector))
newPolygon.append(polygon[int(i/2)][0])
newPolygon.append(polygon[int(i/2)][1])
return newPolygon
def transformRectangle(self,originalRectangle,uVector,vVector): def transformRectangle(self,originalRectangle,uVector,vVector):
""" """
Transforms the four coordinates of a rectangle in space Transforms the four coordinates of a rectangle in space
@ -814,7 +839,7 @@ class VlsiLayout:
""" """
Rotate a coordinate in space. Rotate a coordinate in space.
""" """
# MRG: 9/3/18 Incorrect matrixi 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'|