Merge branch 'dev' of https://github.com/VLSIDA/PrivateRAM into multiport

This commit is contained in:
Michael Timothy Grimes 2018-09-08 18:56:58 -07:00
commit c91735b23b
16 changed files with 166 additions and 150 deletions

View File

@ -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 necessary to import layouts into Magic which requires the select to be in the same GDS
hierarchy as the contact. hierarchy as the contact.
""" """
def __init__(self, layer_stack, dimensions=[1,1], implant_type=None, well_type=None): def __init__(self, layer_stack, dimensions=[1,1], implant_type=None, well_type=None):
if implant_type or well_type: if implant_type or well_type:
name = "{0}_{1}_{2}_{3}x{4}_{5}{6}".format(layer_stack[0], 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], dimensions[1],
implant_type, implant_type,
well_type) well_type)
else: else:
name = "{0}_{1}_{2}_{3}x{4}".format(layer_stack[0], name = "{0}_{1}_{2}_{3}x{4}".format(layer_stack[0],
layer_stack[1], layer_stack[1],
layer_stack[2], layer_stack[2],
dimensions[0], dimensions[0],
dimensions[1]) dimensions[1])
hierarchy_design.hierarchy_design.__init__(self, name) hierarchy_design.hierarchy_design.__init__(self, name)
debug.info(4, "create contact object {0}".format(name)) debug.info(4, "create contact object {0}".format(name))

View File

@ -379,12 +379,10 @@ class layout(lef.lef):
dimensions=size, dimensions=size,
implant_type=implant_type, implant_type=implant_type,
well_type=well_type) well_type=well_type)
debug.check(mirror=="R0","Use rotate to rotate vias instead of mirror.")
height = via.height height = via.height
width = via.width width = via.width
debug.check(mirror=="R0","Use rotate to rotate vias instead of mirror.")
if rotate==0: if rotate==0:
corrected_offset = offset + vector(-0.5*width,-0.5*height) corrected_offset = offset + vector(-0.5*width,-0.5*height)
elif rotate==90: elif rotate==90:
@ -849,10 +847,10 @@ class layout(lef.lef):
""" """
self.add_via_center(layers=("metal1", "via1", "metal2"), self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=loc, offset=loc,
rotate=rotate) rotate=float(rotate))
via=self.add_via_center(layers=("metal2", "via2", "metal3"), via=self.add_via_center(layers=("metal2", "via2", "metal3"),
offset=loc, offset=loc,
rotate=rotate) rotate=float(rotate))
self.add_layout_pin_rect_center(text=name, self.add_layout_pin_rect_center(text=name,
layer="metal3", layer="metal3",
offset=loc, offset=loc,

View File

@ -1,5 +1,5 @@
import debug import debug
from tech import GDS from tech import GDS, drc
from vector import vector from vector import vector
from tech import layer from tech import layer
@ -36,16 +36,29 @@ 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.name==other.name and 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 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): def overlaps(self, other):
""" Check if a shape overlaps with a rectangle """ """ Check if a shape overlaps with a rectangle """
ll = self.rect[0] (ll,ur) = self.rect
ur = self.rect[1] (oll,our) = other.rect
oll = other.rect[0]
our = other.rect[1]
# Start assuming no overlaps # Start assuming no overlaps
x_overlaps = False x_overlaps = False
y_overlaps = False y_overlaps = False

View File

@ -294,7 +294,7 @@ class Gds2reader:
mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy
rotateFlag = bool(transFlags&0x0002) rotateFlag = bool(transFlags&0x0002)
magnifyFlag = bool(transFlags&0x0004) magnifyFlag = bool(transFlags&0x0004)
thisSref.transFlags=[mirrorFlag,rotateFlag,magnifyFlag] thisSref.transFlags=[mirrorFlag,magnifyFlag,rotateFlag]
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\t\tMirror X:"+str(mirrorFlag)) print("\t\t\tMirror X:"+str(mirrorFlag))
print( "\t\t\tRotate:"+str(rotateFlag)) print( "\t\t\tRotate:"+str(rotateFlag))
@ -345,7 +345,7 @@ class Gds2reader:
mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy
rotateFlag = bool(transFlags&0x0002) rotateFlag = bool(transFlags&0x0002)
magnifyFlag = bool(transFlags&0x0004) magnifyFlag = bool(transFlags&0x0004)
thisAref.transFlags=[mirrorFlag,rotateFlag,magnifyFlag] thisAref.transFlags=[mirrorFlag,magnifyFlag,rotateFlag]
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\t\tMirror X:"+str(mirrorFlag)) print("\t\t\tMirror X:"+str(mirrorFlag))
print("\t\t\tRotate:"+str(rotateFlag)) print("\t\t\tRotate:"+str(rotateFlag))
@ -408,7 +408,7 @@ class Gds2reader:
mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy mirrorFlag = bool(transFlags&0x8000) ##these flags are a bit sketchy
rotateFlag = bool(transFlags&0x0002) rotateFlag = bool(transFlags&0x0002)
magnifyFlag = bool(transFlags&0x0004) magnifyFlag = bool(transFlags&0x0004)
thisText.transFlags=[mirrorFlag,rotateFlag,magnifyFlag] thisText.transFlags=[mirrorFlag,magnifyFlag,rotateFlag]
if(self.debugToTerminal==1): if(self.debugToTerminal==1):
print("\t\t\tMirror X:"+str(mirrorFlag)) print("\t\t\tMirror X:"+str(mirrorFlag))
print("\t\t\tRotate:"+str(rotateFlag)) print("\t\t\tRotate:"+str(rotateFlag))

View File

@ -280,8 +280,13 @@ class Gds2writer:
if(thisSref.transFlags!=""): if(thisSref.transFlags!=""):
idBits=b'\x1A\x01' idBits=b'\x1A\x01'
mirrorFlag = int(thisSref.transFlags[0])<<15 mirrorFlag = int(thisSref.transFlags[0])<<15
rotateFlag = int(thisSref.transFlags[1])<<1 # The rotate and magnify flags specify "absolute" rotate and magnify.
magnifyFlag = int(thisSref.transFlags[2])<<3 # 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) transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag)
self.writeRecord(idBits+transFlags) self.writeRecord(idBits+transFlags)
if(thisSref.magFactor!=""): if(thisSref.magFactor!=""):
@ -327,15 +332,20 @@ class Gds2writer:
if(thisAref.transFlags): if(thisAref.transFlags):
idBits=b'\x1A\x01' idBits=b'\x1A\x01'
mirrorFlag = int(thisAref.transFlags[0])<<15 mirrorFlag = int(thisAref.transFlags[0])<<15
rotateFlag = int(thisAref.transFlags[1])<<1 # The rotate and magnify flags specify "absolute" rotate and magnify.
magnifyFlag = int(thisAref.transFlags[0])<<3 # 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) transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag)
self.writeRecord(idBits+transFlags) self.writeRecord(idBits+transFlags)
if(thisAref.magFactor): if(thisAref.magFactor!=""):
idBits=b'\x1B\x05' idBits=b'\x1B\x05'
magFactor=self.ibmDataFromIeeeDouble(thisAref.magFactor) magFactor=self.ibmDataFromIeeeDouble(thisAref.magFactor)
self.writeRecord(idBits+magFactor) self.writeRecord(idBits+magFactor)
if(thisAref.rotateAngle): if(thisAref.rotateAngle!=""):
idBits=b'\x1C\x05' idBits=b'\x1C\x05'
rotateAngle=self.ibmDataFromIeeeDouble(thisAref.rotateAngle) rotateAngle=self.ibmDataFromIeeeDouble(thisAref.rotateAngle)
self.writeRecord(idBits+rotateAngle) self.writeRecord(idBits+rotateAngle)
@ -374,15 +384,20 @@ class Gds2writer:
if(thisText.transFlags != ""): if(thisText.transFlags != ""):
idBits=b'\x1A\x01' idBits=b'\x1A\x01'
mirrorFlag = int(thisText.transFlags[0])<<15 mirrorFlag = int(thisText.transFlags[0])<<15
rotateFlag = int(thisText.transFlags[1])<<1 # The rotate and magnify flags specify "absolute" rotate and magnify.
magnifyFlag = int(thisText.transFlags[0])<<3 # 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) transFlags = struct.pack(">H",mirrorFlag|rotateFlag|magnifyFlag)
self.writeRecord(idBits+transFlags) self.writeRecord(idBits+transFlags)
if(thisText.magFactor != ""): if(thisText.magFactor!=""):
idBits=b'\x1B\x05' idBits=b'\x1B\x05'
magFactor=self.ibmDataFromIeeeDouble(thisText.magFactor) magFactor=self.ibmDataFromIeeeDouble(thisText.magFactor)
self.writeRecord(idBits+magFactor) self.writeRecord(idBits+magFactor)
if(thisText.rotateAngle != ""): if(thisText.rotateAngle!=""):
idBits=b'\x1C\x05' idBits=b'\x1C\x05'
rotateAngle=self.ibmDataFromIeeeDouble(thisText.rotateAngle) rotateAngle=self.ibmDataFromIeeeDouble(thisText.rotateAngle)
self.writeRecord(idBits+rotateAngle) self.writeRecord(idBits+rotateAngle)

View File

@ -141,7 +141,7 @@ class GdsText:
self.plex="" self.plex=""
self.drawingLayer="" self.drawingLayer=""
self.purposeLayer = None self.purposeLayer = None
self.transFlags=[0,00] self.transFlags=[0,0,0]
self.magFactor="" self.magFactor=""
self.rotateAngle="" self.rotateAngle=""
self.pathType="" self.pathType=""

View File

@ -64,10 +64,11 @@ class VlsiLayout:
#helper method to rotate a list of coordinates #helper method to rotate a list of coordinates
angle=math.radians(float(0)) angle=math.radians(float(0))
if(rotateAngle): if(rotateAngle):
angle = math.radians(float(repr(rotateAngle))) angle = math.radians(float(rotateAngle))
coordinatesRotate = [] #this will hold the rotated values coordinatesRotate = [] #this will hold the rotated values
for coordinate in coordinatesToRotate: for coordinate in coordinatesToRotate:
# This is the CCW rotation matrix
newX = coordinate[0]*math.cos(angle) - coordinate[1]*math.sin(angle) newX = coordinate[0]*math.cos(angle) - coordinate[1]*math.sin(angle)
newY = coordinate[0]*math.sin(angle) + coordinate[1]*math.cos(angle) newY = coordinate[0]*math.sin(angle) + coordinate[1]*math.cos(angle)
coordinatesRotate.extend((newX,newY)) coordinatesRotate.extend((newX,newY))
@ -274,8 +275,9 @@ class VlsiLayout:
Method to insert one layout into another at a particular offset. Method to insert one layout into another at a particular offset.
""" """
offsetInLayoutUnits = (self.userUnits(offsetInMicrons[0]),self.userUnits(offsetInMicrons[1])) offsetInLayoutUnits = (self.userUnits(offsetInMicrons[0]),self.userUnits(offsetInMicrons[1]))
if self.debug==1: if self.debug:
debug.info(0,"DEBUG: GdsMill vlsiLayout: addInstance: type %s, nameOfLayout "%type(layoutToAdd),nameOfLayout) 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. # otherwise, if it is a text name of an internal structure, use it.
if layoutToAdd != self: if layoutToAdd != self:
@ -316,9 +318,7 @@ class VlsiLayout:
if mirror or rotate: if mirror or rotate:
layoutToAddSref.transFlags = [0,0,0] layoutToAddSref.transFlags = [0,0,0]
# This is NOT the same as the order in the GDS spec! # transFlags = (mirror around x-axis, magnification, rotation)
# It gets written out in gds2writer in the right order though.
# transFlags = (mirror around x-axis, rotation, magnification)
# If magnification or rotation is true, it is the flags are then # If magnification or rotation is true, it is the flags are then
# followed by an amount in the record # followed by an amount in the record
if mirror=="R90": if mirror=="R90":
@ -328,17 +328,16 @@ class VlsiLayout:
if mirror=="R270": if mirror=="R270":
rotate = 270.0 rotate = 270.0
if rotate: if rotate:
#layoutToAddSref.transFlags = [0,1,0] #layoutToAddSref.transFlags[2] = 1
layoutToAddSref.rotateAngle = rotate layoutToAddSref.rotateAngle = rotate
if mirror == "x" or mirror == "MX": 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 if mirror == "y" or mirror == "MY": #NOTE: "MY" option will override specified rotate angle
#layoutToAddSref.transFlags = [1,1,0] layoutToAddSref.transFlags[0] = 1
layoutToAddSref.transFlags = [1,0,0] #layoutToAddSref.transFlags[2] = 1
layoutToAddSref.rotateAngle = 180.0 layoutToAddSref.rotateAngle = 180.0
if mirror == "xy" or mirror == "XY": #NOTE: "XY" option will override specified rotate angle if mirror == "xy" or mirror == "XY": #NOTE: "XY" option will override specified rotate angle
#layoutToAddSref.transFlags = [0,1,0] #layoutToAddSref.transFlags[2] = 1
layoutToAddSref.transFlags = [0,0,0]
layoutToAddSref.rotateAngle = 180.0 layoutToAddSref.rotateAngle = 180.0
#add the sref to the root structure #add the sref to the root structure
@ -405,10 +404,10 @@ class VlsiLayout:
if(len(text)%2 == 1): if(len(text)%2 == 1):
text = text + '\x00' text = text + '\x00'
textToAdd.textString = text textToAdd.textString = text
textToAdd.transFlags = [0,0,1] #textToAdd.transFlags[1] = 1
textToAdd.magFactor = magnification textToAdd.magFactor = magnification
if rotate: if rotate:
textToAdd.transFlags = [0,1,1] #textToAdd.transFlags[2] = 1
textToAdd.rotateAngle = rotate textToAdd.rotateAngle = rotate
#add the sref to the root structure #add the sref to the root structure
self.structures[self.rootStructureName].texts.append(textToAdd) self.structures[self.rootStructureName].texts.append(textToAdd)
@ -816,10 +815,10 @@ class VlsiLayout:
""" """
(structureName,structureOrigin,structureuVector,structurevVector)=structure (structureName,structureOrigin,structureuVector,structurevVector)=structure
#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:
# Pin enclosures only work on rectangular pins so ignore any non rectangle # FIXME: Right now, this only supports rectangular shapes!
# This may report not finding pins, but the user should fix this by adding a rectangle.
if len(boundary.coordinates)!=5: if len(boundary.coordinates)!=5:
continue continue
if layer==boundary.drawingLayer: if layer==boundary.drawingLayer:
@ -827,10 +826,11 @@ class VlsiLayout:
right_top=boundary.coordinates[2] right_top=boundary.coordinates[2]
# Rectangle is [leftx, bottomy, rightx, topy]. # Rectangle is [leftx, bottomy, rightx, topy].
boundaryRect=[left_bottom[0],left_bottom[1],right_top[0],right_top[1]] boundaryRect=[left_bottom[0],left_bottom[1],right_top[0],right_top[1]]
# perform the rotation
boundaryRect=self.transformRectangle(boundaryRect,structureuVector,structurevVector) boundaryRect=self.transformRectangle(boundaryRect,structureuVector,structurevVector)
# add the offset
boundaryRect=[boundaryRect[0]+structureOrigin[0].item(),boundaryRect[1]+structureOrigin[1].item(), boundaryRect=[boundaryRect[0]+structureOrigin[0].item(),boundaryRect[1]+structureOrigin[1].item(),
boundaryRect[2]+structureOrigin[0].item(),boundaryRect[3]+structureOrigin[1].item()] boundaryRect[2]+structureOrigin[0].item(),boundaryRect[3]+structureOrigin[1].item()]
boundaries.append(boundaryRect) boundaries.append(boundaryRect)
return boundaries return boundaries
@ -858,8 +858,12 @@ class VlsiLayout:
""" """
Rotate a coordinate in space. Rotate a coordinate in space.
""" """
x=coordinate[0]*uVector[0].item()+coordinate[1]*uVector[1].item() # MRG: 9/3/18 Incorrect matrixi multiplication!
y=coordinate[1]*vVector[1].item()+coordinate[0]*vVector[0].item() # 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] transformCoordinate=[x,y]
return transformCoordinate return transformCoordinate

View File

@ -118,9 +118,6 @@ def init_openram(config_file, is_unit_test=True):
init_paths() 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. # Reset the static duplicate name checker for unit tests.
import hierarchy_design import hierarchy_design
hierarchy_design.hierarchy_design.name_map=[] hierarchy_design.hierarchy_design.name_map=[]
@ -257,7 +254,8 @@ def cleanup_paths():
if not OPTS.purge_temp: if not OPTS.purge_temp:
debug.info(0,"Preserving temp directory: {}".format(OPTS.openram_temp)) debug.info(0,"Preserving temp directory: {}".format(OPTS.openram_temp))
return 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 # This annoyingly means you have to re-cd into the directory each debug iteration
#shutil.rmtree(OPTS.openram_temp, ignore_errors=True) #shutil.rmtree(OPTS.openram_temp, ignore_errors=True)
contents = [os.path.join(OPTS.openram_temp, i) for i in os.listdir(OPTS.openram_temp)] 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 += "/" OPTS.openram_temp += "/"
debug.info(1, "Temporary files saved in " + OPTS.openram_temp) debug.info(1, "Temporary files saved in " + OPTS.openram_temp)
cleanup_paths()
def is_exe(fpath): def is_exe(fpath):
@ -316,6 +312,7 @@ def init_paths():
# make the directory if it doesn't exist # make the directory if it doesn't exist
try: try:
debug.info(1,"Creating temp directory: {}".format(OPTS.openram_temp))
os.makedirs(OPTS.openram_temp, 0o750) os.makedirs(OPTS.openram_temp, 0o750)
except OSError as e: except OSError as e:
if e.errno == 17: # errno.EEXIST if e.errno == 17: # errno.EEXIST
@ -330,16 +327,7 @@ def init_paths():
os.chmod(OPTS.output_path, 0o750) os.chmod(OPTS.output_path, 0o750)
except: except:
debug.error("Unable to make output directory.",-1) 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 # imports correct technology directories for testing
def import_tech(): def import_tech():

View File

@ -115,11 +115,11 @@ class dff_inv_array(design.design):
def add_layout_pins(self): def add_layout_pins(self):
for row in range(self.rows): for row in range(self.rows):
for col in range(self.columns): 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") vdd_pin=self.dff_insts[row,col].get_pin("vdd")
self.add_power_pin("vdd", vdd_pin.lc()) 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") gnd_pin=self.dff_insts[row,col].get_pin("gnd")
self.add_power_pin("gnd", gnd_pin.lc()) self.add_power_pin("gnd", gnd_pin.lc())

View File

@ -171,6 +171,8 @@ class pinv(pgate.pgate):
offset=vector(0.5*self.width,self.height), offset=vector(0.5*self.width,self.height),
width=self.width) width=self.width)
def create_ptx(self): def create_ptx(self):
""" """
Create the PMOS and NMOS netlist. Create the PMOS and NMOS netlist.

View File

@ -36,9 +36,6 @@ class grid:
def add_blockage_shape(self,ll,ur,z): 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)) 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 = [] block_list = []
for x in range(int(ll[0]),int(ur[0])+1): for x in range(int(ll[0]),int(ur[0])+1):
for y in range(int(ll[1]),int(ur[1])+1): for y in range(int(ll[1]),int(ur[1])+1):

View File

@ -49,6 +49,12 @@ class router:
""" If we want to route something besides the top-level cell.""" """ If we want to route something besides the top-level cell."""
self.top_name = top_name 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): def set_layers(self, layers):
"""Allows us to change the layers that we are routing on. First layer """Allows us to change the layers that we are routing on. First layer
is always horizontal, middle is via, and last is always 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. Finds the pin shapes and converts to tracks.
Pin can either be a label or a location,layer pair: [[x,y],layer]. 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 = [] pin_list = []
for label in label_list: for shape in shape_list:
(name,layer,boundary)=label (name,layer,boundary)=shape
rect = [vector(boundary[0],boundary[1]),vector(boundary[2],boundary[3])] 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 = pin_layout(pin_name, rect, layer)
pin_list.append(pin_layout(pin, rect, layer)) pin_list.append(pin)
debug.check(len(pin_list)>0,"Did not find any pin shapes for {0}.".format(str(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): 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: for blockage in self.blockages:
# Skip pin shapes
all_pins = [x[0] for x in list(self.pins.values())]
for pin in all_pins: 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 break
else: else:
[ll,ur]=self.convert_blockage_to_tracks(blockage.rect) debug.info(2,"Adding blockage {}".format(str(blockage)))
zlayer = 0 if blockage.layer_num==self.horiz_layer_number else 1 # 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) 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): def get_blockages(self, layer_num):
@ -227,37 +246,6 @@ class router:
rect = [ll,ur] rect = [ll,ur]
new_pin = pin_layout("blockage{}".format(len(self.blockages)),rect,layer_num) new_pin = pin_layout("blockage{}".format(len(self.blockages)),rect,layer_num)
self.blockages.append(new_pin) 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): def convert_point_to_units(self,p):
@ -282,11 +270,15 @@ class router:
old_ur = ur old_ur = ur
ll=ll.scale(self.track_factor) ll=ll.scale(self.track_factor)
ur=ur.scale(self.track_factor) ur=ur.scale(self.track_factor)
ll = ll.floor() # We can round since we are using inflated shapes
ur = ur.ceil() # and the track points are at the center
if ll[0]<45 and ll[0]>35 and ll[1]<10 and ll[1]>0: ll = ll.round()
debug.info(0,"Converting [ {0} , {1} ]".format(old_ll,old_ur)) ur = ur.round()
debug.info(0,"Converted [ {0} , {1} ]".format(ll,ur)) # 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] return [ll,ur]
def convert_pin_to_tracks(self, pin): 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. If a pin has insufficent overlap, it returns the blockage list to avoid it.
""" """
(ll,ur) = pin.rect (ll,ur) = pin.rect
#ll = snap_to_grid(ll)
#ur = snap_to_grid(ur)
#debug.info(1,"Converting [ {0} , {1} ]".format(ll,ur)) #debug.info(1,"Converting [ {0} , {1} ]".format(ll,ur))
# scale the size bigger to include neaby tracks # scale the size bigger to include neaby tracks
@ -306,37 +295,40 @@ class router:
ur=ur.scale(self.track_factor).ceil() ur=ur.scale(self.track_factor).ceil()
# width depends on which layer it is # width depends on which layer it is
zindex = 0 if pin.layer_num==self.horiz_layer_number else 1 zindex=self.get_zindex(pin.layer_num)
if zindex==0: if zindex:
width = self.horiz_layer_width
else:
width = self.vert_layer_width width = self.vert_layer_width
else:
width = self.horiz_layer_width
track_list = [] track_list = []
block_list = [] block_list = []
# include +- 1 so when a shape is less than one grid
for x in range(ll[0]-1,ur[0]+1): track_area = self.track_width*self.track_width
for y in range(ll[1]-1,ur[1]+1): 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)) #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, # 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 # 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_rect = self.convert_track_to_shape(vector3d(x,y,zindex))
full_overlap=max(self.compute_overlap(pin.rect,full_rect)) 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)) #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)) 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)) block_list.append(vector3d(x,y,zindex))
else: else:
debug.info(4,"No overlap: {0} {1} max={2}".format(pin.rect,rect,max_overlap)) 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.warning("Off-grid pin for {0}.".format(str(pin)))
#debug.info(1,"Converted [ {0} , {1} ]".format(ll,ur)) #debug.info(1,"Converted [ {0} , {1} ]".format(ll,ur))
return (track_list,block_list) return (track_list,block_list)
@ -381,7 +373,7 @@ class router:
return [ll,ur] 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 Convert a grid point into a rectangle shape that occupies the entire centered
track. track.
@ -447,9 +439,8 @@ class router:
grid_keys=self.rg.map.keys() grid_keys=self.rg.map.keys()
partial_track=vector(0,self.track_width/6.0) partial_track=vector(0,self.track_width/6.0)
for g in grid_keys: for g in grid_keys:
continue # for now... shape = self.convert_track_to_shape(g)
shape = self.convert_full_track_to_shape(g) self.cell.add_rect(layer="text",
self.cell.add_rect(layer="boundary",
offset=shape[0], offset=shape[0],
width=shape[1].x-shape[0].x, width=shape[1].x-shape[0].x,
height=shape[1].y-shape[0].y) height=shape[1].y-shape[0].y)
@ -481,10 +472,12 @@ class router:
zoom=0.05) zoom=0.05)
for blockage in self.blockages: for blockage in self.blockages:
self.cell.add_rect(layer="boundary", # Display the inflated blockage
offset=blockage.ll(), (ll,ur) = blockage.inflate()
width=blockage.width(), self.cell.add_rect(layer="blockage",
height=blockage.height()) 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 # FIXME: This should be replaced with vector.snap_to_grid at some point

View File

@ -32,12 +32,14 @@ class no_blockages_test(openram_test):
globals.setup_paths() globals.setup_paths()
from control_logic import control_logic from control_logic import control_logic
cell = control_logic(16) 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") #gds_file = "{0}/{1}.gds".format(os.path.dirname(os.path.realpath(__file__)),"control_logic")
#cell = gds_cell(name, gds_file) #cell = gds_cell(name, gds_file)
self.add_inst(name=name, self.add_inst(name=name,
mod=cell, mod=cell,
offset=[0,0]) 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) r=router(module=cell)
layer_stack =("metal3","via2","metal2") layer_stack =("metal3","via2","metal2")

View File

@ -56,6 +56,7 @@ layer["via9"] = 28
layer["metal10"] = 29 layer["metal10"] = 29
layer["text"] = 239 layer["text"] = 239
layer["boundary"]= 239 layer["boundary"]= 239
layer["blockage"]= 239
################################################### ###################################################
##END GDS Layer Map ##END GDS Layer Map

View File

@ -41,6 +41,7 @@ layer["via2"] = 61
layer["metal3"] = 62 layer["metal3"] = 62
layer["text"] = 63 layer["text"] = 63
layer["boundary"] = 63 layer["boundary"] = 63
layer["blockage"] = 83
################################################### ###################################################
##END GDS Layer Map ##END GDS Layer Map

View File

@ -625,7 +625,7 @@ drDefinePacket(
( display deviceAnt stipple0 solid yellow yellow solid ) ( display deviceAnt stipple0 solid yellow yellow solid )
( display winBottomShadow solid solid winColor1 winColor1 solid ) ( display winBottomShadow solid solid winColor1 winColor1 solid )
( display PselectNet dots4 solid brown brown outlineStipple) ( 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 Poly1 dots lineStyle0 red red outlineStipple)
( display Unrouted stipple0 lineStyle1 winColor5 winColor5 solid ) ( display Unrouted stipple0 lineStyle1 winColor5 winColor5 solid )
( display stretch stipple0 solid yellow yellow solid ) ( display stretch stipple0 solid yellow yellow solid )