mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'dev' of https://github.com/VLSIDA/PrivateRAM into multiport
This commit is contained in:
commit
c91735b23b
|
|
@ -15,6 +15,7 @@ class contact(hierarchy_design.hierarchy_design):
|
|||
necessary to import layouts into Magic which requires the select to be in the same GDS
|
||||
hierarchy as the contact.
|
||||
"""
|
||||
|
||||
def __init__(self, layer_stack, dimensions=[1,1], implant_type=None, well_type=None):
|
||||
if implant_type or well_type:
|
||||
name = "{0}_{1}_{2}_{3}x{4}_{5}{6}".format(layer_stack[0],
|
||||
|
|
@ -24,13 +25,14 @@ class contact(hierarchy_design.hierarchy_design):
|
|||
dimensions[1],
|
||||
implant_type,
|
||||
well_type)
|
||||
|
||||
else:
|
||||
name = "{0}_{1}_{2}_{3}x{4}".format(layer_stack[0],
|
||||
layer_stack[1],
|
||||
layer_stack[2],
|
||||
dimensions[0],
|
||||
dimensions[1])
|
||||
|
||||
layer_stack[1],
|
||||
layer_stack[2],
|
||||
dimensions[0],
|
||||
dimensions[1])
|
||||
|
||||
hierarchy_design.hierarchy_design.__init__(self, name)
|
||||
debug.info(4, "create contact object {0}".format(name))
|
||||
|
||||
|
|
|
|||
|
|
@ -379,12 +379,10 @@ class layout(lef.lef):
|
|||
dimensions=size,
|
||||
implant_type=implant_type,
|
||||
well_type=well_type)
|
||||
|
||||
debug.check(mirror=="R0","Use rotate to rotate vias instead of mirror.")
|
||||
|
||||
height = via.height
|
||||
width = via.width
|
||||
|
||||
debug.check(mirror=="R0","Use rotate to rotate vias instead of mirror.")
|
||||
|
||||
if rotate==0:
|
||||
corrected_offset = offset + vector(-0.5*width,-0.5*height)
|
||||
elif rotate==90:
|
||||
|
|
@ -849,10 +847,10 @@ class layout(lef.lef):
|
|||
"""
|
||||
self.add_via_center(layers=("metal1", "via1", "metal2"),
|
||||
offset=loc,
|
||||
rotate=rotate)
|
||||
rotate=float(rotate))
|
||||
via=self.add_via_center(layers=("metal2", "via2", "metal3"),
|
||||
offset=loc,
|
||||
rotate=rotate)
|
||||
rotate=float(rotate))
|
||||
self.add_layout_pin_rect_center(text=name,
|
||||
layer="metal3",
|
||||
offset=loc,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import debug
|
||||
from tech import GDS
|
||||
from tech import GDS, drc
|
||||
from vector import vector
|
||||
from tech import layer
|
||||
|
||||
|
|
@ -36,16 +36,29 @@ class pin_layout:
|
|||
def __eq__(self, other):
|
||||
""" Check if these are the same pins for duplicate checks """
|
||||
if isinstance(other, self.__class__):
|
||||
return (self.name==other.name and self.layer==other.layer and self.rect == other.rect)
|
||||
return (self.layer==other.layer and self.rect == other.rect)
|
||||
else:
|
||||
return False
|
||||
|
||||
def inflate(self, spacing=None):
|
||||
"""
|
||||
Inflate the rectangle by the spacing (or other rule)
|
||||
and return the new rectangle.
|
||||
"""
|
||||
if not spacing:
|
||||
spacing = drc["{0}_to_{0}".format(self.layer)]
|
||||
|
||||
(ll,ur) = self.rect
|
||||
spacing = vector(spacing, spacing)
|
||||
newll = ll - spacing
|
||||
newur = ur + spacing
|
||||
|
||||
return (newll, newur)
|
||||
|
||||
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]
|
||||
(ll,ur) = self.rect
|
||||
(oll,our) = other.rect
|
||||
# Start assuming no overlaps
|
||||
x_overlaps = False
|
||||
y_overlaps = False
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ class Gds2reader:
|
|||
mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy
|
||||
rotateFlag = bool(transFlags&0x0002)
|
||||
magnifyFlag = bool(transFlags&0x0004)
|
||||
thisSref.transFlags=[mirrorFlag,rotateFlag,magnifyFlag]
|
||||
thisSref.transFlags=[mirrorFlag,magnifyFlag,rotateFlag]
|
||||
if(self.debugToTerminal==1):
|
||||
print("\t\t\tMirror X:"+str(mirrorFlag))
|
||||
print( "\t\t\tRotate:"+str(rotateFlag))
|
||||
|
|
@ -345,7 +345,7 @@ class Gds2reader:
|
|||
mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy
|
||||
rotateFlag = bool(transFlags&0x0002)
|
||||
magnifyFlag = bool(transFlags&0x0004)
|
||||
thisAref.transFlags=[mirrorFlag,rotateFlag,magnifyFlag]
|
||||
thisAref.transFlags=[mirrorFlag,magnifyFlag,rotateFlag]
|
||||
if(self.debugToTerminal==1):
|
||||
print("\t\t\tMirror X:"+str(mirrorFlag))
|
||||
print("\t\t\tRotate:"+str(rotateFlag))
|
||||
|
|
@ -408,7 +408,7 @@ class Gds2reader:
|
|||
mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy
|
||||
rotateFlag = bool(transFlags&0x0002)
|
||||
magnifyFlag = bool(transFlags&0x0004)
|
||||
thisText.transFlags=[mirrorFlag,rotateFlag,magnifyFlag]
|
||||
thisText.transFlags=[mirrorFlag,magnifyFlag,rotateFlag]
|
||||
if(self.debugToTerminal==1):
|
||||
print("\t\t\tMirror X:"+str(mirrorFlag))
|
||||
print("\t\t\tRotate:"+str(rotateFlag))
|
||||
|
|
|
|||
|
|
@ -280,8 +280,13 @@ class Gds2writer:
|
|||
if(thisSref.transFlags!=""):
|
||||
idBits=b'\x1A\x01'
|
||||
mirrorFlag = int(thisSref.transFlags[0])<<15
|
||||
rotateFlag = int(thisSref.transFlags[1])<<1
|
||||
magnifyFlag = int(thisSref.transFlags[2])<<3
|
||||
# The rotate and magnify flags specify "absolute" rotate and magnify.
|
||||
# It is unclear what that is (ignore all further rotates/mags in the
|
||||
# hierarchy? But anyway, calibre doesn't support it.
|
||||
rotateFlag=0
|
||||
magnifyFlag = 0
|
||||
#rotateFlag = int(thisSref.transFlags[2])<<1
|
||||
#magnifyFlag = int(thisSref.transFlags[1])<<2
|
||||
transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag)
|
||||
self.writeRecord(idBits+transFlags)
|
||||
if(thisSref.magFactor!=""):
|
||||
|
|
@ -327,15 +332,20 @@ class Gds2writer:
|
|||
if(thisAref.transFlags):
|
||||
idBits=b'\x1A\x01'
|
||||
mirrorFlag = int(thisAref.transFlags[0])<<15
|
||||
rotateFlag = int(thisAref.transFlags[1])<<1
|
||||
magnifyFlag = int(thisAref.transFlags[0])<<3
|
||||
# The rotate and magnify flags specify "absolute" rotate and magnify.
|
||||
# It is unclear what that is (ignore all further rotates/mags in the
|
||||
# hierarchy? But anyway, calibre doesn't support it.
|
||||
rotateFlag=0
|
||||
magnifyFlag = 0
|
||||
#rotateFlag = int(thisAref.transFlags[2])<<1
|
||||
#magnifyFlag = int(thisAref.transFlags[1])<<2
|
||||
transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag)
|
||||
self.writeRecord(idBits+transFlags)
|
||||
if(thisAref.magFactor):
|
||||
if(thisAref.magFactor!=""):
|
||||
idBits=b'\x1B\x05'
|
||||
magFactor=self.ibmDataFromIeeeDouble(thisAref.magFactor)
|
||||
self.writeRecord(idBits+magFactor)
|
||||
if(thisAref.rotateAngle):
|
||||
if(thisAref.rotateAngle!=""):
|
||||
idBits=b'\x1C\x05'
|
||||
rotateAngle=self.ibmDataFromIeeeDouble(thisAref.rotateAngle)
|
||||
self.writeRecord(idBits+rotateAngle)
|
||||
|
|
@ -374,15 +384,20 @@ class Gds2writer:
|
|||
if(thisText.transFlags != ""):
|
||||
idBits=b'\x1A\x01'
|
||||
mirrorFlag = int(thisText.transFlags[0])<<15
|
||||
rotateFlag = int(thisText.transFlags[1])<<1
|
||||
magnifyFlag = int(thisText.transFlags[0])<<3
|
||||
# The rotate and magnify flags specify "absolute" rotate and magnify.
|
||||
# It is unclear what that is (ignore all further rotates/mags in the
|
||||
# hierarchy? But anyway, calibre doesn't support it.
|
||||
rotateFlag=0
|
||||
magnifyFlag = 0
|
||||
#rotateFlag = int(thisText.transFlags[2])<<1
|
||||
#magnifyFlag = int(thisText.transFlags[1])<<2
|
||||
transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag)
|
||||
self.writeRecord(idBits+transFlags)
|
||||
if(thisText.magFactor != ""):
|
||||
if(thisText.magFactor!=""):
|
||||
idBits=b'\x1B\x05'
|
||||
magFactor=self.ibmDataFromIeeeDouble(thisText.magFactor)
|
||||
self.writeRecord(idBits+magFactor)
|
||||
if(thisText.rotateAngle != ""):
|
||||
if(thisText.rotateAngle!=""):
|
||||
idBits=b'\x1C\x05'
|
||||
rotateAngle=self.ibmDataFromIeeeDouble(thisText.rotateAngle)
|
||||
self.writeRecord(idBits+rotateAngle)
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ class GdsText:
|
|||
self.plex=""
|
||||
self.drawingLayer=""
|
||||
self.purposeLayer = None
|
||||
self.transFlags=[0,00]
|
||||
self.transFlags=[0,0,0]
|
||||
self.magFactor=""
|
||||
self.rotateAngle=""
|
||||
self.pathType=""
|
||||
|
|
|
|||
|
|
@ -64,10 +64,11 @@ class VlsiLayout:
|
|||
#helper method to rotate a list of coordinates
|
||||
angle=math.radians(float(0))
|
||||
if(rotateAngle):
|
||||
angle = math.radians(float(repr(rotateAngle)))
|
||||
angle = math.radians(float(rotateAngle))
|
||||
|
||||
coordinatesRotate = [] #this will hold the rotated values
|
||||
for coordinate in coordinatesToRotate:
|
||||
# This is the CCW rotation matrix
|
||||
newX = coordinate[0]*math.cos(angle) - coordinate[1]*math.sin(angle)
|
||||
newY = coordinate[0]*math.sin(angle) + coordinate[1]*math.cos(angle)
|
||||
coordinatesRotate.extend((newX,newY))
|
||||
|
|
@ -274,8 +275,9 @@ class VlsiLayout:
|
|||
Method to insert one layout into another at a particular offset.
|
||||
"""
|
||||
offsetInLayoutUnits = (self.userUnits(offsetInMicrons[0]),self.userUnits(offsetInMicrons[1]))
|
||||
if self.debug==1:
|
||||
debug.info(0,"DEBUG: GdsMill vlsiLayout: addInstance: type %s, nameOfLayout "%type(layoutToAdd),nameOfLayout)
|
||||
if self.debug:
|
||||
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))
|
||||
|
||||
|
||||
|
||||
|
|
@ -295,7 +297,7 @@ class VlsiLayout:
|
|||
|
||||
|
||||
|
||||
# If layoutToAdd is a unique object (not this), then copy heirarchy,
|
||||
# If layoutToAdd is a unique object (not this), then copy hierarchy,
|
||||
# otherwise, if it is a text name of an internal structure, use it.
|
||||
|
||||
if layoutToAdd != self:
|
||||
|
|
@ -316,9 +318,7 @@ class VlsiLayout:
|
|||
if mirror or rotate:
|
||||
|
||||
layoutToAddSref.transFlags = [0,0,0]
|
||||
# This is NOT the same as the order in the GDS spec!
|
||||
# It gets written out in gds2writer in the right order though.
|
||||
# transFlags = (mirror around x-axis, rotation, magnification)
|
||||
# transFlags = (mirror around x-axis, magnification, rotation)
|
||||
# If magnification or rotation is true, it is the flags are then
|
||||
# followed by an amount in the record
|
||||
if mirror=="R90":
|
||||
|
|
@ -328,17 +328,16 @@ class VlsiLayout:
|
|||
if mirror=="R270":
|
||||
rotate = 270.0
|
||||
if rotate:
|
||||
#layoutToAddSref.transFlags = [0,1,0]
|
||||
#layoutToAddSref.transFlags[2] = 1
|
||||
layoutToAddSref.rotateAngle = rotate
|
||||
if mirror == "x" or mirror == "MX":
|
||||
layoutToAddSref.transFlags = [1,0,0]
|
||||
layoutToAddSref.transFlags[0] = 1
|
||||
if mirror == "y" or mirror == "MY": #NOTE: "MY" option will override specified rotate angle
|
||||
#layoutToAddSref.transFlags = [1,1,0]
|
||||
layoutToAddSref.transFlags = [1,0,0]
|
||||
layoutToAddSref.transFlags[0] = 1
|
||||
#layoutToAddSref.transFlags[2] = 1
|
||||
layoutToAddSref.rotateAngle = 180.0
|
||||
if mirror == "xy" or mirror == "XY": #NOTE: "XY" option will override specified rotate angle
|
||||
#layoutToAddSref.transFlags = [0,1,0]
|
||||
layoutToAddSref.transFlags = [0,0,0]
|
||||
#layoutToAddSref.transFlags[2] = 1
|
||||
layoutToAddSref.rotateAngle = 180.0
|
||||
|
||||
#add the sref to the root structure
|
||||
|
|
@ -405,10 +404,10 @@ class VlsiLayout:
|
|||
if(len(text)%2 == 1):
|
||||
text = text + '\x00'
|
||||
textToAdd.textString = text
|
||||
textToAdd.transFlags = [0,0,1]
|
||||
#textToAdd.transFlags[1] = 1
|
||||
textToAdd.magFactor = magnification
|
||||
if rotate:
|
||||
textToAdd.transFlags = [0,1,1]
|
||||
#textToAdd.transFlags[2] = 1
|
||||
textToAdd.rotateAngle = rotate
|
||||
#add the sref to the root structure
|
||||
self.structures[self.rootStructureName].texts.append(textToAdd)
|
||||
|
|
@ -816,10 +815,10 @@ class VlsiLayout:
|
|||
"""
|
||||
|
||||
(structureName,structureOrigin,structureuVector,structurevVector)=structure
|
||||
#print(structureName,"u",structureuVector.transpose(),"v",structurevVector.transpose(),"o",structureOrigin.transpose())
|
||||
boundaries = []
|
||||
for boundary in self.structures[str(structureName)].boundaries:
|
||||
# Pin enclosures only work on rectangular pins so ignore any non rectangle
|
||||
# This may report not finding pins, but the user should fix this by adding a rectangle.
|
||||
# FIXME: Right now, this only supports rectangular shapes!
|
||||
if len(boundary.coordinates)!=5:
|
||||
continue
|
||||
if layer==boundary.drawingLayer:
|
||||
|
|
@ -827,10 +826,11 @@ class VlsiLayout:
|
|||
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
|
||||
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
|
||||
|
|
@ -858,8 +858,12 @@ class VlsiLayout:
|
|||
"""
|
||||
Rotate a coordinate in space.
|
||||
"""
|
||||
x=coordinate[0]*uVector[0].item()+coordinate[1]*uVector[1].item()
|
||||
y=coordinate[1]*vVector[1].item()+coordinate[0]*vVector[0].item()
|
||||
# MRG: 9/3/18 Incorrect matrixi multiplication!
|
||||
# This is fixed to be:
|
||||
# |u[0] v[0]| |x| |x'|
|
||||
# |u[1] v[1]|x|y|=|y'|
|
||||
x=coordinate[0]*uVector[0].item()+coordinate[1]*vVector[0].item()
|
||||
y=coordinate[0]*uVector[1].item()+coordinate[1]*vVector[1].item()
|
||||
transformCoordinate=[x,y]
|
||||
|
||||
return transformCoordinate
|
||||
|
|
|
|||
|
|
@ -118,9 +118,6 @@ def init_openram(config_file, is_unit_test=True):
|
|||
|
||||
init_paths()
|
||||
|
||||
# This depends on the tech, so do it after tech is loaded
|
||||
init_config()
|
||||
|
||||
# Reset the static duplicate name checker for unit tests.
|
||||
import hierarchy_design
|
||||
hierarchy_design.hierarchy_design.name_map=[]
|
||||
|
|
@ -257,7 +254,8 @@ def cleanup_paths():
|
|||
if not OPTS.purge_temp:
|
||||
debug.info(0,"Preserving temp directory: {}".format(OPTS.openram_temp))
|
||||
return
|
||||
if os.path.exists(OPTS.openram_temp):
|
||||
elif os.path.exists(OPTS.openram_temp):
|
||||
debug.info(1,"Purging temp directory: {}".format(OPTS.openram_temp))
|
||||
# This annoyingly means you have to re-cd into the directory each debug iteration
|
||||
#shutil.rmtree(OPTS.openram_temp, ignore_errors=True)
|
||||
contents = [os.path.join(OPTS.openram_temp, i) for i in os.listdir(OPTS.openram_temp)]
|
||||
|
|
@ -293,8 +291,6 @@ def setup_paths():
|
|||
OPTS.openram_temp += "/"
|
||||
debug.info(1, "Temporary files saved in " + OPTS.openram_temp)
|
||||
|
||||
cleanup_paths()
|
||||
|
||||
|
||||
|
||||
def is_exe(fpath):
|
||||
|
|
@ -316,6 +312,7 @@ def init_paths():
|
|||
|
||||
# make the directory if it doesn't exist
|
||||
try:
|
||||
debug.info(1,"Creating temp directory: {}".format(OPTS.openram_temp))
|
||||
os.makedirs(OPTS.openram_temp, 0o750)
|
||||
except OSError as e:
|
||||
if e.errno == 17: # errno.EEXIST
|
||||
|
|
@ -330,16 +327,7 @@ def init_paths():
|
|||
os.chmod(OPTS.output_path, 0o750)
|
||||
except:
|
||||
debug.error("Unable to make output directory.",-1)
|
||||
|
||||
def init_config():
|
||||
""" Initialize the SRAM configurations. """
|
||||
# Create the SRAM configuration
|
||||
from sram_config import sram_config
|
||||
OPTS.sram_config = sram_config(OPTS.word_size,
|
||||
OPTS.num_words,
|
||||
OPTS.num_banks)
|
||||
|
||||
|
||||
|
||||
# imports correct technology directories for testing
|
||||
def import_tech():
|
||||
|
|
|
|||
|
|
@ -115,11 +115,11 @@ class dff_inv_array(design.design):
|
|||
def add_layout_pins(self):
|
||||
for row in range(self.rows):
|
||||
for col in range(self.columns):
|
||||
# Continous vdd rail along with label.
|
||||
# Adds power pin on left of row
|
||||
vdd_pin=self.dff_insts[row,col].get_pin("vdd")
|
||||
self.add_power_pin("vdd", vdd_pin.lc())
|
||||
|
||||
# Continous gnd rail along with label.
|
||||
# Adds gnd pin on left of row
|
||||
gnd_pin=self.dff_insts[row,col].get_pin("gnd")
|
||||
self.add_power_pin("gnd", gnd_pin.lc())
|
||||
|
||||
|
|
|
|||
|
|
@ -171,6 +171,8 @@ class pinv(pgate.pgate):
|
|||
offset=vector(0.5*self.width,self.height),
|
||||
width=self.width)
|
||||
|
||||
|
||||
|
||||
def create_ptx(self):
|
||||
"""
|
||||
Create the PMOS and NMOS netlist.
|
||||
|
|
|
|||
|
|
@ -36,9 +36,6 @@ class grid:
|
|||
def add_blockage_shape(self,ll,ur,z):
|
||||
debug.info(3,"Adding blockage ll={0} ur={1} z={2}".format(str(ll),str(ur),z))
|
||||
|
||||
if ll[0]<42 and ll[0]>38 and ll[1]<3 and ll[1]>0:
|
||||
debug.info(0,"Adding blockage ll={0} ur={1} z={2}".format(str(ll),str(ur),z))
|
||||
|
||||
block_list = []
|
||||
for x in range(int(ll[0]),int(ur[0])+1):
|
||||
for y in range(int(ll[1]),int(ur[1])+1):
|
||||
|
|
|
|||
|
|
@ -49,6 +49,12 @@ class router:
|
|||
""" If we want to route something besides the top-level cell."""
|
||||
self.top_name = top_name
|
||||
|
||||
def get_zindex(self,layer_num):
|
||||
if layer_num==self.horiz_layer_number:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
def set_layers(self, layers):
|
||||
"""Allows us to change the layers that we are routing on. First layer
|
||||
is always horizontal, middle is via, and last is always
|
||||
|
|
@ -84,19 +90,19 @@ class router:
|
|||
|
||||
|
||||
|
||||
def find_pin(self,pin):
|
||||
def find_pin(self,pin_name):
|
||||
"""
|
||||
Finds the pin shapes and converts to tracks.
|
||||
Pin can either be a label or a location,layer pair: [[x,y],layer].
|
||||
"""
|
||||
|
||||
label_list=self.layout.getPinShapeByLabel(str(pin))
|
||||
shape_list=self.layout.getPinShapeByLabel(str(pin_name))
|
||||
pin_list = []
|
||||
for label in label_list:
|
||||
(name,layer,boundary)=label
|
||||
for shape in shape_list:
|
||||
(name,layer,boundary)=shape
|
||||
rect = [vector(boundary[0],boundary[1]),vector(boundary[2],boundary[3])]
|
||||
# this is a list because other cells/designs may have must-connect pins
|
||||
pin_list.append(pin_layout(pin, rect, layer))
|
||||
pin = pin_layout(pin_name, rect, layer)
|
||||
pin_list.append(pin)
|
||||
|
||||
debug.check(len(pin_list)>0,"Did not find any pin shapes for {0}.".format(str(pin)))
|
||||
|
||||
|
|
@ -202,17 +208,30 @@ class router:
|
|||
|
||||
|
||||
def add_blockages(self):
|
||||
""" Add the blockages except the pin shapes """
|
||||
""" Add the blockages except the pin shapes. Also remove the pin shapes from the blockages list. """
|
||||
# Join all the pin shapes into one big list
|
||||
all_pins = [item for sublist in list(self.pins.values()) for item in sublist]
|
||||
|
||||
# Do an n^2 check to see if any shapes are the same, otherwise add them
|
||||
# FIXME: Make faster, but number of pins won't be *that* large
|
||||
real_blockages = []
|
||||
for blockage in self.blockages:
|
||||
# Skip pin shapes
|
||||
all_pins = [x[0] for x in list(self.pins.values())]
|
||||
for pin in all_pins:
|
||||
if blockage.overlaps(pin):
|
||||
# If the blockage overlaps the pin and is on the same layer,
|
||||
# it must be connected, so skip it.
|
||||
if blockage==pin:
|
||||
debug.info(1,"Removing blockage for pin {}".format(str(pin)))
|
||||
break
|
||||
else:
|
||||
[ll,ur]=self.convert_blockage_to_tracks(blockage.rect)
|
||||
zlayer = 0 if blockage.layer_num==self.horiz_layer_number else 1
|
||||
debug.info(2,"Adding blockage {}".format(str(blockage)))
|
||||
# Inflate the blockage by spacing rule
|
||||
[ll,ur]=self.convert_blockage_to_tracks(blockage.inflate())
|
||||
zlayer = self.get_zindex(blockage.layer_num)
|
||||
self.rg.add_blockage_shape(ll,ur,zlayer)
|
||||
real_blockages.append(blockage)
|
||||
|
||||
# Remember the filtered blockages
|
||||
self.blockages = real_blockages
|
||||
|
||||
|
||||
def get_blockages(self, layer_num):
|
||||
|
|
@ -227,37 +246,6 @@ class router:
|
|||
rect = [ll,ur]
|
||||
new_pin = pin_layout("blockage{}".format(len(self.blockages)),rect,layer_num)
|
||||
self.blockages.append(new_pin)
|
||||
|
||||
# for boundary in self.layout.structures[sref].boundaries:
|
||||
# coord_trans = self.translate_coordinates(boundary.coordinates, mirr, angle, xyShift)
|
||||
# shape_coords = self.min_max_coord(coord_trans)
|
||||
# shape = self.convert_shape_to_units(shape_coords)
|
||||
|
||||
# # only consider the two layers that we are routing on
|
||||
# if boundary.drawingLayer in [self.vert_layer_number,self.horiz_layer_number]:
|
||||
# # store the blockages as pin layouts so they are easy to compare etc.
|
||||
# new_pin = pin_layout("blockage",shape,boundary.drawingLayer)
|
||||
# # avoid repeated blockage pins
|
||||
# if new_pin not in self.blockages:
|
||||
# self.blockages.append(new_pin)
|
||||
|
||||
|
||||
# # recurse given the mirror, angle, etc.
|
||||
# for cur_sref in self.layout.structures[sref].srefs:
|
||||
# sMirr = 1
|
||||
# if cur_sref.transFlags[0] == True:
|
||||
# sMirr = -1
|
||||
# sAngle = math.radians(float(0))
|
||||
# if cur_sref.rotateAngle:
|
||||
# sAngle = math.radians(float(cur_sref.rotateAngle))
|
||||
# sAngle += angle
|
||||
# x = cur_sref.coordinates[0]
|
||||
# y = cur_sref.coordinates[1]
|
||||
# newX = (x)*math.cos(angle) - mirr*(y)*math.sin(angle) + xyShift[0]
|
||||
# newY = (x)*math.sin(angle) + mirr*(y)*math.cos(angle) + xyShift[1]
|
||||
# sxyShift = (newX, newY)
|
||||
|
||||
# self.get_blockages(cur_sref.sName, sMirr, sAngle, sxyShift)
|
||||
|
||||
|
||||
def convert_point_to_units(self,p):
|
||||
|
|
@ -282,11 +270,15 @@ class router:
|
|||
old_ur = ur
|
||||
ll=ll.scale(self.track_factor)
|
||||
ur=ur.scale(self.track_factor)
|
||||
ll = ll.floor()
|
||||
ur = ur.ceil()
|
||||
if ll[0]<45 and ll[0]>35 and ll[1]<10 and ll[1]>0:
|
||||
debug.info(0,"Converting [ {0} , {1} ]".format(old_ll,old_ur))
|
||||
debug.info(0,"Converted [ {0} , {1} ]".format(ll,ur))
|
||||
# We can round since we are using inflated shapes
|
||||
# and the track points are at the center
|
||||
ll = ll.round()
|
||||
ur = ur.round()
|
||||
# if ll[0]<45 and ll[0]>35 and ll[1]<5 and ll[1]>-5:
|
||||
# debug.info(0,"Converting [ {0} , {1} ]".format(old_ll,old_ur))
|
||||
# debug.info(0,"Converted [ {0} , {1} ]".format(ll,ur))
|
||||
# pin=self.convert_track_to_shape(ll)
|
||||
# debug.info(0,"Pin {}".format(pin))
|
||||
return [ll,ur]
|
||||
|
||||
def convert_pin_to_tracks(self, pin):
|
||||
|
|
@ -296,9 +288,6 @@ class router:
|
|||
If a pin has insufficent overlap, it returns the blockage list to avoid it.
|
||||
"""
|
||||
(ll,ur) = pin.rect
|
||||
#ll = snap_to_grid(ll)
|
||||
#ur = snap_to_grid(ur)
|
||||
|
||||
#debug.info(1,"Converting [ {0} , {1} ]".format(ll,ur))
|
||||
|
||||
# scale the size bigger to include neaby tracks
|
||||
|
|
@ -306,37 +295,40 @@ class router:
|
|||
ur=ur.scale(self.track_factor).ceil()
|
||||
|
||||
# width depends on which layer it is
|
||||
zindex = 0 if pin.layer_num==self.horiz_layer_number else 1
|
||||
if zindex==0:
|
||||
width = self.horiz_layer_width
|
||||
else:
|
||||
zindex=self.get_zindex(pin.layer_num)
|
||||
if zindex:
|
||||
width = self.vert_layer_width
|
||||
else:
|
||||
width = self.horiz_layer_width
|
||||
|
||||
track_list = []
|
||||
block_list = []
|
||||
# include +- 1 so when a shape is less than one grid
|
||||
for x in range(ll[0]-1,ur[0]+1):
|
||||
for y in range(ll[1]-1,ur[1]+1):
|
||||
|
||||
track_area = self.track_width*self.track_width
|
||||
for x in range(ll[0],ur[0]):
|
||||
for y in range(ll[1],ur[1]):
|
||||
#debug.info(1,"Converting [ {0} , {1} ]".format(x,y))
|
||||
# get the rectangular pin at a track location
|
||||
# if dimension of overlap is greater than min width in any dimension,
|
||||
# it will be an on-grid pin
|
||||
rect = self.convert_track_to_pin(vector3d(x,y,zindex))
|
||||
max_overlap=max(self.compute_overlap(pin.rect,rect))
|
||||
|
||||
# however, if there is not enough overlap, then if there is any overlap at all,
|
||||
# we need to block it to prevent routes coming in on that grid
|
||||
full_rect = self.convert_full_track_to_shape(vector3d(x,y,zindex))
|
||||
full_overlap=max(self.compute_overlap(pin.rect,full_rect))
|
||||
|
||||
full_rect = self.convert_track_to_shape(vector3d(x,y,zindex))
|
||||
overlap_rect=self.compute_overlap(pin.rect,full_rect)
|
||||
overlap_area = overlap_rect[0]*overlap_rect[1]
|
||||
#debug.info(1,"Check overlap: {0} {1} max={2}".format(shape,rect,max_overlap))
|
||||
if max_overlap >= width:
|
||||
|
||||
# Assume if more than half the area, it is occupied
|
||||
overlap_ratio = overlap_area/track_area
|
||||
if overlap_ratio > 0.5:
|
||||
track_list.append(vector3d(x,y,zindex))
|
||||
elif full_overlap>0:
|
||||
# otherwise, the pin may not be accessible, so block it
|
||||
elif overlap_ratio > 0:
|
||||
block_list.append(vector3d(x,y,zindex))
|
||||
else:
|
||||
debug.info(4,"No overlap: {0} {1} max={2}".format(pin.rect,rect,max_overlap))
|
||||
|
||||
print("H:",x,y)
|
||||
if x>38 and x<42 and y>42 and y<45:
|
||||
print(pin)
|
||||
print(full_rect, overlap_rect, overlap_ratio)
|
||||
#debug.warning("Off-grid pin for {0}.".format(str(pin)))
|
||||
#debug.info(1,"Converted [ {0} , {1} ]".format(ll,ur))
|
||||
return (track_list,block_list)
|
||||
|
|
@ -381,7 +373,7 @@ class router:
|
|||
|
||||
return [ll,ur]
|
||||
|
||||
def convert_full_track_to_shape(self,track):
|
||||
def convert_track_to_shape(self,track):
|
||||
"""
|
||||
Convert a grid point into a rectangle shape that occupies the entire centered
|
||||
track.
|
||||
|
|
@ -447,9 +439,8 @@ class router:
|
|||
grid_keys=self.rg.map.keys()
|
||||
partial_track=vector(0,self.track_width/6.0)
|
||||
for g in grid_keys:
|
||||
continue # for now...
|
||||
shape = self.convert_full_track_to_shape(g)
|
||||
self.cell.add_rect(layer="boundary",
|
||||
shape = self.convert_track_to_shape(g)
|
||||
self.cell.add_rect(layer="text",
|
||||
offset=shape[0],
|
||||
width=shape[1].x-shape[0].x,
|
||||
height=shape[1].y-shape[0].y)
|
||||
|
|
@ -481,10 +472,12 @@ class router:
|
|||
zoom=0.05)
|
||||
|
||||
for blockage in self.blockages:
|
||||
self.cell.add_rect(layer="boundary",
|
||||
offset=blockage.ll(),
|
||||
width=blockage.width(),
|
||||
height=blockage.height())
|
||||
# Display the inflated blockage
|
||||
(ll,ur) = blockage.inflate()
|
||||
self.cell.add_rect(layer="blockage",
|
||||
offset=ll,
|
||||
width=ur.x-ll.x,
|
||||
height=ur.y-ll.y)
|
||||
|
||||
|
||||
# FIXME: This should be replaced with vector.snap_to_grid at some point
|
||||
|
|
|
|||
|
|
@ -32,12 +32,14 @@ class no_blockages_test(openram_test):
|
|||
globals.setup_paths()
|
||||
from control_logic import control_logic
|
||||
cell = control_logic(16)
|
||||
#from pinv import pinv
|
||||
#cell = pinv()
|
||||
#gds_file = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),"control_logic")
|
||||
#cell = gds_cell(name, gds_file)
|
||||
self.add_inst(name=name,
|
||||
mod=cell,
|
||||
offset=[0,0])
|
||||
self.connect_inst(["csb","web","clk","s_en","w_en","clk_buf_bar","clk_buf","vdd","gnd"])
|
||||
self.connect_inst(cell.pin_map.keys())
|
||||
|
||||
r=router(module=cell)
|
||||
layer_stack =("metal3","via2","metal2")
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ layer["via9"] = 28
|
|||
layer["metal10"] = 29
|
||||
layer["text"] = 239
|
||||
layer["boundary"]= 239
|
||||
layer["blockage"]= 239
|
||||
|
||||
###################################################
|
||||
##END GDS Layer Map
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ layer["via2"] = 61
|
|||
layer["metal3"] = 62
|
||||
layer["text"] = 63
|
||||
layer["boundary"] = 63
|
||||
layer["blockage"] = 83
|
||||
|
||||
###################################################
|
||||
##END GDS Layer Map
|
||||
|
|
|
|||
|
|
@ -625,7 +625,7 @@ drDefinePacket(
|
|||
( display deviceAnt stipple0 solid yellow yellow solid )
|
||||
( display winBottomShadow solid solid winColor1 winColor1 solid )
|
||||
( display PselectNet dots4 solid brown brown outlineStipple)
|
||||
( display comment stipple0 lineStyle0 winBack winBack solid )
|
||||
( display comment stipple0 lineStyle0 winBack winBack outline )
|
||||
( display Poly1 dots lineStyle0 red red outlineStipple)
|
||||
( display Unrouted stipple0 lineStyle1 winColor5 winColor5 solid )
|
||||
( display stretch stipple0 solid yellow yellow solid )
|
||||
|
|
|
|||
Loading…
Reference in New Issue