mirror of https://github.com/VLSIDA/OpenRAM.git
Added functionality to express polygons in LEF files.
This commit is contained in:
parent
d22d7de195
commit
3bd69d2759
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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'|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue